• 视频、音频打时间戳的方法及其音视频同步(播放)原理


    视频、音频打时间戳的方法

      
    http://blog.csdn.net/wfqxx/article/details/5497138

    1. 视频时间戳

         pts = inc++ *(1000/fps);  其中inc是一个静态的,初始值为0,每次打完时间戳inc加1.

        在ffmpeg,中的代码为

        pkt.pts= m_nVideoTimeStamp++ * (m_VCtx->time_base.num * 1000 / m_VCtx->time_base.den);

    2. 音频时间戳

        pts = inc++ * (frame_size * 1000 / sample_rate)

       在ffmpeg中的代码为

       pkt.pts= m_nAudioTimeStamp++ * (m_ACtx->frame_size * 1000 / m_ACtx->sample_rate);

    采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。

    。正常人听觉的频率范围大约在20Hz~20kHz之间,根据奈奎斯特采样理论,为了保证声音不失真,采样频率应该在40kHz左右。常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果采用更高的采样频率,还可以达到DVD的音质

    对采样率为44.1kHz的AAC音频进行解码时,一帧的解码时间须控制在23.22毫秒内。

    背景知识:

    (一个AAC原始帧包含一段时间内1024个采样及相关数据)

    分析:

    1 AAC

    音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率(单位为s)

    一帧 1024个 sample。采样率 Samplerate 44100KHz,每秒44100个sample, 所以 根据公式   音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率

    当前AAC一帧的播放时间是= 1024*1000000/44100= 22.32ms(单位为ms)

    2 MP3

    mp3 每帧均为1152个字节, 则:

    frame_duration = 1152 * 1000000 / sample_rate

    例如:sample_rate = 44100HZ时, 计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来。

    音视频同步(播放)原理

    每一帧音频或视频都有一个持续时间:duration:
    采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。
    。正常人听觉的频率范围大约在20Hz~20kHz之间,根据奈奎斯特采样理论,为了保证声音不失真,采样频率应该在40kHz左右。常用的音频采样频率有8kHz、

    11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果采用更高的采样频率,还可以达到DVD的音质
    对采样率为44.1kHz的AAC音频进行解码时,一帧的解码时间须控制在23.22毫秒内。
    背景知识:
    (一个AAC原始帧包含一段时间内1024个采样及相关数据)
    分析:
    1) AAC
    音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率(单位为s)
    一帧 1024个 sample。采样率 Samplerate 44100KHz,每秒44100个sample, 所以根据公式   音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率
    当前AAC一帧的播放时间是= 1024*1000000/44100= 22.32ms(单位为ms)
    2) MP3
    mp3 每帧均为1152个字节, 则:
    frame_duration = 1152 * 1000000 / sample_rate
    例如:sample_rate = 44100HZ时,计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来。
    3)H264
    视频的播放时间跟帧率有关 frame_duration = 1000/fps
    例如:fps = 25.00 ,计算出来的时常为40ms,这就是同行所说的40ms一帧视频数据。

    理论上的音视频(播放)同步是这样的:
    由此得到了每一帧数据的持续时间,音视频交叉存储在容器中:一个时间轴:
    时间轴:0   22.32   40     44.62    66.96    80     89.16      111.48    120       ................
    音   频 :0   22.32            44.62    66.96             89.16      111.48                ................
    视   频 :0              40                              80                                   120       ................
    即视频的持续时间相加 和音频的持续时间相加作比较,谁小写入哪个。

    但实际情况(播放)是不成立的

    1:首先解决一个问题

    为什么不 音频播音频的 视频播视频的 即上面的 到 第22.32ms播一帧音频 ,到40ms播一帧视频。

    因为这个22.32ms 或40ms是算不准的或者说和声卡播的时间是不一样的。这里就需要知道声卡播一帧/或者说播放一个buf音频需要多长时间。

    2:声卡每次播一个采样点 而不是一帧。声音当一个采样点丢失了都可以听出来,视频则不然。

    3:音视频同步方式:1----回调方式

    假设声卡有两块缓存都是存放要播放的声音pcm的 一直在播放"B"buf 首先确定几点

    (1)buf大小是固定的这样播放一个buf的时间就是固定的,假设30ms;

    (2)当buf“B”播放完毕即buf用完,再播放buf“A",保证音频pcm一直都连续

    (3)当一个buf播放完毕,那说明系统(声卡)过了30ms, 这时候有可能真正的时间过了40ms(这里不用关心),这里则通过回调得到一次时间30ms;

    (4)再去用视频对应音频的30ms,这时候的时间就是准确的:

    时间轴:0                    30                         60                         90                                        120       ................
    音   频 :0     22.32                 44.62                 66.96     89.16                       111.48                     ................
    视   频 :0                          40                                    80                                                  120       ................

    (5)这里有个问题就是 视频中 30ms 到40ms 这中间的10ms是怎么算出来的,这个是不用关心的,因为人的眼睛10ms是看不出来的,

    即当音频的30ms一次回调时,就可以播放第二帧视频,如上图

    第一次回调(30ms)---播(40ms)视频,

    第一次回调(60ms)---播(80ms)视频,

    第一次回调(90ms)---不播视频,

    第一次回调(120ms)---播(120ms)视频。

    4:音视频同步方式:1----阻塞方式

    还是看上面的图

    (1)buf"B"一直在播放,传入buf"A"的外部buf把数据给buf"A"后 不立即返回,等到buf"B"播放完成再返回,

    这时从传入到经过阻塞出来就是一个buf的时间例如上面的30ms。

    (2)然后buf"A"一直在播放,传入buf"B"的外部buf把数据给buf"B"后 不立即返回,等到buf"A"播放完成再返回,

    这时从传入到经过阻塞出来就是一个buf的时间例如上面的30ms。

    (3)循环上面(1)(2),即得到了如回调方式同样的那个30ms时间。下面和回调方式一样,见回调方式(4)(5)。

    转自   http://blog.csdn.net/zhuweigangzwg/article/details/25815851
  • 相关阅读:
    deferred 对象
    JVM--------3
    JVM类加载机制————2
    JVM加载的初始化类
    补充==的使用和equals的区别
    MyBatis_SelectKey使用oracle 序列插入主键
    MySql_ procedure
    mysql function
    jsonp _____跨域请求实现
    shell(shell变量、条件表达式、流程控制)
  • 原文地址:https://www.cnblogs.com/lidabo/p/7217653.html
Copyright © 2020-2023  润新知