Environment
- OSX Yosemite
- xcode 6.4
- C++
Use-case
Given a h264 GOP consisting of a single Key-Frame and multiple corresponding Delta Frames, decode the GOP, and then, encode a single 4.2Mbit Key-frame
Problem description
I am able to decode the GOP and encode the Key-Frame, however, the resulting Key-Frame is of a low quality ( low bit-rate ), that is, although I specifically set the bit-rate to 4.2Mbit ( this can be seen in the code snap bellow ), Having in mind I need only a single Key-Frame, Is there any way to setup the VideoToolBox Encoder to output a high bit-rate Key-frame ?
const CMVideoCodecType fourcc = (CMVideoCodecType)CMVideoFormatDescriptionGetCodecType(fmt);
// Else, generate a h264 KeyFrame
CFObjectSmartPtr< CFMutableDictionaryRef > dictEncSpec;
dictEncSpec.Attach(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
//dictEncSpec.Attach(CFDictionaryCreateMutable(NULL, 0, 0, 0));
// CFDictionarySetNumVal(dictEncSpec, kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, TRUE);
CFDictionarySetValue(dictEncSpec, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_High_3_2);
// CFDictionarySetValue(dictEncSpec, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
// CFDictionarySetValue(dictEncSpec, kVTCompressionPropertyKey_H264EntropyMode, kVTH264EntropyMode_CABAC);
CFDictionarySetNumVal(dictEncSpec, kVTCompressionPropertyKey_AverageBitRate, 4200000);
CFDictionarySetNumVal(dictEncSpec, kVTCompressionPropertyKey_Quality, 1.0f);
CFDictionarySetNumVal(dictEncSpec, kVTCompressionPropertyKey_MaxFrameDelayCount, 0);
CFDictionarySetNumVal(dictEncSpec, kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, 1);
CFDictionarySetNumVal(dictEncSpec, kVTCompressionPropertyKey_ExpectedDuration, 1);
CFDictionarySetNumVal(dictEncSpec, kVTCompressionPropertyKey_ExpectedFrameRate, 10);
// CFDictionarySetNumVal(dictEncSpec, kVTCompressionPropertyKey_SourceFrameCount, 1);
CFDictionarySetNumVal(dictEncSpec, kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder, TRUE);
CFObjectSmartPtr< VTCompressionSessionRef > sessionCompression;
status = VTCompressionSessionCreate(0, res.width, res.height, fourcc, (CFDictionaryRef)dictEncSpec, 0, 0, CompressionCallback, &ctx, &sessionCompression);
if (noErr != status)
return HRESULT_FROM_ERRNO(status);
if (noErr != (status = VTCompressionSessionEncodeFrame(sessionCompression, ctx.yuvFrame, timestamp, timestamp, 0, 0, 0)))
return HRESULT_FROM_ERRNO(status);
if(noErr != (status = VTCompressionSessionCompleteFrames(sessionCompression, timestamp)))
return HRESULT_FROM_ERRNO(status);
if (0 == ctx.keyFrame) {
assert(false);
return E_UNEXPECTED;
}
ctx.keyFrame Ends up to be of a very low quality