2014-11-03 4 views
3

Я забираю канал камеры и записываю его в кино. Проблема, с которой я столкнулся, заключается в том, что после экспорта у фильма есть пара черных секунд перед ним (относительно фактического времени начала записи).AVAssetWriter/AVAssetWriterInputPixelBufferAdaptor - черные кадры и частота кадров

Я думаю, это связано с [self.assetWriter startSessionAtSourceTime:kCMTimeZero]; У меня было полурабочее решение, имея переменную frameStart, которая только что подсчитана вверх в методе делегата samplebuffer.

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 

    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    frameStart++; 
    if (self.startRecording == YES) { 

     static int64_t frameNumber = 0; 
     if(self.assetWriterInput.readyForMoreMediaData) { 
      [self.pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:CMTimeMake(frameNumber, 25)]; 
     } 
     frameNumber++; 
    } 
} 

и затем вызвать этот метод, когда пользователь нажал кнопку:

[self.assetWriter startSessionAtSourceTime:CMTimeMake(frameStart,25)]; 

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

Кроме того, когда я смотрю на выведенный фильм, частота кадров составляет 25 кадров в секунду, как я этого хочу. но видео выглядит так, как будто оно ускоряется. как будто между кадрами недостаточно места. Таким образом, фильм играет примерно в два раза быстрее.

NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:640], AVVideoWidthKey, [NSNumber numberWithInt:480], AVVideoHeightKey, AVVideoCodecH264, AVVideoCodecKey, nil]; 

self.assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:outputSettings]; 
self.assetWriterInput.expectsMediaDataInRealTime = YES; 

ответ

2

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

CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 

Тем не менее, мне кажется, вы просто проездом пиксельный буфер кадра к адаптеру без изменений. Не было бы проще передать сам буфер проб непосредственно на assetWriterInput следующим образом?

[self.assetWriterInput appendSampleBuffer:sampleBuffer]; 
+0

Это на самом деле очень близко. У меня только один вопрос. Как я могу получить метку времени при нажатии кнопки? Прямо сейчас у меня есть переменная CMTime 'lastTimestamp', которая продолжает получать метку времени из последнего кадра в методе connectOutput: (AVCaptureOutput *) captureOutput didOutputSampleBuffer: (CMSampleBufferRef) sampleBuffer fromConnection: (AVCaptureConnection *). Затем, когда пользователь нажимает кнопку, я делаю [self.assetWriter startSessionAtSourceTime: self.latestFrameTimeStamp]; 'Это работает, но я предполагаю, что должен быть лучший способ. –

+1

Это на самом деле то, что я делаю: начните сеанс записи с отметки времени первого образца, входящего после нажатия пользователем кнопки. Если вы действительно принимаете момент, когда пользователь нажал кнопку в качестве начальной точки, вы могли бы получить несколько пустых кадров в начале видео из-за задержки захвата. –

+0

Но как бы получить этот первый образец? Потому что образец может быть получен только в методе делегирования буфера выборки правильно? предположим, что у меня есть метод '- (void) buttonPressed'. И там я вызываю этот метод '[self.assetWriter startSessionAtSourceTime: timestamp]; 'Как я могу получить последнюю временную метку из метода делегата в методе нажатия кнопки? (в хорошем смысле) –

0

Прежде всего, почему вы увеличиваете число кадров в два раза для каждого кадра? Приращивание один раз, удалите первый. Это должно исправить скорость воспроизведения.

Во-вторых, вы сбрасываете frameNumber до 0, когда закончите запись? Если это не ваша проблема. Если не мне нужно больше объяснений о том, что происходит здесь ..

С уважением

Смежные вопросы