📄 mkv.cpp
字号:
error: delete p_sys; return VLC_EGENERIC;}/***************************************************************************** * Close: frees unused data *****************************************************************************/static void Close( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; delete p_sys;}/***************************************************************************** * Control: *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){ demux_sys_t *p_sys = p_demux->p_sys; int64_t *pi64; double *pf, f; int i_skp; size_t i_idx; vlc_meta_t *p_meta; input_attachment_t ***ppp_attach; int *pi_int; int i; switch( i_query ) { case DEMUX_GET_ATTACHMENTS: ppp_attach = (input_attachment_t***)va_arg( args, input_attachment_t*** ); pi_int = (int*)va_arg( args, int * ); if( p_sys->stored_attachments.size() <= 0 ) return VLC_EGENERIC; *pi_int = p_sys->stored_attachments.size(); *ppp_attach = (input_attachment_t**)malloc( sizeof(input_attachment_t**) * p_sys->stored_attachments.size() ); if( !(*ppp_attach) ) return VLC_ENOMEM; for( i = 0; i < p_sys->stored_attachments.size(); i++ ) { attachment_c *a = p_sys->stored_attachments[i]; (*ppp_attach)[i] = vlc_input_attachment_New( a->psz_file_name.c_str(), a->psz_mime_type.c_str(), NULL, a->p_data, a->i_size ); } return VLC_SUCCESS; case DEMUX_GET_META: p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); vlc_meta_Merge( p_meta, p_sys->meta ); return VLC_SUCCESS; case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->f_duration > 0.0 ) { *pi64 = (int64_t)(p_sys->f_duration * 1000); return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_GET_POSITION: pf = (double*)va_arg( args, double * ); if ( p_sys->f_duration > 0.0 ) *pf = (double)(p_sys->i_pts >= p_sys->i_start_pts ? p_sys->i_pts : p_sys->i_start_pts ) / (1000.0 * p_sys->f_duration); return VLC_SUCCESS; case DEMUX_SET_POSITION: f = (double)va_arg( args, double ); Seek( p_demux, -1, f, NULL ); return VLC_SUCCESS; case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = p_sys->i_pts; return VLC_SUCCESS; case DEMUX_GET_TITLE_INFO: if( p_sys->titles.size() > 1 || ( p_sys->titles.size() == 1 && p_sys->titles[0]->i_seekpoint > 0 ) ) { input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** ); int *pi_int = (int*)va_arg( args, int* ); *pi_int = p_sys->titles.size(); *ppp_title = (input_title_t**)malloc( sizeof( input_title_t**) * p_sys->titles.size() ); for( size_t i = 0; i < p_sys->titles.size(); i++ ) { (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->titles[i] ); } return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_SET_TITLE: /* TODO handle editions as titles */ i_idx = (int)va_arg( args, int ); if( i_idx < p_sys->used_segments.size() ) { p_sys->JumpTo( *p_sys->used_segments[i_idx], NULL ); return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_SET_SEEKPOINT: i_skp = (int)va_arg( args, int ); // TODO change the way it works with the << & >> buttons on the UI (+1/-1 instead of a number) if( p_sys->titles.size() && i_skp < p_sys->titles[p_sys->i_current_title]->i_seekpoint) { Seek( p_demux, (int64_t)p_sys->titles[p_sys->i_current_title]->seekpoint[i_skp]->i_time_offset, -1, NULL); p_demux->info.i_seekpoint |= INPUT_UPDATE_SEEKPOINT; p_demux->info.i_seekpoint = i_skp; return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_GET_FPS: pf = (double *)va_arg( args, double * ); *pf = 0.0; if( p_sys->p_current_segment && p_sys->p_current_segment->Segment() ) { const matroska_segment_c *p_segment = p_sys->p_current_segment->Segment(); for( size_t i = 0; i < p_segment->tracks.size(); i++ ) { mkv_track_t *tk = p_segment->tracks[i]; if( tk->fmt.i_cat == VIDEO_ES && tk->fmt.video.i_frame_rate_base > 0 ) { *pf = (double)tk->fmt.video.i_frame_rate / tk->fmt.video.i_frame_rate_base; break; } } } return VLC_SUCCESS; case DEMUX_SET_TIME: default: return VLC_EGENERIC; }}int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration ){ pp_simpleblock = NULL; pp_block = NULL; *pi_ref1 = 0; *pi_ref2 = 0; for( ;; ) { EbmlElement *el = NULL; int i_level; if ( ep == NULL ) return VLC_EGENERIC; if( pp_simpleblock != NULL || ((el = ep->Get()) == NULL && pp_block != NULL) ) { /* Check blocks validity to protect againts broken files */ if( BlockFindTrackIndex( NULL, pp_block , pp_simpleblock ) ) { delete pp_block; pp_simpleblock = NULL; pp_block = NULL; continue; } /* update the index */#define idx p_indexes[i_index - 1] if( i_index > 0 && idx.i_time == -1 ) { if ( pp_simpleblock != NULL ) idx.i_time = pp_simpleblock->GlobalTimecode() / (mtime_t)1000; else idx.i_time = (*pp_block).GlobalTimecode() / (mtime_t)1000; idx.b_key = *pi_ref1 == 0 ? true : false; }#undef idx return VLC_SUCCESS; } i_level = ep->GetLevel(); if( el == NULL ) { if( i_level > 1 ) { ep->Up(); continue; } msg_Warn( &sys.demuxer, "EOF" ); return VLC_EGENERIC; } /* Verify that we are still inside our cluster * It can happens whith broken files and when seeking * without index */ if( i_level > 1 ) { if( cluster && !ep->IsTopPresent( cluster ) ) { msg_Warn( &sys.demuxer, "Unexpected escape from current cluster" ); cluster = NULL; } if( !cluster ) continue; } /* do parsing */ switch ( i_level ) { case 1: if( MKV_IS_ID( el, KaxCluster ) ) { cluster = (KaxCluster*)el; i_cluster_pos = cluster->GetElementPosition(); /* add it to the index */ if( i_index == 0 || ( i_index > 0 && p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) ) { IndexAppendCluster( cluster ); } // reset silent tracks for (size_t i=0; i<tracks.size(); i++) { tracks[i]->b_silent = false; } ep->Down(); } else if( MKV_IS_ID( el, KaxCues ) ) { msg_Warn( &sys.demuxer, "find KaxCues FIXME" ); return VLC_EGENERIC; } else { msg_Dbg( &sys.demuxer, "unknown (%s)", typeid( el ).name() ); } break; case 2: if( MKV_IS_ID( el, KaxClusterTimecode ) ) { KaxClusterTimecode &ctc = *(KaxClusterTimecode*)el; ctc.ReadData( es.I_O(), SCOPE_ALL_DATA ); cluster->InitTimecode( uint64( ctc ), i_timescale ); } else if( MKV_IS_ID( el, KaxClusterSilentTracks ) ) { ep->Down(); } else if( MKV_IS_ID( el, KaxBlockGroup ) ) { i_block_pos = el->GetElementPosition(); ep->Down(); } else if( MKV_IS_ID( el, KaxSimpleBlock ) ) { pp_simpleblock = (KaxSimpleBlock*)el; pp_simpleblock->ReadData( es.I_O() ); pp_simpleblock->SetParent( *cluster ); } break; case 3: if( MKV_IS_ID( el, KaxBlock ) ) { pp_block = (KaxBlock*)el; pp_block->ReadData( es.I_O() ); pp_block->SetParent( *cluster ); ep->Keep(); } else if( MKV_IS_ID( el, KaxBlockDuration ) ) { KaxBlockDuration &dur = *(KaxBlockDuration*)el; dur.ReadData( es.I_O() ); *pi_duration = uint64( dur ); } else if( MKV_IS_ID( el, KaxReferenceBlock ) ) { KaxReferenceBlock &ref = *(KaxReferenceBlock*)el; ref.ReadData( es.I_O() ); if( *pi_ref1 == 0 ) { *pi_ref1 = int64( ref ) * cluster->GlobalTimecodeScale(); } else if( *pi_ref2 == 0 ) { *pi_ref2 = int64( ref ) * cluster->GlobalTimecodeScale(); } } else if( MKV_IS_ID( el, KaxClusterSilentTrackNumber ) ) { KaxClusterSilentTrackNumber &track_num = *(KaxClusterSilentTrackNumber*)el; track_num.ReadData( es.I_O() ); // find the track for (size_t i=0; i<tracks.size(); i++) { if ( tracks[i]->i_number == uint32(track_num)) { tracks[i]->b_silent = true; break; } } } break; default: msg_Err( &sys.demuxer, "invalid level = %d", i_level ); return VLC_EGENERIC; } }}static block_t *MemToBlock( demux_t *p_demux, uint8_t *p_mem, int i_mem, size_t offset){ block_t *p_block; if( !(p_block = block_New( p_demux, i_mem + offset ) ) ) return NULL; memcpy( p_block->p_buffer + offset, p_mem, i_mem ); //p_block->i_rate = p_input->stream.control.i_rate; return p_block;}static void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock, mtime_t i_pts, mtime_t i_duration, bool f_mandatory ){ demux_sys_t *p_sys = p_demux->p_sys; matroska_segment_c *p_segment = p_sys->p_current_segment->Segment(); size_t i_track; unsigned int i; bool b; if( p_segment->BlockFindTrackIndex( &i_track, block, simpleblock ) ) { msg_Err( p_demux, "invalid track number" ); return; } mkv_track_t *tk = p_segment->tracks[i_track]; if( tk->fmt.i_cat != NAV_ES && tk->p_es == NULL ) { msg_Err( p_demux, "unknown track number" ); return; } if( i_pts + i_duration < p_sys->i_start_pts && tk->fmt.i_cat == AUDIO_ES ) { return; /* discard audio packets that shouldn't be rendered */ } if ( tk->fmt.i_cat != NAV_ES ) { es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b ); if( !b ) { tk->b_inited = false; return; } } /* First send init data */ if( !tk->b_inited && tk->i_data_init > 0 ) { block_t *p_init; msg_Dbg( p_demux, "sending header (%d bytes)", tk->i_data_init ); p_init = MemToBlock( p_demux, tk->p_data_init, tk->i_data_init, 0 ); if( p_init ) es_out_Send( p_demux->out, tk->p_es, p_init ); } tk->b_inited = true; for( i = 0; (block != NULL && i < block->NumberFrames()) || (simpleblock != NULL && i < simpleblock->NumberFrames()); i++ ) { block_t *p_block; DataBuffer *data; if( simpleblock != NULL ) { data = &simpleblock->GetBuffer(i); // condition when the DTS is correct (keyframe or B frame == NOT P frame) f_mandatory = simpleblock->IsDiscarda
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -