[vlc-devel] [PATCH 10/30] mkv: replaced usage of std::vector with std::map (matroska_segment_c::tracks)
Filip Roséen
filip at videolabs.io
Mon May 9 14:53:04 CEST 2016
Managing the tracks by a std::vector has been replaced with a std::map
mapping the track-number to a mkv_track_t.
This patch includes changing BlockFindTrackIndex to FindTrackByBlock,
keeping the same behaviour though using a more accurate name for the new
code.
---
modules/demux/mkv/matroska_segment.cpp | 145 ++++++++++++++-------------
modules/demux/mkv/matroska_segment.hpp | 6 +-
modules/demux/mkv/matroska_segment_parse.cpp | 104 +++++++++++--------
modules/demux/mkv/mkv.cpp | 140 ++++++++++++++++----------
modules/demux/mkv/mkv.hpp | 1 +
modules/demux/mkv/virtual_segment.cpp | 81 ++++++++-------
6 files changed, 267 insertions(+), 210 deletions(-)
diff --git a/modules/demux/mkv/matroska_segment.cpp b/modules/demux/mkv/matroska_segment.cpp
index b317079..017db2c 100644
--- a/modules/demux/mkv/matroska_segment.cpp
+++ b/modules/demux/mkv/matroska_segment.cpp
@@ -66,14 +66,14 @@ matroska_segment_c::matroska_segment_c( demux_sys_t & demuxer, EbmlStream & estr
matroska_segment_c::~matroska_segment_c()
{
- for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
+ for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it)
{
- delete tracks[i_track]->p_compression_data;
- es_format_Clean( &tracks[i_track]->fmt );
- delete tracks[i_track]->p_sys;
- free( tracks[i_track]->p_extra_data );
- free( tracks[i_track]->psz_codec );
- delete tracks[i_track];
+ tracks_map_t::mapped_type& track = it->second;
+
+ es_format_Clean( &track.fmt );
+ delete track.p_compression_data;
+ delete track.p_sys;
+ free( track.p_extra_data );
}
free( psz_writing_application );
@@ -757,27 +757,25 @@ void matroska_segment_c::Seek( mtime_t i_mk_date, mtime_t i_mk_time_offset )
// TODO: implement
}
-int matroska_segment_c::BlockFindTrackIndex( size_t *pi_track,
+
+int matroska_segment_c::FindTrackByBlock(tracks_map_t::iterator* p_track_it,
const KaxBlock *p_block, const KaxSimpleBlock *p_simpleblock )
{
- size_t i_track;
- for( i_track = 0; i_track < tracks.size(); i_track++ )
- {
- const mkv_track_t *tk = tracks[i_track];
+ *p_track_it = tracks.end();
- if( ( p_block != NULL && tk->i_number == p_block->TrackNum() ) ||
- ( p_simpleblock != NULL && tk->i_number == p_simpleblock->TrackNum() ) )
- {
- break;
- }
- }
-
- if( i_track >= tracks.size() )
+ if( p_block == NULL && p_simpleblock == NULL )
return VLC_EGENERIC;
- if( pi_track )
- *pi_track = i_track;
- return VLC_SUCCESS;
+ if (p_block != NULL)
+ {
+ *p_track_it = tracks.find( p_block->TrackNum() );
+ }
+ else if( p_simpleblock != NULL)
+ {
+ *p_track_it = tracks.find( p_simpleblock->TrackNum() );
+ }
+
+ return *p_track_it != tracks.end() ? VLC_SUCCESS : VLC_EGENERIC;
}
void matroska_segment_c::ComputeTrackPriority()
@@ -785,51 +783,52 @@ void matroska_segment_c::ComputeTrackPriority()
bool b_has_default_video = false;
bool b_has_default_audio = false;
/* check for default */
- for(size_t i_track = 0; i_track < tracks.size(); i_track++)
+ for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
{
- mkv_track_t *p_tk = tracks[i_track];
- es_format_t *p_fmt = &p_tk->fmt;
- if( p_fmt->i_cat == VIDEO_ES )
- b_has_default_video |=
- p_tk->b_enabled && ( p_tk->b_default || p_tk->b_forced );
- else if( p_fmt->i_cat == AUDIO_ES )
- b_has_default_audio |=
- p_tk->b_enabled && ( p_tk->b_default || p_tk->b_forced );
+ tracks_map_t::mapped_type& track = it->second;
+
+ bool flag = track.b_enabled && ( track.b_default || track.b_forced );
+
+ switch( track.fmt.i_cat )
+ {
+ case VIDEO_ES: b_has_default_video |= flag; break;
+ case AUDIO_ES: b_has_default_audio |= flag; break;
+ }
}
- for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
+ for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
{
- mkv_track_t *p_tk = tracks[i_track];
- es_format_t *p_fmt = &p_tk->fmt;
+ tracks_map_t::key_type track_id = it->first;
+ tracks_map_t::mapped_type track = it->second;
- if( unlikely( p_fmt->i_cat == UNKNOWN_ES || !p_tk->psz_codec ) )
+ if( unlikely( track.fmt.i_cat == UNKNOWN_ES || !track.psz_codec ) )
{
- msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", static_cast<int>( i_track ), p_tk->i_number );
- p_tk->p_es = NULL;
+ msg_Warn( &sys.demuxer, "invalid track[%d]", static_cast<int>( track_id ) );
+ track.p_es = NULL;
continue;
}
- else if( unlikely( !b_has_default_video && p_fmt->i_cat == VIDEO_ES ) )
+ else if( unlikely( !b_has_default_video && track.fmt.i_cat == VIDEO_ES ) )
{
- p_tk->b_default = true;
+ track.b_default = true;
b_has_default_video = true;
}
- else if( unlikely( !b_has_default_audio && p_fmt->i_cat == AUDIO_ES ) )
+ else if( unlikely( !b_has_default_audio && track.fmt.i_cat == AUDIO_ES ) )
{
- p_tk->b_default = true;
+ track.b_default = true;
b_has_default_audio = true;
}
- if( unlikely( !p_tk->b_enabled ) )
- p_tk->fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE;
- else if( p_tk->b_forced )
- p_tk->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 2;
- else if( p_tk->b_default )
- p_tk->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1;
+ if( unlikely( !track.b_enabled ) )
+ track.fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE;
+ else if( track.b_forced )
+ track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 2;
+ else if( track.b_default )
+ track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1;
else
- p_tk->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN;
+ track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN;
/* Avoid multivideo tracks when unnecessary */
- if( p_tk->fmt.i_cat == VIDEO_ES )
- p_tk->fmt.i_priority--;
+ if( track.fmt.i_cat == VIDEO_ES )
+ track.fmt.i_priority--;
}
}
@@ -932,31 +931,29 @@ bool matroska_segment_c::Select( mtime_t i_mk_start_time )
/* add all es */
msg_Dbg( &sys.demuxer, "found %d es", static_cast<int>( tracks.size() ) );
- for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
+ for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
{
- mkv_track_t *p_tk = tracks[i_track];
- es_format_t *p_fmt = &p_tk->fmt;
+ tracks_map_t::key_type track_id = it->first;
+ tracks_map_t::mapped_type& track = it->second;
- if( unlikely( p_fmt->i_cat == UNKNOWN_ES || !p_tk->psz_codec ) )
+ if( unlikely( track.fmt.i_cat == UNKNOWN_ES || !track.psz_codec ) )
{
- msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", static_cast<int>( i_track ), p_tk->i_number );
- p_tk->p_es = NULL;
+ msg_Warn( &sys.demuxer, "invalid track[%d]", static_cast<int>( track_id ) );
+ track.p_es = NULL;
continue;
}
- if( !p_tk->p_es )
- p_tk->p_es = es_out_Add( sys.demuxer.out, &p_tk->fmt );
+ if( !track.p_es )
+ track.p_es = es_out_Add( sys.demuxer.out, &track.fmt );
/* Turn on a subtitles track if it has been flagged as default -
* but only do this if no subtitles track has already been engaged,
* either by an earlier 'default track' (??) or by default
* language choice behaviour.
*/
- if( p_tk->b_default || p_tk->b_forced )
+ if( track.b_default || track.b_forced )
{
- es_out_Control( sys.demuxer.out,
- ES_OUT_SET_ES_DEFAULT,
- p_tk->p_es );
+ es_out_Control( sys.demuxer.out, ES_OUT_SET_ES_DEFAULT, track.p_es );
}
}
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_mk_start_time );
@@ -973,27 +970,33 @@ bool matroska_segment_c::Select( mtime_t i_mk_start_time )
void matroska_segment_c::UnSelect( )
{
sys.p_ev->ResetPci();
- for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
+
+ for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
{
- if ( tracks[i_track]->p_es != NULL )
+ tracks_map_t::mapped_type& track = it->second;
+
+ if( track.p_es != NULL )
{
-// es_format_Clean( &tracks[i_track]->fmt );
- es_out_Del( sys.demuxer.out, tracks[i_track]->p_es );
- tracks[i_track]->p_es = NULL;
+ es_out_Del( sys.demuxer.out, track.p_es );
+ track.p_es = NULL;
}
}
+
+ /* TODO: we will leak, fix this!
delete ep;
ep = NULL;
+ */
}
int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, bool *pb_key_picture, bool *pb_discardable_picture, int64_t *pi_duration )
{
+ tracks_map_t::iterator track_it;
+
pp_simpleblock = NULL;
pp_block = NULL;
*pb_key_picture = true;
*pb_discardable_picture = false;
- size_t i_tk;
*pi_duration = 0;
struct BlockPayload {
@@ -1136,7 +1139,7 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
if( pp_simpleblock != NULL || ((el = ep->Get()) == NULL && pp_block != NULL) )
{
/* Check blocks validity to protect againts broken files */
- if( BlockFindTrackIndex( &i_tk, pp_block , pp_simpleblock ) )
+ if( FindTrackByBlock( &track_it, pp_block , pp_simpleblock ) )
{
ep->Unkeep();
pp_simpleblock = NULL;
@@ -1151,7 +1154,7 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
/* We have block group let's check if the picture is a keyframe */
else if( *pb_key_picture )
{
- if( tracks[i_tk]->fmt.i_codec == VLC_CODEC_THEORA )
+ if( track_it->second.fmt.i_codec == VLC_CODEC_THEORA )
{
DataBuffer * p_data = &pp_block->GetBuffer(0);
const uint8_t * p_buff = p_data->Buffer();
diff --git a/modules/demux/mkv/matroska_segment.hpp b/modules/demux/mkv/matroska_segment.hpp
index 2672f9a..a653d76 100644
--- a/modules/demux/mkv/matroska_segment.hpp
+++ b/modules/demux/mkv/matroska_segment.hpp
@@ -71,6 +71,7 @@ public:
class matroska_segment_c
{
public:
+ typedef std::map<mkv_track_t::track_id_t, mkv_track_t> tracks_map_t;
typedef std::vector<Tag> tags_t;
matroska_segment_c( demux_sys_t & demuxer, EbmlStream & estream );
@@ -87,7 +88,7 @@ public:
mtime_t i_mk_start_time;
/* all tracks */
- std::vector<mkv_track_t*> tracks;
+ tracks_map_t tracks;
/* from seekhead */
int i_seekhead_count;
@@ -136,12 +137,11 @@ public:
void Seek( mtime_t i_mk_date, mtime_t i_mk_time_offset );
int BlockGet( KaxBlock * &, KaxSimpleBlock * &, bool *, bool *, int64_t *);
- int BlockFindTrackIndex( size_t *pi_track,
- const KaxBlock *, const KaxSimpleBlock * );
bool Select( mtime_t i_mk_start_time );
void UnSelect();
+ int FindTrackByBlock(tracks_map_t::iterator* track_it, const KaxBlock *, const KaxSimpleBlock * );
static bool CompareSegmentUIDs( const matroska_segment_c * item_a, const matroska_segment_c * item_b );
diff --git a/modules/demux/mkv/matroska_segment_parse.cpp b/modules/demux/mkv/matroska_segment_parse.cpp
index e128ad3..c8c6b60 100644
--- a/modules/demux/mkv/matroska_segment_parse.cpp
+++ b/modules/demux/mkv/matroska_segment_parse.cpp
@@ -39,6 +39,7 @@ extern "C" {
#include <vlc_codecs.h>
#include <stdexcept>
+#include <limits>
/* GetFourCC helper */
#define GetFOURCC( p ) __GetFOURCC( (uint8_t*)p )
@@ -200,33 +201,53 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
bool bSupported = true;
/* Init the track */
- mkv_track_t *tk = new mkv_track_t();
- memset( tk, 0, sizeof( mkv_track_t ) );
-
- es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
- tk->p_es = NULL;
- tk->fmt.psz_language = strdup("English");
- tk->fmt.psz_description = NULL;
-
- tk->b_default = true;
- tk->b_enabled = true;
- tk->b_forced = false;
- tk->i_number = tracks.size() - 1;
- tk->i_extra_data = 0;
- tk->p_extra_data = NULL;
- tk->psz_codec = NULL;
- tk->b_dts_only = false;
- tk->i_default_duration = 0;
- tk->b_no_duration = false;
- tk->f_timecodescale = 1.0;
-
- tk->b_inited = false;
- tk->i_data_init = 0;
- tk->p_data_init = NULL;
-
- tk->i_compression_type = MATROSKA_COMPRESSION_NONE;
- tk->i_encoding_scope = MATROSKA_ENCODING_SCOPE_ALL_FRAMES;
- tk->p_compression_data = NULL;
+ mkv_track_t track;
+
+ track.fmt.psz_language = strdup("English");
+ track.fmt.psz_description = NULL;
+
+ track.b_default = true;
+ track.b_enabled = true;
+ track.b_forced = false;
+ track.i_number = 0;
+
+ track.i_extra_data = 0;
+ track.p_extra_data = NULL;
+
+ track.psz_codec = NULL;
+ track.b_dts_only = false;
+ track.b_pts_only = false;
+
+ track.b_no_duration = false;
+ track.i_default_duration = 0;
+ track.f_timecodescale = 1.0;
+ track.i_last_dts = 0;
+ track.i_skip_until_fpos = -1;
+
+ std::memset( &track.fmt, 0, sizeof( track.fmt ) );
+ es_format_Init( &track.fmt, UNKNOWN_ES, 0 );
+ track.f_fps = 0;
+ track.p_es = NULL;
+
+ track.i_original_rate = 0;
+ track.i_chans_to_reorder = 0;
+ std::memset( &track.pi_chan_table, 0, sizeof( track.pi_chan_table ) );
+
+ track.p_sys = NULL;
+
+ track.b_inited = false;
+
+ track.i_data_init = 0;
+ track.p_data_init = NULL;
+
+ track.str_codec_name = "";
+
+ track.i_compression_type = MATROSKA_COMPRESSION_NONE;
+ track.i_encoding_scope = MATROSKA_ENCODING_SCOPE_ALL_FRAMES;
+ track.p_compression_data = NULL;
+
+ track.i_seek_preroll = 0;
+ track.i_codec_delay = 0;
MkvTree( sys.demuxer, 2, "Track Entry" );
@@ -247,7 +268,7 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
} track_video_info;
} metadata_payload = {
- this, tk, &sys.demuxer, bSupported, 3, { }
+ this, &track, &sys.demuxer, bSupported, 3, { }
};
MKV_SWITCH_CREATE( EbmlTypeDispatcher, MetaDataHandlers, MetaDataCapture )
@@ -603,31 +624,34 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
MetaDataHandlers::Dispatcher().iterate ( m->begin(), m->end(), MetaDataHandlers::Payload( metadata_payload ) );
+ if( track.i_number == 0 )
+ {
+ msg_Warn( &sys.demuxer, "Missing KaxTrackNumber, discarding track!" );
+ return;
+ }
if ( bSupported )
{
#ifdef HAVE_ZLIB_H
- if( tk->i_compression_type == MATROSKA_COMPRESSION_ZLIB &&
- tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_PRIVATE &&
- tk->i_extra_data && tk->p_extra_data &&
- zlib_decompress_extra( &sys.demuxer, tk) )
+ if( track.i_compression_type == MATROSKA_COMPRESSION_ZLIB &&
+ track.i_encoding_scope & MATROSKA_ENCODING_SCOPE_PRIVATE &&
+ track.i_extra_data && track.p_extra_data &&
+ zlib_decompress_extra( &sys.demuxer, &track ) )
return;
#endif
- if( TrackInit( tk ) )
+ if( TrackInit( &track ) )
{
- msg_Err(&sys.demuxer, "Couldn't init track %d", tk->i_number );
- free(tk->p_extra_data);
- delete tk;
+ msg_Err(&sys.demuxer, "Couldn't init track %d", track.i_number );
+ free(track.p_extra_data);
return;
}
- tracks.push_back( tk );
+ tracks.insert( std::make_pair( track.i_number, track ) ); // TODO: add warning if two tracks have the same key
}
else
{
- msg_Err( &sys.demuxer, "Track Entry %d not supported", tk->i_number );
- free(tk->p_extra_data);
- delete tk;
+ msg_Err( &sys.demuxer, "Track Entry %d not supported", track.i_number );
+ free(track.p_extra_data);
}
}
diff --git a/modules/demux/mkv/mkv.cpp b/modules/demux/mkv/mkv.cpp
index 3da89bf..7323b42 100644
--- a/modules/demux/mkv/mkv.cpp
+++ b/modules/demux/mkv/mkv.cpp
@@ -418,13 +418,16 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
*pf = 0.0;
if( p_sys->p_current_vsegment && p_sys->p_current_vsegment->CurrentSegment() )
{
+ typedef matroska_segment_c::tracks_map_t tracks_map_t;
+
const matroska_segment_c *p_segment = p_sys->p_current_vsegment->CurrentSegment();
- for( size_t i = 0; i < p_segment->tracks.size(); i++ )
+ for( tracks_map_t::const_iterator it = p_segment->tracks.begin(); it != p_segment->tracks.end(); ++it )
{
- mkv_track_t *tk = p_segment->tracks[i];
- if( tk->fmt.i_cat == VIDEO_ES && tk->fmt.video.i_frame_rate_base > 0 )
+ tracks_map_t::mapped_type const& track = it->second;
+
+ if( track.fmt.i_cat == VIDEO_ES && track.fmt.video.i_frame_rate_base > 0 )
{
- *pf = (double)tk->fmt.video.i_frame_rate / tk->fmt.video.i_frame_rate_base;
+ *pf = (double)track.fmt.video.i_frame_rate / track.fmt.video.i_frame_rate_base;
break;
}
}
@@ -491,53 +494,56 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
mtime_t i_pts, mtime_t i_duration, bool b_key_picture,
bool b_discardable_picture )
{
+ typedef matroska_segment_c::tracks_map_t tracks_map_t;
+
demux_sys_t *p_sys = p_demux->p_sys;
matroska_segment_c *p_segment = p_sys->p_current_vsegment->CurrentSegment();
if( !p_segment ) return;
- size_t i_track;
- if( p_segment->BlockFindTrackIndex( &i_track, block, simpleblock ) )
+ tracks_map_t::iterator track_it;
+
+ if( p_segment->FindTrackByBlock( &track_it, block, simpleblock ) )
{
msg_Err( p_demux, "invalid track number" );
return;
}
- mkv_track_t *tk = p_segment->tracks[i_track];
+ tracks_map_t::mapped_type& track = track_it->second;
- if( tk->fmt.i_cat != NAV_ES && tk->p_es == NULL )
+ if( track.fmt.i_cat != NAV_ES && track.p_es == NULL )
{
msg_Err( p_demux, "unknown track number" );
return;
}
- i_pts -= tk->i_codec_delay;
+ i_pts -= track.i_codec_delay;
- if ( tk->fmt.i_cat != NAV_ES )
+ if ( track.fmt.i_cat != NAV_ES )
{
bool b;
- es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
+ es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, track.p_es, &b );
if( !b )
{
- tk->b_inited = false;
- if( tk->fmt.i_cat == VIDEO_ES || tk->fmt.i_cat == AUDIO_ES )
- tk->i_last_dts = VLC_TS_INVALID;
+ track.b_inited = false;
+ if( track.fmt.i_cat == VIDEO_ES || track.fmt.i_cat == AUDIO_ES )
+ track.i_last_dts = VLC_TS_INVALID;
return;
}
}
/* First send init data */
- if( !tk->b_inited && tk->i_data_init > 0 )
+ if( !track.b_inited && track.i_data_init > 0 )
{
block_t *p_init;
- msg_Dbg( p_demux, "sending header (%d bytes)", tk->i_data_init );
- p_init = MemToBlock( tk->p_data_init, tk->i_data_init, 0 );
- if( p_init ) send_Block( p_demux, tk, p_init, 1, 0 );
+ msg_Dbg( p_demux, "sending header (%d bytes)", track.i_data_init );
+ p_init = MemToBlock( track.p_data_init, track.i_data_init, 0 );
+ if( p_init ) send_Block( p_demux, &track, p_init, 1, 0 );
}
- tk->b_inited = true;
+ track.b_inited = true;
size_t frame_size = 0;
@@ -569,12 +575,12 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
break;
}
- if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER &&
- tk->p_compression_data != NULL &&
- tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
- p_block = MemToBlock( data->Buffer(), data->Size(), tk->p_compression_data->GetSize() );
- else if( unlikely( tk->fmt.i_codec == VLC_CODEC_WAVPACK ) )
- p_block = packetize_wavpack(tk, data->Buffer(), data->Size());
+ if( track.i_compression_type == MATROSKA_COMPRESSION_HEADER &&
+ track.p_compression_data != NULL &&
+ track.i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
+ p_block = MemToBlock( data->Buffer(), data->Size(), track.p_compression_data->GetSize() );
+ else if( unlikely( track.fmt.i_codec == VLC_CODEC_WAVPACK ) )
+ p_block = packetize_wavpack( &track, data->Buffer(), data->Size() );
else
p_block = MemToBlock( data->Buffer(), data->Size(), 0 );
@@ -584,8 +590,8 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
}
#if defined(HAVE_ZLIB_H)
- if( tk->i_compression_type == MATROSKA_COMPRESSION_ZLIB &&
- tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
+ if( track.i_compression_type == MATROSKA_COMPRESSION_ZLIB &&
+ track.i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
{
p_block = block_zlib_decompress( VLC_OBJECT(p_demux), p_block );
if( p_block == NULL )
@@ -593,24 +599,24 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
}
else
#endif
- if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER &&
- tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
+ if( track.i_compression_type == MATROSKA_COMPRESSION_HEADER &&
+ track.i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
{
- memcpy( p_block->p_buffer, tk->p_compression_data->GetBuffer(), tk->p_compression_data->GetSize() );
+ memcpy( p_block->p_buffer, track.p_compression_data->GetBuffer(), track.p_compression_data->GetSize() );
}
if ( b_key_picture )
p_block->i_flags |= BLOCK_FLAG_TYPE_I;
- switch( tk->fmt.i_codec )
+ switch( track.fmt.i_codec )
{
case VLC_CODEC_COOK:
case VLC_CODEC_ATRAC3:
{
- handle_real_audio(p_demux, tk, p_block, i_pts);
+ handle_real_audio(p_demux, &track, p_block, i_pts);
block_Release(p_block);
- i_pts = ( tk->i_default_duration )?
- i_pts + ( mtime_t )tk->i_default_duration:
+ i_pts = ( track.i_default_duration )?
+ i_pts + ( mtime_t )track.i_default_duration:
VLC_TS_INVALID;
continue;
}
@@ -629,17 +635,17 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
break;
case VLC_CODEC_OPUS:
- mtime_t i_length = i_duration * tk-> f_timecodescale *
+ mtime_t i_length = i_duration * track. f_timecodescale *
(double) p_segment->i_timescale / 1000.0;
if ( i_length < 0 ) i_length = 0;
- p_block->i_nb_samples = i_length * tk->fmt.audio.i_rate
+ p_block->i_nb_samples = i_length * track.fmt.audio.i_rate
/ CLOCK_FREQ;
break;
}
- if( tk->fmt.i_cat != VIDEO_ES )
+ if( track.fmt.i_cat != VIDEO_ES )
{
- if ( tk->fmt.i_cat == NAV_ES )
+ if ( track.fmt.i_cat == NAV_ES )
{
// TODO handle the start/stop times of this packet
p_sys->p_ev->SetPci( (const pci_t *)&p_block->p_buffer[1]);
@@ -651,12 +657,12 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
else
{
// correct timestamping when B frames are used
- if( tk->b_dts_only )
+ if( track.b_dts_only )
{
p_block->i_pts = VLC_TS_INVALID;
p_block->i_dts = i_pts;
}
- else if( tk->b_pts_only )
+ else if( track.b_pts_only )
{
p_block->i_pts = i_pts;
p_block->i_dts = i_pts;
@@ -666,20 +672,20 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
p_block->i_pts = i_pts;
// condition when the DTS is correct (keyframe or B frame == NOT P frame)
if ( b_key_picture || b_discardable_picture )
- p_block->i_dts = p_block->i_pts;
- else if ( tk->i_last_dts == VLC_TS_INVALID )
+ p_block->i_dts = p_block->i_pts;
+ else if ( track.i_last_dts == VLC_TS_INVALID )
p_block->i_dts = i_pts;
else
- p_block->i_dts = std::min( i_pts, tk->i_last_dts + ( mtime_t )tk->i_default_duration );
+ p_block->i_dts = std::min( i_pts, track.i_last_dts + ( mtime_t )track.i_default_duration );
}
}
- send_Block( p_demux, tk, p_block, i_number_frames, i_duration );
+ send_Block( p_demux, &track, p_block, i_number_frames, i_duration );
/* use time stamp only for first block */
- i_pts = ( tk->i_default_duration )?
- i_pts + ( mtime_t )tk->i_default_duration:
- ( tk->fmt.b_packetized ) ? VLC_TS_INVALID : i_pts + 1;
+ i_pts = ( track.i_default_duration )?
+ i_pts + ( mtime_t )track.i_default_duration:
+ ( track.fmt.b_packetized ) ? VLC_TS_INVALID : i_pts + 1;
}
}
@@ -739,16 +745,40 @@ static int Demux( demux_t *p_demux)
p_sys->i_pts = (mtime_t)block->GlobalTimecode() / INT64_C(1000);
p_sys->i_pts += p_sys->i_mk_chapter_time + VLC_TS_0;
- mtime_t i_pcr = VLC_TS_INVALID;
- for( size_t i = 0; i < p_segment->tracks.size(); i++)
- if( p_segment->tracks[i]->i_last_dts > VLC_TS_INVALID &&
- ( p_segment->tracks[i]->i_last_dts < i_pcr || i_pcr == VLC_TS_INVALID ))
- i_pcr = p_segment->tracks[i]->i_last_dts;
- if( i_pcr > p_sys->i_pcr + 300000 )
+
+ /* update pcr */
{
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr );
- p_sys->i_pcr = i_pcr;
+ int64_t i_pcr = VLC_TS_INVALID;
+
+ typedef matroska_segment_c::tracks_map_t tracks_map_t;
+
+ for( tracks_map_t::iterator it = p_segment->tracks.begin(); it != p_segment->tracks.end(); ++it )
+ {
+ tracks_map_t::mapped_type& track = it->second;
+
+ if( track.i_last_dts == VLC_TS_INVALID )
+ continue;
+
+ if( track.fmt.i_cat != VIDEO_ES && track.fmt.i_cat != AUDIO_ES )
+ continue;
+
+ if( track.i_last_dts < i_pcr || i_pcr <= VLC_TS_INVALID )
+ {
+ i_pcr = track.i_last_dts;
+ }
+ }
+
+ if( i_pcr > VLC_TS_INVALID && i_pcr > p_sys->i_pcr )
+ {
+ if( es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pcr ) )
+ {
+ msg_Err( p_demux, "ES_OUT_SET_PCR failed, aborting." );
+ return 0;
+ }
+
+ p_sys->i_pcr = i_pcr;
+ }
}
if ( p_vsegment->CurrentEdition() &&
diff --git a/modules/demux/mkv/mkv.hpp b/modules/demux/mkv/mkv.hpp
index b428266..8bad7dc 100644
--- a/modules/demux/mkv/mkv.hpp
+++ b/modules/demux/mkv/mkv.hpp
@@ -52,6 +52,7 @@
#include <string>
#include <vector>
#include <algorithm>
+#include <map>
/* libebml and matroska */
#include "ebml/EbmlHead.h"
diff --git a/modules/demux/mkv/virtual_segment.cpp b/modules/demux/mkv/virtual_segment.cpp
index 42643f8..1b0b674 100644
--- a/modules/demux/mkv/virtual_segment.cpp
+++ b/modules/demux/mkv/virtual_segment.cpp
@@ -678,72 +678,71 @@ void virtual_chapter_c::print()
void virtual_segment_c::KeepTrackSelection( matroska_segment_c & old, matroska_segment_c & next )
{
- size_t i, j;
+ typedef matroska_segment_c::tracks_map_t tracks_map_t;
+
char *sub_lang = NULL, *aud_lang = NULL;
- /* get the current ES language selection */
- for( i = 0; i < old.tracks.size(); i++)
+ for( tracks_map_t::iterator it = old.tracks.begin(); it != old.tracks.end(); ++it )
{
- mkv_track_t *p_tk = old.tracks[i];
- es_format_t *p_ofmt = &p_tk->fmt;
- if( p_tk->p_es )
+ tracks_map_t::mapped_type& track = it->second;
+ if( track.p_es )
{
bool state = false;
- es_out_Control( old.sys.demuxer.out, ES_OUT_GET_ES_STATE, p_tk->p_es, &state );
+ es_out_Control( old.sys.demuxer.out, ES_OUT_GET_ES_STATE, track.p_es, &state );
if( state )
{
- if( p_ofmt->i_cat == AUDIO_ES )
- aud_lang = p_tk->fmt.psz_language;
- else if( p_ofmt->i_cat == SPU_ES )
- sub_lang = p_tk->fmt.psz_language;
+ if( track.fmt.i_cat == AUDIO_ES )
+ aud_lang = track.fmt.psz_language;
+ else if( track.fmt.i_cat == SPU_ES )
+ sub_lang = track.fmt.psz_language;
}
}
}
- for( i = 0; i < next.tracks.size(); i++)
+ for( tracks_map_t::iterator it = next.tracks.begin(); it != next.tracks.end(); ++it )
{
- mkv_track_t *p_tk = next.tracks[i];
- es_format_t *p_nfmt = &p_tk->fmt;
+ tracks_map_t::mapped_type& new_track = it->second;
+ es_format_t & new_fmt = new_track.fmt;
/* Let's only do that for audio and video for now */
- if( p_nfmt->i_cat == AUDIO_ES || p_nfmt->i_cat == VIDEO_ES )
+ if( new_fmt.i_cat == AUDIO_ES || new_fmt.i_cat == VIDEO_ES )
{
-
/* check for a similar elementary stream */
- for( j = 0; j < old.tracks.size(); j++)
+ for( tracks_map_t::iterator old_it = old.tracks.begin(); old_it != old.tracks.end(); ++old_it )
{
- es_format_t * p_ofmt = &old.tracks[j]->fmt;
+ tracks_map_t::mapped_type& old_track = old_it->second;
+ es_format_t& old_fmt = old_track.fmt;
- if( !old.tracks[j]->p_es )
+ if( !old_track.p_es )
continue;
- if( ( p_nfmt->i_cat == p_ofmt->i_cat ) &&
- ( p_nfmt->i_codec == p_ofmt->i_codec ) &&
- ( p_nfmt->i_priority == p_ofmt->i_priority ) &&
- ( p_nfmt->i_bitrate == p_ofmt->i_bitrate ) &&
- ( p_nfmt->i_extra == p_ofmt->i_extra ) &&
- ( p_nfmt->i_extra == 0 ||
- !memcmp( p_nfmt->p_extra, p_ofmt->p_extra, p_nfmt->i_extra ) ) &&
- !strcasecmp( p_nfmt->psz_language, p_ofmt->psz_language ) &&
- ( ( p_nfmt->i_cat == AUDIO_ES &&
- !memcmp( &p_nfmt->audio, &p_ofmt->audio, sizeof(audio_format_t) ) ) ||
- ( p_nfmt->i_cat == VIDEO_ES &&
- !memcmp( &p_nfmt->video, &p_ofmt->video, sizeof(video_format_t) ) ) ) )
+ if( ( new_fmt.i_cat == old_fmt.i_cat ) &&
+ ( new_fmt.i_codec == old_fmt.i_codec ) &&
+ ( new_fmt.i_priority == old_fmt.i_priority ) &&
+ ( new_fmt.i_bitrate == old_fmt.i_bitrate ) &&
+ ( new_fmt.i_extra == old_fmt.i_extra ) &&
+ ( new_fmt.i_extra == 0 ||
+ !memcmp( new_fmt.p_extra, old_fmt.p_extra, new_fmt.i_extra ) ) &&
+ !strcasecmp( new_fmt.psz_language, old_fmt.psz_language ) &&
+ ( ( new_fmt.i_cat == AUDIO_ES &&
+ !memcmp( &new_fmt.audio, &old_fmt.audio, sizeof(audio_format_t) ) ) ||
+ ( new_fmt.i_cat == VIDEO_ES &&
+ !memcmp( &new_fmt.video, &old_fmt.video, sizeof(video_format_t) ) ) ) )
{
/* FIXME handle video palettes... */
- msg_Warn( &old.sys.demuxer, "Reusing decoder of old track %zu for track %zu", j, i);
- p_tk->p_es = old.tracks[j]->p_es;
- old.tracks[j]->p_es = NULL;
+ msg_Warn( &old.sys.demuxer, "Reusing decoder of old track %u for track %u", old_track.i_number, new_track.i_number);
+ new_track.p_es = old_track.p_es;
+ old_track.p_es = NULL;
break;
}
}
}
- p_tk->fmt.i_priority &= ~(0x10);
- if( ( sub_lang && p_nfmt->i_cat == SPU_ES && !strcasecmp(sub_lang, p_nfmt->psz_language) ) ||
- ( aud_lang && p_nfmt->i_cat == AUDIO_ES && !strcasecmp(aud_lang, p_nfmt->psz_language) ) )
+ new_track.fmt.i_priority &= ~(0x10);
+ if( ( sub_lang && new_fmt.i_cat == SPU_ES && !strcasecmp(sub_lang, new_fmt.psz_language) ) ||
+ ( aud_lang && new_fmt.i_cat == AUDIO_ES && !strcasecmp(aud_lang, new_fmt.psz_language) ) )
{
- msg_Warn( &old.sys.demuxer, "Since previous segment used lang %s forcing track %zu",
- p_nfmt->psz_language, i);
- p_tk->fmt.i_priority |= 0x10;
- p_tk->b_forced = true;
+ msg_Warn( &old.sys.demuxer, "Since previous segment used lang %s forcing track %u",
+ new_fmt.psz_language, new_track.i_number );
+ new_fmt.i_priority |= 0x10;
+ new_track.b_forced = true;
}
}
}
--
2.8.2
More information about the vlc-devel
mailing list