【VLC核心一】播放流程梳理->live555收流+ffmpeg:AVCodec解码
来源:互联网 发布:c语言 void 编辑:程序博客网 时间:2024/06/05 20:04
一、前言
VLC播放音视频的核心流程梳理,从live555收流到ffmpeg解码的整套流程
涉及到MultiFramedRTPSource、RTPSource、FramedSource、live555、es_out、decoder、video、clock、video_output、araw、mtime、dec、input、output、filters、directx等核心类。
二、核心点备注
1、RTPSource中使用报文时间戳与当前时间计算抖动的核心代码
unsigned arrival = (timestampFrequency*timeNow.tv_sec);//音频8000,视频90000 arrival += (unsigned)((2.0*timestampFrequency*timeNow.tv_usec + 1000000.0)/2000000); // note: rounding int transit = arrival - rtpTimestamp; if (fLastTransit == (~0)) fLastTransit = transit; // hack for first time int d = transit - fLastTransit; fLastTransit = transit; if (d < 0) d = -d; fJitter += (1.0/16.0) * ((double)d - fJitter);
2、RTPSource中使用报文时间戳差值计算出timeval 类型的presentationTime的核心代码
// Return the 'presentation time' that corresponds to "rtpTimestamp": if (fSyncTime.tv_sec == 0 && fSyncTime.tv_usec == 0) { // This is the first timestamp that we've seen, so use the current // 'wall clock' time as the synchronization time. (This will be // corrected later when we receive RTCP SRs.) fSyncTimestamp = rtpTimestamp; fSyncTime = timeNow; } int timestampDiff = rtpTimestamp - fSyncTimestamp; // Note: This works even if the timestamp wraps around // (as long as "int" is 32 bits) // Divide this by the timestamp frequency to get real time://视频timeDiff =0.040000000000000001 double timeDiff = timestampDiff/(double)timestampFrequency; // Add this to the 'sync time' to get our result: unsigned const million = 1000000; unsigned seconds, uSeconds; if (timeDiff >= 0.0) { seconds = fSyncTime.tv_sec + (unsigned)(timeDiff); uSeconds = fSyncTime.tv_usec + (unsigned)((timeDiff - (unsigned)timeDiff)*million); if (uSeconds >= million) { uSeconds -= million; ++seconds; } } else { timeDiff = -timeDiff; seconds = fSyncTime.tv_sec - (unsigned)(timeDiff); uSeconds = fSyncTime.tv_usec - (unsigned)((timeDiff - (unsigned)timeDiff)*million); if ((int)uSeconds < 0) { uSeconds += million; --seconds; } }
3、live555.cpp中将timeval转换为微秒级时间戳i_pts的要点
int64_t i_pts = (int64_t)pts.tv_sec * INT64_C(1000000) + (int64_t)pts.tv_usec;/* XXX Beurk beurk beurk Avoid having negative value XXX */ i_pts &= INT64_C(0x00ffffffffffffff);<span style="color:#3333FF;">1)注意避免翻转为负数 2、block里i_pts+1,i_dts根据sdp中的packetization-mode=1字段判断</span>4、处理H.264视频的要点
1)丢帧策略可以设置丢B帧、非参考帧、除关键帧以外所有帧等,可以在处理延时的情况下加速解码,尝试赶上发流速度,是明智之举;
2)如果存在过期的帧,且当前时间减第一个过期帧的时间>5S,则认为该帧过期时间太长,直接释放;如果统计的过期帧数>4且<12,则设置ffmpeg的解码器丢帧策略;
3)解码后得到pts,如果frame_rate和frame_rate_base>0,或者p_context->time_base.den > 0计算获得下一帧的pts,更新p_sys->i_pts,用于下一帧解码时校验数据;
4)每次ffmpeg解码后,使用clock机制将pts流时间戳转换为系统时间,然后检查转换后的时间是否过期,过期算法为:判断显示时间<=mdate() 说明已过期,累加过期帧数;备注:*pi_ts0 >= mdate() + i_ts_delay + i_ts_buffering + i_ts_bound( i_ts_bound默认值为9s)
5)最后在送渲染队列前使用clock::input_clock_ConvertTS将时戳拉伸到播放rate对应区间。
5、处理音频的要点
1)计算比特率和样本数 unsigned samples = (8 * p_block->i_buffer) / framebits;
2)通过采样数计算时间增量 mtime_t date_Increment( date_t *p_date, uint32_t i_nb_samples )
3)a、发现正确的播放频率 b、重新制作音频帧。核心流程如下:
1、仅正常播放速率支持音频播放,否则丢弃2、if ( start_date != VLC_TS_INVALID && start_date < now )期望时间戳帧已严重过期,重刷音频缓存数据,停止重采样(主要发生在用户暂停或解码器错误)3、if ( p_buffer->i_pts < now + AOUT_MIN_PREPARE_TIME )帧已过期,直接丢弃;AOUT_MIN_PREPARE_TIME为40ms4、mtime_t drift = start_date - p_buffer->i_pts;偏移量drift = 期望播放时间戳-当前帧的实际时间戳,drift<0说明帧滞后来了,drift>0说明帧提前来了;5、if( drift < -i_input_rate * 3 * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT )如果偏移量<-3*40ms,则停止缓冲,停止重采样。预设值。6、if( drift > +i_input_rate * 3 * AOUT_MAX_PTS_DELAY / INPUT_RATE_DEFAULT )如果偏移量>3*60ms,缓冲太晚,直接丢弃7、if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) && ( drift < -AOUT_MAX_PTS_ADVANCE || drift > +AOUT_MAX_PTS_DELAY ) && p_input->i_nb_resamplers > 0 )drift漂移量<-40ms或>60ms,则重新发现播放频率.即滞后40ms或提前60ms(主要原因是:1、输入时钟偏移有误2、用户短暂暂停 3、输出端有点延时,丢失了一点同步--费解,4、现网有部分摄像头的采样率和码流里的时间戳不匹配,也会导致该问题)8、根据偏移结果微调采样频率9、p_buffer->i_pts = start_date;最终将期望时间戳送渲染;
三、核心流程时序图
- 【VLC核心一】播放流程梳理->live555收流+ffmpeg:AVCodec解码
- FFMPEG--裸码流解码AVCodec
- 整理 live555 rtsp ffmpeg 客户端解码流程
- VLC音频重采样Audio resample核心流程梳理
- windows下live555+rtsp+ffmpeg媒体源,nginx+rtmp转发服务器,vlc播放rtmp媒体流
- ffmpeg--------------avcodec----------
- VLC播放简单流程
- vlc播放流程分析
- VLC解码播放H264文件
- FFMpeg的解码流程
- FFMpeg的解码流程
- FFMPEG解码流程
- ffmpeg解码流程
- ffmpeg解码流程
- FFMpeg的解码流程
- ffmpeg解码流程
- FFMPEG解码流程
- FFMpeg的解码流程
- 用angularjs做全选和反选遇到的问题
- c++ java相互调用
- 拓扑排序题集
- RN(react native)入坑指南-01,Hello RN,Windows下的环境搭建
- VmProtect v2.12.3 安装注册
- 【VLC核心一】播放流程梳理->live555收流+ffmpeg:AVCodec解码
- C++第三次实验——项目1-静态成员应用
- Sublime3 Terminal UBuntu install
- Linux学习笔记11
- JspSmartUpload中文乱码问题解决
- zoj 3209 Treasure Map dancing links
- Android-->原生保存Bitmap(图片),压缩图片,创建图片缩略图和视频缩略图(任意大小)
- iOS ShareSDK实现分享——微信分享
- Python 练习实例8