2014-11-03 123 views
3

我正在捕獲攝像頭並將其寫入影片。 我遇到的問題是導出後電影在它前面有幾個黑色秒(相對於實際的錄製開始時間)。AVAssetWriter/AVAssetWriterInputPixelBufferAdaptor - 黑幀和幀速率

我認爲這與[self.assetWriter startSessionAtSourceTime:kCMTimeZero]; 我有一個半工作解決方案,有一個frameStart變量,在samplebuffer委託方法中向上計數。

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

這個工程:

- (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++; 
    } 
} 

,然後當用戶按下一個按鈕調用此方法。但只有一次......如果我想錄制第二部電影,那麼黑色框架又回來了。

另外,當我看輸出的電影時,幀速率是25fps,就像我想要的那樣。但視頻看起來好像在加速。好像幀之間沒有足夠的空間。所以這部電影的播放速度要快一倍。

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變量'latestTimestamp',它一直從'captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)連接'方法的最後一幀獲取時間戳。然後,當用戶按下一個按鈕,我做'[self.assetWriter startSessionAtSourceTime:self.latestFrameTimeStamp];'這工作,但我猜應該有一個更好的方法。 – 2014-11-12 14:04:54

+1

這實際上就是我所做的:在用戶按下按鈕之後,用第一個樣本的時間戳開始記錄會話。如果真的把用戶按下按鈕作爲起點,那麼由於捕捉延遲,視頻開始時可能會出現一些空白幀。 – 2014-11-12 21:04:07

+0

但是,我會如何得到第一個樣本?因爲樣本只能在樣本緩衝區委託方法中得到嗎?假設我有一個方法' - (void)buttonPressed'。並在那裏我調用這個方法'[self.assetWriter startSessionAtSourceTime:timestamp]; '然後我會如何從委託方法中獲取最後一個'timestamp'到我按鈕按下的方法中? (以一種好的方式) – 2014-11-13 16:40:04

0

首先,你爲什麼要增加frameNumber的兩倍,每幀? 增量一次,刪除第一個。 這應該修復播放速度。

其次,您是否在完成錄製時將frameNumber重置爲0? 如果不是這個是你的問題。 如果不是我需要什麼這裏發生了更多的解釋..

問候