Vlc部分功能
来源:互联网 发布:淘宝联盟点击赚钱 编辑:程序博客网 时间:2024/06/05 11:13
Vlc部分功能流程图
block_FifoGet
获取编码的block
DecoderProcess
Decoder thread
DecoderProcessVideo
packetizer_Packetize将接受到的block进行packet组装为一个完整的NAL
DecoderDecodeVideo
使用ffmpeg解码
DecodeVideo
判断当前packet是否过期需要丢弃,无需解码
填充AVPacket,解码avcodec_decode_video2
Compute the PTS,Stream pts转换为system pts,并加上缓冲延时时间。判断当前帧是否已经滞后,并记统计滞后数目。解码下一帧时根据滞后标记,决定解码还是直接丢弃。更新p_pic->date =i_pts
DecoderPlayVideo stream pts到system pts的转换,加上缓冲时间延迟。display thread会用于判断显示
Display thread
ThreadDisplayPicture
ThreadDisplayPreparePicture
ThreadDisplayRenderPicture
picture_fifo_Pop获取解码过的picture
根据decoded->date与当前系统时间相减,若超过20ms直接丢弃,若不到则显示并打印提示滞后时间。
将decoded的picture赋值vout->p->displayed.decoded = picture_Hold(decoded);
若current为空则直接赋值currentvout->p->displayed.current =picture;否则赋给next。vout->p->displayed.next=picture;
date_refresh = vout->p->displayed.date +VOUT_REDISPLAY_DELAY - render_delay计算刷新时间,与当前比较决定是否refresh =date_refresh <=date;
vout->p->displayed.current获取current显示的picture
vout_display_Prepare进行subpic和todisplay的blend
Direct3DImportPicture将picture的surface copy到系统texture的surface
Direct3DImportSubpicture将subpicture blend入到texture
vout_display_Display完成显示
1. 对于ts流和一些封装过的流在live555接收到数据未作处理直接调用block_FifoPut放入p_sys->block_fifo_t之中。
2. 需要Demux线程调用block_FifoGet(p_sys->p_fifo )分析数据去掉封装最后调用block_FifoPut(p_owner->p_fifo,p_block );放入到decoder_owner_sys_t的p_fifo中。对于直接是h264的数据的block是直接放入decoder_owner_sys_t的p_fifo中的。
解码线程
i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
&b_gotpicture, &pkt );
利用ffmpeg decode解码得到AVFrame即p_sys->p_ff_pic,里面包含有解码的frame的pts,vlc将对这个pts进行修正,确保时间戳的合法性。
渲染线程
ThreadDisplayPicture在渲染线程中执行。
vout_display_Prepare主要讲subpic与todisplay进行blend
解码线程与渲染线程的同步:
Decode thread和renderthrad通过picture_fifo_t对解码过的picture_t进行同步使用
sys->pool:Direct3DCreatePool调用picture_pool_NewExtended,picture_reserved为false,会创建count为1的pool
sys->decoder_pool:vout_InitWrapper会创建count为33的pool,前四个的picture_reserved设置为true。XXX3 for filter, 1 for SPU. 1 for last displayed picture,28 for decoder picture
sys->private_pool:picture_pool_Reserve(sys->decoder_pool,private_picture);同时将sys->decoder_pool的前四个的picture_reserved设置为true,并会创建count为4的pool。
以下使用ts stream作为source进行debug调试:
call stack
decode thread:
Decode thread get display date
input_clock_ConvertTS
根据ffmpeg解码给出的pts,pts转换为系统时间加上delay时间与当前系统时间比较判断当前frame是否过期。
判断当前帧是否滞后,并统计滞后的数目
更新picture的pts,直接等于ffmpeg解码给出的时间戳。
丢弃过期的block:
主要用于判断当前frame的时间戳是否已经过期,并统计过期的frame数目,当只有一帧数据时需要更新第一个过期时间,此时间可用于后面的frame是解码还是丢弃的时间参考。
一般由于网络延迟或者cpu解码性能不够导致。
Display thread:
prepare
Prepare render 时会将pts与当前的系统的时间进行比较,若有延迟则会log显示滞后时间。可以通过vlc的消息窗口显示当前的log信息。
消息窗口在vlc 的工具菜单选项下面,或者按快捷键Ctrl+M显示出来。图如下。
Buffering的过程:
i_buffering_duration的时常就是的预先设置好的缓冲时间,如1000ms,则i_buffering_duration = 1000*1000;
call stack:
typedef struct
{
/* Program ID */
int i_id;
/* Number of es for this pgrm */
int i_es;
bool b_selected;
bool b_scrambled;
/* Clock for this program */
input_clock_t *p_clock; //此处使用了这个clock
char *psz_name;
char *psz_now_playing;
char *psz_publisher;
}es_out_pgrm_t;
PCR: program clock reference
Ts stream block 更新pcr
根据streamclock和system clock创建clock_point_t。
Demux使用input_clock_Update将frame的stream时间和系统时间更新到clock->last中,而clock->ref参考时钟只有在cl->b_has_reference没有的情况下才会进行更新。
i_ck_stream的时间间隔一般为33.3ms。
ClockStreamToSystem,将当前的stream clock减去stream ref,再加上system ref,得到期望的时间;滞后时间即为当前时间减去cache的缓冲时间,再减去期望时间。通过滞后时间可以判断当前frame是否已经滞后。
具体stream和system的duration通过cl的ref和last来计算。
int input_clock_GetState( input_clock_t *cl,
mtime_t *pi_stream_start,mtime_t *pi_system_start,
mtime_t *pi_stream_duration,mtime_t *pi_system_duration )
{
vlc_mutex_lock( &cl->lock );
if( !cl->b_has_reference )
{
vlc_mutex_unlock( &cl->lock );
return VLC_EGENERIC;
}
*pi_stream_start = cl->ref.i_stream;
*pi_system_start = cl->ref.i_system;
*pi_stream_duration = cl->last.i_stream -cl->ref.i_stream;
*pi_system_duration = cl->last.i_system -cl->ref.i_system;
vlc_mutex_unlock( &cl->lock );
return VLC_SUCCESS;
}
render
network-caching参数主要用于修改pts。
/*PTS delay: request from demux first. This is required for
* access_demux and some special caseslike SDP demux. Otherwise,
* fallback to access */
if( demux_Control( in->p_demux,DEMUX_GET_PTS_DELAY,
&in->i_pts_delay ) )
Ts流的pts一般是以90khz为单位,计算时间戳时使用i_pcr *100 / 9,得到单位是us。
cl->last = clock_point_Create( i_ck_stream, i_ck_system );
调用clock_point_Create用于更新参考时钟的cl->last.i_stream和cl->last.i_system。
Clock referenceaverage counter
i_cr_average = var_GetInteger(p_input,"cr-average" );一般等于40
#define CLOCK_FREQINT64_C(1000000)
#define DEFAULT_PTS_DELAY (3*CLOCK_FREQ/10)
当设置network-caching=1000时,i_cr_average = 133;
const inti_cr_average =var_GetInteger( p_input, "cr-average" ) * i_pts_delay / DEFAULT_PTS_DELAY;
es_out_SetJitter( p_input->p->p_es_out,i_pts_delay, 0,i_cr_average );
streamclock convert to system clock
ClockStreamToSystem ( cl, *pi_ts0 + AvgGet( &cl->drift ) );
然后加上delay时间得到最终的时间戳。
返回的时间单位为us
About packetizer_Packetize
- Vlc部分功能
- VLC部分API学习
- VLC-android开机启动部分
- VLC 服务器RTSP功能实现
- vlc的流输出功能
- vlc的流输出功能
- Linux 下VLC服务器RTSP功能实现
- Linux 下VLC服务器RTSP功能实现
- 使用vlc-2.21的rtsp点播功能
- VLC
- VLC
- VLC
- VLC
- vlc
- vlc-android的视频播放部分的解析
- jdbc部分功能介绍
- IE部分功能总结
- DataGrid部分功能实现
- Vue2.0子父组件通信
- 产生25个int类型的随机数。对于每一个随机值,使用if-else语句来将其分类为大于、小于或等于紧随它而随机生成的值。
- 【教程】将Java条形码添加到PDF文档的两种方法
- Android vector标签 PathData 画图超详解
- 深入理解MVC
- Vlc部分功能
- Vuejs(15)——Vue的异步组件
- IntelliJ IDEA开发Spark、打JAR包
- idea使用心得
- staruml文字换行
- Linux虚拟机下载和安装
- Vuejs(16)——Vue插件写、用详解(附demo)
- Airport Announcements URAL
- QT定时器使用的实例