ffmpeg-ffplay代码架构简述

全局变量

/* Minimum SDL audio buffer size, in samples. */

// 最小音频缓冲

#define SDL_AUDIO_MIN_BUFFER_SIZE 512

/* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */

// 计算实际音频缓冲大小,并不需要太频繁回调,这里设置的是最大音频回调次数是每秒30

#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30/* Step size for volume control in dB */

// 音频控制 db为单位的步进

#define SDL_VOLUME_STEP (0.75)/* no AV sync correction is done if below the minimum AV sync threshold */

// 最低同步阈值,如果低于该值,则不需要同步校正

#define AV_SYNC_THRESHOLD_MIN 0.04

/* AV sync correction is done if above the maximum AV sync threshold */

// 最大同步阈值,如果大于该值,则需要同步校正

#define AV_SYNC_THRESHOLD_MAX 0.1

/* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */

// 帧补偿同步阈值,如果帧持续时间比这更长,则不用来补偿同步

#define AV_SYNC_FRAMEDUP_THRESHOLD 0.1

/* no AV correction is done if too big error */

// 同步阈值。如果误差太大,则不进行校正

#define AV_NOSYNC_THRESHOLD 10.0/* maximum audio speed change to get correct sync */

// 正确同步的最大音频速度变化值(百分比)

#define SAMPLE_CORRECTION_PERCENT_MAX 10/* external clock speed adjustment constants for realtime sources based on buffer fullness */

// 根据实时码流的缓冲区填充时间做外部时钟调整

// 最小值

#define EXTERNAL_CLOCK_SPEED_MIN  0.900

// 最大值

#define EXTERNAL_CLOCK_SPEED_MAX  1.010

// 步进

#define EXTERNAL_CLOCK_SPEED_STEP 0.001/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */

// 使用差值来实现平均值

#define AUDIO_DIFF_AVG_NB   20/* polls for possible required screen refresh at least this often, should be less than 1/fps */

// 刷新频率 应该小于 1/fps

#define REFRESH_RATE 0.01/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */

/* TODO: We assume that a decoded and resampled frame fits into this buffer */

// 采样大小

#define SAMPLE_ARRAY_SIZE (8 * 65536)#define CURSOR_HIDE_DELAY 1000000#define USE_ONEPASS_SUBTITLE_RENDER 1// 冲采样标志

static unsigned sws_flags = SWS_BICUBIC;// 包列表结构

typedef struct MyAVPacketList {AVPacket pkt;struct MyAVPacketList *next;int serial;

} MyAVPacketList;// 待解码包队列

typedef struct PacketQueue {MyAVPacketList *first_pkt, *last_pkt;int nb_packets;int size;int64_t duration;int abort_request;int serial;SDL_mutex *mutex;SDL_cond *cond;

} PacketQueue;#define VIDEO_PICTURE_QUEUE_SIZE 3

#define SUBPICTURE_QUEUE_SIZE 16

#define SAMPLE_QUEUE_SIZE 9

#define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))// 音频参数

typedef struct AudioParams {int freq;                                   // 频率int channels;                               // 声道数int64_t channel_layout;             // 声道设计,单声道,双声道还是立体声enum AVSampleFormat fmt;        // 采样格式int frame_size;                         //  采样大小int bytes_per_sec;                      // 每秒多少字节

} AudioParams;// 时钟

typedef struct Clock {double pts;                 // 时钟基准 /* clock base */double pts_drift;           // 更新时钟的差值 /* clock base minus time at which we updated the clock */double last_updated;        // 上一次更新的时间double speed;               // 速度int serial;                     // 时钟基于使用该序列的包 /* clock is based on a packet with this serial */int paused;                 // 停止标志int *queue_serial;          // 指向当前数据包队列序列的指针,用于过时的时钟检测 /* pointer to the current packet queue serial, used for obsolete clock detection */

} Clock;/* Common struct for handling all types of decoded data and allocated render buffers. */

// 解码帧结构

typedef struct Frame {AVFrame *frame;     // 帧数据AVSubtitle sub;         // 字幕int serial;                 // 序列double pts;             // 帧的显示时间戳 /* presentation timestamp for the frame */double duration;        // 帧显示时长 /* estimated duration of the frame */int64_t pos;                // 文件中的位置 /* byte position of the frame in the input file */int width;                  // 帧的宽度int height;                 // 帧的高度int format;             // 格式AVRational sar;         // 额外参数int uploaded;           // 上载int flip_v;                 // 反转

} Frame;// 解码后的帧队列

typedef struct FrameQueue {Frame queue[FRAME_QUEUE_SIZE];  // 队列数组int rindex;                                         // 读索引int windex;                                     // 写索引int size;                                               // 大小int max_size;                                       // 最大大小int keep_last;                                      // 保持上一个int rindex_shown;                               // 读显示SDL_mutex *mutex;                           // 互斥变量SDL_cond *cond;                             // 条件变量PacketQueue *pktq;

} FrameQueue;// 时钟同步类型

enum {AV_SYNC_AUDIO_MASTER,       // 音频作为同步,默认以音频同步 /* default choice */AV_SYNC_VIDEO_MASTER,       // 视频作为同步AV_SYNC_EXTERNAL_CLOCK, // 外部时钟作为同步 /* synchronize to an external clock */

};// 解码器结构

typedef struct Decoder {AVPacket pkt;                               // AVPacket pkt_temp;                      // 中间包PacketQueue *queue;                 // 包队列AVCodecContext *avctx;              // 解码上下文int pkt_serial;                             // 包序列int finished;                                   // 是否已经结束int packet_pending;                     // 是否有包在等待SDL_cond *empty_queue_cond;     // 空队列条件变量int64_t start_pts;                          // 开始的时间戳AVRational start_pts_tb;                // 开始的额外参数int64_t next_pts;                           // 下一帧时间戳AVRational next_pts_tb;                 // 下一帧的额外参数SDL_Thread *decoder_tid;                // 解码线程

} Decoder;// 视频状态结构

typedef struct VideoState {SDL_Thread *read_tid;                   // 读取线程AVInputFormat *iformat;             // 输入格式int abort_request;                                终止int force_refresh;                            强制刷新int paused;                                 // 停止int last_paused;                                // 最后停止int queue_attachments_req;          // 队列附件请求int seek_req;                                   // 查找请求int seek_flags;                             // 查找标志int64_t seek_pos;                           // 查找位置int64_t seek_rel;                           // int read_pause_return;                  // 读停止返回AVFormatContext *ic;                    // 解码格式上下文int realtime;                                   // 是否实时码流Clock audclk;                               // 音频时钟Clock vidclk;                                   // 视频时钟Clock extclk;                                   // 外部时钟FrameQueue pictq;                       // 视频队列FrameQueue subpq;                       // 字幕队列FrameQueue sampq;                       // 音频队列Decoder auddec;                         // 音频解码器Decoder viddec;                         // 视频解码器Decoder subdec;                         // 字幕解码器int audio_stream;                           // 音频码流Idint av_sync_type;                           // 同步类型double audio_clock;                     // 音频时钟int audio_clock_serial;                 // 音频时钟序列double audio_diff_cum;                  // 用于音频差分计算 /* used for AV difference average computation */double audio_diff_avg_coef;         //  double audio_diff_threshold;            // 音频差分阈值int audio_diff_avg_count;               // 平均差分数量AVStream *audio_st;                     // 音频码流PacketQueue audioq;                 // 音频包队列int audio_hw_buf_size;                  // 硬件缓冲大小uint8_t *audio_buf;                     // 音频缓冲区uint8_t *audio_buf1;                        // 音频缓冲区1unsigned int audio_buf_size;            // 音频缓冲大小 /* in bytes */unsigned int audio_buf1_size;       // 音频缓冲大小1int audio_buf_index;                        // 音频缓冲索引 /* in bytes */int audio_write_buf_size;               // 音频写入缓冲大小int audio_volume;                           // 音量int muted;                                      // 是否静音struct AudioParams audio_src;       // 音频参数

#if CONFIG_AVFILTER                         struct AudioParams audio_filter_src; // 音频过滤器

#endifstruct AudioParams audio_tgt;       // 音频参数struct SwrContext *swr_ctx;         // 音频转码上下文int frame_drops_early;                  // int frame_drops_late;                       // enum ShowMode {                     // 显示类型SHOW_MODE_NONE = -1,        // 无显示SHOW_MODE_VIDEO = 0,            // 显示视频SHOW_MODE_WAVES,                // 显示波浪,音频SHOW_MODE_RDFT,                 // 自适应滤波器SHOW_MODE_NB                        // } show_mode;int16_t sample_array[SAMPLE_ARRAY_SIZE]; // 采样数组int sample_array_index;                 // 采样索引int last_i_start;                               // 上一开始RDFTContext *rdft;                      // 自适应滤波器上下文int rdft_bits;                                  // 自使用比特率FFTSample *rdft_data;                   // 快速傅里叶采样int xpos;                                       // double last_vis_time;                       // SDL_Texture *vis_texture;               // 音频TextureSDL_Texture *sub_texture;               // 字幕TextureSDL_Texture *vid_texture;               // 视频Textureint subtitle_stream;                        // 字幕码流IdAVStream *subtitle_st;                  // 字幕码流PacketQueue subtitleq;                  // 字幕包队列double frame_timer;                     // 帧计时器double frame_last_returned_time;    // 上一次返回时间double frame_last_filter_delay;     // 上一个过滤器延时int video_stream;                           // 视频码流IdAVStream *video_st;                     // 视频码流PacketQueue videoq;                 // 视频包队列double max_frame_duration;          // 最大帧显示时间 // maximum duration of a frame - above this, we consider the jump a timestamp discontinuitystruct SwsContext *img_convert_ctx; // 视频转码上下文struct SwsContext *sub_convert_ctx; // 字幕转码上下文int eof;                                            // 结束标志char *filename;                             // 文件名int width, height, xleft, ytop;         // 宽高,其实坐标int step;                                       // 步进#if CONFIG_AVFILTERint vfilter_idx;                                // 过滤器索引AVFilterContext *in_video_filter;   // 第一个视频滤镜 // the first filter in the video chainAVFilterContext *out_video_filter;  // 最后一个视频滤镜 // the last filter in the video chainAVFilterContext *in_audio_filter;   // 第一个音频过滤器 // the first filter in the audio chainAVFilterContext *out_audio_filter;  // 最后一个音频过滤器 // the last filter in the audio chainAVFilterGraph *agraph;                  // 音频过滤器 // audio filter graph

#endif// 上一个视频码流Id、上一个音频码流Id、上一个字幕码流Idint last_video_stream, last_audio_stream, last_subtitle_stream;SDL_cond *continue_read_thread; // 连续读线程

} VideoState;/* options specified by the user */

static AVInputFormat *file_iformat; // 文件输入格式

static const char *input_filename;      // 输入文件名

static const char *window_title;            // 标题

static int default_width  = 640;            // 默认宽度

static int default_height = 480;            // 默认高度

static int screen_width  = 0;               // 屏幕宽度

static int screen_height = 0;               // 屏幕高度

static int audio_disable;                       // 是否禁止播放声音

static int video_disable;                       // 是否禁止播放视频

static int subtitle_disable;                    // 是否禁止播放字幕

static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};

static int seek_by_bytes = -1;              //

static int display_disable;                 // 显示禁止

static int borderless;                          //

static int startup_volume = 100;        // 起始音量

static int show_status = 1;                 // 显示状态

static int av_sync_type = AV_SYNC_AUDIO_MASTER; // 同步类型

static int64_t start_time = AV_NOPTS_VALUE;         // 开始时间

static int64_t duration = AV_NOPTS_VALUE;               // 间隔

static int fast = 0;                                // 快速

static int genpts = 0;                          //

static int lowres = 0;                          // 慢速

static int decoder_reorder_pts = -1;    // 解码器重新排列时间戳

static int autoexit;                                // 否自动退出

static int exit_on_keydown;             // 是否按下退出

static int exit_on_mousedown;           // 是否鼠标按下退出

static int loop = 1;                                // 循环

static int framedrop = -1;                  // 舍弃帧

static int infinite_buffer = -1;                // 缓冲区大小限制   =1表示不限制(is->realtime实时传输时不限制

static enum ShowMode show_mode = SHOW_MODE_NONE; // 显示类型

static const char *audio_codec_name;    // 音频解码器名称

static const char *subtitle_codec_name; // 字幕解码器名称

static const char *video_codec_name;    // 视频解码器名称

double rdftspeed = 0.02;                        // 自适应滤波器的速度

static int64_t cursor_last_shown;           // 上一次显示光标

static int cursor_hidden = 0;                   // 光标隐藏

#if CONFIG_AVFILTER

static const char **vfilters_list = NULL;   // 视频滤镜

static int nb_vfilters = 0;                     // 视频滤镜数量

static char *afilters = NULL;                   // 音频滤镜

#endif

static int autorotate = 1;                      // 是否自动旋转/* current context */

static int is_full_screen;                          // 是否全屏

static int64_t audio_callback_time;         // 音频回调时间static AVPacket flush_pkt;                      // 刷新的包#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)static SDL_Window *window;              // 窗口

static SDL_Renderer *renderer;              // 渲染器

设计的流程

包含文件读取、解封装、解码、音视频输出、音视频同步,流程如下图所示:

在这里插入图片描述

ffplay中使用的线程

(1)读线程。读取文件、解封装

(2)音频解码线程。解码音频压缩数据为PCM数据。
(3)视频解码线程。解码视频压缩数据为图像数据。

(4)音频输出线程。基于SDL播放,该线程实际上是SDL的内部线程。
(5)视频输出线程。基于SDL播放,该线程为程序主线程。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/24949.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈React中的ref和useRef

目录 什么是useRef? 使用 ref 访问 DOM 元素 Ref和useRef之间的区别 Ref和useRef的使用案例 善用工具 结论 在各种 JavaScript 库和框架中,React 因其开发人员友好性和支持性而得到认可。 大多数开发人员发现 React 非常舒适且可扩展,…

51单片机(普中HC6800-EM3 V3.0)实验例程软件分析 实验三 LED流水灯

目录 前言 一、原理图及知识点介绍 二、代码分析 知识点五:#include 中的库函数解析 _crol_,_irol_,_lrol_ _cror_,_iror_,_lror_ _nop_ _testbit_ 前言 第一个实验:51单片机(普中HC6800-EM3 V3.0…

深度学习——注意力机制、自注意力机制

什么是注意力机制? 1.注意力机制的概念: 我们在听到一句话的时候,会不自觉的捕获关键信息,这种能力叫做注意力。 比如:“我吃了100个包子” 有的人会注意“我”,有的人会注意“100个”。 那么对于机器来说…

Docker Compose构建lnmp

目录 Compose的优点 编排和部署 Compose原理 Compose应用案例 安装docker-ce 阿里云镜像加速器 安装docker-compose docker-compose用法 Yaml简介 验证LNMP环境 Compose的优点 先来了解一下我们平时是怎么样使用docker的?把它进行拆分一下: 1…

BS框架说明

B/S架构 1.B/S框架,意思是前端(Browser 浏览器,小程序、app、自己写的)和服务器端(Server)组成的系统的框架结构 2.B/S框架,也可理解为web架构,包含前端、后端、数据库三大组成部分…

[深度学习] GPU处理能力(TFLOPS/TOPS)

计算能力换算 理论峰值 = GPU芯片数量GPU Boost主频核心数量*单个时钟周期内能处理的浮点计算次数 只不过在GPU里单精度和双精度的浮点计算能力需要分开计算,以最新的Tesla P100为例: 双精度理论峰值 = FP64 Cores *…

RK3588平台开发系列讲解(文件系统篇)什么是 VFS

文章目录 一、什么是 VFS二、VFS 数据结构2.1、超级块结构2.2、目录结构2.3、文件索引结点2.4、打开的文件2.5、四大对象结构的关系沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 今天我们一起来瞧一瞧 Linux 是如何管理文件,也验证一下 Linux 那句口号:一切皆为文…

【枚举,构造】CF1582 C D

Problem - C - Codeforces 题意: 思路: 思路很简单,只删除一种,直接枚举删除的是哪一种即可 但是回文子序列的判定我vp的时候写的很答辩,也不知道为什么当时要从中间往两边扫,纯纯自找麻烦 然后就越改越…

软件架构师高级——3、数据库系统

• 数据库概述(★★★) 集中式数据库系统 •数据管理是集中的 •数据库系统的素有功能 (从形式的用户接口到DBMS核心) 者口集中在DBMS所在的计算机。 B/S结构 •客户端负责数据表示服务 •服务器主要负责数据库服务 •数据 和后端…

【Linux】【预】配置虚拟机的桥接网卡+nfs

【Linux】【预】配置虚拟机的桥接网卡 1. 配置VM虚拟机的桥接网络2 配置Win10中的设置3.配置Linux中的IP4. 串口连接开发板,配置nfs5 修改网络文件6 验证nfs 是否成功总结 1. 配置VM虚拟机的桥接网络 右击设置,选择添加网络,按照如下顺序操作…

MySQL语句性能分析与优化

目录 SQL性能分析 SQL执行频率 SQL慢查询日志 Profile Explain SQL优化 插入数据的优化 主键优化 Order By优化 Group By优化 Limit 优化 Count 优化 Update 优化 多表连接查询优化 SQL性能分析 通过SQL性能分析来做SQL的优化,主要是优化SQL的查询语…

Springboot+Easyexcel将数据写入模板文件并导出Excel

SpringbootEasyexcel将数据写入模板文件并导出Excel 一、导入依赖二、根据excel表头创建对应的实体类Pojo三、Controller类接收请求四、Service层获取待写入数据五、效果展示六、总结 一、导入依赖 <!--操作excel工具包--> <dependency><groupId>com.alibab…

[Flask]SSTI1

根据题目提示&#xff0c;这关应该是基于Python flask的模版注入&#xff0c;进入靶场环境后就是一段字符串&#xff0c;而且没有任何提示&#xff0c;有点难受&#xff0c;主要是没有提示注入点 随机尝试一下咯&#xff0c;首先尝试一下guest&#xff0c;GET传参 但是没有反应…

离散Hopfield神经网络的联想记忆与matlab实现

1案例背景 1.1离散Hopfield神经网络概述 Hopfield网络作为一种全连接型的神经网络,曾经为人工神经网络的发展开辟了新的研究途径。它利用与阶层型神经网络不同的结构特征和学习方法,模拟生物神经网络的记忆机理,获得了令人满意的结果。这一网络及学习算法最初是由美国物理学家…

react中hooks的理解与使用

一、作用 我们知道react组件有两种写法一种是类组件&#xff0c;另一种是函数组件。而函数组件是无状态组件&#xff0c;如果我们要想改变组件中的状态就无法实现了。为此&#xff0c;在react16.8版本后官方推出hooks&#xff0c;用于函数组件更改状态。 二、常用API 1、use…

【css】css隐藏元素

display:none&#xff1a;可以隐藏元素。该元素将被隐藏&#xff0c;并且页面将显示为好像该元素不在其中。visibility:hidden&#xff1a; 可以隐藏元素。但是&#xff0c;该元素仍将占用与之前相同的空间。元素将被隐藏&#xff0c;但仍会影响布局。 代码&#xff1a; <!…

go编译文件

1.编译go文件 go build [go文件]2.执行文件编译文件 ./demo [demo为go文件名称]

当服务器域名出现解析错误的问题该怎么办?

​  域名解析是互联网用户接收他们正在寻找的域的地址的过程。更准确地说&#xff0c;域名解析是人们在浏览器中输入时使用的域名与网站IP地址之间的转换过程。您需要站点的 IP 地址才能知道它所在的位置并加载它。但&#xff0c;在这个过程中&#xff0c;可能会出现多种因素…

web服务

静态网页与动态网页的区别 在网站设计中&#xff0c;静态网页是网站建设的基础&#xff0c;纯粹 HTML 格式的网页通常被称为“静态网页”&#xff0c;静态网页是标准的 HTML 文件&#xff0c;它的文件扩展名是 .htm、.html&#xff0c;可以包含文本、图像、声音、FLASH 动画、…

MySQL(1)

MySQL创建数据库和创建数据表 创建数据库 1. 连接 MySQL mysql -u root -p 2. 查看当前的数据库 show databases; 3. 创建数据库 create database 数据库名; 创建数据库 4. 创建数据库时设置字符编码 create database 数据库名 character set utf8; 5. 查看和显示…