InputStream数据结构示例解析
作者:Loken1 发布时间:2022-06-12 20:11:53
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_index
,input_files
数组里面的下标,代表 InputStream
对应的 InputFile
。
2, AVStream *st
,AVFormatContext
里面的 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_decoded
,uint64_t samples_decoded
,从解码器解码出来的 AVFrame
的数量。
34, int64_t *dts_buffer
,int nb_dts_buffer
,我没看懂这两个字段干什么的,可能是旧代码没有删除。
35, int got_output
,只要解码器已经解码出一帧 AVFrame
,这个字段就会置为 1。
来源:https://juejin.cn/post/7159136303391440909
猜你喜欢
- 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很
- 一、SpringMVC使用1.工程创建创建maven工程。添加java、resources目录。引入Spring-webmvc 依赖。<
- 基础铺垫在java中,关于json的lib有很多,比如jackjson、fastjson、gson等等,本人都用过,但是对于我等只需要让ja
- Java.util.Collections类下有一个静态的shuffle()方法,如下:1)static void shuffle(List
- 前言在手写sql的时候,根据参数处理查询条件.select * from staff where 1 = 1 and staff_id in
- 框架的概述JDBC存在的问题:我们要想研究mybatis就必须知道jdbc所存在的问题,那我那么我们首先来复习一下jdbc操作数据库的大致流
- 一、什么是CharacterEncodingFilter官方解释如下是spring内置过滤器的一种,用来指定请求或者响应的编码格式。在web
- 中断线程线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡、还是等
- Mybatis注解查找@Select( "SELECT * FROM tt_user WHERE username Like #{
- 因为最近用报表导出比较多,所有就提成了一个工具类,本工具类使用的场景为 根据提供的模板来导出Excel报表并且可根据提供的模板S
- 我们写的主类中的main()方法是如何被Java虚拟机调用到的?在Java类中的一些方法会被由C/C++编写的HotSpot虚拟机的C/C+
- 这篇文章主要介绍了spring如何实现两个xml配置文件间的互调,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- Mutex类、Event类、SemaphoreSlim类和ReaderWriterLockSlim类等提供了多个进程之间的线程同步。&nbs
- 一,二分法检索算法介绍二分法检索(binary search)又称折半检索,二分法检索的基本思想是设字典中的元素从小到大有序地存放在数组(a
- 本文实例讲述了C#连接ODBC数据源的方法。分享给大家供大家参考。具体实现方法如下:// Namespaces, variables, an
- kotlin基础教程之类和继承类声明使用class关键字声明类,查看其声明格式:: modifiers ("class"
- idea 很强大,但是初次安装默认的有很多设置并不是满足我们开发的需要。以前经常一安装就要捣鼓很久,为此吐血整理初次安装设置一、切换主题(配
- C#中,有些类型是可以隐式转换的,我整理了这些可以隐式转换的类型,供大家参考 static
- 概述基于java + swing + JFrame 的图书馆管理系统,租车,还车,管理员管理用户,付款等。部分代码public class
- Java中的动态和静态编译实例详解首先,我们来说说动态和静态编译的问题。 Q: java和javascript有什么