看了别人的解码方法,感觉ffmepg 解码时有点繁杂,想对解码进行改进。
花了点时间,进行改进。
主要有三个地方。
1,初始化scale:
if (codec == CODEC_ID_MJPEG)
{
m_Convert = sws_getContext(m_width, m_height, PIX_FMT_YUVJ420P,
m_width, m_height,m_format ,
SWS_BICUBIC, NULL, NULL, NULL);
}
else
m_Convert = sws_getContext(m_width, m_height,m_pCodecCtx->pix_fmt,
m_width, m_height,m_format ,
SWS_BICUBIC, NULL, NULL, NULL);
if(NULL == m_Convert)
return 0;
2.解码:
int Decoder::DecodeVideoData(int width,int height,char *data,int size,char *out_buffer,int &bufsize)
{
m_pCodecCtx->width = width;
m_pCodecCtx->height = height;
int nFrameFinished = 0;
int nRet = 0;
try
{
avpicture_fill((AVPicture *)pFrameYUV, (uint8_t *)out_buffer, m_format, width, height);
nRet = avcodec_decode_video(m_pCodecCtx, m_pFrame, &nFrameFinished, (uint8_t *)data, size);
if (nRet> 0 && nFrameFinished)
{
sws_scale(m_Convert, m_pFrame->data, m_pFrame->linesize,0, height, pFrameYUV->data, pFrameYUV->linesize);
bufsize = nRet;
}
else
bufsize = 0;
}
catch(...)
{
DBG_MSG("Decoder frame failed\n");
}
return nRet;
}
3,图像倒立:
经过上面的解码,在DX 下面能正常显示,但是dsow 却是倒立的,看了网上的一些介绍,有介绍说自己用代码倒过来,不过我感觉效果不是很好。
也有人说设置 scale 的值,src[0] 和srcStride[0],我比较笨,试了几下没试出来。后面网上有人说转BMP 时设置高为负数。我觉得这种应该可以倒过来,而且效率应该可以,只是猜测。我试着在DSHOW 下修改输出pin 的高为负数,没想到结果居然图像倒过来,正常了,哈哈。
HRESULT
CVideoNetworkDec::GetMediaType(int iPosition, CMediaType *mtOut)
{
BITMAPINFOHEADER * bmih;
BOOL bIsRGB = TRUE;
if (m_pInput->IsConnected() == FALSE)
{
return E_UNEXPECTED;
}
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
if (vih == NULL) return E_OUTOFMEMORY;
ZeroMemory(vih, sizeof (VIDEOINFOHEADER));
bmih = &(vih->bmiHeader);
mtOut->SetFormatType(&FORMAT_VideoInfo);
if (iPosition < 0) return E_INVALIDARG;
if (iPosition > 0) return VFW_S_NO_MORE_ITEMS;
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biBitCount = 16;
bmih->biWidth = m_nVideoFrameWidth;
bmih->biHeight = -m_nVideoFrameHeight;
bmih->biPlanes = 1;
//
if (!bIsRGB)
{
bmih->biCompression = MEDIASUBTYPE_YV12.Data1;
bmih->biBitCount = 12;
mtOut->SetSubtype(&MEDIASUBTYPE_YV12);
}
else
{
bmih->biCompression = BI_RGB;//MEDIASUBTYPE_RGB32.Data1;
bmih->biBitCount = 32;
mtOut->SetSubtype( &MEDIASUBTYPE_RGB32/*MEDIASUBTYPE_RGB24*/);
}
bmih->biSizeImage = GetBitmapSize(bmih);
mtOut->SetType(&MEDIATYPE_Video);
mtOut->SetTemporalCompression(FALSE);
mtOut->SetSampleSize(bmih->biSizeImage);
return S_OK;
}