由于使用 FFMPEG 解码 所以解码速度应该没有问题
代码 如下 分块了
//-----------------------------------------
// 解码并输出
// 1. 更新解码参数
// 2. FFMPEG 解码 输入流 到 YUV420P 图像帧
// 3. 转换 YUV420P 图像帧 置 指定格式
// 4. 复制 帧时间戳
//-----------------------------------------
HRESULT CVideoFilter::Transform(IMediaSample *pIn, IMediaSample *pOut)
{// 检查 Sample 输入 和 输出
CheckPointer(pIn,E_POINTER);
CheckPointer(pOut,E_POINTER);
// 更新解码数据
update_dec_parameter(pOut);
// 输入数据解码
AVFrame * frame = NULL;
if (Decoder(pIn,frame) == 1) // 解码成功
{
Convert(frame,pOut); // 转换图像格式
av_free(frame);
}
CopyTimeStamp(pIn,pOut);
return S_OK;
}
//-----------------------------------------
// 解码 ( 只 解码 输入 Pin 数据)
// 1. DirectShow 输出 Pin 数据 转换 FFMPEG Packet 数据
// 2. FFMPEG 解码 输入数据
// return -1 失败
// return 1 成功
//-----------------------------------------
int CVideoFilter::Decoder(IMediaSample *pSource, AVFrame *& frame)
{
// 声明解码数据
AVPacket pkt = {0};
// 初始化 解码包
av_init_packet(&pkt);
pkt.size = pSource->GetActualDataLength();
pSource->GetPointer(&(pkt.data));
// 解码原始帧初始化
frame = avcodec_alloc_frame();
// 声明解码返参变量
int bytesDecoded = -1;
int frameFinished = -1;
// 解码
bytesDecoded = avcodec_decode_video2(avcore_codec->pCodecCtx, frame, &frameFinished, &pkt);
if (bytesDecoded > 0) // 解码成功
{
if (frameFinished > 0) // 解码数据 正常
return 1;
}
return -1;
}
//-----------------------------------------
// 转换图像
// 1. 获取 DirectShow 输出图像格式
// 2. 根据 DirectShow 输出图像格式 分情况处理
//-----------------------------------------
int bmp;
HRESULT CVideoFilter::Convert(AVFrame * frame,IMediaSample * pDest)
{
// RGB32
if (m_dshow_pixfmt == VOFMT_RGB32)
{
// 直接分配 Frame 缓存指针 为 Dest 指针
AVFrame * pDest_Frame = NULL;
BYTE * pDestBuffer = NULL;
pDest_Frame = avcodec_alloc_frame();
pDest->GetPointer(&pDestBuffer);
int size = avpicture_get_size(m_pixfmt,m_width,avcore_codec->pCodecCtx->height);
uint8_t * buffer = (uint8_t *)av_malloc(size);
avpicture_fill((AVPicture *)pDest_Frame, (uint8_t*)pDestBuffer, m_pixfmt, m_width, avcore_codec->pCodecCtx->height);
// 转换图像 至 RGB32
int height;
height = sws_scale(m_swsctx,frame->data,frame->linesize,0,frame->height,pDest_Frame->data,pDest_Frame->linesize);
pDest->SetActualDataLength(m_width*height*4);
// avcore_savebyte(pDestBuffer,m_width,frame->height,bmp++,32);
// memcpy(pDestBuffer,pDest_Frame->data[0],m_width * height * 4);
av_free(pDest_Frame);
av_free(buffer);
return S_OK;
}
return S_FALSE;
}
代码 如下 分块了
//-----------------------------------------
// 解码并输出
// 1. 更新解码参数
// 2. FFMPEG 解码 输入流 到 YUV420P 图像帧
// 3. 转换 YUV420P 图像帧 置 指定格式
// 4. 复制 帧时间戳
//-----------------------------------------
HRESULT CVideoFilter::Transform(IMediaSample *pIn, IMediaSample *pOut)
{// 检查 Sample 输入 和 输出
CheckPointer(pIn,E_POINTER);
CheckPointer(pOut,E_POINTER);
// 更新解码数据
update_dec_parameter(pOut);
// 输入数据解码
AVFrame * frame = NULL;
if (Decoder(pIn,frame) == 1) // 解码成功
{
Convert(frame,pOut); // 转换图像格式
av_free(frame);
}
CopyTimeStamp(pIn,pOut);
return S_OK;
}
//-----------------------------------------
// 解码 ( 只 解码 输入 Pin 数据)
// 1. DirectShow 输出 Pin 数据 转换 FFMPEG Packet 数据
// 2. FFMPEG 解码 输入数据
// return -1 失败
// return 1 成功
//-----------------------------------------
int CVideoFilter::Decoder(IMediaSample *pSource, AVFrame *& frame)
{
// 声明解码数据
AVPacket pkt = {0};
// 初始化 解码包
av_init_packet(&pkt);
pkt.size = pSource->GetActualDataLength();
pSource->GetPointer(&(pkt.data));
// 解码原始帧初始化
frame = avcodec_alloc_frame();
// 声明解码返参变量
int bytesDecoded = -1;
int frameFinished = -1;
// 解码
bytesDecoded = avcodec_decode_video2(avcore_codec->pCodecCtx, frame, &frameFinished, &pkt);
if (bytesDecoded > 0) // 解码成功
{
if (frameFinished > 0) // 解码数据 正常
return 1;
}
return -1;
}
//-----------------------------------------
// 转换图像
// 1. 获取 DirectShow 输出图像格式
// 2. 根据 DirectShow 输出图像格式 分情况处理
//-----------------------------------------
int bmp;
HRESULT CVideoFilter::Convert(AVFrame * frame,IMediaSample * pDest)
{
// RGB32
if (m_dshow_pixfmt == VOFMT_RGB32)
{
// 直接分配 Frame 缓存指针 为 Dest 指针
AVFrame * pDest_Frame = NULL;
BYTE * pDestBuffer = NULL;
pDest_Frame = avcodec_alloc_frame();
pDest->GetPointer(&pDestBuffer);
int size = avpicture_get_size(m_pixfmt,m_width,avcore_codec->pCodecCtx->height);
uint8_t * buffer = (uint8_t *)av_malloc(size);
avpicture_fill((AVPicture *)pDest_Frame, (uint8_t*)pDestBuffer, m_pixfmt, m_width, avcore_codec->pCodecCtx->height);
// 转换图像 至 RGB32
int height;
height = sws_scale(m_swsctx,frame->data,frame->linesize,0,frame->height,pDest_Frame->data,pDest_Frame->linesize);
pDest->SetActualDataLength(m_width*height*4);
// avcore_savebyte(pDestBuffer,m_width,frame->height,bmp++,32);
// memcpy(pDestBuffer,pDest_Frame->data[0],m_width * height * 4);
av_free(pDest_Frame);
av_free(buffer);
return S_OK;
}
return S_FALSE;
}










