MPMoviePlayerController зависает AVCaptureVideoPreviewLayer

Я создаю приложение, которое показывает слой предварительного просмотра видео, используя AVCaptureVideoPreviewLayer. Настройка этого довольно проста и, кажется, работает хорошо:

newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:[[self captureManager] session]];
CGRect tmpRect = CGRectInset(recordingView.bounds, 3, 3);
[newCaptureVideoPreviewLayer setFrame:CGRectInset(tmpRect, 3, 3)];
CALayer *viewLayer = [recordingView layer];
[newCaptureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[viewLayer insertSublayer:newCaptureVideoPreviewLayer below:[[viewLayer sublayers] objectAtIndex:0]];
[self setCaptureVideoPreviewLayer:newCaptureVideoPreviewLayer];
[newCaptureVideoPreviewLayer release];

Позже у меня возникает ситуация, когда пользователь может заменить представление, содержащее слой предварительного просмотра, на представление, содержащее записанное видео, с помощью MPMoviePlayerController. Я настроил его так (предыдущий блок кода исходит из метода viewDidLoad: UIViewController, и это в том же контроллере, как часть его собственного метода для изменения представления:

MPMoviePlayerController * player = [[MPMoviePlayerController alloc] initWithContentURL:url];
[player.view setFrame:[detailView playerView].bounds];  // player's frame must match parent's

player.view.backgroundColor = [UIColor clearColor];
player.shouldAutoplay = NO;
player.fullscreen = NO;
player.scalingMode = MPMovieScalingModeAspectFit;

[[detailView playerView] addSubview:player.view];

Проблема в том, что когда MPMoviePlayerController добавляется к представлению, предварительный просмотр «зависает» — он показывает последний кадр того, что было перед камерой до ввода этого блока кода. Я не получаю сообщений об ошибках и не могу найти источник проблемы.

Обратите внимание, что я не выпускаю переменную player. Любые попытки сделать это ломают проигрыватель, в том числе его автоматическое освобождение или попытка освободить его в обратном вызове уведомления. Тем не менее, я не думаю, что эта проблема (хотя она и сама по себе может быть проблемой) является причиной уничтожения моего слоя предварительного просмотра.

Я был бы признателен за любую информацию, которую вы могли бы иметь в этом вопросе!

Обновление: @boredastronaut спросил ниже, как я настроил здесь представления. У меня есть один контроллер, на котором работают все представления. В моем приложении у меня есть слой предварительного просмотра и в том же месте представление, содержащее проигрыватель. Все представления загружаются в -loadView:, и я использую свойство hidden, чтобы показать/скрыть эти слои по мере необходимости.


person Aaron Vegh    schedule 04.10.2011    source источник
comment
Это правда, что вы не должны выпускать свой плеер (который является контроллером), если вы не добавили его в иерархию контроллеров, но вы также не хотите просто слить его. Вероятно, вы хотите сделать его свойством вашего пользовательского контроллера представления или, возможно, вашего делегата приложения. Мне не понятна ваша техника замены вида предварительного просмотра (вида, содержащего слой предварительного просмотра) на вид игрока. Являются ли предварительный просмотр и представления проигрывателя подвидами подробного представления? Не совсем понятно, как устроена иерархия представлений.   -  person Bored Astronaut    schedule 05.10.2011
comment
Для сравнения, у меня есть тестовое приложение, которое я написал некоторое время назад, чтобы поиграть с этим (хотя оно использует AVPlayerLayer вместо MPMoviePlayerController и пользовательскую кнопку для запуска/остановки фильма). У меня есть вкладка с двумя вкладками: одна для плеера, одна для предварительного просмотра/записи. Я настроил превью аналогично вам. Настройка уровня проигрывателя выглядит так... ну, я не могу поместить это в комментарий, но Руководство по программированию AV Foundation поможет читателю разобраться с этим.   -  person Bored Astronaut    schedule 05.10.2011


Ответы (3)


Спасибо за этот пост! Я наконец заставил свое приложение работать после 3 часов отладки. Я использовал второй подход, предложенный здесь, и он работал прекрасно.

if([self.capMan.session isInterrupted]) { [self.capMan.session startRunning]; }

person Nancy    schedule 26.04.2013

После немалых усилий я остановился на другом решении. Я сохранял слой предварительного просмотра в памяти и работал, переключая представление на DetailView. Теперь я снимаю предварительный слой и полностью закрываю сеанс записи, когда он исчезает с экрана, а затем снова создаю его, когда пользователь возвращается. Это вызывает задержку примерно в одну секунду при повторной инициализации previewLayer, но это работает, и я думаю, что это нормально.

person Aaron Vegh    schedule 15.10.2011

Вы можете просто проверить, запущен ли сеанс слоя предварительного просмотра, и если нет, вызвать startRunning метод сеанса.

person Percius    schedule 15.05.2012