Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVAssetWriter / AVAssetWriterInputPixelBufferAdaptor - black frames and frame rate

I'm capturing the camera feed and writing it to a movie. The problem I'm having is that after the export the movie has a couple of black seconds in front of it (relative to the actual recording start time).

I think this is related to [self.assetWriter startSessionAtSourceTime:kCMTimeZero]; I had a half working solution by having a frameStart variable that just counted upwards in the samplebuffer delegate method.

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

and then call this method when the user pressed a button:

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

this works. but only once... if I want to record a second movie the black frames are back again.

Also, when I look at the outputted movie the frame rate is 25fps like I want it to. but the video looks as if it's sped up. as if there is not enough space between the frames. So the movie plays about twice as fast.

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;
like image 587
Ramin Afshar Avatar asked Dec 09 '25 21:12

Ramin Afshar


1 Answers

You don't need to count frame timestamps on your own. You can get the timestamp of the current sample with

CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);

However, it seems to me you are just passing the pixel buffer of the frame to the adaptor without modifications. Wouldn't it be easier to pass the sample buffer itself directly to the assetWriterInput like the following?

[self.assetWriterInput appendSampleBuffer:sampleBuffer];
like image 107
Frank Schlegel Avatar answered Dec 11 '25 10:12

Frank Schlegel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!