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.rhkb.cn/news/77962.html

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

相关文章

ELK日志分析系统

文章目录 一. ELK日志分析系统概述1.ELK 简介2.ELK日志分析系统2.1 ElasticSearch2.1.1 ElasticSearch概述2.1.2 ElasticSearch核心概念(作用) 2.2 Kiabana2.2.1 Kiabana 概念2.2.2 Kiabana 主要功能 2.3 Logstash2.3.1 Logstash 概念2.3.2 Logstash主要…

侧边栏的打开与收起

侧边栏的打开与收起 <template><div class"box"><div class"sideBar" :class"showBox ? : controller-box-hide"><div class"showBnt" click"showBox!showBox"><i class"el-icon-arrow-r…

【爬虫实践】使用Python从网站抓取数据

一、说明 本周我不得不为客户抓取一个网站。我意识到我做得如此自然和迅速&#xff0c;分享它会很有用&#xff0c;这样你也可以掌握这门艺术。【免责声明&#xff1a;本文展示了我的抓取做法&#xff0c;如果您有更多相关做法请在评论中分享】 二、计划策略 2.1 策划 确定您…

python3学习--使用pandas 数据透视表分析数据--入门示例

什么是透视表&#xff1f; 透视表是一种可以对数据动态排布并且分类汇总的表格格式&#xff0c;可以以多种方式和视角查看数据特征 Pandas库提供了一个名为pivot_table的函数&#xff0c;它将一个特性的值汇总在一个整洁的二维表中。 使用示例 pivot_table函数说明 pandas.…

基于STM32设计的自动刹车灯

一、项目介绍 随着科技的发展&#xff0c;人们对低碳环保的认知和需求不断提高。骑自行车既能够低碳环保&#xff0c;又能够锻炼身体&#xff0c;成为了很多人出行的首选。然而&#xff0c;由于自行车本身没有带指示灯&#xff0c;比如刹车指示灯等&#xff0c;所以自行车的安…

Scala编程语言入门教程

Scala教程 方便个人学习和查阅 学习目标 Scala介绍 简介 Scala创始人Martin Odersky马丁奥德斯基 再回到我们的scala语言&#xff0c;在Scala官网https://www.scala-lang.org/介绍了其六大特征。 Java和scala可以混编 类型推测(自动推测类型) 并发和分布式&#xff08;Ac…

AcWing 4310:树的DFS ← vector、auto、邻接表

【题目来源】https://www.acwing.com/problem/content/description/4313/【题目描述】 给定一棵 n 个节点的树。 节点的编号为 1∼n&#xff0c;其中 1 号节点为根节点&#xff0c;每个节点的编号都大于其父节点的编号。 现在&#xff0c;你需要回答 q 个询问。 每个询问给定两…

RabbitMQ(二)

二、高级特性、应用问题以及集群搭建 高级特性 1.消息的可靠性投递 在使用RabbitMQ的时候&#xff0c;作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。 rabbitMQ整个消息投递的路径为&#xff1a; produ…

springCache-缓存

SpringCache 简介&#xff1a;是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;底层可以切换不同的cache的实现&#xff0c;具体是通过CacheManager接口实现 使用springcache,根据实现的缓存技术&#xff0c;如使用的redis,需要导入redis的依赖包 基于map缓存 …

简述静态网页和动态网页的区别。简述 Webl.0 和 Web2.0 的区别。安装tomcat8,配置服务启动脚本,部署jpress应用

静态网页和动态网页区别 静态网页和动态网页是两种常见的网页类型&#xff0c;它们在内容生成和交互方式上存在不同。 静态网页是在服务器上提前生成好的网页&#xff0c;它的内容在访问时不会发生变化。静态网页通常由HTML、CSS和JavaScript等静态文件组成&#xff0c;这些文…

无涯教程-Perl - bless函数

描述 此函数告诉REF引用的实体,它现在是CLASSNAME包中的对象,如果省略CLASSNAME,则为当前包中的对象。建议使用bless的两个参数形式。 语法 以下是此函数的简单语法- bless REF, CLASSNAMEbless REF返回值 该函数返回对祝福到CLASSNAME中的对象的引用。 例 以下是显示其…

Python web实战之 Django 的模板语言详解

关键词&#xff1a; Python、web开发、Django、模板语言 概要 作为 Python Web 开发的框架之一&#xff0c;Django 提供了一套完整的 MVC 模式&#xff0c;其中的模板语言为开发者提供了强大的渲染和控制前端的能力。本文介绍 Django 的模板语言。 1. Django 模板语言入门 Dj…

【Android】控件与布局入门 - 简易计算器

目录 1. 基础开发环境 2. 计算器的布局和相关按钮 3. 计算器的主要运算逻辑 4. APK 文件 5. 项目源码 1. 基础开发环境 JDK&#xff1a;JDK17 Android Studio&#xff1a;Android Studio Giraffe | 2022.3.1 Android SDK&#xff1a;Android API 34 Gradle: gradle-8.0-bi…

【Nginx基础】Nginx基础及安装

目录 Nginx出现背景Nginx 概念Nginx 作用Http 代理&#xff0c;反向代理负载均衡&#xff1a;内置策略和扩展策略内置策略&#xff1a;轮询内置策略&#xff1a;加权轮询内置策略&#xff1a;IP hash 动静分离 安装 NginxWindows下安装&#xff08;nginx-1.16.1&#xff09;Lin…

计算机毕设 深度学习实现行人重识别 - python opencv yolo Reid

文章目录 0 前言1 课题背景2 效果展示3 行人检测4 行人重识别5 其他工具6 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉…

EtherCAT转Profinet网关连接西门子PLC与凯福科技总线步进驱动器通讯

西门子S7-1200/1500系列的PLC&#xff0c;采用Profinet实时以太网通讯协议&#xff0c;需要连接带EtherCAT的通讯功能的伺服驱动器等设备&#xff0c;就必须进行通讯协议转换。捷米特JM-EIP-RTU系列的网关提供了&#xff0c;快速可行的解决方案 捷米特JM-ECTM-PN在PROFINET一侧…

Linux下进程的特点与环境变量

目录 进程的特点 进程特点的介绍 进程时如何实现并发性的 进程间如何切换 概念铺设 PC指针 上下文 环境变量 PATH 修改PATH HOME SHELL env 命令行参数 什么是命令行参数&#xff1f; 打印命令行参数 通过函数获得环境变量 getenv 命令行参数 env 修改环境变…

Linux从安装到实战 常用命令 Bash常用功能 用户和组管理

1.0初识Linux 1.1虚拟机介绍 1.2VMware Workstation虚拟化软件 下载CentOS; 1.3远程链接Linux系统 &FinalShell 链接finalshell半天没连接进去 他说ip adress 看IP地址是在虚拟机上 win11主机是 终端输入&#xff1a; ifconfig VMware虚拟机的设置 & ssh连接_snge…

[Pytorch]卷积运算conv2d

文章目录 [Pytorch]卷积运算conv2d一.F.Conv2d二.nn.Conv2d三.nn.Conv2d的运算过程 [Pytorch]卷积运算conv2d 一.F.Conv2d torch.nn.functional.Conv2d()的详细参数&#xff1a; conv2d(input: Tensor, weight: Tensor, bias: Optional[Tensor]None, stride: Union[_int, _s…

如何在 Android 上恢复已删除的视频|快速找回丢失的记忆

想知道是否有任何成功的方法可以从 Android 手机中检索已删除的视频&#xff1f;好吧&#xff0c;本指南将向您展示分步说明&#xff0c;让您轻松从手机中找回丢失的视频文件&#xff01; 您是否不小心从 Android 智能手机中删除了珍贵的生日视频&#xff1f;难道是无处可寻吗…