FFmpeg对颠倒的RGB图像翻转显示

很多使用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图像翻转过来。

最后,记得释放临时的图像内存:

delete[] m_PicBuf; //释放内存

 

你可能感兴趣的:(ffmpeg)