前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Ubuntu 14.04LTS FFmpeg H264解码实战

Ubuntu 14.04LTS FFmpeg H264解码实战

原创
作者头像
dejunzhang
发布2018-10-04 11:36:33
1.7K0
发布2018-10-04 11:36:33
举报
文章被收录于专栏:默认默认

安装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 found\n");

return -1;

}

parser = av_parser_init(codec->id);

if (!parser) {

fprintf(stderr, "parser not found\n");

return -1;

}

context = avcodec_alloc_context3(codec);

if (!context) {

fprintf(stderr, "Could not allocate video codec context\n");

exit(1);

}

if (avcodec_open2(context, codec, NULL) < 0) {

fprintf(stderr, "Could not open codec\n");

return -1;

}

frame = av_frame_alloc();

rgb_frame = av_frame_alloc();

if (!frame || !rgb_frame) {

fprintf(stderr, "Could not allocate video frame\n");

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 parsing\n");

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 decoding\n");

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 decoding\n");

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安装FFmpeg
  • 解码过程
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com