FFMPEG处理音频时间戳的主要逻辑
来源:http://www.xuebuyuan.com/1466771.html
FFMPEG处理音频时间戳的主要逻辑
FFMPEG处理音频时间戳的主要逻辑是:
1. demux读取AVPacket。以输入flv为例,timebase是1/1000,第一个音频包可能是46,代表0.046秒。
2. decoder解码AVPacket为AVFrame,frame的pts为NOPTS,需要设置,否则后面都会有问题。主要是调用:av_rescale_delta:
AVRational in_tb = decoded_frame_tb;
AVRational fs_tb = (AVRational){1, ist->codec->sample_rate};
int duration = decoded_frame->nb_samples;
AVRational out_tb = (AVRational){1, ist->codec->sample_rate}; decoded_frame->pts = av_rescale_delta(in_tb, decoded_frame->pts, fs_tb, duration, &rescale_last_pts, out_tb);
相当于下面的逻辑:
// init the rescale_last_pts, set to 0 for the first decoded_frame->pts is 0
if (rescale_last_pts == AV_NOPTS_VALUE) {
rescale_last_pts = av_rescale_q(decoded_frame->pts, in_tb, fs_tb) + duration;
}
// the fs_tb equals to out_tb, so decoded_frame->pts equals to rescale_last_pts
decoded_frame->pts = av_rescale_q(rescale_last_pts, fs_tb, out_tb);;
rescale_last_pts += duration;
还可以简化为:
/**
* for audio encoding, we simplify the rescale algorithm to following.
*/
if (rescale_last_pts == AV_NOPTS_VALUE) {
rescale_last_pts = 0;
}
decoded_frame->pts = rescale_last_pts;
rescale_last_pts += decoded_frame->nb_samples; // duration
实际上就是以nb_samples为时长,让pts为这个的总和,累积的samples就可以。因为默认把tb设置为sample_rate,所以samples数目就是pts。
3. filter过滤,实际上没有处理。
// correct the pts
int64_t filtered_frame_pts = AV_NOPTS_VALUE;
if (picref->pts != AV_NOPTS_VALUE) {
// rescale the tb, actual the ofilter tb equals to ost tb,
// so this step canbe ignored and we always set start_time to 0.
filtered_frame_pts = av_rescale_q(picref->pts, ofilter->inputs[0]->time_base, ost->codec->time_base)
- av_rescale_q(start_time, AV_TIME_BASE_Q, ost->codec->time_base);
} // convert to frame
avfilter_copy_buf_props(filtered_frame, picref);
printf("filter -> picref_pts=%"PRId64", frame_pts=%"PRId64", filtered_pts=%"PRId64"\n",
picref->pts, filtered_frame->pts, filtered_frame_pts);
filtered_frame->pts = filtered_frame_pts;
4. encoder编码,主要是生成dts。
5. muxer输出前,需要做处理。譬如输出rtmp流,要将tb变为1/1000,flv的tb,也就是毫秒单位。
另外,时间戳从零开始。
// correct the output, enforce start at 0.
static int64_t starttime = -1;
#if 1
if (starttime < 0) {
starttime = (pkt.dts < pkt.pts)? pkt.dts : pkt.pts;
}
pkt.dts -= starttime;
pkt.pts -= starttime;
#endif #if 1
// rescale audio ts to AVRational(1, 1000) for flv format.
AVRational flv_tb = (AVRational){1, 1000};
pkt.dts = av_rescale_q(pkt.dts, ost->codec->time_base, flv_tb);
pkt.pts = av_rescale_q(pkt.pts, ost->codec->time_base, flv_tb);
#endif
6. 最后一步,写入:
ret = av_interleaved_write_frame(oc, &pkt);
就OK了。
FFMPEG处理音频时间戳的主要逻辑的更多相关文章
- [总结]FFMPEG视音频编解码零基础学习方法--转
ffmpeg编解码学习 目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ...
- FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- 最简单的基于FFMPEG的音频编码器(PCM编码为AAC)
http://blog.csdn.net/leixiaohua1020/article/details/25430449 本文介绍一个最简单的基于FFMPEG的音频编码器.该编码器实现了PCM音频采样 ...
- FFMPEG视音频编解码零基础学习方法-b
感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...
- [总结]FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- [Audio processing] FFMPEG转音频格式和采样率
利用FFMPEG转音频格式和采样率 import os import string import subprocess as sp #Full path of ffmpeg FFMPEG_BIN = ...
- 【转】[总结]FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——解码篇:(二)用ffmpeg解码音频
其实这篇的内容和(一)用ffmpeg解码视频基本是一样的,重点还是给ffmpeg指定callback函数,而这个函数是从RTSP服务端那里获取音频数据的. 这里,解码音频的示例代码量之所以比解码视频的 ...
- C# 使用 ffmpeg 进行音频转码
先放一下 ffmpeg 的官方文档以及下载地址: 官方文档:http://ffmpeg.org/ffmpeg.html 下载地址:http://ffmpeg.org/download.html 用 f ...
随机推荐
- 关于System.FormatException异常
什么是FormatException 参数格式无效或复合格式字符串不正确时引发的异常. 继承 Object Exception SystemException FormatException 详细说明 ...
- zabbix-钉钉报警媒介
(1)第三方报警平台(钉钉) 先指定要发送的群,在群里创建机器人 添加机器人 可以参考 “说明文档” 创建测试文档 vim ceshi.sh curl 'https://oapi.dingta ...
- ERROR:Simulator861-Failed to link the design解决办法
在安装目录下找到collect2.exe文件,删除就可以解决了.D:\install_dir\ISE2\14.7\ISE_DS\ISE\gnu\MinGW\5.0.0\nt\libexec\gcc\m ...
- 【CF10D】 LCIS
题目链接 最长公共上升子序列 \(f[i][j]\)表示\(A\)的前\(i\)个数,匹配\(B\)的第\(j\)个数,且\(B[j]\)必选时的最长公共上升子序列长度 转移: if(A[i]==B[ ...
- 决策单调性优化dp 专题练习
决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...
- php获取客户端公网ip代码
<?php /*如果是本地服务器获取客户端的ip地址是 127.0.0.1 如果是域名服务器获取客户端的是公网ip地址*/ function get_client_ip() { $ipaddre ...
- NIO (一) NIO是什么
参考文档:java为什么需要NIO:https://liuchi.coding.me/2017/08/01/浅谈Java为什么需要NIO/美团技术团队 NIO浅析:https://tech.meitu ...
- springboot项目打包成jar/war包
springboot项目打包过程中包含第三方jar 开发IDE是IntelliJ IDEA,数据库是mysql,内置服务器tomcat. 打包步骤: 1. 确定项目调试运行没问题 2. 将第三方jar ...
- FCB CCB FileObject
CCB ContextControlBlock 是存Private信息的,这个FO的特殊信息 FCB FileControlBlock 是存全局信息的 FO FileOb ...
- 前端与算法 leetcode 125. 验证回文串
目录 # 前端与算法 leetcode 125. 验证回文串 题目描述 概要 提示 解析 解法一:api侠 解法二:双指针 算法 传入测试用例的运行结果 执行结果 GitHub仓库 查看更多 # 前端 ...