📄 mkv.cpp
字号:
if ( ep == NULL ) return VLC_EGENERIC; el = ep->Get(); i_level = ep->GetLevel(); if( el == NULL && pp_block != NULL ) { /* update the index */#define idx p_indexes[i_index - 1] if( i_index > 0 && idx.i_time == -1 ) { idx.i_time = (*pp_block).GlobalTimecode() / (mtime_t)1000; idx.b_key = *pi_ref1 == -1 ? VLC_TRUE : VLC_FALSE; }#undef idx return VLC_SUCCESS; } if( el == NULL ) { if( ep->GetLevel() > 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(); } 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 == -1 ) { *pi_ref1 = int64( ref ); } else { *pi_ref2 = int64( ref ); } } 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){ block_t *p_block; if( !(p_block = block_New( p_demux, i_mem ) ) ) return NULL; memcpy( p_block->p_buffer, 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, mtime_t i_pts, mtime_t i_duration ){ 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( tk->i_number == block->TrackNum() ) { break; } } if( i_track >= p_segment->tracks.size() ) { msg_Err( p_demux, "invalid track number=%d", block->TrackNum() ); return; } if( tk->fmt.i_cat != NAV_ES && tk->p_es == NULL ) { msg_Err( p_demux, "unknown track number=%d", block->TrackNum() ); return; } if( i_pts < 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 ); if( p_init ) es_out_Send( p_demux->out, tk->p_es, p_init ); } tk->b_inited = VLC_TRUE; for( i = 0; i < block->NumberFrames(); i++ ) { block_t *p_block; DataBuffer &data = block->GetBuffer(i); p_block = MemToBlock( p_demux, data.Buffer(), data.Size() ); if( p_block == NULL ) { break; }#if defined(HAVE_ZLIB_H) if( tk->i_compression_type ) { p_block = block_zlib_decompress( VLC_OBJECT(p_demux), p_block ); }#endif 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; } // TODO implement 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 { p_block->i_dts = i_pts; p_block->i_pts = 0; } 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( EbmlStream *p_estream ){ int i_upper_lvl = 0; size_t i; EbmlElement *p_l0, *p_l1, *p_l2; bool b_keep_stream = false, b_keep_segment; // verify the EBML Header p_l0 = p_estream->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL); if (p_l0 == NULL) { return NULL; } p_l0->SkipData(*p_estream, EbmlHead_Context); delete p_l0; // find all segments in this file p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFFLL); if (p_l0 == NULL) { return NULL; } matroska_stream_c *p_stream1 = new matroska_stream_c( *this ); while (p_l0 != 0) { if (EbmlId(*p_l0) == KaxSegment::ClassInfos.GlobalId) { EbmlParser *ep; matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream ); b_keep_segment = false; ep = new EbmlParser(p_estream, p_l0, &demuxer ); p_segment1->ep = ep; p_segment1->segment = (KaxSegment*)p_l0; while ((p_l1 = ep->Get())) { if (MKV_IS_ID(p_l1, KaxInfo)) { // find the families of this segment KaxInfo *p_info = static_cast<KaxInfo*>(p_l1); p_info->Read(*p_estream, KaxInfo::ClassInfos.Context, i_upper_lvl, p_l2, true); for( i = 0; i < p_info->ListSize(); i++ ) { EbmlElement *l = (*p_info)[i]; if( MKV_IS_ID( l, KaxSegmentUID ) ) { KaxSegmentUID *p_uid = static_cast<KaxSegmentUID*>(l); b_keep_segment = (FindSegment( *p_uid ) == NULL); if ( !b_keep_segment ) break; // this segment is already known opened_segments.push_back( p_segment1 ); delete p_segment1->p_segment_uid; p_segment1->p_segment_uid = new KaxSegmentUID(*p_uid); } else if( MKV_IS_ID( l, KaxPrevUID ) ) { p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) ); } else if( MKV_IS_ID( l, KaxNextUID ) ) { p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) ); } else if( MKV_IS_ID( l, KaxSegmentFamily ) ) { KaxSegmentFamily *p_fam = new KaxSegmentFamily( *static_cast<KaxSegmentFamily*>(l) ); p_segment1->families.push_back( *p_fam ); } } break; } } if ( b_keep_segment ) { b_keep_stream = true; p_stream1->segments.push_back( p_segment1 ); } else delete p_segment1; } p_l0->SkipData(*p_estream, EbmlHead_Context); p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL); } if ( !b_keep_stream ) { delete p_stream1; p_stream1 = NULL; } return p_stream1;}bool matroska_segment_c::Select( mtime_t i_start_time ){ size_t i_track; /* add all es */ msg_Dbg( &sys.demuxer, "found %d es", tracks.size() ); sys.b_pci_packet_set = false; for( i_track = 0; i_track < tracks.size(); i_track++ ) { if( tracks[i_track]->fmt.i_cat == UNKNOWN_ES ) { msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", i_track, tracks[i_track]->i_number ); tracks[i_track]->p_es = NULL; continue; } if( !strcmp( tracks[i_track]->psz_codec, "V_MS/VFW/FOURCC" ) ) { if( tracks[i_track]->i_extra_data < (int)sizeof( BITMAPINFOHEADER ) ) { msg_Err( &sys.demuxer, "missing/invalid BITMAPINFOHEADER" ); tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' ); } else { BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)tracks[i_track]->p_extra_data; tracks[i_track]->fmt.video.i_width = GetDWLE( &p_bih->biWidth ); tracks[i_track]->fmt.video.i_height= GetDWLE( &p_bih->biHeight ); tracks[i_track]->fmt.i_codec = GetFOURCC( &p_bih->biCompression ); tracks[i_track]->fmt.i_extra = GetDWLE( &p_bih->biSize ) - sizeof( BITMAPINFOHEADER ); if( tracks[i_track]->fmt.i_extra > 0 ) { tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra ); memcpy( tracks[i_track]->fmt.p_extra, &p_bih[1], tracks[i_track]->fmt.i_extra ); } } } else if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG1" ) || !strcmp( tracks[i_track]->psz_codec, "V_MPEG2" ) ) { tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' ); } else if( !strncmp( tracks[i_track]->psz_codec, "V_MPEG4", 7 ) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -