1. ffmpeg 视频解码一
2. ffmpeg 视频解码二
3. ffmpeg 音频解码一
4. ffmpeg 音频解码二
5. ffmpeg 音视频解码
6. ffmpeg 视频编码一
7. ffmpeg 视频编码一(精简版)
8. ffmpeg 视频编码二(基于 libswscale 转换视频)
9. ffmpeg 过滤器libavfilter的使用
10. ffmpeg 视频编码三(基于 libavfilter 转换视频)

前言

ffmpeg的大版本都已经更新到4了,近段时间我也研究了一下,从这篇文章开始,我将写一个系列,阐述一下ffmpeg API的使用。这篇文章为第一篇,就仅仅讲述一下视频解码相关的使用吧(视频解码会写两篇,这为第一篇,分别使用不同的API)。

流程图


代码流程即如流程图所示,下面讲解一下当中部分函数的作用。

  1. av_parser_init
    这是一个解析器,我们根据解码器,实例化这个解析器,后面解析数据时使用。
  2. av_parser_parse2
    我们从输入文件得到的原始数据(不适用ffmpeg自带的api的话),直接使用是不行的,此时我们就需要把这个原始数据使用上面实例化的解析器来解析,把数据分割成帧,为后面解码数据做准备。
  3. avcodec_send_packet
    发送我们刚刚得到的解析数据到解码器做解码。
  4. avcodec_receive_frame
    获取解码之后的数据。

源码


#pragma once
#define __STDC_CONSTANT_MACROS
#define _CRT_SECURE_NO_WARNINGSextern "C"
{#include "libavcodec/avcodec.h"
}#define INBUF_SIZE 4096using namespace std;#define INPUT_FILE_NAME "lh_online.h264"
#define OUTPUT_FILE_NAME "lh_online.yuv"static void decode(AVCodecContext* dec_ctx, AVFrame* frame, AVPacket* pkt,FILE* ofile)
{int ret;int y_size;ret = avcodec_send_packet(dec_ctx, pkt);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "发送数据包到解码器出错。\n");exit(1);}while (ret >= 0) {ret = avcodec_receive_frame(dec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Error sending a packet for decoding.\n");exit(1);}//此时一帧视频已经保存到frame中了// //打印输出的视频帧的帧数av_log(NULL, AV_LOG_INFO, "saving frame:%d , width: %d ,height: %d.\n", dec_ctx->frame_number, frame->width, frame->height);//获取一帧视频数据大小y_size = frame->width * frame->height;fwrite(frame->data[0], 1, y_size, ofile);    //Yfwrite(frame->data[1], 1, y_size / 4, ofile);  //Ufwrite(frame->data[2], 1, y_size / 4, ofile);  //V}
}int main(int argc, char* argv[])
{const AVCodec* codec;AVCodecParserContext* parser;AVCodecContext* c = NULL;FILE* ifile, * ofile;AVFrame* frame;AVPacket* pkt;uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];uint8_t* data;size_t   data_size;int ret;//初始化inbuf数组memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);//获取解码器(此处需要读取的文件是H264,故)codec = avcodec_find_decoder(AV_CODEC_ID_H264);if (!codec) {av_log(NULL, AV_LOG_ERROR, "Codec not found.\n");exit(1);}//注册解析器parser = av_parser_init(codec->id);if (!parser) {av_log(NULL, AV_LOG_ERROR, "parser not found.\n");exit(1);}//分配解析器上下文c = avcodec_alloc_context3(codec);if (!c) {av_log(NULL, AV_LOG_ERROR, "Could not allocate video codec context.\n");exit(1);}//打开解码器if (avcodec_open2(c, codec, NULL) < 0) {av_log(NULL, AV_LOG_ERROR, "Could not open codec.\n");exit(1);}//分配AVPacketpkt = av_packet_alloc();if (!pkt) {exit(1);}//分配AVFrameframe = av_frame_alloc();if (!frame) {exit(1);}//打开输入文件ifile = fopen(INPUT_FILE_NAME, "rb");if (!ifile) {av_log(NULL, AV_LOG_ERROR, "Could not open \s.\n", INPUT_FILE_NAME);exit(1);}//打开输入文件ofile = fopen(OUTPUT_FILE_NAME, "wb+");if (!ofile) {av_log(NULL, AV_LOG_ERROR, "Could not open \s.\n", OUTPUT_FILE_NAME);exit(1);}while (!feof(ifile)) {//从输入流 ifile 读取数据到 inbuf 所指向的数组中data_size = fread(inbuf, 1, INBUF_SIZE, ifile);if (!data_size)break;//使用注册的解析器 parser 把数据分割成帧data = inbuf;while (data_size > 0) {ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size,data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Error while parsing.\n");exit(1);}//根据使用情况重置数据位置data += ret;data_size -= ret;if (pkt->size) {decode(c, frame, pkt, ofile);}}}//flush 解码器decode(c, frame, NULL, ofile);//资源释放fclose(ifile);fclose(ofile);av_parser_close(parser);avcodec_free_context(&c);av_frame_free(&frame);av_packet_free(&pkt);return 0;
}

这个示例中我们把一个H264编码的 lh_online.h264 的文件解码成原始YUV视频文件 lh_online.yuv(这里不做YUV的介绍)。
下面我们使用ffplay来播放我们刚刚解码出来的视频原始数据(播放路径以自己实际路劲为准)。

ffplay -i C:\...\lh_online.yuv -pix_fmt yuv420p -s 512*288

注意两点:

  1. 此时我们播放的数据格式是 yuv 的(此处可设置可不设置,ffplay默认可播放)。
  2. 我们需要知道视频的原始宽高,代码里有个位置获取了宽高的(dec_ctx->frame_number, frame->width, frame->height),我们需要把快其设置到命令里,否者是不能播放的(我这个文件是512*288的)。

下面看下效果。

到此,基于parser解析器的解码就完成了,我们任何知道文件格式的视频,如果直接基于文件读取的方式都可以使用这种方式。
下一篇将讲述纯基于API的方式,应该是比这个方便很多。

ffmpeg 视频解码一相关推荐

  1. FFmpeg视频解码中的YUV420P格式

    参考文章 在做基于FFmpeg解码的视频播放时,需要涉及到帧数据存储的YUV与RGB格式,所以了解了一下,参考下述博文. https://blog.csdn.net/lanxiaziyi/articl ...

  2. 一文读懂 Android FFmpeg 视频解码过程与实战分析

    概述 本文首先以 FFmpeg 视频解码为主题,主要介绍了 FFmpeg 进行解码视频时的主要流程.基本原理:其次,文章还讲述了与 FFmpeg 视频解码有关的简单应用,包括如何在原有的 FFmpeg ...

  3. libpng库编码图片为png(RGB压缩为png图片:与ffmpeg视频解码存储为png图片)

    //*====== 参考:1.http://blog.csdn.net/solstice/article/details/2062 2.libpng库的example.c文件 ======*// 一. ...

  4. FFmpeg视频解码流程详解及demo

    本文主要讲解FFmpeg的视频解码具体流程,API使用,以及相关结构体介绍.最后再以一个非常简单的demo演示将一个mp4格式的视频文件解码为原始数据yuv文件. FFmpeg解码流程有2套API接口 ...

  5. QT中使用FFmpeg视频解码

    视频解码 流程图 步骤  加入需要的头文件 1,注册所有组件 av_register_all() 2,打开视频文件 avformat_open_input(),(判断是否打开成功) 3,取视频相关信息 ...

  6. Qt:ffmpeg视频解码实现

    环境配置 1.与ffmpeg有关的dll文件放进项目debug文件下 与ffmpeg有关的lib文件,include文件放入项目当前目录下 2.pro文件配置路径(根据你自己放的路径) LIBS是导入 ...

  7. FFmpeg 视频解码(秒懂)

    1.简介 解码如下图所示,将H.264数据解码为YUV. 2.流程 2.1 在使用FFmpeg API之前,需要先注册API,然后才能使用API.当然,新版本的库不需要再调用下面的方法. av_reg ...

  8. FFmpeg视频解码硬件加速

    <音视频应用开发系列文章目录> ffmpeg支持的硬件解码器 enum AVHWDeviceType {AV_HWDEVICE_TYPE_NONE,AV_HWDEVICE_TYPE_VDP ...

  9. FFmpeg学习1:视频解码

    在视频解码前,先了解以下几个基本的概念: 编解码器(CODEC):能够进行视频和音频压缩(CO)与解压缩(DEC),是视频编解码的核心部分. 容器/多媒体文件(Container/File):没有了解 ...

最新文章

  1. 谷歌Chrome 11对早期开发者开放使用
  2. 数据机房建设常用材料有哪些?
  3. 向webServices请求失败
  4. vue3.0、cli4项目引入element plus
  5. SpringBoot + MyBatis(注解版),常用的SQL方法
  6. php 网络图片 转本地,PHP将Base64图片转换为本地图片并保存
  7. 5和6 objbc oracle_Oracle测试题
  8. [转]mysql优化——show processlist命令详解
  9. 强大的负载均衡+静态文件WEB服务器nginx实战
  10. python安装计算机丢失api_Python安装后提示api-ms-win-crt-runtime-|1-1-0.dll丢失
  11. 【window操作系统下Github版本的回滚问题】
  12. java 表单字段扩展_如何从Chrome扩展程序填写网页表单中的文本字段?
  13. Windows 7 SP1 语言包下载
  14. Python交通流仿真【含源码】
  15. 项目管理的49个过程整理
  16. 技术团队管理者的软技能(上):关于团队文化和领导力
  17. RedHat认证笔记-RH124
  18. Rom制作工具让你一键root畅想未来
  19. 加班申请 ----中间表--系统自动算出---可调休天数
  20. 计算机组织结构南京大学,南京大学09年计算机组织结构期中考试试题.docx

热门文章

  1. linux14.04网卡驱动,Ubuntu14.04 没有无线网卡驱动的解决方法
  2. 计算机相关的迎新标语,迎新横幅的标语(精选50句)
  3. 旧调重弹Hibernate与Ibatis区别——深入架构设计
  4. Day_05盒子模型
  5. android唤醒音乐播放器,android调用音乐播放器,三种方
  6. 智慧城市-疫情流调系列1-Prompt-文本分类
  7. QT5 创建“打开文件”按钮
  8. 2021年广西省安全员B证找解析及广西省安全员B证模拟考试题库
  9. 什么是交换机、路由器、防火墙?
  10. java le下载安装_跟老杨学java系列(五) JDK的安装与配置