Видео останавливается на переключателе камеры с AVFoundation - PullRequest
6 голосов
/ 18 апреля 2011

Я сделал приложение с функцией захвата и сохранения видео.Я использовал 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;

Мой текущий «обходной путь» заключается впросто оставь это, даже если мне это не нужно.

Может кто-нибудь объяснить, почему это происходит и как это решить.

РЕДАКТИРОВАТЬ: Решено
Как указывал В. Дайсон вего ответ я должен был остановить сессию перед выпуском моего videoViewController следующим образом:

[[[self.videoViewController captureManager] session] stopRunning];
[self.videoViewController.view removeFromSuperview];
self.videoViewController = nil;

Спасибо W Dyson.

Ответы [ 2 ]

9 голосов
/ 17 января 2013

Попробуй это - это сработало как чемпион для меня:

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 in VideoRecorderCaptureManager.m

Происхождение: пример кода Apple SquareCam.

3 голосов
/ 18 апреля 2011

Получаете ли вы журналы ошибок?Если нет, вам нужно исправить приведенный выше код и посмотреть, что они говорят.Какую версию 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;
}
...