InputStream数据结构示例解析

目录
  • 正文
  • struct InputStream数据结构定义
  • 各个字段的解析

正文

struct InputStream 是单个输入流的管理器。是由 add_input_stream() 函数申请内存,以及赋值 InputStream 的各个字段的。

而 input_streams 数组是一个全局变量,包含了所有输入文件里面的所有输入流。

nputStream **input_streams = NULL;
int        nb_input_streams = 0;

你在二次开发 ffmpeg.exe 的时候,可以用 input_streams 全局变量来获取到所有的输入流

struct InputStream数据结构定义

typedef struct InputStream {
    int file_index;
    AVStream *st;
    int discard;             /* true if stream data should be discarded */
    int user_set_discard;
    int decoding_needed;     /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */
#define DECODING_FOR_OST    1
#define DECODING_FOR_FILTER 2
    AVCodecContext *dec_ctx;
    const AVCodec *dec;
    AVFrame *decoded_frame;
    AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */
    AVPacket *pkt;
    int64_t       start;     /* time when read started */
    /* predicted dts of the next packet read for this stream or (when there are
     * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */
    int64_t       next_dts;
    int64_t       dts;       ///< dts of the last packet read for this stream (in AV_TIME_BASE units)
    int64_t       next_pts;  ///< synthetic pts for the next decode frame (in AV_TIME_BASE units)
    int64_t       pts;       ///< current pts of the decoded frame  (in AV_TIME_BASE units)
    int           wrap_correction_done;
    int64_t filter_in_rescale_delta_last;
    int64_t min_pts; /* pts with the smallest value in a current stream */
    int64_t max_pts; /* pts with the higher value in a current stream */
    // when forcing constant input framerate through -r,
    // this contains the pts that will be given to the next decoded frame
    int64_t cfr_next_pts;
    int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */
    double ts_scale;
    int saw_first_ts;
    AVDictionary *decoder_opts;
    AVRational framerate;               /* framerate forced with -r */
    int top_field_first;
    int guess_layout_max;
    int autorotate;
    ...省略字幕相关字段...
    int dr1;
    /* decoded data from this stream goes into all those filters
     * currently video and audio only */
    InputFilter **filters;
    int        nb_filters;
    int reinit_filters;
    /* hwaccel options */
    ...省略硬件解码相关字段...
    /* hwaccel context */
   ...省略硬件解码相关字段...
    /* stats */
    // combined size of all the packets read
    uint64_t data_size;
    /* number of packets successfully read for this stream */
    uint64_t nb_packets;
    // number of frames/samples retrieved from the decoder
    uint64_t frames_decoded;
    uint64_t samples_decoded;
    int64_t *dts_buffer;
    int nb_dts_buffer;
    int got_output;
} InputStream;

各个字段的解析

(省略了字幕相关的字段):

1, int file_indexinput_files 数组里面的下标,代表 InputStream 对应的 InputFile

2, AVStream *stAVFormatContext 里面的 AVStream 。

3, int discard,如果是 1 会丢弃读取到的 AVPacket,刚开始的时候都是 1。例如文件里面有多个视频流,会全部都把 discard 设置为 1,然后再从中选出质量最好的视频流,把它的 discard 设置为 0 。

或者当输出流需要这个输入流的时候,也会置为 0 ,如下:

if (source_index >= 0) {
    ost->sync_ist = input_streams[source_index];
    input_streams[source_index]->discard = 0;
    input_streams[source_index]->st->discard = input_streams[source_index]->user_set_discard;
}

因此,如果你用 ffmpeg.exe 对一个有多个视频流的文件进行转换,默认只会输出一个视频流。

4, int user_set_discard,命令行选项 -discard 的值,默认是 AVDISCARD_NONE,可选的值在 AVDiscard 枚举里面。

enum AVDiscard{
    /* We leave some space between them for extensions (drop some
     * keyframes for intra-only or drop just some bidir frames). */
    AVDISCARD_NONE    =-16, ///< discard nothing
    AVDISCARD_DEFAULT =  0, ///< discard useless packets like 0 size packets in avi
    AVDISCARD_NONREF  =  8, ///< discard all non reference
    AVDISCARD_BIDIR   = 16, ///< discard all bidirectional frames
    AVDISCARD_NONINTRA= 24, ///< discard all non intra frames
    AVDISCARD_NONKEY  = 32, ///< discard all frames except keyframes
    AVDISCARD_ALL     = 48, ///< discard all
};

5, int decoding_needed,大于 0 代表输入流需要进行解码操作,有两个值,DECODING_FOR_OST ,DECODING_FOR_FILTER

6, AVCodecContext *dec_ctx,解码器上下文/解码器实例,输入流的 AVPacket 会丢给解码实例进行解码。

7, const AVCodec *dec,解码器信息

8, AVFrame *decoded_frame,从解码器上下文 解码出来的 AVFrame

9, AVFrame *filter_frame,这个字段主要是用来增加引用计数的,可能在调用 av_buffersrc_add_frame_flags() 之后,AVFrame 的引用技术会减一,所以需要先复制一份引用,如下:

10, AVPacket *pkt,从 av_read_frame() 里面读出来的 AVPacket,只是复制了一下引用。

11, int64_t start,记录此流是什么时候开始处理的,主要是给 -re 选项使用的,模拟帧率速度,录制视频模拟直播用的。

12, int64_t next_dts,下一帧的 解码时间,这是通过计算得到的预估值,如果读取出来的 AVPacket 没有 dts ,会用这个值代替。

13, int64_t dts,最近一次从 av_read_frame() 读出来的 AVPacket 的 dts

14, int64_t next_pts,下一个 AVFrame 的 pts,通过当前 AVFrame 的 pts 加上 duration 计算出来的,应该是给一些没有 pts 值的 AVFrame 用的。

15, int64_t pts,最近一次从解码器里面解码出来的 AVFrame 的 pts,记录这个值主要是给 send_filter_eof() 用的,防止回滚。

15, int64_t wrap_correction_done,在一些流格式,例如 TS,会有时间戳环回的问题,int64 是有大小限制的,超过这个大小会环回,ffmpeg.exe 需要处理环回的逻辑。

16, int64_t filter_in_rescale_delta_last,专门给音频帧转换时间基用的,因为音频的连续性太强,如果有些许误差需要保存下来,在下次转换的时候进行补偿。

17, int64_t min_pts, 从 av_read_frame() 读出来的 AVPacket 的最小 pts ,不一定是第一帧的 pts,因为命令行参数通过 -ss 选项,指定从哪里开始处理。

18, int64_t max_pts,从 av_read_frame() 读出来的 AVPacket 的最大 pts ,不一定是最后一帧的 pts,因为命令行参数通过 -t 选项,指定只处理多久的时长。

19, int64_t cfr_next_pts,给 -r 选项用的。

20, int64_t nb_samples,记录的是最近一次解码出来的 AVFrame 里面的 nb_samples。用途我也不清楚,后面补充。

21, double ts_scale,默认值是 1.0,可通过命令行选项 -itsscale 进行改变,主要作用是将 pts ,dts 进行放大,放大的方法是乘以 ts_scale

22, int saw_first_ts,标记是不是已经读取到属于该流的第一个 AVPacket

23, AVDictionary *decoder_opts,从 OptionsContext 里面转移过来的解码器参数。

24, AVRational framerate,命令行选项 -r 的值。

25, int top_field_first,命令行选项 -top 的值,好像是给隔行扫描视频用的。

26, int guess_layout_max,命令行选项 -guess_layout_max 的值,猜测的最大的声道布局。

27, int autorotate,命令行选项 -autorotate 的值,是否插入纠正旋转的 filter 滤镜,有些视频的画面中途会上下旋转,设置这个选项可以自动纠正旋转,不会上下颠倒。

28, int dr1,用 Find Useage 找不到使用这个字段的代码,所以是没用的字段。

29, InputFilter **filters 跟 int nb_filters,输入流绑定的 入口滤镜,可以是绑定多个入口滤镜的,输入流解码出来的 AVFrame 会往多个入口滤镜发送。

30, int reinit_filters,命令行选项 -reinit_filter 的值,0 代表输入信息如果产生变化也不重新初始化 FilterGraph,输入信息产生变化是指 解码出来的 AVFrame 的宽高中途变大或者变小之类的。reinit_filters 默认是 -1,就是会重新初始化 FilterGraph

下面这些都是统计相关的字段。

31, uint64_t data_size,从 av_read_frame() 读出来的 AVPacket 的 size 的总和。也就是统计当前流一共读出出来了多少字节的数据。

32, uint64_t nb_packets,从 av_read_frame() 读出来的 AVPacket 数量的总和。

33, uint64_t frames_decodeduint64_t samples_decoded,从解码器解码出来的 AVFrame 的数量。

34, int64_t *dts_bufferint nb_dts_buffer,我没看懂这两个字段干什么的,可能是旧代码没有删除。

35, int got_output,只要解码器已经解码出一帧 AVFrame,这个字段就会置为 1。

以上就是InputStream数据结构示例解析的详细内容,更多关于InputStream 数据结构的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter使用 input chip 标签组件示例详解

    目录 前言 正文 类构造 属性 如何在 Dart 文件中实现代码 全部代码 结论 前言 这里有一些拥有属性的 chip,其中之一就是 input chip.input chip 通常用于以保守的结构处理客户端输入或向客户端提供想法.除了 label 和 avtar 之外,input chip 还可以有一个删除图标.在 Flutter 中,您可以利用 InputChip widget 制作这种 chip. InputChip 是一个 material widget ,它以保守的结构处理令人难以置信

  • Input系统之InputReader处理合成事件详解

    目录 正文 生成合成事件 加载并解析输入设备的配置 InputReader 处理合成事件 创建与配置 InputDevice 配置基本参数 配置坐标系 配置 Surface 小结 正文 Input系统: InputReader 概要性分析 把 InputReader 的事件分为了两类,一类是合成事件,例如设备的增.删事件,另一类是元输入事件,也就是操作设备产生的事件,例如手指在触摸屏上滑动. 本文承接前文,以设备的扫描过程为例,分析合成事件的产生与处理过程.虽然设备的扫描过程只会生成部分合成事件

  • Android开发InputManagerService创建与启动流程

    目录 前言 启动流程 创建输入系统 启动输入系统 输入系统就绪 结束 前言 之前写过几篇关于输入系统的文章,但是还没有写完,后来由于工作的变动,这个事情就一直耽搁了.而现在,在工作中,遇到输入系统相关的事情也越来越多,其中有一个非常有意思的需求,因此是时候继续分析 InputManagerService. InputManagerService 系统文章,基于 Android 12 进行分析. 本文将以 IMS 简称 InputManagerService. 启动流程 InputManagerS

  • Input系统之InputReader概要性实例分析

    目录 InputReader 的创建 EventHub 创建过程如下 InputReader 的运行 EventHub 提供事件 InputReader 的创建 从 InputManagerService: 创建与启动 可知,Input 系统的主要功能,主要集中在 native 层,并且Input 系统的 native 层又包含 InputReader, InputClassifer, InputDispatcher 三个子模块.本文来分析 InputReader 从创建到启动的基本流程,为后续

  • 可定制react18 input otp 一次性密码输入组件

    目录 正文 主要特点 基本用法 1.安装和导入 2.将OtpInput组件添加到应用程序中 3.所有默认的道具 预览 正文 一个完全可定制的.用于React驱动的应用程序的一次性密码(OTP).电话号码和pin码输入组件. 主要特点 它在React和ionic应用程序上都很好用.在手机上也能正常工作. 你可以用inputNum道具只指定数字输入. 在网页和手机上与剪贴板粘贴功能完美配合. npm上唯一支持'enter'键提交的OTP输入包. 在Android上没有OTP粘贴问题. 在iOS ch

  • Input系统之InputReader处理按键事件详解

    目录 前言 认识按键事件 处理按键事件 扫描码映射按键码 结束 前言 前面几篇文章已经为 Input 系统的分析打好了基础,现在是时候进行更深入的分析了. 通常,手机是不带键盘的,但是手机上仍然有按键,就是我们经常使用的电源键以及音量键.因此还是有必要分析按键事件的处理流程. 那么,掌握按键事件的处理流程,对我们有什么用处呢?例如,手机上添加了一个功能按键,你知道如何把这个物理按键映射到上层,然后处理这个按键吗?又例如,如果设备是不需要电源键,但是系统默认把某一个按键映射为电源键,那么我们如何使

  • 基于JavaScript的数据结构队列动画实现示例解析

    ###一 摘要 今天给大家介绍一个基于数据结构中的队列的一个动画,在实现这个动画之前呢,还是给大家讲讲,在JavaScript中我们如何实现一个队列. ###二 队列 队列是一种列表,不同的是队列只能在末尾插入元素,在队首删除元素.队列用于存储按顺序排列的数据.先进先出.这点和栈不一样,在栈中,最后入栈的元素反被优先处理.可以将队列想象成银行排队办理业务的人,排队在第一个的人先办理业务,其它人只能排着,直到轮到他们为止. 队列是一种先进先出(FIFO)的数据结构.队列被用在很多地方.比如提交操作

  • java eclipse 中文件的上传和下载示例解析

    文件的上传与下载(一) 在实现文件上传和下载之前我们需要做一些准备工作,在Apache官网去下载文件上传下载的两个组件,下载链接这里给出:common-fileupload组件下载:http://commons.apache.org/proper/commons-fileupload/ common-io组件下载:http://commons.apache.org/proper/commons-io/根据自己需求下载对应版本 一.创建工程 将所需要的两个开发包导入到工程项目中如图: 二.代码编写

  • java爬取豆瓣电影示例解析

    为什么我们要爬取数据 在大数据时代,我们要获取更多数据,就要进行数据的挖掘.分析.筛选,比如当我们做一个项目的时候,需要大量真实的数据的时候,就需要去某些网站进行爬取,有些网站的数据爬取后保存到数据库还不能够直接使用,需要进行清洗.过滤后才能使用,我们知道有些数据是非常真贵的. 分析豆瓣电影网站 我们使用Chrome浏览器去访问豆瓣的网站如 https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=re

  • react fiber执行原理示例解析

    目录 为什么要使用fiber,要解决什么问题? fiber是什么? 数据结构 执行单元 浏览器工作: Fiber执行原理 workInProgress tree: currentFiber tree: Effects list: render阶段: 遍历节点过程: 收集effect list: commit阶段: 为什么commit必须是同步的操作的? 为什么要使用fiber,要解决什么问题? 在 react16 引入 Fiber 架构之前,react 会采用递归方法对比两颗虚拟DOM树,找出需

  • Nest 复杂查询示例解析

    目录 Nest 复杂查询 QueryUserDto是查询参数类型 UserService如何实现 Nest 复杂查询 复杂查询包括分页.模糊查询.多条件筛选.排序等,满足前端对查询的所有诉求. Nest 复杂查询,主要使用 repository.findAndCount()方法实现. 假设有一个能分页查询所有用户,可根据用户名进行筛选,并对结果按照更新时间倒序排序的需求,它的 controller 如下: @Post() @Roles(Role.Admin, Role.SuperAdmin) a

  • Mybatis TypeHandler接口及继承关系示例解析

    目录 开篇 TypeHandler接口 TypeHandler继承体系 IntegerTypeHandler DateTypeHandler TypeHandlerRegistry TypeHandlerRegistry#register方法 总结 开篇 JDBC类型与Java类型并不是完全一一对应的.所以在PreparedStatement绑定参数的时候需要把Java类型转为JDBC类型.JDBC类型的枚举值在JdbcType枚举值中存储. MyBatis中提供了一个接口专用于JDBC类型与J

  • OpenMP task construct 实现原理及源码示例解析

    目录 前言 从编译器角度看 task construct Task Construct 源码分析 总结 前言 在本篇文章当中主要给大家介绍在 OpenMP 当中 task 的实现原理,以及他调用的相关的库函数的具体实现. 在本篇文章当中最重要的就是理解整个 OpenMP 的运行机制. 从编译器角度看 task construct 在本小节当中主要给大家分析一下编译器将 openmp 的 task construct 编译成什么样子,下面是一个 OpenMP 的 task 程序例子: #inclu

  • PHP常用算法和数据结构示例(必看篇)

    实例如下: </pre><pre name="code" class="php"><?php /** * Created by PhpStorm. * User: qishou * Date: 15-8-2 * Time: 上午9:12 */ header("content-type:text/html;charset=utf-8"); $arr = array(3,5,8,4,9,6,1,7,2); echo im

  • Java正则表达式的语法及示例解析

    1匹配验证-验证Email是否正确 Java | 复制 public static void main(String[] args) { // 要验证的字符串 String str = "service@xsoftlab.net"; // 邮箱验证规则 String regEx = "[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\\.){1,3}[a-zA-z\\-]{1,}"; // 编译正则表达式 Pattern pat

  • Oracle PL/SQL中异常高级特性示例解析

    PL/SQL(Procedural Language/SQL,过程语言/SQL)是结合了Oracel过程语言和结构化查询语言(SQL)的一种扩展语言. 优点: (1)PL/SQL具有编程语言的特点,它能把一组SQL语句放到一个模块中,使其更具模块化种序的特点. (2)PL/SQL可以采用过程性语言控制程序的结构. (3)PL/SQL有自动处理的异常处理机制. (4)PL/SQL程序块具有更好的可移植性,可移植到另一个Oracle数据库中. (5)PL/SQL程序减少了网络的交互,有助于提高程序性

随机推荐