gpt4 book ai didi

ios - 在 iOS 中使用 AVFoundation 切换摄像头后视频录制不工作

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:18:31 32 4
gpt4 key购买 nike

我正在使用 AVFoundation 在我的应用程序中录制视频。如果我不切换相机,录制工作正常。一旦我切换相机,录制就会停止工作。调试后我发现在缓冲区委托(delegate)方法中,我没有获取 videoConnection 对象。所以我的委托(delegate)方法不会被调用,因为条件不满足。

不知何故,我找不到代码中的错误。这是我的代码

非常感谢任何形式的帮助。谢谢。

    // I am calling this method to setup the session from viewDidLoad 
- (BOOL) setupSessionWithPreview:(UIView *)preview usingFrontCamera:(BOOL)frontCamera
{
AVCaptureDevice *videoDevice = nil;
if (frontCamera) {
videoDevice = [self getFrontCamera];
self.videoDeviceType = VideoDeviceTypeFrontCamera;
}
else {
videoDevice = [self getRearCamera];
self.videoDeviceType = VideoDeviceTypeRearCamera;
}
AVCaptureDevice *audioDevice = [self getAudioDevice];

self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoDevice error:nil];
AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:nil];

self.session = [[AVCaptureSession alloc] init];
if([self.session canAddInput:self.videoInput])
[self.session addInput:self.videoInput];

if([self.session canAddInput:audioInput])
[self.session addInput:audioInput];

self.audioOutput = [[AVCaptureAudioDataOutput alloc] init];
dispatch_queue_t audioCaptureQ = dispatch_queue_create("Audio Capture Q", DISPATCH_QUEUE_SERIAL);
[self.audioOutput setSampleBufferDelegate:self queue:audioCaptureQ];

if([self.session canAddOutput:self.audioOutput])
[self.session addOutput:self.audioOutput];
self.audioConnection = [self.audioOutput connectionWithMediaType:AVMediaTypeAudio];

self.videoOutput = [[AVCaptureVideoDataOutput alloc] init];
[self.videoOutput setAlwaysDiscardsLateVideoFrames:YES];

dispatch_queue_t videoCaptureQ = dispatch_queue_create("Video Capture Q", DISPATCH_QUEUE_SERIAL);
[self.videoOutput setSampleBufferDelegate:self queue:videoCaptureQ];

if([self.session canAddOutput:self.videoOutput])
[self.session addOutput:self.videoOutput];

self.videoConnection = [self.videoOutput connectionWithMediaType:AVMediaTypeVideo];

self.videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
self.videoOrientation = [self.videoConnection videoOrientation];

movieWriterQ = dispatch_queue_create("Movie Writer Q", DISPATCH_QUEUE_SERIAL);

self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
self.viewLayer = [preview layer];
[self.viewLayer setMasksToBounds:YES];

CGRect bounds = [preview bounds];
[self.previewLayer setFrame:bounds];

[self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[self.viewLayer insertSublayer:self.previewLayer below:[[self.viewLayer sublayers] objectAtIndex:0]];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.session startRunning];
});

return YES;
}

// When user tap on switch camera button , I am calling this method
-(void)toggleCameraIsFront:(BOOL)isFront
{
AVCaptureDevicePosition desiredPosition;
if (isFront) {
desiredPosition = AVCaptureDevicePositionFront;
self.videoDeviceType = VideoDeviceTypeFrontCamera;
}
else {
desiredPosition = AVCaptureDevicePositionBack;
self.videoDeviceType = VideoDeviceTypeRearCamera;
}

NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in videoDevices)
{
if ([device position] == desiredPosition)
{
AVCaptureDeviceInput *videoDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:device error:nil];
[self.session beginConfiguration];
[self.session removeInput:self.videoInput];
if ([self.session canAddInput:videoDeviceInput])
{
[self.session addInput:videoDeviceInput];
[self setVideoInput:videoDeviceInput];
}
else
{
[self.session addInput:self.videoInput];
}
[self.session commitConfiguration];
break;
}
}
}

// This is delegate method
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);

CFRetain(sampleBuffer);
CFRetain(formatDescription);

dispatch_async(movieWriterQ, ^{
NSString *mediaType = nil;
if(self.assetWriter)
{
BOOL wasReadyToRecord = (readyToRecordAudio && readyToRecordVideo);
if(connection == self.videoConnection)// this condition is not excuting after switch camera
{
if(!readyToRecordVideo)
readyToRecordVideo = [self setupAssetWriterVideoInput:formatDescription];
mediaType = AVMediaTypeVideo;
}
else if(connection == self.audioConnection)
{
if(!readyToRecordAudio)
readyToRecordAudio = [self setupAssetWriterAudioInput:formatDescription];
mediaType = AVMediaTypeAudio;
}
BOOL isReadyToRecord = (readyToRecordAudio && readyToRecordVideo);
if(!wasReadyToRecord && isReadyToRecord)
{
LogDebug(LOG_MODULE, @"Send recording did being");
recordingWillStart = NO;
recording = YES;

dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate recordingDidBeginToOutputFileURL:self.outputUrl withID:self.recordingID];
});
}

if(mediaType != nil)
{
if(readyToRecordVideo && readyToRecordAudio)
[self writeSampleBuffer:sampleBuffer ofType:mediaType];
}
}
CFRelease(sampleBuffer);
CFRelease(formatDescription);
});
}

最佳答案

如下更新切换方法后,视频录制工作正常

    -(void)toggleCameraIsFront:(BOOL)isFront
{
AVCaptureDevicePosition desiredPosition;
if (isFront) {
desiredPosition = AVCaptureDevicePositionFront;
self.videoDeviceType = VideoDeviceTypeFrontCamera;
}
else {
desiredPosition = AVCaptureDevicePositionBack;
self.videoDeviceType = VideoDeviceTypeRearCamera;
}


NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in videoDevices)
{
if ([device position] == desiredPosition)
{
AVCaptureDeviceInput *videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
[self.session beginConfiguration];
[self.session removeInput:self.videoInput];
if ([self.session canAddInput:videoDeviceInput])
{
[self.session addInput:videoDeviceInput];
[self setVideoInput:videoDeviceInput];
}
else
{
[self.session addInput:self.videoInput];
}

[self.session removeOutput:self.videoOutput];

AVCaptureVideoDataOutput *videoDeviceOutput = [[AVCaptureVideoDataOutput alloc] init];
if ([self.session canAddOutput:videoDeviceOutput])
{
[self.session addOutput:videoDeviceOutput];
[self setVideoOutput:videoDeviceOutput];
[self.videoOutput setAlwaysDiscardsLateVideoFrames:YES];

// How to manage previously created videoCaptureQ in setupSessionWithPreview method ???
// or do we need create instance variable as dispatch_queue_t videoCaptureQ ???
dispatch_queue_t videoCaptureQ = dispatch_queue_create("Video Capture Q", DISPATCH_QUEUE_SERIAL);
[self.videoOutput setSampleBufferDelegate:self queue:videoCaptureQ];

self.videoConnection = [self.videoOutput connectionWithMediaType:AVMediaTypeVideo];

self.videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
self.videoOrientation = [self.videoConnection videoOrientation];
}
else
{
[self.session addOutput:self.videoOutput];
}

[self.session commitConfiguration];
break;
}
}
}

关于ios - 在 iOS 中使用 AVFoundation 切换摄像头后视频录制不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22652023/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com