VLC无声问题总结

本文总结了使用VLC播放时遇到的无声问题,包括seek后无声和起播无声。分析了由于片源AV PTS差异、PTS跳变、AudioTrack起播慢等原因导致的无声现象,并探讨了VLC的AV同步策略及其带来的挑战。针对这些问题,提出了相应的解决思路。

VLC的avsync方案是audio video同步到系统时钟,且audio sync的阈值比较敏感,很容易出现丢帧的情况。相对于audio master的同步方案,VLC的同步方案比较“理想”化,经常会出现无声问题。

下面记录下目前遇到过的无声问题及分析记录:

目录

一、seek后无声

1.片源av pts差异较大

2.pts跳变

二、起播无声

1.AudioTrack起播慢


一、seek后无声

1.片源av pts差异较大

首先先介绍下ffmpeg的demux方式,ffmpeg在解封装视频文件时,是按照文件位置从0开始顺序解封装并获取packet的,这也是一种比较省时省力的读取方式。然而对于一些视频文件,它们在封装的时候,临近位置的video packet和audio packet的pts可能会差很多,这就导致demux同一时间解出的video和audio的pts差异会比较大,无法同时送给解码器解码,这也是demux和decoder之间要添加缓存buffer的原因之一。回到问题,对于上面提到的这种问题片源,player seek之后,demux解出的第一帧video和audio的pts会差很多,而VLC的clock会用seek后第一帧的pts做参考时间基准。后续,VLC会根据该时间基准,将音视频帧的pts转换到系统时间上。具体换算关系如下:

/*****************************************************************************

 * ClockStreamToSystem: converts a movie clock to system date

 *****************************************************************************/

//i_stream        :当前帧的原始pts

//cl->ref.i_stream:stream的参考时间基准,即收到第一帧的原始pts

//cl->ref.i_system:系统参考时间基准,即收到第一帧的系统时间

static mtime_t ClockStreamToSystem( input_clock_t *cl, mtime_t i_stream )

{

    if( !cl->b_has_reference )

        return VLC_TS_INVALID;

 

    return ( i_stream - cl->ref.i_stream ) * cl->i_rate / INPUT_RATE_DEFAULT +

           cl->ref.i_system;

}


以下面的日志为例,demux seek后解到的第一帧是video数据,因此以这一帧数据的pts做时间基准。后续demux解出了第一帧audio数据,然而这帧数据的pts要比video的大很多,导致换算成系统时间的pts也大很多,在Audio同步时(参考VLC Audio同步原理分析),触发了too early条件,往AudioTrack塞0导致无声。

//seek后demux的第一帧audio和video数据pts差异较大,因为先解出video数据,因此以video pts为时间基准

04-28 15:32:49.791 15181 15495 D VLC     : [cebd5930/3c87] libvlc demux: 1st video dts 106873434, pts 106873434

04-28 15:32:49.795 15181 15495 D VLC     : [cebd5930/3c87] libvlc demux: 1st audio dts 107456000, pts 107456000

//触发too early,往AudioTrack塞0导致无声

04-28 15:32:49.958 15181 15517 W VLC     : [cf15d6b0/3c9d] libvlc audio output: playback way too early (-538238) than (-240000), cache 480585: playing silence

04-28 15:32:49.958 15181 15517 D VLC     : [cf15d6b0/3c9d] libvlc audio output: inserting 25835 zeroes

2.pts跳变

pts跳变比较好理解,就是audio的pts因为各种原因发生了跳变,在audio同步时触发too early条件,导致无声。

//fifo demux后的pts发生了跳变

04-28 11:33:11.578 10825 11073 D VLC     : [88486a30/2b41] libvlc decoder: FFmpeg vlc_fifo_DequeueUnlocked i_pts 80495001

04-28 11:33:11.579 10825 11073 D VLC     : [88486a30/2b41] libvlc decoder: FFmpeg vlc_fifo_DequeueUnlocked i_pts 81796001

//avcodec送往audio软解的pts发生了跳变

04-28 11:12:08.052  6481  6656 W VLC     : [8a8ee3b0/1a00] libvlc decoder: avcodec_send_packet i_pts 93441001

04-28 11:12:08.053  6481  6656 W VLC     : [8a8ee3b0/1a00] libvlc decoder: avcodec_send_packet i_pts 94799001

//送往AudioTrack的pts发生了跳变

04-28 11:12:08.053  6481  6656 D VLC     : [a5a8d430/1a00] libvlc audio output: aout_DecSynchronize drift 15430, cache 1783006 ,cur 57511259532, pts 57513027108

04-28 11:12:09.161  6481  6656 D VLC     : [a5a8d430/1a00] libvlc audio output: aout_DecSynchronize drift -1306330, cache 693339 ,cur 57512368064, pts 57514367732

//触发too early条件,往AudioTrack塞0

04-28 11:33:12.554 10825 11073 W VLC     : [a5a8d430/2b41] libvlc audio output: playback way too early (-1264388) than (-240000), cache 734153: playing silence

04-28 11:33:12.555 10825 11073 D VLC     : [a5a8d430/2b41] libvlc audio output: inserting 27879 zeroes

二、起播无声

1.AudioTrack起播慢

VLC Audio同步原理分析中有介绍过,audio在做同步时需要考虑AudioTrack和RingBuffer的缓存值,如果在往AudioTrack喂数据的一段时间内AudioTrack都没有播放,就会导致缓存值过大,进而触发too late条件导致player强制flush缓存,出现无声问题。如果片源含有视频流,因为视频和音频起播速度可能存在差异,刚起播的阶段应该还会有轻微的音画不同步。(在audio master的方案上,video需要向audio对齐,如果audio没有播放,audio clock不会增长,video也就不会播放,因此不会存在这个问题)

//刚起播的200ms内,player往AudioTrack写入了大量数据

04-28 14:34:36.891  8427  9017 E VLC     : [ce8cffb0/2339] libvlc audio output: AudioTrack_Play write bytes: 12288, frames: 3072

04-28 14:34:36.894  8427  9006 D VLC     : [ce8cffb0/232e] libvlc audio output: i_audiotrack_us 3494, written 64000, circular 0, delay 60506

04-28 14:34:37.119  8427  9017 E VLC     : [ce8cffb0/2339] libvlc audio output: AudioTrack_Play write bytes: 6136, frames: 1534

04-28 14:34:37.127  8427  9006 D VLC     : [ce8cffb0/232e] libvlc audio output: i_audiotrack_us 117401, written 1114645, circular 0, delay 997244

//这段时间通过AudioTrack_getPlaybackHeadPosition获取的position一直为0

04-28 14:34:36.891  8427  9006 D VLC     : [ce8cffb0/232e] libvlc audio output: i_audiotrack_us 0us in AudioTrack_GetSmoothPositionUs

04-28 14:34:37.127  8427  9006 D VLC     : [ce8cffb0/232e] libvlc audio output: i_audiotrack_us 0us in AudioTrack_GetSmoothPositionUs

//大量数据积压在AudioTrack和RingBuffer中,导致cache不断变大,进而导致drift不断变大

04-28 14:34:37.127  8427  9006 D VLC     : [ce8cffb0/232e] libvlc audio output: aout_DecSynchronize drift 180914, cache 997244 ,cur 2119317784, pts 2120134113

//player判断audio播放太慢,触发too late逻辑,flushing buffers导致无声

04-28 14:34:37.127  8427  9006 W VLC     : [ce8cffb0/232e] libvlc audio output: playback way too late (180914) than (180000), cache 997244: flushing buffers

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值