专栏首页默认Ubuntu 14.04LTS FFmpeg H264解码实战
原创

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 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

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Redis Sentinel的工作原理

    dejunzhang
  • Spring、Spring Boot和TestNG测试指南 - 测试@Configuration

    在Spring引入Java Config机制之后,我们会越来越多的使用@Configuration来注册Bean,并且Spring Boot更广泛地使用了这一机...

    颇忒脱
  • Spring Cloud 项目 SpringApplication Run 执行两次解密

    作用是在ConfigurableApplicationContext类型的ApplicationContext.refresh 操作 之前,允许我们对Confi...

    冷冷
  • 商业计划书哪家强?当然是红杉资本出品的这份模版,果断收藏了!

    下面这个商业计划书的模版来自红杉资本,它多年来投资了包括苹果、思科、甲骨文、谷歌、Airbnb、京东、滴滴、美团等产业潮流的领导者,完全称得上是世界风投领域的祖...

    辉哥
  • 基于Glide的二次封装

    更多代码可以查询本人GitHub:欢迎阅读,star点起来。 Glide二次封装库源码

    先知先觉
  • 为什么大公司“人才”创业更容易失败?

    image.png 大公司人才特点 1、分工细,比如产品,会分为 B 端和 C 端,C 端又会分为用户研究、行为分析、竞品分析、用户体验、场景化设置、功能设置、...

    BestSDK
  • 卫星授时(网络授时服务器)源代码挥泪吐血共享

    《Linux 应用程序开发班》 / 第 8 天 -NTP 网络协议实现 /培训视频 /NTP网络协议实现 .avi 。

    NTP网络同步时钟
  • 比原链BTM评测

    用户2196435
  • WordPress的主题添加AJAX无刷新提交评论功能

    有时主题在提交评论后会刷新整个网页才可获取资源,别人家的都不是这样的,以下可以改善评论后无刷新即可获取资源。

    空木白博客
  • CodeForces 17D Notepad(同余定理)

    D. Notepad time limit per test 2 seconds memory limit per test 64 megabyte...

    ShenduCC

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动