zoukankan      html  css  js  c++  java
  • 利用ffmpeg将H264解码为RGB

    因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作。在网上找了一圈,H264解码比較方便的也就是ffmpeg一系列的函数库了,原本设备中也是用这套函数库解码,但厂家不给提供,没办法,仅仅得自己搞了。

    利用H264解码分为几个步骤:

    注意一点在加入头文件的时候要加入extern "C",不然会出现错误

    extern "C"
    {
    #include <avcodec.h>
    #include <avformat.h>
    #include <avutil.h>
    #include <swscale.h>
    };


     

    这里申明了几个全局变量

    AVCodec         *pCodec = NULL;
    AVCodecContext  *pCodecCtx = NULL;
    SwsContext      *img_convert_ctx = NULL;
    AVFrame         *pFrame = NULL;
    AVFrame         *pFrameRGB = NULL;


     

    1. 初始化

    int H264_Init(void)
    {
    	/* must be called before using avcodec lib*/
    	avcodec_init();
    	/* register all the codecs */
    	avcodec_register_all();
    
    	/* find the h264 video decoder */
    	pCodec = avcodec_find_decoder(CODEC_ID_H264);
    	if (!pCodec) {
    		fprintf(stderr, "codec not found
    ");
    	}
    	pCodecCtx = avcodec_alloc_context();
    
    	/* open the coderc */
    	if (avcodec_open(pCodecCtx, pCodec) < 0) {
    		fprintf(stderr, "could not open codec
    ");
    	}
    	// Allocate video frame
    	pFrame = avcodec_alloc_frame();
    	if(pFrame == NULL)
    		return -1;
    	// Allocate an AVFrame structure
    	pFrameRGB=avcodec_alloc_frame();
    	if(pFrameRGB == NULL)
    		return -1;
    
    
    	
    	return 0;
    
    }

    在最早使用的时候没有使用全局变量,初始化中也就仅仅有init和regisger这两个函数,而这样做的下场是,非关键帧所有无法解码,仅仅有关键帧才有办法解码。

    2. 解码

    解码的时候avcodec_decode_video函数是进行解码操作,在外部定义outputbuf的大小时,pixes*3,outsize是返回的outputbuf的size,值也是pixes*3。

    在解码的时候这几句话的意义是将YUV420P的数据倒置。在原先使用中,发现解出来的图像竟然是中心旋转图,后面在网上找了些办法,认为这个比較有用。解码实时是非常重要的,图像转化完之后也能够讲RGB图再次转化,那样也能成为一个正的图,可是那样效率就明显低了。

    	pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);
    	pFrame->linesize[0] *= -1;
    	pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;
    	pFrame->linesize[1] *= -1;
    	pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;
    	pFrame->linesize[2] *= -1;
    


     

    int H264_2_RGB(unsigned char *inputbuf, int frame_size, unsigned char *outputbuf, unsigned int*outsize)
    {
    	
    	int             decode_size;
    	int             numBytes;
    	int             av_result;
    	uint8_t         *buffer = NULL;
    
    	printf("Video decoding
    ");
    
    	av_result = avcodec_decode_video(pCodecCtx, pFrame, &decode_size, inputbuf, frame_size);
    	if (av_result < 0)
    	{
    		fprintf(stderr, "decode failed: inputbuf = 0x%x , input_framesize = %d
    ", inputbuf, frame_size);
    		return -1;
    	}
    
    	// Determine required buffer size and allocate buffer
    	numBytes=avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width,
    		pCodecCtx->height);
    	buffer = (uint8_t*)malloc(numBytes * sizeof(uint8_t));
    	// Assign appropriate parts of buffer to image planes in pFrameRGB
    	avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24,
    		pCodecCtx->width, pCodecCtx->height);
    
    	img_convert_ctx = sws_getCachedContext(img_convert_ctx,pCodecCtx->width,pCodecCtx->height,
    		//PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,
    		pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,PIX_FMT_RGB24 ,
    		SWS_X ,NULL,NULL,NULL) ;
    	if (img_convert_ctx == NULL) 
    	{
    
    		printf("can't init convert context!
    ") ;
    		return -1;
    	}
    	pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);
    	pFrame->linesize[0] *= -1;
    	pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;
    	pFrame->linesize[1] *= -1;
    	pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;
    	pFrame->linesize[2] *= -1;
    	sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,
    		0, 0 - pCodecCtx->width, pFrameRGB->data, pFrameRGB->linesize);
    	
    	if (decode_size)
    	{
    		*outsize = pCodecCtx->width * pCodecCtx->height * 3;
    		memcpy(outputbuf, pFrameRGB->data[0], *outsize);
    	}	
    
    
    	free(buffer);
    	return 0;
    }


    3. 释放资源

    资源的回收。

    void H264_Release(void)
    {
    	avcodec_close(pCodecCtx);
    	av_free(pCodecCtx);
    	av_free(pFrame);
    	av_free(pFrameRGB);
    }
    


     

  • 相关阅读:
    Mac014--Sourcetree安装(Git client)
    SSM003/构建Maven单模块项目(二)
    Git016--Work
    Mac013--Docker安装
    前端002/常用标签属性(工作应用)
    Python 38 初识数据库
    Python 38 sql基础
    Python 39 数据库的数据类型
    Python 39 数据库
    Python 37 进程池与线程池 、 协程
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3992596.html
Copyright © 2011-2022 走看看