Перемещение на один кадр в CMTime и AVFoundation - PullRequest
6 голосов
/ 24 июня 2011

Я пытаюсь воспроизвести видео с помощью AVFoundation. Я использую следующий код для кнопки, которая ускоряет воспроизведение на один кадр.

Он работает с перебоями, при некоторых исполнениях он будет делать правильные вещи и продвигаться на один кадр, но в большинстве случаев мне придется нажимать кнопку 3 или 4 раза, прежде чем он будет продвигать кадр.

Это заставляет меня думать, что это какая-то проблема точности, но я не могу понять, что это такое. Каждый раз, когда он запускается, новый CMTime, кажется, продвигается на ту же сумму.

Моя другая теория заключается в том, что это может быть вызвано тем, что currentTime не имеет точной границы кадра при моей частоте кадров (вызванной поиском по видео). Но я не знаю, как «привязаться» к ближайшему кадру при моей частоте кадров.

AVAssetTrack *videoTrack = ...;
Float64 frameRate = [videoTrack nominalFrameRate];

CMTime currentTime = [self.playerItem currentTime];
CMTime oneFrame = CMTimeMakeWithSeconds(1.0 / frameRate, currentTime.timescale);
CMTime added = CMTimeAdd(currentTime, oneFrame);

[self.player seekToTime:added toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];

Спасибо за вашу помощь!

Ответы [ 2 ]

5 голосов
/ 25 июня 2011

Ответ на ваш вопрос находится во второй строке кода, где вы удаляете «номинал» из nominalFrameRate.

В вашем коде предполагается, что частота кадров в вашем видео постоянна.Это неверно.

Видео может иметь постоянную частоту кадров, но это не обязательно.Например, если вы снимаете пленку на телефон в условиях переменного освещения, время экспозиции кадра может измениться, а частота кадров будет изменяться обратно.

Чтобы «привязаться» к границам кадра, вам нужно использовать AVAssetReader длячерез отдельные кадры.Каждый кадр помечен меткой времени представления (его «t»), но если вы шагаете, это не имеет большого значения, если вы не обновляете маркер позиции.

4 голосов
/ 11 октября 2013

Это не очень очевидно (поскольку, как ни странно, это доступно только в AVPlayerItem, а не AVPlayer), но если AVPlayerItem возвращает YES для canStepForward/canStepBackward, тогда вы можете вызвать stepByCount:(NSInteger)stepCount: для перемещения вперед или назад на определенное количество кадров.

...