在上一篇文章 FFmpeg学习(四):FFmpeg API 介绍与通用 API 分析 中,我们简单的讲解了一下FFmpeg 的API基本概念,并分析了一下通用API,本文我们将分析 FFmpeg 在编解码时使用的API。

一、FFmpeg 解码 API 分析

1. avformat_open_input 分析

函数 avformat_open_input 会根据所提供的文件路径判断文件的格式,其实就是通过这一步来决定到底是使用哪个Demuxer。

举个例子:如果是flv,那么Demuxer就会使用对应的ff_flv_demuxer,所以对应的关键生命周期的方法read_header、read_packet、read_seek、read_close都会使用该flv的Demuxer中函数指针指定的函数。read_header会将AVStream结构体构造好,以方便后续的步骤继续使用AVStream作为输入参数。

2. avformat_find_stream_info 分析

该方法的作用就是把所有的Stream的MetaData信息填充好。方法内部会先查找对于的解码器,然后打开对应的解码器,紧接着会利用Demuxer中的read_packet函数读取一段数据进行解码,当然,解码的数据越多,分析出来的流信息就越准确,如果是本地资源,那么很快就可以得到准确的信息了。但是对于网络资源来说,则会比较慢,因此该函数有几个参数可以控制读取数据的长度,一个是probe size,一个是max_analyze_duration, 还有一个就是fps_probe_size,这三个参数共同控制解码数据的长度,如果配置的这几个参数的数值越小,那么这个函数执行的时间就会越快,但会导致AVStream结构体里面的信息(视频的宽、高、fps、编码类型)不准确。

3. av_read_frame 分析

该方法读取出来的数据是AVPacket,在FFmpeg的早期版本中开发给开发者的函数其实就是av_read_packet,但是需要开发者自己来处理AVPacket中的数据不能被解码器处理完的情况,即需要把未处理完的压缩数据缓存起来的问题。所以在新版本的FFmpeg中,提供了该函数,用于处理此状况。  该函数的实现首先会委托到Demuxer的read_packet方法中,当然read_packet通过解服用层和协议层的处理后,会将数据返回到这里,在该函数中进行数据缓冲处理。

对于音频流,一个AVPacket可能会包含多个AVFrame,但是对于一个视频流,一个AVPacket只包含一个AVFrame,该函数最终只会返回一个AVPacket结构体。

4. avcodec_decode分析

该方法包含了两部分内容:一部分是解码视频,一部分是解码音频。在上面的函数分析中,我们知道,解码是会委托给对应的解码器来实施的,在打开解码器的时候就找到了对应的解码器的实现,比如对于解码H264来讲,会找到ff_h264_decoder,其中会有对应的生命周期函数的实现,最重要的就是init,decode,close三个方法,分别对应于打开解码器、解码及关闭解码器的操作,而解码过程就是调用decode方法。

5. avformat_close_input 分析

该函数负责释放对应的资源,首先会调用对应的Demuxer中的生命周期read_close方法,然后释放掉,AVFormatContext,最后关闭文件或者远程网络链接。

二、FFmpeg 编码 API 分析

1. avformat_alloc_output_context2 分析

该函数内部需要调用方法avformat_alloc_context来分配一个AVFormatContext结构体,当然最关键的还是根据上一步注册的Muxer和Demuxer部分(也就是封装格式部分)去找对应的格式。有可能是flv格式、MP4格式、mov格式,甚至是MP3格式等,如果找不到对应的格式(应该是因为在configure选项中没有打开这个格式的开关),那么这里会返回找不到对于的格式的错误提示。在调用API的时候,可以使用av_err2str把返回的整数类型的错误代码转换为肉眼可读的字符串,这是个在调试中非常有用的工具函数。该函数最终会将找出来的格式赋值给AVFormatContext类型的oformat。

2. avio_open2 分析

首先会调用函数ffurl_open,构造出URLContext结构体,这个结构体中包含了URLProtocol(需要去第一步register_protocol中已经注册的协议链表)中去寻找;接着会调用avio_alloc_contex方法,分配出AVIOContext结构体,并将上一步构造出来的URLProtocol传递进来;然后把上一步分配出来的AVIOContext结构体赋值给AVFormatContext属性。

下面就是针对上面的描述总结的结构之间的构架图,各位可以参考此图进行进一步的理解:

avio_open2的过程也恰好是在上面我们分析avformat_open_input过程的一个逆过程。编码过程和解码过程从逻辑上来讲,也是一个逆过程,所以在FFmpeg实现的过程中,他们也互为逆过程。

3. 编码其他API(步骤)分析

编码的其他步骤也是解码的一个逆过程,解码过程中的avformat_find_stream_info对应到编码就是avformat_new_stream和avformat_write_header。

  • avformat_new_stream函数会将音频流或者视频流的信息填充好,分配出AVStream结构体,在音频流中分配声道、采样率、表示格式、编码器等信息,在视频中分配宽、高、帧率、表示格式、编码器等信息。
  • avformat_write_header函数与解码过程中的read_header恰好是一个逆过程,这里就不多赘述了。

接下来就是编码阶段了:

1. 将手动封装好的AVFrame结构体,作为avcodec_encodec_video方法的输入,然后将其编码成为AVPacket,然后调用av_write_frame方法输出到媒体文件中。

2. av_write_frame 方法会将编码后的AVPacket结构体作为Muxer中的write_packet生命周期方法的输入,write_packet会加上自己封装格式的头信息,然后调用协议层,写到本地文件或者网络服务器上。

3. 最后一步就是av_write_trailer(该函数有一个非常大的坑,如果没执行write_header操作,就直接执行write_trailer操作,程序会直接Carsh掉,所以这两个函数必须成对出现),av_write_trailer会把没有输出的AVPacket全部丢给协议层去做输出,然后会调用Muxer的write_trailer生命周期方法(不同的格式,写出的尾部也不一样)。

FFmpeg 学习(五):FFmpeg 编解码 API 分析的更多相关文章

  1. FFmpeg再学习 -- 硬件加速编解码

    为了搞硬件加速编解码,用了一周时间来看 CUDA,接下来开始加以总结. 一.什么是 CUDA (1)首先需要了解一下,什么是 CUDA. 参看:百度百科 -- CUDA 参看:CUDA基础介绍 参看: ...

  2. 【转】Netty系列之Netty编解码框架分析

    http://www.infoq.com/cn/articles/netty-codec-framework-analyse/ 1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称 ...

  3. Netty系列之Netty编解码框架分析

    1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 反之,解码(Decod ...

  4. netty权威指南学习笔记八——编解码技术之JBoss Marshalling

    JBoss Marshalling 是一个java序列化包,对JDK默认的序列化框架进行了优化,但又保持跟java.io.Serializable接口的兼容,同时增加了一些可调参数和附加特性,这些参数 ...

  5. ISD9160学习笔记03_ISD9160音频解码代码分析

    录音例程涉及了录音和播放两大块内容,这篇笔记就先来说说播放,暂且先击破解码这部分功能. 我的锤子便签中有上个月记下的一句话,“斯蒂芬·平克说,写作之难,在于把网状思考,用树状结构,体现在线性展开的语句 ...

  6. Netty学习(九)-Netty编解码技术之Marshalling

    前面我们讲过protobuf的使用,主流的编解码框架其实还有很多种: ①JBoss的Marshalling包 ②google的Protobuf ③基于Protobuf的Kyro ④Apache的Thr ...

  7. Netty学习(七)-Netty编解码技术以及ProtoBuf和Thrift的介绍

    在前几节我们学习过处理粘包和拆包的问题,用到了Netty提供的几个解码器对不同情况的问题进行处理.功能很是强大.我们有没有去想这么强大的功能是如何实现的呢?背后又用到了什么技术?这一节我们就来处理这个 ...

  8. netty权威指南学习笔记六——编解码技术之MessagePack

    编解码技术主要应用在网络传输中,将对象比如BOJO进行编解码以利于网络中进行传输.平常我们也会将编解码说成是序列化/反序列化 定义:当进行远程跨进程服务调用时,需要把被传输的java对象编码为字节数组 ...

  9. netty权威指南学习笔记七——编解码技术之GoogleProtobuf

    首先我们来看一下protobuf的优点: 谷歌长期使用成熟度高: 跨语言支持多种语言如:C++,java,Python: 编码后消息更小,更利于存储传输: 编解码性能高: 支持不同协议版本的兼容性: ...

随机推荐

  1. 七 Git版本控制

    把环境准备 主机名 node1  ip地址10.0.0.11              node2             10.0.0.12              node3           ...

  2. thymleaf th:text="|第${user.courseSort}课|" 对于不知道的真的是解渴了

    简单描述:最近再做一个课程管理,列表显示第几课,但是后台传递过来的只是数字0~9,意味着,我得自己拼了ヾ(◍°∇°◍)ノ゙  我最烦的就是这种拼,各种难调,果真和我想的一样,4.5遍了还没出来. 我的 ...

  3. mongodb基本的配置和使用

    一.连接配置,使用自动配置方式,在applicaiton.properties中配置连接信息即可 spring.data.mongodb.host=127.0.0.1 //连接地址 spring.da ...

  4. iOS开发之获取文件的md5值

    我们经常有下载文件上的需求 为了安全我们经常需要对文件进行md5校验 那我就来给大家分享一个很方便的获取文件md5值得方法. 首先需要引用系统库文件 #include <CommonCrypto ...

  5. 使用docker 部署rabbitmq 镜像

    1.使用带有web管理功能 sudo docker pull rabbitmq:management 2.运行镜像文件创建容器 sudo docker run -d --name rabbitmq - ...

  6. UML绘图工具——PlantUML

    1 简介 PlantUML是一个开源项目,支持通过简单直观的语言来定义以下UML图. 时序图 用例图 类图 活动图 组件图 状态图 对象图 部署图 定时图 支持生成图片格式有: PNG SVG LaT ...

  7. UOJ#335. 【清华集训2017】生成树计数 多项式,FFT,下降幂,分治

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ335.html 前言 CLY大爷随手切这种题. 日常被CLY吊打系列. 题解 首先从 pruffer 编码的角度考虑这个问 ...

  8. Py:数据挖掘之对个人微信朋友圈好友的性别、区域、昵称、签名信息进行情感分析——Jason niu

    #Py:数据挖掘之对微信朋友圈好友的性别.区域.昵称.签名信息进行情感分析——Jason niu import os import re import csv import time import j ...

  9. selenium操作浏览器窗口最大化和刷新

    实际测试过程中经常遇到打开一个页面并不是全屏显示,但是却希望它能够全屏显示或者新增一条记录后需要刷新一下看能不能再列表中正常显示. 于是就有了今天的关于对浏览器窗口的最大化和刷新页面.需要说明的一点: ...

  10. vue获取当前对象

    <li v-for="img in willLoadImg" @click="selectImg($event)"> <img class=& ...