Browse Source

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 <jb@videolan.org>
pull/46/head
Filip Roséen 10 years ago
committed by Jean-Baptiste Kempf
parent
commit
46d18e6bb0
  1. 145
      modules/demux/mkv/matroska_segment.cpp
  2. 6
      modules/demux/mkv/matroska_segment.hpp
  3. 104
      modules/demux/mkv/matroska_segment_parse.cpp
  4. 140
      modules/demux/mkv/mkv.cpp
  5. 1
      modules/demux/mkv/mkv.hpp
  6. 81
      modules/demux/mkv/virtual_segment.cpp

145
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();

6
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 );

104
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);
}
}

140
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() &&

1
modules/demux/mkv/mkv.hpp

@ -52,6 +52,7 @@
#include <string>
#include <vector>
#include <algorithm>
#include <map>
/* libebml and matroska */
#include "ebml/EbmlHead.h"

81
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;
}
}
}

Loading…
Cancel
Save