📄 mkv.cpp
字号:
{ 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: std::vector<matroska_segment_c*> linked_segments; std::vector<KaxSegmentUID> linked_uids; size_t i_current_segment; int i_current_edition; chapter_item_c *psz_current_chapter; void AppendUID( const EbmlBinary * UID );};class matroska_stream_c{public: matroska_stream_c( demux_sys_t & demuxer ) :p_in(NULL) ,p_es(NULL) ,sys(demuxer) {} virtual ~matroska_stream_c() { delete p_in; delete p_es; } IOCallback *p_in; EbmlStream *p_es; std::vector<matroska_segment_c*> segments; demux_sys_t & sys;};typedef struct{ VLC_COMMON_MEMBERS demux_t *p_demux; vlc_mutex_t lock; bool b_moved; bool b_clicked; int i_key_action;} event_thread_t;class attachment_c{public: attachment_c() :p_data(NULL) ,i_size(0) {} virtual ~attachment_c() { free( p_data ); } std::string psz_file_name; std::string psz_mime_type; void *p_data; int i_size;};class demux_sys_t{public: demux_sys_t( demux_t & demux ) :demuxer(demux) ,i_pts(0) ,i_start_pts(0) ,i_chapter_time(0) ,meta(NULL) ,i_current_title(0) ,p_current_segment(NULL) ,dvd_interpretor( *this ) ,f_duration(-1.0) ,b_ui_hooked(false) ,p_input(NULL) ,b_pci_packet_set(false) ,p_ev(NULL) { vlc_mutex_init( &lock_demuxer ); } virtual ~demux_sys_t() { StopUiThread(); size_t i; for ( i=0; i<streams.size(); i++ ) delete streams[i]; for ( i=0; i<opened_segments.size(); i++ ) delete opened_segments[i]; for ( i=0; i<used_segments.size(); i++ ) delete used_segments[i]; for ( i=0; i<stored_attachments.size(); i++ ) delete stored_attachments[i]; if( meta ) vlc_meta_Delete( meta ); while( titles.size() ) { vlc_input_title_Delete( titles.back() ); titles.pop_back();} vlc_mutex_destroy( &lock_demuxer ); } /* current data */ demux_t & demuxer; mtime_t i_pts; mtime_t i_start_pts; mtime_t i_chapter_time; vlc_meta_t *meta; std::vector<input_title_t*> titles; // matroska editions size_t i_current_title; std::vector<matroska_stream_c*> streams; std::vector<attachment_c*> stored_attachments; std::vector<matroska_segment_c*> opened_segments; std::vector<virtual_segment_c*> used_segments; virtual_segment_c *p_current_segment; dvd_command_interpretor_c dvd_interpretor; /* duration of the stream */ float f_duration; matroska_segment_c *FindSegment( const EbmlBinary & uid ) const; 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, virtual_segment_c * & p_segment_found ); chapter_item_c *FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found ); void PreloadFamily( const matroska_segment_c & of_segment ); void PreloadLinked( matroska_segment_c *p_segment ); bool PreparePlayback( virtual_segment_c *p_new_segment ); matroska_stream_c *AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial = false ); void JumpTo( virtual_segment_c & p_segment, chapter_item_c * p_chapter ); void StartUiThread(); void StopUiThread(); bool b_ui_hooked; inline void SwapButtons(); /* for spu variables */ input_thread_t *p_input; pci_t pci_packet; bool b_pci_packet_set; uint8_t palette[4][4]; vlc_mutex_t lock_demuxer; /* event */ event_thread_t *p_ev; static void * EventThread( vlc_object_t *p_this ); static int EventMouse( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ); static int EventKey( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data );protected: virtual_segment_c *VirtualFromSegments( matroska_segment_c *p_segment ) const; bool IsUsedSegment( matroska_segment_c &p_segment ) const;};static int Demux ( demux_t * );static int Control( demux_t *, int, va_list );static void Seek ( demux_t *, mtime_t i_date, double f_percent, chapter_item_c *psz_chapter );#define MKV_IS_ID( el, C ) ( EbmlId( (*el) ) == C::ClassInfos.GlobalId )static inline char * ToUTF8( const UTFstring &u ){ return strdup( u.GetUTF8().c_str() );}/***************************************************************************** * Open: initializes matroska demux structures *****************************************************************************/static int Open( vlc_object_t * p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; matroska_stream_c *p_stream; matroska_segment_c *p_segment; const uint8_t *p_peek; std::string s_path, s_filename; vlc_stream_io_callback *p_io_callback; EbmlStream *p_io_stream; /* peek the begining */ if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC; /* is a valid file */ if( p_peek[0] != 0x1a || p_peek[1] != 0x45 || p_peek[2] != 0xdf || p_peek[3] != 0xa3 ) return VLC_EGENERIC; /* Set the demux function */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = new demux_sys_t( *p_demux ); p_io_callback = new vlc_stream_io_callback( p_demux->s, false ); p_io_stream = new EbmlStream( *p_io_callback ); if( p_io_stream == NULL ) { msg_Err( p_demux, "failed to create EbmlStream" ); delete p_io_callback; delete p_sys; return VLC_EGENERIC; } p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_io_stream, true ); if( p_stream == NULL ) { msg_Err( p_demux, "cannot find KaxSegment" ); goto error; } p_sys->streams.push_back( p_stream ); p_stream->p_in = p_io_callback; p_stream->p_es = p_io_stream; for (size_t i=0; i<p_stream->segments.size(); i++) { p_stream->segments[i]->Preload(); } p_segment = p_stream->segments[0]; if( p_segment->cluster == NULL ) { msg_Err( p_demux, "cannot find any cluster, damaged file ?" ); goto error; } if (config_GetInt( p_demux, "mkv-preload-local-dir" )) { /* get the files from the same dir from the same family (based on p_demux->psz_path) */ if (p_demux->psz_path[0] != '\0' && !strcmp(p_demux->psz_access, "")) { // assume it's a regular file // get the directory path s_path = p_demux->psz_path; if (s_path.at(s_path.length() - 1) == DIRECTORY_SEPARATOR) { s_path = s_path.substr(0,s_path.length()-1); } else { if (s_path.find_last_of(DIRECTORY_SEPARATOR) > 0) { s_path = s_path.substr(0,s_path.find_last_of(DIRECTORY_SEPARATOR)); } } DIR *p_src_dir = utf8_opendir(s_path.c_str()); if (p_src_dir != NULL) { char *psz_file; while ((psz_file = utf8_readdir(p_src_dir)) != NULL) { if (strlen(psz_file) > 4) { s_filename = s_path + DIRECTORY_SEPARATOR + psz_file;#ifdef WIN32 if (!strcasecmp(s_filename.c_str(), p_demux->psz_path))#else if (!s_filename.compare(p_demux->psz_path))#endif { free (psz_file); continue; // don't reuse the original opened file }#if defined(__GNUC__) && (__GNUC__ < 3) if (!s_filename.compare("mkv", s_filename.length() - 3, 3) || !s_filename.compare("mka", s_filename.length() - 3, 3))#else if (!s_filename.compare(s_filename.length() - 3, 3, "mkv") || !s_filename.compare(s_filename.length() - 3, 3, "mka"))#endif { // test wether this file belongs to our family const uint8_t *p_peek; bool file_ok = false; stream_t *p_file_stream = stream_UrlNew( p_demux, s_filename.c_str()); /* peek the begining */ if( p_file_stream && stream_Peek( p_file_stream, &p_peek, 4 ) >= 4 && p_peek[0] == 0x1a && p_peek[1] == 0x45 && p_peek[2] == 0xdf && p_peek[3] == 0xa3 ) file_ok = true; if ( file_ok ) { vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( p_file_stream, true ); EbmlStream *p_estream = new EbmlStream(*p_file_io); p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_estream ); if ( p_stream == NULL ) { msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() ); delete p_estream; delete p_file_io; } else { p_stream->p_in = p_file_io; p_stream->p_es = p_estream; p_sys->streams.push_back( p_stream ); } } else { if( p_file_stream ) { stream_Delete( p_file_stream ); } msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() ); } } } free (psz_file); } closedir( p_src_dir ); } } p_sys->PreloadFamily( *p_segment ); } p_sys->PreloadLinked( p_segment ); if ( !p_sys->PreparePlayback( NULL ) ) { msg_Err( p_demux, "cannot use the segment" ); goto error; } p_sys->StartUiThread(); return VLC_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -