Подтвердить что ты не робот

IOS альтернатива QTMovieLayer, которая имеет не-nil `contents`?

Фон

QTKit (QuickTime Kit) - это среда Mac с 10,3 дней, которая получила некоторые дополнения к слою в 10.5, например, QTMovieLayer. Одна из приятных вещей с QTMovieLayer заключается в том, что вы можете получить доступ к содержимому фильма с помощью обычного свойства content на этом слое и вернуть объект CAImageQueue. Самое приятное в том, что вы можете создать кучу регулярных CALayer и установить очередь изображений в качестве своего контента и предоставить всем слоям свою часть фильма, установив правильный contentRect. Это означает, что вы можете создать что-то вроде изображения ниже, когда работает только один фильм, и вы получаете как синхронизацию, так и эффективность памяти.

enter image description here

Я могу опубликовать этот код, но я сомневаюсь, что это относится к моему вопросу, так как вопрос о iOS и QTKit там не существует.

Моя проблема

Я хочу сделать то же самое в iOS, но QTKit там не существует. То есть, я ищу альтернативу QTMovieLayer, которые существуют в iOS, где свойство content не является nil (это важная часть), поэтому я могу поделиться содержимым между несколькими слоями.

Кроме того, когда мне удается получить видеоролик для воспроизведения в нескольких слоях, я хочу указать, какую часть видео должно воспроизводиться на каком уровне (например, на изображении выше)


Что я пробовал

В iOS у вас есть AVFoundation или среда MediaPlayer для воспроизведения видеороликов. В AVFoundation у вас есть AVPlayerLayer, который может отображать фильмы. (У вас также есть AVCaptureVideoPreviewLayer для отображения предварительного просмотра ввода камеры и AVSynchronizedLayer для синхронизации, но не для отображения видео).

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

Я прочитал Техническая нота TN2300 - Переход кода QTKit в AV Foundation, но ничего не нашел о совместном использовании видеоконтента между слоями.

AVPlayerLayer

Если я создаю слой игрока как это и попытаюсь получить contents, я получаю только nil назад

NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"m4v"];
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
[player play];
AVPlayerLayer *videoLayer = [AVPlayerLayer playerLayerWithPlayer:player];
id videoContent = videoLayer.contents // <-- this is nil :(

AVCaptureVideoPreviewLayer

Несмотря на то, что мне действительно интересно воспроизводить видеофайл, я попытался использовать слой предварительного просмотра захвата, но контент равен нулю, как и раньше.

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

AVCaptureSession *captureSession = [AVCaptureSession new];
[captureSession addInput:input];
AVCaptureVideoPreviewLayer *Layer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];

[captureSession startRunning];

id videoContent = videoLayer.contents // <-- this is still nil :(

AVSynchronizedLayer

Из его имени вы можете подумать, что синхронизированный слой будет тем, что я ищу, но он не используется для отображения чего-либо (документация заголовка формы):

AVSynchronizedLayer похож на CATransformLayer тем, что он сам ничего не отображает, а только присваивает состояние его поддереву слоев.

Рамка MediaPlayer

Рамка медиаплеера не имеет варианта слоя, и создание контроллера просмотра игроков и получение слоя просмотра игроков не похоже на действительный вариант для меня. (Да, я даже не потрудился попробовать.)


Резюме вопроса:

Есть ли какая-либо альтернатива QTMovieLayer, которая существует в iOS, где вы можете получать содержимое воспроизводимого в данный момент видео и отображать его части в нескольких других слоях одновременно?

4b9b3361

Ответ 1

Для получения буфера видео/аудио данных из сеанса захвата или сеанса проигрывателя,

  • Создайте объект AVCaptureVideoDataOutput/AVCaptureAudioDataOutput.
  • Подтвердите одно из ваших AVCaptureVideoDataOutputSampleBufferDelegate.
  • Добавьте AVCaptureVideoDataOutput в сеанс Capture/Player.
  • Реализация методов протокола. Вы получите объект CMSampleBufferRef, содержащий видео/аудио кадры, когда носитель захватывается/воспроизводится в методе captureOutput... для AVCaptureVideoDataOutputSampleBufferDelegate.

Объект CMSampleBufferRef содержит данные фрейма носителя, информацию о временной отметке и описание формата носителя. Затем вы можете отобразить этот кадр, преобразовывая его в CGImageRef и отображая его на любом представлении.

Вы также можете указать желаемый формат сжатия кадра (или формат несжатого кадра) в свойстве AVCaptureVideoDataOutput.videoSettings.