利用ffmpeg将H264流 解码为RGB


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

 

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

[cpp] view plaincopy

  1. extern "C"  
  2. {  
  3. #include <avcodec.h>  
  4. #include <avformat.h>  
  5. #include <avutil.h>  
  6. #include <swscale.h>  
  7. };  

 

 

这里申明了几个全局变量

[cpp] view plaincopy

  1. AVCodec         *pCodec = NULL;  
  2. AVCodecContext  *pCodecCtx = NULL;  
  3. SwsContext      *img_convert_ctx = NULL;  
  4. AVFrame         *pFrame = NULL;  
  5. AVFrame         *pFrameRGB = NULL;  

 

1. 初始化

[cpp] view plaincopy

  1. int H264_Init(void)  
  2. {  
  3.     /* must be called before using avcodec lib*/  
  4.     avcodec_init();  
  5.     /* register all the codecs */  
  6.     avcodec_register_all();  
  7.   
  8.     /* find the h264 video decoder */  
  9.     pCodec = avcodec_find_decoder(CODEC_ID_H264);  
  10.     if (!pCodec) {  
  11.         fprintf(stderr, "codec not found\n");  
  12.     }  
  13.     pCodecCtx = avcodec_alloc_context();  
  14.   
  15.     /* open the coderc */  
  16.     if (avcodec_open(pCodecCtx, pCodec) < 0) {  
  17.         fprintf(stderr, "could not open codec\n");  
  18.     }  
  19.     // Allocate video frame  
  20.     pFrame = avcodec_alloc_frame();  
  21.     if(pFrame == NULL)  
  22.         return -1;  
  23.     // Allocate an AVFrame structure  
  24.     pFrameRGB=avcodec_alloc_frame();  
  25.     if(pFrameRGB == NULL)  
  26.         return -1;  
  27.   
  28.   
  29.       
  30.     return 0;  
  31.   
  32. }  

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

2. 解码

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

 

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

[cpp] view plaincopy

  1. pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);  
  2. pFrame->linesize[0] *= -1;  
  3. pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;  
  4. pFrame->linesize[1] *= -1;  
  5. pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;  
  6. pFrame->linesize[2] *= -1;  

 

 

[cpp] view plaincopy

  1. int H264_2_RGB(unsigned char *inputbuf, int frame_size, unsigned char *outputbuf, unsigned int*outsize)  
  2. {  
  3.       
  4.     int             decode_size;  
  5.     int             numBytes;  
  6.     int             av_result;  
  7.     uint8_t         *buffer = NULL;  
  8.   
  9.     printf("Video decoding\n");  
  10.   
  11.     av_result = avcodec_decode_video(pCodecCtx, pFrame, &decode_size, inputbuf, frame_size);  
  12.     if (av_result < 0)  
  13.     {  
  14.         fprintf(stderr, "decode failed: inputbuf = 0x%x , input_framesize = %d\n", inputbuf, frame_size);  
  15.         return -1;  
  16.     }  
  17.   
  18.     // Determine required buffer size and allocate buffer  
  19.     numBytes=avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width,  
  20.         pCodecCtx->height);  
  21.     buffer = (uint8_t*)malloc(numBytes * sizeof(uint8_t));  
  22.     // Assign appropriate parts of buffer to image planes in pFrameRGB  
  23.     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24,  
  24.         pCodecCtx->width, pCodecCtx->height);  
  25.   
  26.     img_convert_ctx = sws_getCachedContext(img_convert_ctx,pCodecCtx->width,pCodecCtx->height,  
  27.         //PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,  
  28.         pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,PIX_FMT_RGB24 ,  
  29.         SWS_X ,NULL,NULL,NULL) ;  
  30.     if (img_convert_ctx == NULL)   
  31.     {  
  32.   
  33.         printf("can't init convert context!\n") ;  
  34.         return -1;  
  35.     }  
  36.     pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);  
  37.     pFrame->linesize[0] *= -1;  
  38.     pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;  
  39.     pFrame->linesize[1] *= -1;  
  40.     pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;  
  41.     pFrame->linesize[2] *= -1;  
  42.     sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,  
  43.         0, 0 - pCodecCtx->width, pFrameRGB->data, pFrameRGB->linesize);  
  44.       
  45.     if (decode_size)  
  46.     {  
  47.         *outsize = pCodecCtx->width * pCodecCtx->height * 3;  
  48.         memcpy(outputbuf, pFrameRGB->data[0], *outsize);  
  49.     }     
  50.   
  51.   
  52.     free(buffer);  
  53.     return 0;  
  54. }  

//解码yuv 修改 PIX_FMT_YUV420P
memcpy(outputbuf, pFrameRGB->data[2], 720*576/4);
			memcpy(outputbuf, pFrameRGB->data[1], 720*576/4);
			memcpy(outputbuf, pFrameRGB->data[0], 720*576);

3. 释放资源
资源的回收。

[cpp] view plaincopy

  1. void H264_Release(void)  
  2. {  
  3.     avcodec_close(pCodecCtx);  
  4.     av_free(pCodecCtx);  
  5.     av_free(pFrame);  
  6.     av_free(pFrameRGB);  
  7. }  
时间: 2024-09-15 02:54:31

利用ffmpeg将H264流 解码为RGB的相关文章

264解码-h264流解码图像显示,请大神帮忙指点迷津

问题描述 h264流解码图像显示,请大神帮忙指点迷津 我们这个程序是从IP摄像头获取H264 Streaming 然后播放出来!因为必须走Http/tcp/rtsp 所以不能用安卓的MediaPlayer 直接给定URL 来播放!因为这样走的是Http/udp/rtsp.所以看到安卓4.1的版本有一个MediaCodec可以来解析H264可是我看到那个只能解析文件,而且不知道怎么把解析出来的数据变成图像.所以请高人帮忙····· MediaCodec是怎么使用的 解析出来的数据又怎么组成图像播放

FFMPEG实现H264的解码(从源代码角度)

农历2014年底了,将前段时间工作中研究的FFMPEG解码H264流程在此做一下整理,也算作年终技术总结了! H264解码原理: H264的原理参考另一篇博文 http://blog.csdn.net/rootusers/article/details/43563133 H264分为NAL(网络抽象层)和VCL(视频编码层)   解码器的总框架: 解码器的流程为:将NAL数据位流输入到H264的解码器中,熵解码模块解码后输出量化系数X:系数经过反量化和反变换得到残差数据R:解码器使用从码流中解码

用ffmpeg把H264数据流解码成YUV420P

在网上找了很久这方面的内容,发现网上的代码都太旧了,所使用的函数旧到连最新版本的ffmpeg都已经不包含了,所以对于我这个初学者来说太坑拉.不过经过多次查找ffmpeg的头文件和结合网上的内容,终于成功可以解码拉.现在贴出来. 首先是初始化一些参数   [cpp] view plaincopy     //下面初始化h264解码库   avcodec_init();   av_register_all();      AVFrame *pFrame_ = NULL;      AVCodecCo

编码-FFMPEG实时解码RTP传输的H264流视频花屏

问题描述 FFMPEG实时解码RTP传输的H264流视频花屏 自己用QT写的程序,在PC上采集视频编码RTP打包发送.如果发送给自己,然后用VLC播放的话是可以正常显示的(尽管延迟会不断增大,这个问题再待解决),但是用自己编的软件确无法正常显示,能看到一瞬间有部分画面正常,然后一会画面就糊掉了. 同样的代码, 我在树莓派上,用OPENMAX硬件加速编码,然后同样的打包方式发送,发送给树莓派自己或者给PC,都能正常地显示. 不知道这个是哪部分出了原因?到底是FFMPEG编码部分出问题,还是接收的代

byte-java有什么技术可以把H264编码的音视频码流解码成视频与音频分开??

问题描述 java有什么技术可以把H264编码的音视频码流解码成视频与音频分开?? 小弟最近在做个视频播放相关项目,我接收到一段H264的音视频码流数据, 存放在byte[]中,由于项目需要,我需要从byte[] 分别取出视频流和音频流.但是,由于本人... 还请牛人点拨!!! 越详细越好,我第一次接触h264,解码需要知道些什么参数之类的,各种点拨,谢谢了!! 解决方案 http://jolestar.iteye.com/blog/177522 看看这个

代码-如何利用ffmpeg库实现对实时rtsp流每一秒截一张图

问题描述 如何利用ffmpeg库实现对实时rtsp流每一秒截一张图 我想实现这个功能,利用ffmpeg库,对实时rtsp流每一秒截一张图.我自己写了段代码 while(av_read_frame(pAVFormatContext,&pAVPacket) >= 0){ if(pAVPacket.stream_index == videoStreamIndex){ avcodec_decode_video2(pAVCodecContext,pAVFrame,&m_i_frameFinis

android-Android 采集摄像头数据 , 通过ffmpeg推送流至服务器

问题描述 Android 采集摄像头数据 , 通过ffmpeg推送流至服务器 Android 采集摄像头数据 , 通过ffmpeg推送流, 通过AdobeMediaServer查看 , 为什么播放视频总是隔一段时间一缓冲 , 而且播放有延迟.求大神帮忙啊 AVFormatContext *ofmt_ctx; AVStream* video_st; //视音频流对应的结构体,用于视音频编解码. AVCodecContext* pCodecCtx; AVCodec* pCodec; AVPacket

利用Ffmpeg获得flv视频缩略图和视频时间的代码_php技巧

问题描述:获得flv视频的缩略图和视频时间长度 谷歌了半天发现可以使用Ffmpeg获得视频的一些信息,先介绍一下FFMEPG 这里简单说一下:FFmpeg是用于录制.转换和流化音频和视频的完整解决方案,一套领先的音/视频编解码类库.官方正式版ffmpeg不支持rmvb和rm格式. 不过有很多解决方法 FFmpeg的官方网址是 http://ffmpeg.mplayerhq.hu/ . 中文Wiki是 http://www.ffmpeg.com.cn/ ,资料很多. ㈠安装FFMEPG 操作系统:

android保存h264流文件为mp4

问题描述 android保存h264流文件为mp4 网络预览视频,收到的是H264编码的流,有个保存按钮,可以把收到的留实时保存为H264的流文件,用特定播放器可以播放,想收到流的同时,另外实时生成一个MP4文件,有什么好的方法 解决方案 调用ffmpeg实现http://blog.csdn.net/hclydao/article/details/36415975http://blog.csdn.net/hclydao/article/details/18546757http://blog.cs