当前位置: 首页 > news >正文

openrtp 音视频时间戳问题

解决音视频发送的rtp问题

openrtp增加了音频aac的发送,地址
OpenRTP Gitee开源地址

同时使用两个rtp ,来发送音频和视频
使用以下音频rtp,是可以发送和接收的,音频端口在视频端口上+2

v=0
o=- 0 0 IN IP4 127.0.0.1
s=My Stream
c=IN IP4 0.0.0.0
t=0 0
m=audio 1234 RTP/AVP 97
a=rtpmap:97 mpeg4-generic/44100/2
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3

音视频合成发送rtp
vlc 使用分开的端口来接收,经过测试无误

v=0
o=- 0 0 IN IP4 127.0.0.1
s=My Stream
c=IN IP4 0.0.0.0
t=0 0
m=audio 6002 RTP/AVP 97
a=rtpmap:97 mpeg4-generic/44100/2
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3
m=video 6000 RTP/AVP 96
a=rtpmap:96 H264/90000

我把sdp文件放在了这里,
在这里插入图片描述

在这里插入图片描述

是否使用同一端口发送音视频

一、协议规范
RTP(Real-time Transport Protocol)通常为音频和视频分别分配不同的端口以区分不同类型的媒体流。这样做符合协议设计的常规做法,使得接收端能够明确地识别和处理不同类型的媒体数据。
二、处理复杂性
解码和播放:如果音频和视频使用同一个端口,接收端在处理数据时需要更加复杂的逻辑来区分音频和视频数据包。这增加了处理的难度和出错的可能性,可能导致播放不稳定或不同步。
同步问题:不同的媒体流需要进行同步才能保证良好的播放效果。使用不同的端口可以更容易地实现音频和视频的同步,因为接收端可以独立地处理每个流的时间戳和同步信息。如果使用同一个端口,同步处理会变得更加复杂,可能会影响播放质量。
三、网络传输考虑
带宽管理:音频和视频通常具有不同的带宽需求。分开使用不同的端口可以更好地进行带宽管理和流量控制。例如,可以为视频流分配更多的带宽,以确保高质量的视频播放,而音频流可以使用相对较少的带宽。
网络故障处理:如果音频和视频使用同一个端口,当该端口出现网络问题时,音频和视频都会受到影响。而使用不同的端口可以在一定程度上隔离问题,使得在一个流出现问题时,另一个流可能仍然能够正常传输。
综上所述,为了保证音频和视频的稳定播放、便于处理和同步,以及更好地进行网络管理,建议为音频流和视频流分别使用不同的端口。

以上其实问题都能解决,比如rtmp协议就是一个端口,处理所有音视频,对于rtp协议,如果使用udp,其实可以使用不同的端口来发送视频和音频,这样处理逻辑更为简单,但不是必要。

计算时间戳增量:

音频时间戳

音频时间戳的单位就是采样率的倒数,例如采样率44100,那么1秒就有44100个采样,每个采样1/44ms,每个采样对应一个时间戳。RTP音频包如果是10毫秒的数据,对应的采样数为 44100 * 10 / 1000 = 441,也就是说每个音频包里携带440个左右的音频采样,因为1个采样对应1个时间戳,那么相邻两个音频RTP包的时间戳之差就是960。

那如果是回调函数采集的音频,我们可以计算回调两次之间的时间差t - t0,t0是第一次的时间,这样有可能造成越来越来的累计时间,如果我们知道是采样一次位1024个样本,那样就好计算了

1024 ,每次就是增加1024,缓冲区计算就是1024* channel(声道)* (perbytes)字节,比如16位就是2字节,那就是1024 X 2 X 2 = 4096个字节的缓冲,每次增加1024时间戳就行

nt rtp_pakc_aac(unsigned char *ptr,int bytes,unsigned char *rtpPkt)
{if (0xFF == ptr[0] && 0xF0 == (ptr[1] & 0xF0) && bytes > 7){// skip ADTS headerassert(bytes == (((ptr[3] & 0x03) << 11) | (ptr[4] << 3) | ((ptr[5] >> 5) & 0x07)));ptr += 7;bytes -= 7;}int rtpHeadLen = rtp_pack_header(rtpPkt);//RTP Headerunsigned char * header = rtpPkt + rtpHeadLen;// 3.3.6. High Bit-rate AAC// SDP fmtp: mode=AAC-hbr;sizeLength=13;indexLength=3;indexDeltaLength=3;header[0] = 0;header[1] = 16; // 16-bits AU headers-lengthheader[2] = (uint8_t)(bytes >> 5); header[3] = (uint8_t)(bytes & 0x1f) << 3;//13bit AU-size、3bit AU-Index/AU-Index-deltaunsigned char * pPayload = rtpPkt + rtpHeadLen + 4;memcpy(pPayload, ptr,bytes);return bytes + rtpHeadLen + 4;
从RTP包里面得到AAC音频数据的方法://功能:解RTP AAC音频包,声道和采样频率必须知道。
//参数:1.RTP包缓冲地址 2.RTP包数据大小 3.H264输出地址 4.输出数据大小
//返回:true:表示一帧结束  false:帧未结束 一般AAC音频包比较小,没有分片。
bool UnpackRTPAAC(void * bufIn, int recvLen, void** pBufOut,  int* pOutLen)
{unsigned char*  bufRecv = (unsigned char*)bufIn;//char strFileName[20];unsigned char ADTS[] = {0xFF, 0xF1, 0x00, 0x00, 0x00, 0x00, 0xFC}; int audioSamprate = 32000;//音频采样率int audioChannel = 2;//音频声道 1或2int audioBit = 16;//16位 固定switch(audioSamprate){case  16000:ADTS[2] = 0x60;break;case  32000:ADTS[2] = 0x54;break;case  44100:ADTS[2] = 0x50;break;case  48000:ADTS[2] = 0x4C;break;case  96000:ADTS[2] = 0x40;break;default:break;}ADTS[3] = (audioChannel==2)?0x80:0x40;int len = recvLen - 16 + 7;len <<= 5;//8bit * 2 - 11 = 5(headerSize 11bit)len |= 0x1F;//5 bit    1            ADTS[4] = len>>8;ADTS[5] = len & 0xFF;*pBufOut = (char*)bufIn+16-7;memcpy(*pBufOut, ADTS, sizeof(ADTS));*pOutLen = recvLen - 16 + 7;unsigned char* bufTmp = (unsigned char*)bufIn;bool bFinishFrame = false;if (bufTmp[1] & 0x80){//DebugTrace::D("Marker");bFinishFrame = true;}else{bFinishFrame = false;}return true;
}

视频时间戳

rtp协议中视频一般以90000为时间基,一帧应该是对应多少次的采集;比如视频20帧,采样率是90KHZ,那么1帧就3600次的采集(90000 / 20 = 4500 ),也就是时间戳每帧每次增加4500个单位。

在这里插入图片描述

其他

rtp receive 暂时没有增加音频的接收,仍然是ps流的接收和普通rtp流的接收,rtmp流发送照旧是视频,近期增加音频的同步发送

相关文章:

openrtp 音视频时间戳问题

解决音视频发送的rtp问题 openrtp增加了音频aac的发送&#xff0c;地址 OpenRTP Gitee开源地址 同时使用两个rtp &#xff0c;来发送音频和视频 使用以下音频rtp&#xff0c;是可以发送和接收的&#xff0c;音频端口在视频端口上2 v0 o- 0 0 IN IP4 127.0.0.1 sMy Stream cI…...

了解Android中为什么需要多线程?

在Android开发中&#xff0c;多线程是一个至关重要的概念。理解并合理应用多线程&#xff0c;可以显著提升应用的性能和用户体验。 一、Android多线程的基本概念 1. 主线程与UI线程 在Android中&#xff0c;主线程也称为UI线程&#xff0c;它负责处理用户输入、事件分发、绘…...

Kaggle Python练习:使用外部库(Exercise: Working with External Libraries)

文章目录 问题1&#xff1a;坐标轴及标签显示问题2&#xff1a;赢得比赛的最佳项目并计数问题3&#xff1a;21点游戏方法1&#xff1a;把超过21点的最后记为0方法2&#xff1a;把超过21点在最后进行判断方法3&#xff1a;官方代码与方法2相似 问题1&#xff1a;坐标轴及标签显示…...

React 子组件调用父组件的方法,以及互相传递数据

<script type"text/babel" data-type"module"> import React, { StrictMode, useState } from react; import { createRoot } from react-dom/client;const ParentComponent () > {const [message, setMessage] useState("")//父组件…...

爬虫基础---python爬虫系列2

爬虫基础 文章目录 爬虫基础爬虫简介爬虫的用途爬虫的合法性规避风险看懂协议反爬机制反反爬策略 认识HTTPHTTP协议--HyperText Transfer ProtocolHTML--HyperText Markup LanguageHTTPS如何查看网站是什么协议呢使用端口号 URL组成部分详解常用的请求- Request Method常见的请…...

jmeter在beanshell中使用props.put()方法的注意事项

在jmeter中&#xff0c;通常使用beanshell去处理一些属性的设置和获取的操作&#xff0c;而这些操作也是有一定的规则的。 1. 设置属性时&#xff0c;在属性名上要加双引号&#xff0c;这代表它不是一个需要用var去声明的变量 这种设置属性的方式才是有效可行的&#xff0c;在…...

息肉检测数据集 yolov5 yolov8适用于目标检测训练已经调整为yolo格式可直接训练yolo网络

息肉检测数据集 yolov5 yolov8格式 息肉检测数据集介绍 数据集概述 名称&#xff1a;息肉检测数据集&#xff08;基于某公开的分割数据集调整&#xff09;用途&#xff1a;适用于目标检测任务&#xff0c;特别是内窥镜图像中的息肉检测格式&#xff1a;YOLO格式&#xff08;边…...

通过API进行Milvus实例配置

更新Milvus各个组件的配置参数。 调试 您可以在OpenAPI Explorer中直接运行该接口&#xff0c;免去您计算签名的困扰。运行成功后&#xff0c;OpenAPI Explorer可以自动生成SDK代码示例。 ​编辑调试 授权信息 下表是API对应的授权信息&#xff0c;可以在RAM权限策略语句的…...

Excelize 开源基础库 2.9.0 版本正式发布

Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库&#xff0c;基于 ECMA-376&#xff0c;ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Excel、WPS、OpenOffice 等办公软件创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式&#xf…...

人脸识别-特征算法

文章目录 一、LBPH算法1.基本原理2.实现步骤3.代码实现 二、Eigenfaces算法1.特点2.代码实习 三、FisherFaces算法1.算法原理2.算法特点3.代码实现 四、总结 人脸识别特征识别器是数字信息发展中的一种生物特征识别技术&#xff0c;其核心在于通过特定的算法和技术手段&#xf…...

C++【内存管理】(超详细讲解C++内存管理以及new与delete的使用和原理)

文章目录 1.C/C内存分布2.C语言中动态内存管理方式3.C内存管理方式3.1 new/delete操作内置类型3. 2new/delete操作自定义类型 4. operator new与operator delete函数&#xff08;重点&#xff09;5. new和delete的实现原理5.1 内置类型5.2 自定义类型5.2.1 自定义类型调用new[]…...

elementUi el-table 表头高度异常问题

1、现象 在同一个页面通过状态切换不同table时&#xff0c;当从有合并标头行的table切换到无合并表头的table时&#xff0c;无合并表头的table的表头的高度异常了&#xff0c;如下图 切换后 2、解决 给每个el-table 加上一个唯一的key <el-table key"1"></…...

kubekey的应用

随着 Kubernetes 社区的不断发展&#xff0c;即将迎来 Kubernetes 1.30 版本的迭代。在早先的 1.24 版本中&#xff0c;社区作出一个重要决策&#xff1a;不再默认集成 Docker 作为容器运行时&#xff0c;即取消了对 Docker 的默认支持。这就像咱们家厨房换了个新灶头&#xff…...

如何识别并分类转录因子的家族

愿武艺晴小朋友一定得每天都开心 当我们有了差异表达的转录因子列表以后,接下来可能就想知道这些转录因子的家族分布情况是怎样的?有没有1-2个Family在其中起主要作用,占比较多。 基于这种需求,可以按以下几步来实现: 1)从AnimalTFDB4转录因子数据库中,根据需要…...

【C++11】可变模板参数详解

个人主页&#xff1a;chian-ocean 文章专栏 C 可变模板参数详解 1. 引言 C模板是现代C编程中一个非常强大且灵活的工具。在C11标准中&#xff0c;引入了可变模板参数&#xff08;variadic templates&#xff09;&#xff0c;它为模板编程带来了革命性改变。它的出现允许我们…...

本地群晖NAS安装phpMyAdmin管理MySQ数据库实战指南

文章目录 前言1. 安装MySQL2. 安装phpMyAdmin3. 修改User表4. 本地测试连接MySQL5. 安装cpolar内网穿透6. 配置MySQL公网访问地址7. 配置MySQL固定公网地址8. 配置phpMyAdmin公网地址9. 配置phpmyadmin固定公网地址 前言 本文主要介绍如何在群晖NAS安装MySQL与数据库管理软件p…...

QTableWidget 接口详情

Qt Widgets->C Classes->QTableWidget Qt 5.12版本QTableWidget接口详情&#xff08;机翻&#xff09; QTableWidget类提供了一个带有默认模型的基于项的表视图。 属性 列数columnCount : int 行数rowCount : int 细节描述 QTableWidget类提供了一个带有默认模型的基…...

GESP CCF python四级编程等级考试认证真题 2024年9月

一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 据有关资料&#xff0c;山东大学于1972年研制成功DJL-1计算机&#xff0c;并于1973年投入运行&#xff0c;其综合性能居当时全国第三位。DJL-1计算机运算控制部分所使用的磁心存储元件由磁心颗粒组成…...

oracle数据库名实例名服务名

Oracle数据库是一个复杂的系统&#xff0c;它包含多个组件&#xff0c;包括数据库服务器、实例和服务。 数据库名&#xff08;DB_NAME&#xff09;&#xff1a;这是数据库的内部名称&#xff0c;通常在创建数据库时指定&#xff0c;并在整个数据库生命周期内保持不变。 实例名…...

python+appium+雷电模拟器安卓自动化及踩坑

一、环境安装 环境&#xff1a;window11 1.1 安装Android SDK AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 这里面任选一个就可以&#xff0c;最终下载完主要要安装操作安卓的工具adb&#xff0c;安装这个步骤的前提是要…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...