Ubuntu 14.04LTS FFmpeg H264解码实战
安装FFmpeg
sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next
sudo apt-get update
sudo apt-get install ffmpeg
sudo apt-get install libavcodec-ffmpeg-dev
解码过程
1. 包含头文件,C++中,需要extern "C"起来
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h> //如果不做图像处理时,不需要包含
#include <libavutil/imgutils.h> //如果不做图像处理时,不需要包含
};
2. 声明变量
AVCodec* codec;
AVCodecParserContext *parser;
AVCodecContext* context;
AVFrame* frame;
AVPacket* pkt;
//如果需要做图像处理,比如需要转换成位图,再声明两个变量。
SwsContext* img_convert_ctx; //图像处理上下文
AVFrame* rgb_frame; //转换后的图片数据
bool is_init_output_buffer = false;
3. 初始化
int Init()
{
avcodec_register_all();
pkt = av_packet_alloc();
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "Codec not foundn");
return -1;
}
parser = av_parser_init(codec->id);
if (!parser) {
fprintf(stderr, "parser not foundn");
return -1;
}
context = avcodec_alloc_context3(codec);
if (!context) {
fprintf(stderr, "Could not allocate video codec contextn");
exit(1);
}
if (avcodec_open2(context, codec, NULL) < 0) {
fprintf(stderr, "Could not open codecn");
return -1;
}
frame = av_frame_alloc();
rgb_frame = av_frame_alloc();
if (!frame || !rgb_frame) {
fprintf(stderr, "Could not allocate video framen");
return -1;
}
}
4. 解码
int decode(unsigned char* data, int data_size)
{
while (data_size > 0) {
int ret = av_parser_parse2(parser, context, &pkt->data, &pkt->size,
data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
fprintf(stderr, "Error while parsingn");
return -1;
}
data += ret;
data_size -= ret;
if (pkt->size) {
ret = avcodec_send_packet(context, pkt);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decodingn");
return -1;
}
while (ret >= 0) {
ret = avcodec_receive_frame(context, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
fprintf(stderr, "Error during decodingn");
return -1;
}
//至此解码已经成功,下面进行YUV到RGB的转换
if (!is_init_output_buffer) {
//初试化转换后的图像数据buffer,只要初始化一次就行。
uint8_t *out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB24, context->width, context->height, 1));
av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, out_buffer, AV_PIX_FMT_RGB24, context->width, context->height, 1);
is_init_output_buffer = true;
}
//获取图像转换上下文
img_convert_ctx = sws_getCachedContext(img_convert_ctx, context->width, context->height,
context->pix_fmt, context->width, context->height, AV_PIX_FMT_RGB24,
SWS_X, NULL, NULL, NULL);
//图像转换
sws_scale(img_convert_ctx, frame->data, frame->linesize, 0, context->height, rgb_frame->data, rgb_frame->linesize);
//下面是3种数据的获取方式
//YUV数据
int y_size = context->width * context->height;
fwrite(rgb_frame->data[0], 1, y_size, fp_yuv); //Y
fwrite(rgb_frame->data[1], 1, y_size / 4, fp_yuv); //U
fwrite(rgb_frame->data[2], 1, y_size / 4, fp_yuv); //V
// RGB数据
fwrite(rgb_frame->data[0], (context->width) * (context->height) * 3, 1, fp);
// UYVY数据
//fwrite(rgb_frame->data[0], (context->width) * (context->height), 2, fp);
}
}
}
return 0;
}
5. 编译包含的库
LIBS += /usr/local/lib/libavcodec.a /usr/local/lib/libavutil.a /usr/local/lib/libswresample.a /usr/local/lib/libswscale.a -lz -ldl
- 初学js钻太深,不太好
- Linux shell 程序设计3——命令行程序
- Linux shell 程序设计2——bash的内置命令
- T-SQL Enhancement in SQL Server 2005[下篇]
- JS原型,a和b是不是失散多年的兄弟?
- Linux shell 程序设计1——安装及入门
- 偶遇--《坑新人--前端专用面试题》
- 简单的说下,(function(){...})() 与 (function(){...}()) 有什么区别?
- ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇]
- Shell常用命令小结
- 插入法排序
- ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part II
- 震惊了!这样的js面试题让所有人-男默女泪
- 前端知识学了却不会用,都是没走心
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 表达量矩阵分组很复杂也可以使用limma的3大策略
- 一日一技:loguru 如何把不同的日志写入不同的文件中
- 如何迁移SSDB数据到Tendis解决方案
- 第40期:Keep Balance,平衡二叉树!
- 第38期:BST 的搜索(小白必看)
- 第39期:小白一看就会的 BST 删除!
- 基于OpenCV的区域分割、轮廓检测和阈值处理
- 基于OpenCV的实用图像处理操作
- LDAP 中 DN CN DC OU
- Spring Boot入门系列(十九)集成mybatis
- 当我们做后仿时我们究竟在仿些什么(四)
- Scala学习一
- kafka学习二 -发送消息
- 【ACL2020】使用问题图生成解决multi-hop复杂KBQA
- R语言实现DNA结构预测