📄 mkv.cpp
字号:
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() ) { 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_SET_TIME: case DEMUX_GET_FPS: default: return VLC_EGENERIC; }}#if LIBMATROSKA_VERSION >= 0x000800int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )#elseint matroska_segment_c::BlockGet( KaxBlock * & pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )#endif{#if LIBMATROSKA_VERSION >= 0x000800 pp_simpleblock = NULL;#endif pp_block = NULL; *pi_ref1 = 0; *pi_ref2 = 0; for( ;; ) { EbmlElement *el = NULL; int i_level; if ( ep == NULL ) return VLC_EGENERIC;#if LIBMATROSKA_VERSION >= 0x000800 if( pp_simpleblock != NULL || ((el = ep->Get()) == NULL && pp_block != NULL) )#else if( (el = ep->Get()) == NULL && pp_block != NULL )#endif { /* update the index */#define idx p_indexes[i_index - 1] if( i_index > 0 && idx.i_time == -1 ) {#if LIBMATROSKA_VERSION >= 0x000800 if ( pp_simpleblock != NULL ) idx.i_time = pp_simpleblock->GlobalTimecode() / (mtime_t)1000; else#endif idx.i_time = (*pp_block).GlobalTimecode() / (mtime_t)1000; idx.b_key = *pi_ref1 == 0 ? VLC_TRUE : VLC_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; } /* 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 = VLC_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(); }#if LIBMATROSKA_VERSION >= 0x000800 else if( MKV_IS_ID( el, KaxSimpleBlock ) ) { pp_simpleblock = (KaxSimpleBlock*)el; pp_simpleblock->ReadData( es.I_O() ); pp_simpleblock->SetParent( *cluster ); }#endif 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 = VLC_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;}#if LIBMATROSKA_VERSION >= 0x000800static void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock, mtime_t i_pts, mtime_t i_duration, bool f_mandatory )#elsestatic void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts, mtime_t i_duration, bool f_mandatory )#endif{ 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; vlc_bool_t b;#define tk p_segment->tracks[i_track] for( i_track = 0; i_track < p_segment->tracks.size(); i_track++ ) {#if LIBMATROSKA_VERSION >= 0x000800 if( (block != NULL && tk->i_number == block->TrackNum()) || (simpleblock != NULL && tk->i_number == simpleblock->TrackNum()))#else if( tk->i_number == block->TrackNum() )#endif { break; } } if( i_track >= p_segment->tracks.size() ) { msg_Err( p_demux, "invalid track number" ); return; } 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 = VLC_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 = VLC_TRUE;#if LIBMATROSKA_VERSION >= 0x000800 for( i = 0; (block != NULL && i < block->NumberFrames()) || (simpleblock != NULL && i < simpleblock->NumberFrames()); i++ )#else for( i = 0; i < block->NumberFrames(); i++ )#endif { block_t *p_block; DataBuffer *data;#if LIBMATROSKA_VERSION >= 0x000800 if ( simpleblock != NULL ) { data = &simpleblock->GetBuffer(i); // condition when the DTS is correct (keyframe or B frame == NOT P frame) f_mandatory = simpleblock->IsDiscardable() || simpleblock->IsKeyframe(); } else#endif data = &block->GetBuffer(i); if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER && tk->p_compression_data != NULL ) p_block = MemToBlock( p_demux, data->Buffer(), data->Size(), tk->p_compression_data->GetSize() ); else p_block = MemToBlock( p_demux, data->Buffer(), data->Size(), 0 ); if( p_block == NULL ) { break; }#if defined(HAVE_ZLIB_H) if( tk->i_compression_type == MATROSKA_COMPRESSION_ZLIB ) { p_block = block_zlib_decompress( VLC_OBJECT(p_demux), p_block ); } else#endif if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER ) { memcpy( p_block->p_buffer, tk->p_compression_data->GetBuffer(), tk->p_compression_data->GetSize() ); } if ( tk->fmt.i_cat == NAV_ES ) { // TODO handle the start/stop times of this packet if ( p_sys->b_ui_hooked ) { vlc_mutex_lock( &p_sys->p_ev->lock ); memcpy( &p_sys->pci_packet, &p_block->p_buffer[1], sizeof(pci_t) ); p_sys->SwapButtons(); p_sys->b_pci_packet_set = true; vlc_mutex_unlock( &p_sys->p_ev->lock ); block_Release( p_block ); } return; } // correct timestamping when B frames are used if( tk->fmt.i_cat != VIDEO_ES ) { p_block->i_dts = p_block->i_pts = i_pts; } else { if( !strcmp( tk->psz_codec, "V_MS/VFW/FOURCC" ) ) { // in VFW we have no idea about B frames p_block->i_pts = 0; p_block->i_dts = i_pts; } else { p_block->i_pts = i_pts; if ( f_mandatory ) p_block->i_dts = p_block->i_pts; else p_block->i_dts = min( i_pts, tk->i_last_dts + (mtime_t)(tk->i_default_duration >> 10)); p_sys->i_pts = p_block->i_dts; } } tk->i_last_dts = p_block->i_dts;#if 0msg_Dbg( p_demux, "block i_dts: "I64Fd" / i_pts: "I64Fd, p_block->i_dts, p_block->i_pts);#endif if( strcmp( tk->psz_codec, "S_VOBSUB" ) ) { p_block->i_length = i_duration * 1000; } es_out_Send( p_demux->out, tk->p_es, p_block ); /* use time stamp only for first block */ i_pts = 0; }#undef tk}matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial ){ int i_upper_lvl = 0; size_t i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -