Commit 46d18e6b authored by Filip Roséen's avatar Filip Roséen Committed by Jean-Baptiste Kempf
Browse files

mkv: replaced usage of std::vector with std::map (matroska_segment_c::tracks)



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.
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent 72e98d2e
......@@ -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();
......
......@@ -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 );
......
......@@ -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);
}
}
......
......@@ -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 *