📄 mkv.cpp
字号:
static const uint16 CMD_DVD_GPREG_MOV_VALUE = 0x7100; static const uint16 CMD_DVD_SUB_GPREG = 0x7400; static const uint16 CMD_DVD_MULT_GPREG = 0x7500; static const uint16 CMD_DVD_GPREG_DIV_VALUE = 0x7600; static const uint16 CMD_DVD_GPREG_AND_VALUE = 0x7900; // callbacks when browsing inside CodecPrivate static bool MatchIsDomain ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchIsVMG ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchVTSNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchVTSMNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchTitleNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchPgcType ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchPgcNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchChapterNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ); static bool MatchCellNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );};class dvd_chapter_codec_c : public chapter_codec_cmds_c{public: dvd_chapter_codec_c( demux_sys_t & sys ) :chapter_codec_cmds_c( sys, 1 ) {} bool Enter(); bool Leave(); std::string GetCodecName( bool f_for_title = false ) const; int16 GetTitleNumber();};class matroska_script_interpretor_c{public: matroska_script_interpretor_c( demux_sys_t & demuxer ) :sys( demuxer ) {} bool Interpret( const binary * p_command, size_t i_size ); // DVD command IDs static const std::string CMD_MS_GOTO_AND_PLAY; protected: demux_sys_t & sys;};const std::string matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAndPlay";class matroska_script_codec_c : public chapter_codec_cmds_c{public: matroska_script_codec_c( demux_sys_t & sys ) :chapter_codec_cmds_c( sys, 0 ) ,interpretor( sys ) {} bool Enter(); bool Leave();protected: matroska_script_interpretor_c interpretor; };class chapter_translation_c{public: chapter_translation_c() :p_translated(NULL) {} ~chapter_translation_c() { delete p_translated; } KaxChapterTranslateID *p_translated; unsigned int codec_id; std::vector<uint64_t> editions;};class chapter_item_c{public: chapter_item_c() :i_start_time(0) ,i_end_time(-1) ,i_user_start_time(-1) ,i_user_end_time(-1) ,i_seekpoint_num(-1) ,b_display_seekpoint(true) ,b_user_display(false) ,psz_parent(NULL) ,b_is_leaving(false) {} virtual ~chapter_item_c() { std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin(); while ( index != codecs.end() ) { delete (*index); index++; } std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin(); while ( index_ != sub_chapters.end() ) { delete (*index_); index_++; } } int64_t RefreshChapters( bool b_ordered, int64_t i_prev_user_time ); int PublishChapters( input_title_t & title, int & i_user_chapters, int i_level = 0 ); virtual chapter_item_c * FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current, bool & b_found ); void Append( const chapter_item_c & edition ); chapter_item_c * FindChapter( int64_t i_find_uid ); virtual chapter_item_c *BrowseCodecPrivate( unsigned int codec_id, bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ), const void *p_cookie, size_t i_cookie_size ); std::string GetCodecName( bool f_for_title = false ) const; bool ParentOf( const chapter_item_c & item ) const; int16 GetTitleNumber( ) const; int64_t i_start_time, i_end_time; int64_t i_user_start_time, i_user_end_time; /* the time in the stream when an edition is ordered */ std::vector<chapter_item_c*> sub_chapters; int i_seekpoint_num; int64_t i_uid; bool b_display_seekpoint; bool b_user_display; std::string psz_name; chapter_item_c *psz_parent; bool b_is_leaving; std::vector<chapter_codec_cmds_c*> codecs; bool operator<( const chapter_item_c & item ) const { return ( i_user_start_time < item.i_user_start_time || (i_user_start_time == item.i_user_start_time && i_user_end_time < item.i_user_end_time) ); } bool Enter( bool b_do_subchapters ); bool Leave( bool b_do_subchapters ); bool EnterAndLeave( chapter_item_c *p_item, bool b_enter = true );};class chapter_edition_c : public chapter_item_c{public: chapter_edition_c() :b_ordered(false) {} void RefreshChapters( ); mtime_t Duration() const; std::string GetMainName() const; chapter_item_c * FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current ); bool b_ordered;};class matroska_segment_c{public: matroska_segment_c( demux_sys_t & demuxer, EbmlStream & estream ) :segment(NULL) ,es(estream) ,i_timescale(MKVD_TIMECODESCALE) ,i_duration(-1) ,i_start_time(0) ,i_cues_position(-1) ,i_chapters_position(-1) ,i_tags_position(-1) ,cluster(NULL) ,i_block_pos(0) ,i_cluster_pos(0) ,i_start_pos(0) ,p_segment_uid(NULL) ,p_prev_segment_uid(NULL) ,p_next_segment_uid(NULL) ,b_cues(VLC_FALSE) ,i_index(0) ,i_index_max(1024) ,psz_muxing_application(NULL) ,psz_writing_application(NULL) ,psz_segment_filename(NULL) ,psz_title(NULL) ,psz_date_utc(NULL) ,i_default_edition(0) ,sys(demuxer) ,ep(NULL) ,b_preloaded(false) { p_indexes = (mkv_index_t*)malloc( sizeof( mkv_index_t ) * i_index_max ); } virtual ~matroska_segment_c() { for( size_t i_track = 0; i_track < tracks.size(); i_track++ ) { if( tracks[i_track]->fmt.psz_description ) { free( tracks[i_track]->fmt.psz_description ); }/* if( tracks[i_track]->psz_codec ) { free( tracks[i_track]->psz_codec ); } if( tracks[i_track]->fmt.psz_language ) { free( tracks[i_track]->fmt.psz_language ); }*/ delete tracks[i_track]; } if( psz_writing_application ) { free( psz_writing_application ); } if( psz_muxing_application ) { free( psz_muxing_application ); } if( psz_segment_filename ) { free( psz_segment_filename ); } if( psz_title ) { free( psz_title ); } if( psz_date_utc ) { free( psz_date_utc ); } if ( p_indexes ) free( p_indexes ); delete ep; delete p_segment_uid; delete p_prev_segment_uid; delete p_next_segment_uid; std::vector<chapter_edition_c*>::iterator index = stored_editions.begin(); while ( index != stored_editions.end() ) { delete (*index); index++; } std::vector<chapter_translation_c*>::iterator indext = translations.begin(); while ( indext != translations.end() ) { delete (*indext); indext++; } } KaxSegment *segment; EbmlStream & es; /* time scale */ uint64_t i_timescale; /* duration of the segment */ mtime_t i_duration; mtime_t i_start_time; /* all tracks */ std::vector<mkv_track_t*> tracks; /* from seekhead */ int64_t i_cues_position; int64_t i_chapters_position; int64_t i_tags_position; KaxCluster *cluster; uint64 i_block_pos; uint64 i_cluster_pos; int64_t i_start_pos; KaxSegmentUID *p_segment_uid; KaxPrevUID *p_prev_segment_uid; KaxNextUID *p_next_segment_uid; vlc_bool_t b_cues; int i_index; int i_index_max; mkv_index_t *p_indexes; /* info */ char *psz_muxing_application; char *psz_writing_application; char *psz_segment_filename; char *psz_title; char *psz_date_utc; /* !!!!! GCC 3.3 bug on Darwin !!!!! */ /* when you remove this variable the compiler issues an atomicity error */ /* this variable only works when using std::vector<chapter_edition_c> */ std::vector<chapter_edition_c*> stored_editions; int i_default_edition; std::vector<chapter_translation_c*> translations; std::vector<KaxSegmentFamily> families; demux_sys_t & sys; EbmlParser *ep; bool b_preloaded; bool Preload( ); bool PreloadFamily( const matroska_segment_c & segment ); void ParseInfo( KaxInfo *info ); void ParseChapters( KaxChapters *chapters ); void ParseSeekHead( KaxSeekHead *seekhead ); void ParseTracks( KaxTracks *tracks ); void ParseChapterAtom( int i_level, KaxChapterAtom *ca, chapter_item_c & chapters ); void ParseTrackEntry( KaxTrackEntry *m ); void ParseCluster( ); void IndexAppendCluster( KaxCluster *cluster ); void LoadCues( ); void LoadTags( ); void InformationCreate( ); void Seek( mtime_t i_date, mtime_t i_time_offset ); int BlockGet( KaxBlock * & pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration ); bool Select( mtime_t i_start_time ); void UnSelect( ); static bool CompareSegmentUIDs( const matroska_segment_c * item_a, const matroska_segment_c * item_b );};// class holding hard-linked segment together in the playback orderclass virtual_segment_c{public: virtual_segment_c( matroska_segment_c *p_segment ) :p_editions(NULL) ,i_sys_title(0) ,i_current_segment(0) ,i_current_edition(-1) ,psz_current_chapter(NULL) { linked_segments.push_back( p_segment ); AppendUID( p_segment->p_segment_uid ); AppendUID( p_segment->p_prev_segment_uid ); AppendUID( p_segment->p_next_segment_uid ); } void Sort(); size_t AddSegment( matroska_segment_c *p_segment ); void PreloadLinked( ); mtime_t Duration( ) const; void LoadCues( ); void Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter ); inline chapter_edition_c *Edition() { if ( i_current_edition >= 0 && size_t(i_current_edition) < p_editions->size() ) return (*p_editions)[i_current_edition]; return NULL; } matroska_segment_c * Segment() const { if ( linked_segments.size() == 0 || i_current_segment >= linked_segments.size() ) return NULL; return linked_segments[i_current_segment]; } inline chapter_item_c *CurrentChapter() { return psz_current_chapter; } bool SelectNext() { if ( i_current_segment < linked_segments.size()-1 ) { i_current_segment++; return true; } return false; } bool FindUID( KaxSegmentUID & uid ) const { for ( size_t i=0; i<linked_uids.size(); i++ ) { if ( linked_uids[i] == uid ) return true; } return false; } bool UpdateCurrentToChapter( demux_t & demux ); void PrepareChapters( ); chapter_item_c *BrowseCodecPrivate( unsigned int codec_id, bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ), const void *p_cookie, size_t i_cookie_size ); chapter_item_c *FindChapter( int64_t i_find_uid ); std::vector<chapter_edition_c*> *p_editions; int i_sys_title;protected:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -