利用ffmpeg将H264流 解码为RGB
利用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\n");
- }
- pCodecCtx = avcodec_alloc_context();
- /* open the coderc */
- if (avcodec_open(pCodecCtx, pCodec) < 0) {
- fprintf(stderr, "could not open codec\n");
- }
- // 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\n");
- 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\n", 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!\n") ;
- 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;
- }
//解码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. 释放资源
资源的回收。
- void H264_Release(void)
- {
- avcodec_close(pCodecCtx);
- av_free(pCodecCtx);
- av_free(pFrame);
- av_free(pFrameRGB);
- }
利用ffmpeg将H264流 解码为RGB的更多相关文章
- FFMPEG实现H264的解码(从源代码角度)
农历2014年底了,将前段时间工作中研究的FFMPEG解码H264流程在此做一下整理,也算作年终技术总结了! H264解码原理: H264的原理参考另一篇博文 http://blog.csdn.net ...
- 利用ffmpeg将H264解码为RGB
因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作.在网上找了一圈,H264解码比較方便的也就是ffmpeg一系列的函数库了,原本设备中也是用这套函数库解码,但厂家不给提供,没办法,仅仅得 ...
- 用ffmpeg把H264数据流解码成YUV420P
在网上找了很久这方面的内容,发现网上的代码都太旧了,所使用的函数旧到连最新版本的ffmpeg都已经不包含了,所以对于我这个初学者来说太坑拉.不过经过多次查找ffmpeg的头文件和结合网上的内容,终于成 ...
- 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中
既然已经可以通过 RTSP 获取h264 裸流了.那么通过 FFmpeg 将其保存到文件中怎么做呢? 一.首先RTSP获取 h264 裸流 我们上面两篇文章主要讲的是通过 rtsp://Your ip ...
- [ffmpeg] h264并行解码
ffmpeg中的并行解码分为两种: Frame-level Parallelism Slice-level Parallelism Frame-level Parallelism 帧间依赖 我们之前讨 ...
- VS2015编译FFMPEG,修改FFmpeg缓冲区大小解决实时流解码丢包问题,FFmpeg错误rtsp流地址卡死的问题,设置超时
之前尝试过很多网上利用Windows编译FFmpeg的文章,都没有办法编译X64位的FFmpeg,有些教程中有专门提到编译64位的FFmpeg需要下载mingw-w64-install,但是编译的过程 ...
- ps流提取H264并解码播放
因为需要从海康ps流中提取H264数据并进行解码播放,才有了这篇文章.因为是视频编解码领域的纯入门新手,个别理解或者方法有误,需要自行判断,不过相关方法已经测试通过,对于 像我这样的新手还是有一定的借 ...
- ffmpeg H264 编解码配置
ffmpeg H264编解码前面有文章介绍下,本文主要介绍一些参数配置. 编码: int InitEncoderCodec( int iWidth, int iHeight) { AVCodec * ...
- 【VS开发】【视频开发】利用ffmpeg+opencv实现画中画
需求:把两路视频合成一路,即一个画面同时显示两路视频,其中一路缩小成小视频叠在大视频上面,和电视机的画中画效果类似. 思路:用h264编码的视频举例,文件中存储的es流是h264,经过解码成yuv,y ...
随机推荐
- template.compile()方法
template.compile(source, options) source:必传,渲染模板的内容. options:可选,通常不传.(其实是我还没研究明白) return:一个渲染函数. 示例如 ...
- selenium模拟浏览器对搜狗微信文章进行爬取
在上一篇博客中使用redis所维护的代理池抓取微信文章,开始运行良好,之后运行时总是会报501错误,我用浏览器打开网页又能正常打开,调试了好多次都还是会出错,既然这种方法出错,那就用selenium模 ...
- zalenium 应用
zalenium是一个Selenium Grid扩展,用Docker容器动态扩展你的本地网格.它使用docker-selenium在本地运行Firefox和Chrome中的测试,如果需要不同的浏览器, ...
- Java中的递归调用
Java中不合理的使用递归调用,可能会导致栈内存溢出,这点是需要注意的. java将为每个线程维护一个栈,栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态. 也就是我们常说的方法栈.最后一个 ...
- Cookie、session和localStorage、以及sessionStorage之间的区别
一.Cookie.session和localStorage的区别 cookie的内容主要包括:名字.值.过期时间.路径和域.路径与域一起构成cookie的作用范围.若不设置时间,则表示这个cookie ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
- BZOJ 2004: [Hnoi2010]Bus 公交线路 [DP 状压 矩阵乘法]
传送门 题意: $n$个公交站点,$k$辆车,$1...k$是起始站,$n-k+1..n$是终点站 每个站只能被一辆车停靠一次 每辆车相邻两个停靠位置不能超过$p$ 求方案数 $n \le 10^9, ...
- 利用Effmpeg 提取视频中的音频(mp3)
在B站看到一个up发的病名为爱的钢琴曲,感觉很好听,然后当然是要加入歌单啊.然而不知道怎么转换成mp3,找来找去找到了EFFmpeg 这篇只是达到了我简单的需求,以后可能会有EFFmpeg更详细的使用 ...
- jenkins入门系列之一 jenkins的安装
Jenkins是一个CI(持续集成环境)工具.它可以根据设定持续定期编译,运行相应代码:运行UT或集成测试:将运行结果发送至邮件,或展示成报告... 这样做的最终目的是: 让项目保持健康的状态.如果任 ...
- js压缩上传图片
初学有不当之处,请多多指点, <body> <div class="cc"> <input type="file" id=&quo ...
