因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作。在网上找了一圈,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\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;
}

3. 释放资源

资源的回收。

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

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

  1. 利用ffmpeg将H264流 解码为RGB

    利用H264解码分为几个步骤: 注意一点在添加头文件的时候要添加extern "C",不然会出现错误 [cpp] view plaincopy extern "C&quo ...

  2. linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)

    在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示. 420显示如 ...

  3. 用ffmpeg把H264数据流解码成YUV420P

    在网上找了很久这方面的内容,发现网上的代码都太旧了,所使用的函数旧到连最新版本的ffmpeg都已经不包含了,所以对于我这个初学者来说太坑拉.不过经过多次查找ffmpeg的头文件和结合网上的内容,终于成 ...

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

    农历2014年底了,将前段时间工作中研究的FFMPEG解码H264流程在此做一下整理,也算作年终技术总结了! H264解码原理: H264的原理参考另一篇博文 http://blog.csdn.net ...

  5. 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中

    既然已经可以通过 RTSP 获取h264 裸流了.那么通过 FFmpeg 将其保存到文件中怎么做呢? 一.首先RTSP获取 h264 裸流 我们上面两篇文章主要讲的是通过 rtsp://Your ip ...

  6. 利用FFmpeg玩转Android视频录制与压缩(二)<转>

    转载出处:http://blog.csdn.net/mabeijianxi/article/details/72983362 预热 时光荏苒,光阴如梭,离上一次吹牛逼已经过去了两三个月,身边很多人的女 ...

  7. 【VS开发】【视频开发】利用ffmpeg+opencv实现画中画

    需求:把两路视频合成一路,即一个画面同时显示两路视频,其中一路缩小成小视频叠在大视频上面,和电视机的画中画效果类似. 思路:用h264编码的视频举例,文件中存储的es流是h264,经过解码成yuv,y ...

  8. H264解码学习-2015.04.16

    今天看了不少,却感觉收获寥寥. 1.H264相关知识 因为RTP协议发过来的数据已经经过了H264编码,所以这边需要解码.补充一下H264的相关知识. 与以往的视频压缩标准相比,H.264 视频压缩标 ...

  9. [ffmpeg] h.264解码所用的主要缓冲区介绍

    在进行h264解码过程中,有两个最重要的结构体,分别为H264Picture.H264SliceContext. H264Picture H264Picture用于维护一帧图像以及与该图像相关的语法元 ...

随机推荐

  1. uu云验证码识别平台,验证码,验证码识别,全自动验证码识别技术,优优云全自动打码,代答题系统,优优云远程打码平台,uu云打码

    uu云验证码识别平台,验证码,验证码识别,全自动验证码识别技术,优优云全自动打码,代答题系统,优优云远程打码平台,uu云打码 优优云验证码识别答题平台介绍 优优云|UU云(中国公司)是全球唯一领先的智 ...

  2. Setup SSH and SVN on Windows Server

    cygwin: install sshd, cygrunsrv http://lifehacker.com/205090/geek-to-live--set-up-a-personal-home-ss ...

  3. C#验证字符串是否是数字,是否包括中文,是否是邮箱格式,是否是电话格式

    using System;     using System.Web;     using System.Text;     using System.Web.UI.WebControls;     ...

  4. HDU 2444 The Accomodation of Students(推断是否是二分图)

    题目链接 题意:n个学生,m对关系,每一对互相认识的能住一个房间.问否把这些学生分成两组,要求每组的学生都互不认识.求最多须要多少个房间. 能否分成两组?也就是说推断是不是二分图,推断二分图的办法,用 ...

  5. Ajaxterm

    Index of /software/ajaxterm Ajaxterm Since Mon Feb 28 03:22:42 CET 2011, hosted here: github.com/ant ...

  6. poj 2586 Y2K Accounting Bug(贪心算法,水题一枚)

    #include <iostream> using namespace std; /*248K 32MS*/ int main() { int s,d; while(cin>> ...

  7. hdu4035(概率dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4035 题意:有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 从结点1出发,开始走,在每个结 ...

  8. 【Java 它 JVM】对象的创建过程

    虚拟机会new 指令: 1.检查指令的参数可在对类的符号引用的恒定饮食定位,并检查是否已装上代表这个类的符号引用.分析和初始化.假设没有.您必须运行相应的类加载过程. 2.类加载通过审查,虚拟机将分配 ...

  9. TMS320F28335项目开发记录9_28335中断系统

    28335中断系统 1.中断系统 在这里我们要十分清楚DSP的中断系统. C28XX一共同拥有16个中断源,当中有2个不可屏蔽的中断RESET和NMI.定时器1和定时器2分别使用中断13和14.这样还 ...

  10. SE 2014年4月17日

    描述BGP路由属性 MED.首选值 的特点 MED相当于IGP协议中的度量值,在其他条件相同时,当本自治系统有多条到达外部自治系统的链路时,MED值小的路由优选.MED属性只能在两个自治系统间传递. ...