bool matroska_segment_c::ParseSimpleTags( SimpleTag* pout_simple, KaxTagSimple *tag, int target_type ) { EbmlParser eparser ( &es, tag, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) ); EbmlElement *el; size_t max_size = tag->GetSize(); size_t size = 0; if( !sys.meta ) sys.meta = vlc_meta_New(); msg_Dbg( &sys.demuxer, "| + Simple Tag "); try { while( ( el = eparser.Get() ) != NULL && size < max_size) { if( unlikely( !el->ValidateSize() ) ) { msg_Err( &sys.demuxer, "Error %s too big ignoring the tag", typeid(*el).name() ); delete ep; return false; } if( MKV_CHECKED_PTR_DECL ( ktn_ptr, KaxTagName, el ) ) { ktn_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA ); pout_simple->tag_name = UTFstring( *ktn_ptr ).GetUTF8().c_str(); } else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagString, el ) ) { kts_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA ); pout_simple->value = UTFstring( *kts_ptr ).GetUTF8().c_str(); } else if( MKV_CHECKED_PTR_DECL ( ktl_ptr, KaxTagLangue, el ) ) { ktl_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA ); pout_simple->lang = *ktl_ptr; } else if( MKV_CHECKED_PTR_DECL ( ktd_ptr, KaxTagDefault, el ) ) { VLC_UNUSED(ktd_ptr); // TODO: we do not care about this value, but maybe we should? } /*Tags can be nested*/ else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el) ) { SimpleTag st; // ParseSimpleTags will write to this variable // the SimpleTag is valid if ParseSimpleTags returns `true` if (ParseSimpleTags( &st, kts_ptr, target_type )) { pout_simple->sub_tags.push_back( st ); } } /*TODO Handle binary tags*/ size += el->HeadSize() + el->GetSize(); } } catch(...) { msg_Err( &sys.demuxer, "Error while reading Tag "); delete ep; return false; } if( pout_simple->tag_name.empty() ) { msg_Warn( &sys.demuxer, "Invalid MKV SimpleTag found."); return false; } for( int i = 0; metadata_map[i].key; i++ ) { if( pout_simple->tag_name == metadata_map[i].key && (metadata_map[i].target_type == 0 || target_type == metadata_map[i].target_type ) ) { vlc_meta_Set( sys.meta, metadata_map[i].type, pout_simple->value.c_str () ); msg_Dbg( &sys.demuxer, "| | + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ()); goto done; } } msg_Dbg( &sys.demuxer, "| | + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ()); vlc_meta_AddExtra( sys.meta, pout_simple->tag_name.c_str (), pout_simple->value.c_str ()); done: return true; }
void matroska_segment_c::LoadTags( KaxTags *tags ) { /* Master elements */ EbmlParser eparser = EbmlParser( &es, tags, &sys.demuxer, true ); EbmlElement *el; while( ( el = eparser.Get() ) != NULL ) { if( MKV_IS_ID( el, KaxTag ) ) { Tag tag; msg_Dbg( &sys.demuxer, "+ Tag" ); eparser.Down(); int target_type = 50; while( ( el = eparser.Get() ) != NULL ) { if( MKV_IS_ID( el, KaxTagTargets ) ) { msg_Dbg( &sys.demuxer, "| + Targets" ); eparser.Down(); while( ( el = eparser.Get() ) != NULL ) { try { if( unlikely( !el->ValidateSize() ) ) { msg_Err( &sys.demuxer, "Invalid size while reading tag"); break; } if( MKV_CHECKED_PTR_DECL ( ktttv_ptr, KaxTagTargetTypeValue, el ) ) { ktttv_ptr->ReadData( es.I_O() ); msg_Dbg( &sys.demuxer, "| | + TargetTypeValue: %u", uint32(*ktttv_ptr)); target_type = static_cast<uint32>( *ktttv_ptr ); } else if( MKV_CHECKED_PTR_DECL ( kttu_ptr, KaxTagTrackUID, el ) ) { tag.i_tag_type = TRACK_UID; kttu_ptr->ReadData( es.I_O() ); tag.i_uid = static_cast<uint64>( *kttu_ptr ); msg_Dbg( &sys.demuxer, "| | + TrackUID: %" PRIu64, tag.i_uid); } else if( MKV_CHECKED_PTR_DECL ( kteu_ptr, KaxTagEditionUID, el ) ) { tag.i_tag_type = EDITION_UID; kteu_ptr->ReadData( es.I_O() ); tag.i_uid = static_cast<uint64>( *kteu_ptr ); msg_Dbg( &sys.demuxer, "| | + EditionUID: %" PRIu64, tag.i_uid); } else if( MKV_CHECKED_PTR_DECL ( ktcu_ptr, KaxTagChapterUID, el ) ) { tag.i_tag_type = CHAPTER_UID; ktcu_ptr->ReadData( es.I_O() ); tag.i_uid = static_cast<uint64>( *ktcu_ptr ); msg_Dbg( &sys.demuxer, "| | + ChapterUID: %" PRIu64, tag.i_uid); } else if( MKV_CHECKED_PTR_DECL ( ktau_ptr, KaxTagAttachmentUID, el ) ) { tag.i_tag_type = ATTACHMENT_UID; ktau_ptr->ReadData( es.I_O() ); tag.i_uid = static_cast<uint64>( *ktau_ptr ); msg_Dbg( &sys.demuxer, "| | + AttachmentUID: %" PRIu64, tag.i_uid); } else { msg_Dbg( &sys.demuxer, "| | + LoadTag Unknown (%s)", typeid( *el ).name() ); } } catch(...) { msg_Err( &sys.demuxer, "Error while reading tag"); break; } } eparser.Up(); } else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el ) ) { SimpleTag simple; if (ParseSimpleTags(&simple, kts_ptr, target_type )) { tag.simple_tags.push_back( simple ); } } else { msg_Dbg( &sys.demuxer, "| + LoadTag Unknown (%s)", typeid( *el ).name() ); } } eparser.Up(); this->tags.push_back(tag); } else { msg_Dbg( &sys.demuxer, "+ Unknown (%s)", typeid( *el ).name() ); } } msg_Dbg( &sys.demuxer, "loading tags done." ); }
/***************************************************************************** * Tools * ***************************************************************************** * * LoadCues : load the cues element and update index * * LoadTags : load ... the tags element * * InformationCreate : create all information, load tags if present *****************************************************************************/ void matroska_segment_c::LoadCues( KaxCues *cues ) { EbmlElement *el; if( b_cues ) { msg_Err( &sys.demuxer, "There can be only 1 Cues per section." ); return; } EbmlParser eparser (&es, cues, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) ); while( ( el = eparser.Get() ) != NULL ) { if( MKV_IS_ID( el, KaxCuePoint ) ) { uint64_t cue_position = -1; mtime_t cue_mk_time = -1; unsigned int track_id = 0; bool b_invalid_cue = false; eparser.Down(); while( ( el = eparser.Get() ) != NULL ) { if ( MKV_CHECKED_PTR_DECL( kct_ptr, KaxCueTime, el ) ) { try { if( unlikely( !kct_ptr->ValidateSize() ) ) { msg_Err( &sys.demuxer, "CueTime size too big"); b_invalid_cue = true; break; } kct_ptr->ReadData( es.I_O() ); } catch(...) { msg_Err( &sys.demuxer, "Error while reading CueTime" ); b_invalid_cue = true; break; } cue_mk_time = static_cast<uint64>( *kct_ptr ) * i_timescale / INT64_C(1000); } else if( MKV_IS_ID( el, KaxCueTrackPositions ) ) { eparser.Down(); try { while( ( el = eparser.Get() ) != NULL ) { if( unlikely( !el->ValidateSize() ) ) { eparser.Up(); msg_Err( &sys.demuxer, "Error %s too big, aborting", typeid(*el).name() ); b_invalid_cue = true; break; } if( MKV_CHECKED_PTR_DECL ( kct_ptr, KaxCueTrack, el ) ) { kct_ptr->ReadData( es.I_O() ); track_id = static_cast<uint16>( *kct_ptr ); } else if( MKV_CHECKED_PTR_DECL ( kccp_ptr, KaxCueClusterPosition, el ) ) { kccp_ptr->ReadData( es.I_O() ); cue_position = segment->GetGlobalPosition( static_cast<uint64>( *kccp_ptr ) ); _seeker.add_cluster_position( cue_position ); } else if( MKV_CHECKED_PTR_DECL ( kcbn_ptr, KaxCueBlockNumber, el ) ) { VLC_UNUSED( kcbn_ptr ); } #if LIBMATROSKA_VERSION >= 0x010401 else if( MKV_IS_ID( el, KaxCueRelativePosition ) ) { b_invalid_cue = true; // since we do not support this type of cue: IGNORE } else if( MKV_IS_ID( el, KaxCueBlockNumber ) ) { b_invalid_cue = true; // since we do not support this type of cue: IGNORE } else if( MKV_IS_ID( el, KaxCueReference ) ) { b_invalid_cue = true; // since we do not support this type of cue: IGNORE } else if( MKV_IS_ID( el, KaxCueDuration ) ) { /* For future use */ } #endif else { msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() ); } } } catch(...) { eparser.Up(); msg_Err( &sys.demuxer, "Error while reading %s", typeid(*el).name() ); b_invalid_cue = true; break; } eparser.Up(); } else { msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() ); } } eparser.Up(); if( track_id != 0 && cue_mk_time != -1 && cue_position != static_cast<uint64_t>( -1 ) ) { if( tracks.find( track_id ) != tracks.end() ) { int level = SegmentSeeker::Seekpoint::DISABLED; if( ! b_invalid_cue ) { level = SegmentSeeker::Seekpoint::QUESTIONABLE; // TODO: var_InheritBool( ..., "mkv-trust-cues" ); } _seeker.add_seekpoint( track_id, level, cue_position, cue_mk_time ); } else msg_Warn( &sys.demuxer, "Found cue with invalid track id = %u", track_id ); } } else { msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() ); } } b_cues = true; msg_Dbg( &sys.demuxer, "| - loading cues done." ); }