转载:https://blog.youkuaiyun.com/zhoubotong2012/article/details/103304698
很多使用FFmpeg做解码的用户都可能遇到过一个问题,他们对解码出来的图像转为RGB格式之后显示图像是颠倒的。
有些用户对其原因不大明白,其实原因跟RGB图像的存储方式有关。
RGB图像即RGB位图有两种存储方式:一种是从上往下扫描,另一种是从下往上扫描。
从上扫描的图像第一行的首地址即为图像Buffer的起始地址,而从下往上扫描的图像第一行的首地址为:buffer_data + linesize*(height-1),
其中buffer_data为图像Buffer的起始地址,linesize为图像的行字节宽度,
对于RGB24图像,linesize = (width * 3 + 3)/4×4,
对于YUV420图像,linesize = (width + 3)/4 *4。
对于颠倒显示的RGB图像我们可以用FFmpeg的函数把它翻转过来显示,处理方法很简单,下面是实现步骤和代码:
第一步:先定义几个用于FFmpeg解码和转换图像的变量。
AVCodec *codec;
AVCodecContext *codecCtx;
AVFrame *m_picture;
AVFrame *m_pFrameRGB;
SwsContext *m_pImgCtx;
uint8_t *m_PicBuf;
int m_PicBytes;
第二步:初始化变量。
m_pImgCtx = NULL;
m_PicBuf = NULL;
m_PicBytes = 0;
第三步:解码图像,并转换图像为RGB格式
int ret, got_picture;
ret = avcodec_decode_video2(codecCtx, m_picture, &got_picture, &packet);
if (ret > 0 )
{
if(got_picture)
{
if(m_PicBuf == NULL)
{
m_PicBytes = avpicture_get_size(PIX_FMT_BGR24, codecCtx->width, codecCtx->height);
m_PicBuf = new uint8_t[m_PicBytes];
avpicture_fill((AVPicture *)m_pFrameRGB, m_PicBuf, PIX_FMT_BGR24, codecCtx->width, codecCtx->height);
}
if(m_pImgCtx == NULL)
{
m_pImgCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt, codecCtx->width, codecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
}
m_picture->data[0] += m_picture->linesize[0]*(codecCtx->height-1);
m_picture->linesize[0] *= -1;
m_picture->data[1] += m_picture->linesize[1]*(codecCtx->height/2-1);
m_picture->linesize[1] *= -1;
m_picture->data[2] += m_picture->linesize[2]*(codecCtx->height/2-1);
m_picture->linesize[2] *= -1;
sws_scale(m_pImgCtx, (const uint8_t* const*)m_picture->data, m_picture->linesize, 0, codecCtx->height, m_pFrameRGB->data, m_pFrameRGB->linesize);
display_pic(m_pFrameRGB->data[0], codecCtx->width, codecCtx->height); //显示视频
}
}
上面的sws_scale函数除了将YUV420的图像转为BGR24,并且同时将颠倒的BGR24图像翻转过来。
最后,记得释放临时的图像内存:
sws_freeContext(m_pImgCtx);//转换函数也要释放
delete[] m_PicBuf; //释放内存