音视频同步的关键:深入解析PTS和DTS

在这里插入图片描述

😎 作者介绍:我是程序员行者孙,一个热爱分享技术的制能工人。计算机本硕,人工制能研究生。公众号:AI Sun,视频号:AI-行者Sun
🎈 本文专栏:本文收录于《音视频》系列专栏,相信一份耕耘一份收获,我会分享音视频相关学习内容,不说废话,祝大家都offer拿到手软
🤓 欢迎大家关注其他专栏,我将分享Web前后端开发、人工智能、机器学习、深度学习从0到1系列文章。
🖥随时欢迎您跟我沟通,一起交流,一起成长、进步!

音视频同步的关键:深入解析PTS和DTS

在多媒体播放和处理领域,音视频同步是保证用户体验的关键因素。而在这个过程中,PTS(Presentation Time Stamp)和DTS(Decoding Time Stamp)起着至关重要的作用。本文将深入解析这两个概念,并探讨它们在音视频同步中的作用和联系。

视频的播放过程可以简单理解为一帧一帧的画面按照时间顺序呈现出来的过程,就像在一个本子的每一页画上画,然后快速翻动的感觉。
在这里插入图片描述
但是在实际应用中,并不是每一帧都是完整的画面,因为如果每一帧画面都是完整的图片,那么一个视频的体积就会很大,这样对于网络传输或者视频数据存储来说成本太高,所以通常会对视频流中的一部分画面进行压缩(编码)处理。由于压缩处理的方式不同,视频中的画面帧就分为了不同的类别,其中包括:I 帧、P 帧、B 帧。

具体IPB帧的介绍看这里:深入解析视频编码中的IPB帧

什么是PTS和DTS?

在这里插入图片描述
在这里插入图片描述

PTS(显示时间戳)

PTS是音视频帧应该被显示或播放的时间戳。它确保了在播放过程中,无论是视频帧还是音频帧,都能在正确的时间点呈现给用户,保持音视频的同步性。例如,在视频播放中,PTS会指示每个帧在何时显示,以维持连贯的视觉体验。

DTS(解码时间戳)

DTS是音视频帧应该被解码的时间戳。由于一些编码格式可能会对帧进行重新排序,解码顺序可能与显示顺序不一致。DTS确保解码器能够按照正确的顺序解码帧,特别是在处理需要重新排序的编码格式时,DTS显得尤为重要。

DTS和PTS的区别

概念上的区别

  • DTS:标识帧被解码的时间。
  • PTS:标识帧被显示或播放的时间。

功能上的区别

  • DTS:主要用于解码过程,确保帧按照正确的顺序进行解码。
  • PTS:主要用于播放过程,确保帧在正确的时间点被显示或播放。

应用场景的区别

  • DTS:更多应用于解码器内部,用于管理帧的解码顺序。
  • PTS:更多应用于播放器,用于管理帧的显示和音频的播放时间。

DTS和PTS的联系

尽管DTS和PTS在功能和应用场景上有所区别,但它们共同服务于音视频同步这一目标。解码器使用DTS来决定帧的解码顺序,而播放器使用PTS来决定帧的显示顺序。这种同步工作机制确保了帧在正确的时间点被解码和播放,实现了音视频同步。

音视频同步的实例

以H.264编码格式为例,由于该编码格式支持B帧(双向预测帧),帧的解码顺序可能与播放顺序不一致。例如,假设有以下帧序列:

显示顺序:I B B P
解码顺序:I P B B

在这种情况下,解码器会按照DTS顺序解码帧,但播放器会按照PTS顺序显示帧。这样,即使在解码过程中帧的顺序被打乱,最终在播放时仍然能够保证音视频的同步性。

示例代码

音视频同步是一个复杂的过程,通常涉及到对音频和视频流的解码、时间戳处理以及适当的同步机制。在C++中实现这一功能,我们通常会使用像FFmpeg这样的库来处理媒体数据。以下是一个简化的示例,展示如何使用FFmpeg解码音频和视频流,并尝试进行基本的同步。

请注意,这个示例假设你已经安装了FFmpeg,并配置了相应的开发环境。此外,这个示例不包括实际的音频和视频播放代码,而是专注于解码和时间戳的处理。

#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <thread>extern "C" {#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libavutil/time.h>
}// 用于存储解码后的帧
struct Frame {AVFrame* av_frame;int64_t pts; // 表示帧的显示/播放时间戳
};// 模拟解码队列
std::vector<Frame> video_frames;
std::vector<Frame> audio_frames;// 模拟播放队列
std::vector<Frame> play_queue;// 同步播放函数
void play_frames(std::vector<Frame>& queue) {// 这里只是一个示例,实际播放逻辑会更复杂for (auto& frame : queue) {// 根据帧的pts进行适当的延时以实现同步int64_t delay = frame.pts - av_gettime();if (delay < 0) delay = 0; // 防止负延时std::this_thread::sleep_for(std::chrono::milliseconds(delay));// 模拟播放帧std::cout << "Playing frame with PTS: " << frame.pts << std::endl;av_frame_unref(frame.av_frame);}queue.clear();
}// 主函数
int main() {// 初始化FFmpeg库av_register_all();avcodec_register_all();// 打开视频文件AVFormatContext* format_ctx = nullptr;if (avformat_open_input(&format_ctx, "input.mp4", nullptr, nullptr) < 0) {std::cerr << "Cannot open input file" << std::endl;return -1;}// 检索流信息if (avformat_find_stream_info(format_ctx, nullptr) < 0) {std::cerr << "Cannot find stream information" << std::endl;return -1;}// 找到音频和视频流的索引int video_stream_idx = -1, audio_stream_idx = -1;for (unsigned i = 0; i < format_ctx->nb_streams; i++) {if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream_idx = i;} else if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {audio_stream_idx = i;}}if (video_stream_idx == -1 || audio_stream_idx == -1) {std::cerr << "No audio or video streams found" << std::endl;return -1;}AVCodecContext* video_codec_ctx = avcodec_alloc_context3(nullptr);AVCodecContext* audio_codec_ctx = avcodec_alloc_context3(nullptr);// 打开音频和视频编解码器// ...// 模拟解码过程AVPacket packet;while (av_read_frame(format_ctx, &packet) == 0) {if (packet.stream_index == video_stream_idx || packet.stream_index == audio_stream_idx) {// 分配帧Frame frame{av_frame_alloc(), packet.pts};// 解码帧// ...// 根据类型将帧添加到相应的队列if (packet.stream_index == video_stream_idx) {video_frames.push_back(frame);} else {audio_frames.push_back(frame);}// 同步逻辑(简化示例)// 这里需要更复杂的逻辑来处理实际的同步if (!play_queue.empty() && video_frames.back().pts < play_queue.front().pts) {play_frames(play_queue);}av_packet_unref(&packet);}}// 清理资源avformat_close_input(&format_ctx);// ...return 0;
}

这个代码提供了一个基本的框架,展示了如何使用FFmpeg库来打开视频文件、检索流信息、找到音频和视频流,以及模拟解码过程。示例没有实现真正的解码和播放逻辑,而是展示了如何组织代码结构以及如何考虑同步问题。

结论

PTS和DTS是音视频同步中不可或缺的两大时间戳。它们确保了在多媒体播放和处理过程中,无论是视频帧还是音频帧,都能在正确的时间点被解码和播放。理解和正确应用PTS和DTS,对于开发高质量的多媒体播放和处理软件至关重要。通过深入理解这些概念,我们可以为用户提供更加流畅和同步的多媒体体验。

祝大家学习顺利~
如有任何错误,恳请批评指正~~
以上是我通过各种方式学习的经验和方法,欢迎大家评论区留言讨论呀,如果文章对你们产生了帮助,也欢迎点赞收藏,我会继续努力分享更多干货~


🎈关注我的公众号AI Sun可以获取Chatgpt最新发展报告以及腾讯字节等众多大厂面经。
😎也欢迎大家和我交流,相互学习,提升技术,风里雨里,我在等你~


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

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

相关文章

STM32 ADC精度提升方法

STM32 ADC精度提升方法 Fang XS.1452512966qq.com如果有错误&#xff0c;希望被指出&#xff0c;学习技术的路难免会磕磕绊绊量的积累引起质的变化 硬件方法 优化布局布线&#xff0c;尽量减小其他干扰增加电源、Vref去耦电容使用低通滤波器&#xff0c;或加磁珠使用DCDC时尽…

vue+js实现鼠标右键页面时在鼠标位置出现弹窗

首先是弹窗元素 <div class"tanchuang move-win1"id"tanchuang1"><el-button>111</el-button></div>然后在需要弹窗的地方监听点击事件&#xff0c;可以将这个方法写在页面载入事件中 // 获取弹窗元素 var tanchuang document.…

lua中判断2个表是否相等

当我们获取 table 长度的时候无论是使用 # 还是 table.getn 其都会在索引中断的地方停止计数&#xff0c;而导致无法正确取得 table 的长度&#xff0c;而且还会出现奇怪的现象。例如&#xff1a;t里面有3个元素&#xff0c;但是因为最后一个下表是5和4&#xff0c;却表现出不一…

一篇文章搞懂时间复杂度和空间复杂度

不知道小伙伴们有没有刷过力扣上的算法题&#xff0c;我在上研究生的时候&#xff0c;刷过了前40道题&#xff0c;上面的算法题&#xff0c;我觉得还挺难的&#xff0c;当你写完代码的时候&#xff0c;就可以提交自己写的代码到系统上&#xff0c;系统会给你写的代码计算时间复…

页面速度是如何影响SEO的?

搜索引擎使用复杂的算法来衡量您网站的重要方面&#xff0c;以决定是否向您发送流量。 搜索引擎使用您网站的小元素来确定您网站的质量和真实性&#xff0c;然后此操作将转化为您的网页在搜索引擎结果页面 中出现的位置。提高您在 SERP 中的排名的过程称为搜索引擎优化 (SEO)。…

第57期|GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

Datawhale - 角色要素提取竞赛

文章目录 赛题要求一、赛事背景二、赛事任务三、评审规则1.平台说明2.数据说明3.评估指标4.评测及排行 四、作品提交要求五、 运行BaselineStep1&#xff1a;下载相关库Step2&#xff1a;配置导入Step3&#xff1a;模型测试Step4&#xff1a;数据读取Step5&#xff1a;Prompt设…

Yi-1.5 9B Chat 上线Amazon SageMaker JumpStart

你是否对简单的API调用大模型感到不满足&#xff1f;是否因为无法亲自部署属于自己的大模型而烦恼&#xff1f; 好消息来了&#xff0c;Amazon SageMaker JumpStart 初体验 CloudLab实验上线啦&#xff01; 本实验将以零一万物最新发布的中文基础模型 Yi-1.5 9B Chat 为例&am…

kettle从入门到精通 第七十四课 ETL之kettle kettle调用https接口教程,忽略SSL校验

场景&#xff1a;kettle调用https接口&#xff0c;跳过校验SSL。&#xff08;有些公司内部系统之间的https的接口是没有SSL校验这一说&#xff0c;无需使用用证书的&#xff09; 解决方案&#xff1a;自定义插件或者自定义jar包通过javascript调用https接口。 1、http post 步…

嵌入式UI开发-lvgl+wsl2+vscode系列:8、控件(Widgets)(一)

一、前言 这里将介绍一系列控件&#xff0c;了解后就可以开始基础的开发了。 二、示例 1、Base Obj&#xff08;基础对象&#xff09; 1.1、示例1 #include "../../lv_examples.h" #if LV_BUILD_EXAMPLESvoid lv_example_obj_1(void) {lv_obj_t * obj1;obj1 lv…

Python容器 之 列表--列表的常用操作方法

1.查询相关方法&#xff1a;index()、count() &#xff08;1&#xff09;index() 说明&#xff1a; 和 字符串中的 find() 的作用是一样 列表中是没有 find() 方法的, 只有 index() 方法&#xff1b;字符串中 同时存在 find() 和 index() 方法 格式&#xff1a;列表.index(要查…

你必须要知道的自闭症知识,推荐收藏

自闭症&#xff0c;一种日益受到关注的神经发育障碍&#xff0c;对于许多人来说&#xff0c;仍充满了神秘和误解。以下是 12 个你必须知道的关于自闭症的重要知识点&#xff1a; 1、自闭症并非心理问题 自闭症是一种生理上的神经发育障碍&#xff0c;不是由于孩…

亚马逊TM商标跟卖,同行截流采集,人工手动跟卖选品更方便!

区分TM标&#xff0c;软件自动查询&#xff0c;人工手动查询方便。 大家好&#xff0c;跟大家说下如何区分TM标。 选择相对于的站点&#xff0c;选择TM。 软件采集出来的已备案、未备案TMR标&#xff0c;现在点击TM标就会跳到美国商标局。 可以清晰的看到这个地方只有一个序…

张颂文百花提名,男配界笑出“颂”彩

在这个星光熠熠的百花奖舞台上&#xff0c; 张颂文老师犹如一坛陈年老酒&#xff0c;越品越有味&#xff0c; 竟不声不响地提名了最佳男配角&#xff01;这下可好&#xff0c; 男配界仿佛一夜之间被“颂”风吹得花枝乱颤&#xff0c;笑料百出。你说张颂文老师这演技&#xf…

DreamTech联合南大和牛津发布最强3D内容生成大模型——Direct3D

文章链接&#xff1a;https://arxiv.org/pdf/2405.14832 github链接&#xff1a;https://nju-3dv.github.io/projects/Direct3D/ 从文本和图像生成高质量的3D资产一直是一项挑战&#xff0c;主要是由于缺乏能够捕捉复杂几何分布的可扩展3D表示。在这项工作中&#xff0c;介绍…

详解反向传播(BP)算法

文章目录 what&#xff08;是什么&#xff09;where&#xff08;用在哪&#xff09;How&#xff08;原理&&怎么用&#xff09;原理以及推导过程pytorch中的反向传播 what&#xff08;是什么&#xff09; 反向传播算法&#xff08;Backpropagation&#xff09;是一种用于…

自动驾驶水泥搅拌车在梁场的应用(下)

自动驾驶水泥搅拌车在梁场的应用&#xff08;下&#xff09; 北京渡众机器人科技有限公司的自动驾驶水泥搅拌车在梁场&#xff08;也称为预制梁场&#xff09;的应用可以带来多方面的优势和效益&#xff1a; 1. 自动化搅拌和运输 在梁场中&#xff0c;通常需要大量的混凝土搅…

自动化一些操作

下拉选择框 from selenium import webdriver from time import sleep # 导包 from selenium.webdriver.support.select import Select driver webdriver.Edge() driver.get(r"D:\WORK\ww\web自动化_day01_课件笔记资料代码\web自动化_day01_课件笔记资料代码\02_其他资料…

调试支付分回调下载平台证书

之前的原生代码放到webman里面&#xff0c;死活跑不通 没办法&#xff0c;只能用esayWeChat6.7 &#xff08;自行下载&#xff09; 它里面配置要用到平台证书 平台证书又要用到 composer require wechatpay/wechatpay 但是请求接口之前&#xff0c;你先要用到一个临时的平台…

配置atuin记录

https://atuin.sh/ 运行 curl --proto https --tlsv1.2 -LsSf https://setup.atuin.sh | sh报错 $ curl --proto https --tlsv1.2 -LsSf https://setup.atuin.sh | sh curl: (77) error setting certificate verify locations:CAfile: /etc/ssl/certs/ca-certificates.crtCAp…