3

I'm using AVFoundation on OSX Lion to do screen capture. Accomplished as follows:

    self->screenInput = [[AVCaptureScreenInput alloc] initWithDisplayID:self->screen];
    self->dataOutput = [[AVCaptureVideoDataOutput alloc] init];
    self->session = [[AVCaptureSession alloc] init];
    self->assetWriter = [[AVAssetWriter alloc] initWithURL:url
                                                  fileType:AVFileTypeQuickTimeMovie 
                                                     error:&error];
    self->writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
                                                           outputSettings:nil] retain];
    self->dataOutput.videoSettings=videosettings;

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

    if(!self->startedWriting)
    {
        [self->assetWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
        self->startedWriting = YES;
    }

    if(self->writerInput.readyForMoreMediaData)
    {
        [self->writerInput appendSampleBuffer:sampleBuffer]
    }

}

This results in a framerate roughly 1 Mbps -> 3 Mbps. The problem with this is that in video settings I've specified:

NSMutableDictionary * compressionSettings = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease];
[compressionSettings setObject:[NSNumber numberWithInt:512000] forKey:AVVideoAverageBitRateKey];
[videosettings setObject:compressionSettings forKey:AVVideoCompressionPropertiesKey];

are for 512K, and having a higher bitrate causes the files to be too big (we need to upload these files after all).

When I remove the line

    self->dataOutput.videoSettings=videosettings;

and instead apply the video settings to the writerinput via

self->writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
                                                       outputSettings:videosettings] retain];

I get a bitrate that is too low (usually 100 Kbps => 300 Kbps). I assume this is because the encoding is taking place via software instead of hardware (it is happening after the data is returned from the AVCaptureSession).

What can I do to force the capture to go down from 1-3 Mbps and down to just 512K? If it can go higher, I can't imagine why it wouldn't be able to just cap the rate it's using.

Thanks,

-G

George
  • 1,457
  • 11
  • 26

1 Answers1

1

From the docs for the AVCaptureVideoDataOutput videoSettings property

Currently, the only supported key is kCVPixelBufferPixelFormatTypeKey. Supported pixel formats are
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange and kCVPixelFormatType_32BGRA,
except on iPhone 3G, where the supported pixel formats are kCVPixelFormatType_422YpCbCr8 and kCVPixelFormatType_32BGRA.

Setting compression settings on this class is meaningless. This means your compression settings for AVAssetWriterInput are nil. Thus you will get whatever default rate for the device.

While there could definitely be a bug in the OS-X AVFoundaton implementation, the bitrate you are receiving could be right. For instance how much motion is there in the video? How complex is the scene? Also keep in mind that H264/AVC is not a constant bitrate codec.

Steve McFarlin
  • 3,576
  • 1
  • 25
  • 24
  • "except on iPhone 3G" leads me to believe that this is from the documentation of the iPhone version of AVFoundation. – George Oct 02 '11 at 01:59
  • You are correct. Even so it does not, at least to me, make a lot of sense to attach H264 encoding parameters to the video output. At least on iOS the only class that does H264 encoding directly is AVAssetWriter. – Steve McFarlin Oct 02 '11 at 16:01