// 关闭 void CVideoEncodeVt::Close() { if(NULL != m_EncodeSession) { VTCompressionSessionCompleteFrames(m_EncodeSession, kCMTimeIndefinite); CFRelease(m_EncodeSession); m_EncodeSession = NULL; } ClearEncodeBuffQueue(); if(NULL != m_pExtraData) { av_free(m_pExtraData); m_pExtraData = NULL; m_iExtraDataSize = 0; } m_bOpen = false; }
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 }
int CVideoEncodeVt::GetExtraData(const STRUCT_PUSH_STREAM_PARAM& aPushStreamParam, CMVideoCodecType aeCodecType, CFStringRef aProfileLevel, CFDictionaryRef aPixelBufferInfo) { int ret = 0; AVFrame* pFrame = NULL; VTCompressionSessionRef session = NULL; CMSampleBufferRef sampleBuf = NULL; do { //创建编码器 ret = CreateEncoder(aPushStreamParam, aeCodecType, aProfileLevel, aPixelBufferInfo, &session); if(ret < 0) { CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "CreateEncoder failed!"); assert(false); break; } //创建一个avframe,并分配缓存,设置参数 pFrame = av_frame_alloc(); if(NULL == pFrame) { CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "av_frame_alloc failed!"); assert(false); break; } int iWidth = aPushStreamParam.iVideoPushStreamWidth; int iHeight = aPushStreamParam.iVideoPushStreamHeight; int iYSize = iWidth * iHeight; int iUVSize = (iWidth / 2) * (iHeight / 2); pFrame->buf[0] = av_buffer_alloc(iYSize + iUVSize * 2); if(NULL == pFrame->buf[0]) { CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "av_buffer_alloc failed!"); assert(false); break; } pFrame->data[0] = pFrame->buf[0]->data; pFrame->data[1] = pFrame->buf[0]->data + iYSize; pFrame->data[2] = pFrame->buf[0]->data + iYSize + iUVSize; memset(pFrame->data[0], 0, iYSize); memset(pFrame->data[1], 128, iUVSize); memset(pFrame->data[2], 128, iUVSize); pFrame->linesize[0] = iWidth; pFrame->linesize[1] = (iWidth + 1) / 2; pFrame->linesize[2] = (iWidth + 1) / 2; pFrame->format = AV_PIX_FMT_YUV420P; pFrame->width = iWidth; pFrame->height = iHeight; pFrame->pts = 0; //编码 ret = EncodeFrame(pFrame, session); if(ret < 0) { CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "EncodeFrame failed!"); assert(false); break; } //等待编码结束 ret = VTCompressionSessionCompleteFrames(session, kCMTimeIndefinite); if(0 != ret) { CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "VTCompressionSessionCompleteFrames failed!"); break; } //取得编码后的数据 ret = PopBuff(&sampleBuf); if(ret < 0) { CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, "PopBuff failed!"); assert(false); break; } }while(0); if(NULL != sampleBuf) { CFRelease(sampleBuf); sampleBuf = NULL; } if(NULL != pFrame) { av_frame_unref(pFrame); av_frame_free(&pFrame); } if(NULL != session) { CFRelease(session); session = NULL; } assert(0 == ret && m_pExtraData && m_iExtraDataSize > 0); return ret; }