示例#1
0
    void
    H264Encode::setBitrate(int bitrate)
    {
#if VERSION_OK
        if(bitrate == m_bitrate) {
            return;
        }
        m_bitrate = bitrate;
        if(m_compressionSession) {
            m_encodeMutex.lock();
            int v = m_bitrate * 0.9; // headroom
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            
            VTCompressionSessionCompleteFrames((VTCompressionSessionRef)m_compressionSession, kCMTimeInvalid);
            
            VTSessionSetProperty((VTCompressionSessionRef)m_compressionSession, kVTCompressionPropertyKey_AverageBitRate, ref);
            CFRelease(ref);
            
            
            v = bitrate / 8;
            CFNumberRef bytes = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &v);
            v = 1;
            CFNumberRef duration = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &v);
            
            CFMutableArrayRef limit = CFArrayCreateMutable(kCFAllocatorDefault, 2, &kCFTypeArrayCallBacks);
            CFArrayAppendValue(limit, bytes);
            CFArrayAppendValue(limit, duration);
            
            VTSessionSetProperty((VTCompressionSessionRef)m_compressionSession, kVTCompressionPropertyKey_DataRateLimits, limit);
            
            CFRelease(bytes);
            CFRelease(duration);
            CFRelease(limit);
            
            //m_forceKeyframe = true;
            m_encodeMutex.unlock();
            
        }
#endif
    }
示例#2
0
static void h264_enc_configure(VTH264EncCtx *ctx) {
	OSStatus err;
	const char *error_msg = "Could not initialize the VideoToolbox compresson session";
	int max_payload_size = ms_factory_get_payload_max_size(ctx->f->factory);
	CFNumberRef value;
	CFMutableDictionaryRef pixbuf_attr = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
	int pixel_type = kCVPixelFormatType_420YpCbCr8Planar;

	value = CFNumberCreate(NULL, kCFNumberIntType, &pixel_type);
	CFDictionarySetValue(pixbuf_attr, kCVPixelBufferPixelFormatTypeKey, value);

	err =VTCompressionSessionCreate(NULL, ctx->conf.vsize.width, ctx->conf.vsize.height, kCMVideoCodecType_H264,
									NULL, pixbuf_attr, NULL, (VTCompressionOutputCallback)h264_enc_output_cb, ctx, &ctx->session);
	CFRelease(pixbuf_attr);
	if(err) {
		ms_error("%s: error code %d", error_msg, err);
		goto fail;
	}

	VTSessionSetProperty(ctx->session, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel);
	VTSessionSetProperty(ctx->session, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse);
	value = CFNumberCreate(NULL, kCFNumberIntType, &ctx->conf.required_bitrate);
	VTSessionSetProperty(ctx->session, kVTCompressionPropertyKey_AverageBitRate, value);
	value = CFNumberCreate(NULL, kCFNumberFloatType, &ctx->conf.fps);
	VTSessionSetProperty(ctx->session, kVTCompressionPropertyKey_ExpectedFrameRate, value);

	if((err = VTCompressionSessionPrepareToEncodeFrames(ctx->session)) != 0) {
		ms_error("Could not prepare the VideoToolbox compression session: error code %d", err);
		goto fail;
	}

	rfc3984_init(&ctx->packer_ctx);
	rfc3984_set_mode(&ctx->packer_ctx, 1);
	ctx->packer_ctx.maxsz = max_payload_size;
	ctx->is_configured = TRUE;
	return;

fail:
	if(ctx->session) CFRelease(ctx->session);
}
示例#3
0
int CVideoEncodeVt::CreateEncoder(const STRUCT_PUSH_STREAM_PARAM& aPushStreamParam,
                                  CMVideoCodecType aeCodecType,
                                  CFStringRef aProfileLevel,
                                  CFDictionaryRef aPixelBufferInfo,
                                  VTCompressionSessionRef* apSession)
{
    VTCompressionSessionRef session;
    int ret = 0;
    
    
    do
    {
        //创建编码会话
        ret = VTCompressionSessionCreate(kCFAllocatorDefault,
                                         aPushStreamParam.iVideoPushStreamWidth,
                                         aPushStreamParam.iVideoPushStreamHeight,
                                         aeCodecType,
                                         NULL,
                                         aPixelBufferInfo,
                                         kCFAllocatorDefault,
                                         EncodeOutputCallback,
                                         (void*)this,
                                         &session);
        if (0 != ret)
        {
            
            CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "VTCompressionSessionCreate failed!");
            
            assert(false);
            break;
        }
        
        //realtime
        ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
        if (0 != ret)
        {
            CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "kVTCompressionPropertyKey_RealTime failed!");
            break;
        }
        
        //profile level
        ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_ProfileLevel, aProfileLevel);
        if (0 != ret)
        {
            CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "kVTCompressionPropertyKey_ProfileLevel failed!");
            break;
        }
        
        //bit rate
        int iBitRate = aPushStreamParam.iVideoMaxBitRate;
        CFNumberRef bitRate = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &iBitRate);
        ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_AverageBitRate, bitRate);
        CFRelease(bitRate);
        if (0 != ret)
        {
            CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "kVTCompressionPropertyKey_AverageBitRate failed!");
            break;
        }
        
        CFNumberRef keyFrameInterval = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aPushStreamParam.iVideoFrameRate);
        ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_MaxKeyFrameInterval, keyFrameInterval);
        CFRelease(keyFrameInterval);
        if (0 != ret)
        {
            CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "kVTCompressionPropertyKey_MaxKeyFrameInterval failed!");
            break;
        }
        
        //fame rate
        CFNumberRef frameRate = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aPushStreamParam.iVideoFrameRate);
        ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_ExpectedFrameRate, frameRate);
        CFRelease(frameRate);
        if (0 != ret)
        {
            CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "kVTCompressionPropertyKey_ExpectedFrameRate failed!");
            break;
        }
        
        //是否使用b帧
        if (!m_bHasBFrames)
        {
            ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse);
            if (0 != ret)
            {
                CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "kVTCompressionPropertyKey_AllowFrameReordering failed!");
                break;
            }
        }
        
        //entropy
        if (m_iEntropy != H264_ENTROPY_NOT_SET)
        {
            CFStringRef entropy = m_iEntropy == H264_CABAC ? kVTH264EntropyMode_CABAC : kVTH264EntropyMode_CAVLC;
            
            ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_H264EntropyMode, entropy);
            if (0 != ret)
            {
                CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "kVTCompressionPropertyKey_H264EntropyMode failed!");
                break;
            }
        }
        
        //准备编码
        ret = VTCompressionSessionPrepareToEncodeFrames(session);
        if (0 != ret)
        {
            CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "prepare to encode frames failed!");
            assert(false);
            break;
        }
        
        *apSession = session;

        return 0;
    }while(0);
    
    
    if(session)
    {
        CFRelease(session);
        session = NULL;
    }
    
    return -1;
}
示例#4
0
    void
    H264Encode::setupCompressionSession()
    {
        
#if VERSION_OK
        // Parts of this code pulled from https://github.com/galad87/HandBrake-QuickSync-Mac/blob/2c1332958f7095c640cbcbcb45ffc955739d5945/libhb/platform/macosx/encvt_h264.c
        // More info from WWDC 2014 Session 513
        
        OSStatus err = noErr;
        CFMutableDictionaryRef encoderSpecifications = nullptr;
        
#if !TARGET_OS_IPHONE
        /** iOS is always hardware-accelerated **/
        CFStringRef key = kVTVideoEncoderSpecification_EncoderID;
        CFStringRef value = CFSTR("com.apple.videotoolbox.videoencoder.h264.gva");
        
        CFStringRef bkey = CFSTR("EnableHardwareAcceleratedVideoEncoder");
        CFBooleanRef bvalue = kCFBooleanTrue;
        
        CFStringRef ckey = CFSTR("RequireHardwareAcceleratedVideoEncoder");
        CFBooleanRef cvalue = kCFBooleanTrue;
        
        encoderSpecifications = CFDictionaryCreateMutable(
                                                                                 kCFAllocatorDefault,
                                                                                 3,
                                                                                 &kCFTypeDictionaryKeyCallBacks,
                                                                                 &kCFTypeDictionaryValueCallBacks);
        
        CFDictionaryAddValue(encoderSpecifications, bkey, bvalue);
        CFDictionaryAddValue(encoderSpecifications, ckey, cvalue);
        CFDictionaryAddValue(encoderSpecifications, key, value);
        
#endif
        VTCompressionSessionRef session = nullptr;
        
        err = VTCompressionSessionCreate(
                                         kCFAllocatorDefault,
                                         m_frameW,
                                         m_frameH,
                                         kCMVideoCodecType_H264,
                                         encoderSpecifications,
                                         NULL,
                                         NULL,
                                         &vtCallback,
                                         this,
                                         &session);
        
        
        if(err == noErr) {
            m_compressionSession = session;
            const int32_t v = m_fps*2; // 2-second kfi
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_MaxKeyFrameInterval, ref);
            CFRelease(ref);
        }
        
        if(err == noErr) {
            const int v = m_fps;
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_ExpectedFrameRate, ref);
            CFRelease(ref);
        }
  
        if(err == noErr) {
            err = VTSessionSetProperty(session , kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse);
        }

        if(err == noErr) {
            const int v = m_bitrate;
            CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v);
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_AverageBitRate, ref);
            CFRelease(ref);
        }

        if(err == noErr) {
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
        }
        
        if(err == noErr) {
            err = VTSessionSetProperty(session, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel);
        }
        if(err == noErr) {
            VTCompressionSessionPrepareToEncodeFrames(session);
        }
#endif
        
    }