Skip to content

Instantly share code, notes, and snippets.

@gyk
Created April 15, 2019 09:23
Show Gist options
  • Save gyk/777c6ea122f08ec25c107042f7eec44e to your computer and use it in GitHub Desktop.
Save gyk/777c6ea122f08ec25c107042f7eec44e to your computer and use it in GitHub Desktop.
VLC MP4_GetInterleaving, annotated source code
/* Analyzes chunks to find max interleave length
* sets flat flag if no interleaving is in use */
static void MP4_GetInterleaving( demux_t *p_demux, vlc_tick_t *pi_max_contiguous, bool *pb_flat )
{
demux_sys_t *p_sys = p_demux->p_sys;
*pi_max_contiguous = 0;
*pb_flat = true;
/* Find first recorded chunk */
mp4_track_t *tk = NULL;
uint64_t i_duration = 0;
/// 遍历所有 track,找到位置最前的一个
for( unsigned i=0; i < p_sys->i_tracks; i++ )
{
mp4_track_t *cur = &p_sys->track[i];
if( !cur->i_chunk_count )
continue;
if( tk == NULL || cur->chunk[0].i_offset < tk->chunk[0].i_offset )
tk = cur;
}
/// `i_chunk`: 每个 track 当前 chunk 的游标
/// `i_offset`: chunk 在文件中的绝对位置
/// `i_virtual_run_number`: chunks interleaving sequence (WTF is it?)
for( ; tk != NULL; )
{
i_duration += tk->chunk[tk->i_chunk].i_duration;
tk->i_chunk++;
/// 遍历所有 track,找到未处理 chunk 位置最靠前的 track
/* Find next chunk in data order */
mp4_track_t *nexttk = NULL;
for( unsigned i=0; i < p_sys->i_tracks; i++ )
{
mp4_track_t *cur = &p_sys->track[i];
/// 已经到结尾,略过
if( cur->i_chunk == cur->i_chunk_count )
continue;
if( nexttk == NULL ||
cur->chunk[cur->i_chunk].i_offset < nexttk->chunk[nexttk->i_chunk].i_offset )
nexttk = cur;
}
/* copy previous run */
if( nexttk && nexttk->i_chunk > 0 )
nexttk->chunk[nexttk->i_chunk].i_virtual_run_number =
nexttk->chunk[nexttk->i_chunk - 1].i_virtual_run_number;
if( tk != nexttk )
{
vlc_tick_t i_dur = MP4_rescale_mtime( i_duration, tk->i_timescale );
if( i_dur > *pi_max_contiguous )
*pi_max_contiguous = i_dur;
i_duration = 0;
/// 当前的 track 尚未结束,但是另一 track 的 chunk 出现,所以是交织的排布
if( tk->i_chunk != tk->i_chunk_count )
*pb_flat = false;
if( nexttk && nexttk->i_chunk > 0 ) /* new run number */
nexttk->chunk[nexttk->i_chunk].i_virtual_run_number++;
}
tk = nexttk;
}
/* reset */
for( unsigned i=0; i < p_sys->i_tracks; i++ )
p_sys->track[i].i_chunk = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment