Видео останавливается на переключателе камеры с AVFoundation
Я сделал приложение с функцией захвата и сохранения видео. Я использовал AVFoundation для этого, и AVCam от Apple был моим гидом.
Я надеюсь, что смогу прояснить:
Все работает нормально, пока я не выпущу videoViewController, который впервые обрабатывает AVCamCaptureManager (в AVCam это будет AVCamViewController). После этого при повторном создании видео зависает сразу после переключения камеры. Даже повторный запуск не поможет, не очистит и не перезагрузит устройство. (Иногда что-то помогает, но это не правило).
Я выпускаю videoViewController, когда не нужно экономить память.
Код для переключения камеры в основном такой же, как в AVCam:
NSError *error;
AVCaptureDeviceInput *newVideoInput;
AVCaptureDevicePosition position = currentVideoInput.device.position;
if (position == AVCaptureDevicePositionBack)
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:frontFacingCamera error:&error];
else if (position == AVCaptureDevicePositionFront)
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:backFacingCamera error:&error];
if (newVideoInput != nil) {
[session beginConfiguration];
[session removeInput:currentVideoInput];
if ([session canAddInput:newVideoInput]) {
[session addInput:newVideoInput];
[self setVideoInput:newVideoInput];
} else {
[session addInput:currentVideoInput];
}
[session commitConfiguration];
[newVideoInput release];
} else if (error) {
NSLog(@"%@",[error localizedDescription]);
}
Код, с которым я отклоняю videoView
[self.videoViewController.view removeFromSuperview];
self.videoViewController = nil;
Мой нынешний "обходной путь" - просто оставить все как есть, даже если он мне не нужен.
Может кто-нибудь объяснить, почему это происходит и как это решить.
РЕДАКТИРОВАТЬ: Решено
Как отметил W Dyson в своем ответе, я должен был прекратить сеанс, прежде чем выпускать мой videoViewController, вот так:
[[[self.videoViewController captureManager] session] stopRunning];
[self.videoViewController.view removeFromSuperview];
self.videoViewController = nil;
Спасибо Дайсон.
2 ответа
Вы получаете журналы ошибок? Если нет, вам нужно исправить приведенный выше код и посмотреть, что они говорят. Какую версию AVCam вы используете? Недавно они обновили проект до версии 1.2, которая намного эффективнее и использует блоки.
По моему опыту, вы не должны создавать и воссоздавать сеанс, вы можете просто оставить его включенным. Возможно, вам нужно структурировать свое приложение немного по-другому. О чем конкретно ваше приложение? Может быть, мы можем помочь вам. Если ваше приложение сосредоточено вокруг камеры, то легче оставить сеанс включенным, если вы просто снимаете видео модально, то, возможно, использование AVCam является излишним.
Мне кажется, что ваша настоящая проблема звучит так, как будто она связана с AVCaptureDeviceInput. Загрузите оригинальный пакет AVCam и посмотрите, изменили ли вы какие-либо сохраняемые значения или заявления о безопасности. Если есть другой код, пожалуйста, напишите.
ОБНОВЛЕНИЕ: вы можете изменить
} else if (error) {
NSLog(@"%@",[error localizedDescription]);
}
в
} if (error) {
NSLog(@"%@",[error localizedDescription]);
}
и скажите мне, если есть ошибка?
Кроме того, прежде чем выпускать контроллер представления, которому принадлежит сеанс, убедитесь, что вы остановили сеанс и задали для менеджера захвата значение nil.
ОБНОВЛЕНИЕ 2: Попробуйте этот код переключения. Это то, что я использовал. AVCamMirringMode представляет собой следующую структуру:
enum {
AVCamMirroringOff = 1,
AVCamMirroringOn = 2,
AVCamMirroringAuto = 3
};
typedef NSInteger AVCamMirroringMode;
- (BOOL) toggleCamera
{
BOOL success = NO;
if ([self cameraCount] > 1) {
NSError *error;
AVCaptureDeviceInput *newVideoInput;
AVCaptureDevicePosition position = [[videoInput device] position];
BOOL mirror;
if (position == AVCaptureDevicePositionBack){
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontFacingCamera] error:&error];
switch ([self mirroringMode]) {
case AVCamMirroringOff:
mirror = NO;
break;
case AVCamMirroringOn:
mirror = YES;
break;
case AVCamMirroringAuto:
default:
mirror = YES;
break;
}
}
else if (position == AVCaptureDevicePositionFront){
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:&error];
switch ([self mirroringMode]) {
case AVCamMirroringOff:
mirror = NO;
break;
case AVCamMirroringOn:
mirror = YES;
break;
case AVCamMirroringAuto:
default:
mirror = NO;
break;
}
}
else
goto bail;
if (newVideoInput != nil) {
[[self session] beginConfiguration];
[[self session] removeInput:[self videoInput]];
if ([[self session] canAddInput:newVideoInput]) {
[[self session] addInput:newVideoInput];
AVCaptureConnection *connection = [AVCamUtilities connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
if ([connection isVideoMirroringSupported]) {
[connection setVideoMirrored:mirror];
}
[self setVideoInput:newVideoInput];
} else {
[[self session] addInput:[self videoInput]];
}
[[self session] commitConfiguration];
success = YES;
[newVideoInput release];
} else if (error) {
if ([[self delegate] respondsToSelector:@selector(captureManager:didFailWithError:)]) {
[[self delegate] captureManager:self didFailWithError:error];
}
}
}
bail:
return success;
}
Попробуйте это - это сработало как чемпион для меня:
BOOL isUsingFrontFacingCamera;
- (BOOL) swapCameras
{
if ([self cameraCount] > 1) {
AVCaptureDevicePosition desiredPosition;
if (isUsingFrontFacingCamera) {
desiredPosition = AVCaptureDevicePositionBack;
} else {
desiredPosition = AVCaptureDevicePositionFront;
}
for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]) {
if ([d position] == desiredPosition) {
[[self session] beginConfiguration];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
for (AVCaptureInput *oldInput in [[self session] inputs]) {
[[self session] removeInput:oldInput];
}
[[self session] addInput:input];
[[self session] commitConfiguration];
break;
}
}
isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
return YES;
}
return NO;
}
Вы должны иметь возможность вставить этот код для замены оригинальных swapCameras в VideoRecorderCaptureManager.m
Происхождение: пример кода Apple SquareCam.