Commit ffcc0623 authored by Filip Roséen's avatar Filip Roséen Committed by Jean-Baptiste Kempf

mkv: use EbmlTypeDispatcher in matroska_segment_c::BlockGet

parent f5cdfd6e
......@@ -27,6 +27,7 @@
#include "demux.hpp"
#include "util.hpp"
#include "Ebml_parser.hpp"
#include "Ebml_dispatcher.hpp"
#include <new>
......@@ -1297,6 +1298,154 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
size_t i_tk;
*pi_duration = 0;
struct BlockPayload {
matroska_segment_c * const obj;
EbmlParser * const ep;
demux_t * const p_demuxer;
KaxBlock *& block;
KaxSimpleBlock *& simpleblock;
int64_t & i_duration;
bool & b_key_picture;
bool & b_discardable_picture;
} payload = {
this, ep, &sys.demuxer, pp_block, pp_simpleblock,
*pi_duration, *pb_key_picture, *pb_discardable_picture
};
MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l1, BlockPayload )
{
MKV_SWITCH_INIT();
E_CASE( KaxCluster, kcluster )
{
vars.obj->cluster = &kcluster;
vars.obj->i_cluster_pos = vars.obj->cluster->GetElementPosition();
for ( size_t i = 0; i < vars.obj->tracks.size(); ++i)
{
vars.obj->tracks[i]->b_silent = false;
}
vars.ep->Down ();
}
E_CASE( KaxCues, kcue )
{
VLC_UNUSED( kcue );
msg_Warn( vars.p_demuxer, "find KaxCues FIXME" );
throw VLC_EGENERIC;
}
E_CASE_DEFAULT(element)
{
msg_Dbg( vars.p_demuxer, "Unknown (%s)", typeid (element).name () );
}
};
MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l2, BlockPayload )
{
MKV_SWITCH_INIT();
E_CASE( KaxClusterTimecode, ktimecode )
{
ktimecode.ReadData( vars.obj->es.I_O(), SCOPE_ALL_DATA );
vars.obj->cluster->InitTimecode( static_cast<uint64>( ktimecode ), vars.obj->i_timescale );
}
E_CASE( KaxClusterSilentTracks, ksilent )
{
vars.obj->ep->Down ();
VLC_UNUSED( ksilent );
}
E_CASE( KaxBlockGroup, kbgroup )
{
vars.obj->i_block_pos = kbgroup.GetElementPosition();
vars.obj->ep->Down ();
}
E_CASE( KaxSimpleBlock, ksblock )
{
vars.simpleblock = &ksblock;
vars.simpleblock->ReadData( vars.obj->es.I_O() );
vars.simpleblock->SetParent( *vars.obj->cluster );
}
};
MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l3, BlockPayload )
{
MKV_SWITCH_INIT();
E_CASE( KaxBlock, kblock )
{
vars.block = &kblock;
vars.block->ReadData( vars.obj->es.I_O() );
vars.block->SetParent( *vars.obj->cluster );
vars.obj->ep->Keep ();
}
E_CASE( KaxBlockDuration, kduration )
{
kduration.ReadData( vars.obj->es.I_O() );
vars.i_duration = static_cast<uint64>( kduration );
}
E_CASE( KaxReferenceBlock, kreference )
{
kreference.ReadData( vars.obj->es.I_O() );
if( vars.b_key_picture )
vars.b_key_picture = false;
else if( static_cast<int64>( kreference ) )
vars.b_discardable_picture = true;
}
E_CASE( KaxClusterSilentTrackNumber, kstrackn )
{
kstrackn.ReadData( vars.obj->es.I_O() );
std::vector<mkv_track_t*> const& tracks = vars.obj->tracks;
uint32 i_number = static_cast<uint32> ( kstrackn );
for (size_t i = 0; i < tracks.size(); ++i )
{
if( tracks[i]->i_number == i_number )
{
tracks[i]->b_silent = true;
break;
}
}
}
#if LIBMATROSKA_VERSION >= 0x010401
E_CASE( KaxDiscardPadding, kdiscardp )
{
kdiscardp.ReadData( vars.obj->es.I_O() );
int64 i_duration = static_cast<int64>( kdiscardp );
if( vars.i_duration < i_duration )
vars.i_duration = 0;
else
vars.i_duration -= i_duration;
}
#endif
E_CASE_DEFAULT( element )
{
VLC_UNUSED(element);
msg_Err( vars.p_demuxer, "invalid level = %d", vars.obj->ep->GetLevel() );
throw VLC_EGENERIC;
}
};
static EbmlTypeDispatcher const * const dispatchers[] = {
&BlockGetHandler_l1::Dispatcher(),
&BlockGetHandler_l2::Dispatcher(),
&BlockGetHandler_l3::Dispatcher()
};
for( ;; )
{
EbmlElement *el = NULL;
......@@ -1323,24 +1472,19 @@ 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 )
{
switch(tracks[i_tk]->fmt.i_codec)
if( tracks[i_tk]->fmt.i_codec == VLC_CODEC_THEORA )
{
case VLC_CODEC_THEORA:
{
DataBuffer *p_data = &pp_block->GetBuffer(0);
size_t sz = p_data->Size();
const uint8_t * p_buff = p_data->Buffer();
/* if the second bit of a Theora frame is 1
it's not a keyframe */
if( sz && p_buff )
{
if( p_buff[0] & 0x40 )
*pb_key_picture = false;
}
else
*pb_key_picture = false;
break;
}
DataBuffer * p_data = &pp_block->GetBuffer(0);
const uint8_t * p_buff = p_data->Buffer();
/* if the second bit of a Theora frame is 1
it's not a keyframe */
if( p_data->Size() && p_buff )
{
if( p_buff[0] & 0x40 )
*pb_key_picture = false;
}
else
*pb_key_picture = false;
}
}
......@@ -1388,134 +1532,43 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
}
/* do parsing */
try
{
switch ( i_level )
{
case 1:
if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCluster, el ) )
{
cluster = kc_ptr;
i_cluster_pos = cluster->GetElementPosition();
// reset silent tracks
for (size_t i=0; i<tracks.size(); i++)
{
tracks[i]->b_silent = false;
}
ep->Down();
}
else if( MKV_IS_ID( el, KaxCues ) )
{
msg_Warn( &sys.demuxer, "find KaxCues FIXME" );
return VLC_EGENERIC;
}
else
{
msg_Dbg( &sys.demuxer, "unknown (%s)", typeid( el ).name() );
}
break;
try {
switch( i_level )
{
case 2:
if( unlikely( !el->ValidateSize() ||
( el->IsFiniteSize() && el->GetSize() >= SIZE_MAX ) ) )
{
msg_Err( &sys.demuxer, "Error while reading %s... upping level", typeid(*el).name());
ep->Up();
break;
}
if( MKV_CHECKED_PTR_DECL ( kct_ptr, KaxClusterTimecode, el ) )
{
kct_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
cluster->InitTimecode( static_cast<uint64>( *kct_ptr ), i_timescale );
/* add it to the index */
if( index_idx() == 0 ||
( prev_index().i_position < static_cast<int64_t>( cluster->GetElementPosition() ) ) )
{
IndexAppendCluster( cluster );
}
}
else if( MKV_IS_ID( el, KaxClusterSilentTracks ) )
{
ep->Down();
}
else if( MKV_IS_ID( el, KaxBlockGroup ) )
{
i_block_pos = el->GetElementPosition();
ep->Down();
}
else if( MKV_CHECKED_PTR_DECL ( ksb_ptr, KaxSimpleBlock, el ) )
{
pp_simpleblock = ksb_ptr;
pp_simpleblock->ReadData( es.I_O() );
pp_simpleblock->SetParent( *cluster );
}
break;
case 3:
if( unlikely( !el->ValidateSize() ||
( el->IsFiniteSize() && el->GetSize() >= SIZE_MAX ) ) )
if( unlikely( !el->ValidateSize() || ( el->IsFiniteSize() && el->GetSize() >= SIZE_MAX ) ) )
{
msg_Err( &sys.demuxer, "Error while reading %s... upping level", typeid(*el).name());
ep->Up();
if ( i_level == 2 )
break;
ep->Unkeep();
pp_simpleblock = NULL;
pp_block = NULL;
break;
}
if( MKV_CHECKED_PTR_DECL ( kb_ptr, KaxBlock, el ) )
{
pp_block = kb_ptr;
pp_block->ReadData( es.I_O() );
pp_block->SetParent( *cluster );
ep->Keep();
}
else if( MKV_CHECKED_PTR_DECL ( kbd_ptr, KaxBlockDuration, el ) )
{
kbd_ptr->ReadData( es.I_O() );
*pi_duration = static_cast<uint64>( *kbd_ptr );
}
else if( MKV_CHECKED_PTR_DECL ( krb_ptr, KaxReferenceBlock, el ) )
{
krb_ptr->ReadData( es.I_O() );
if( *pb_key_picture )
*pb_key_picture = false;
else if( int64( *krb_ptr ) > 0 )
*pb_discardable_picture = true;
}
else if( MKV_CHECKED_PTR_DECL ( kcstn_ptr, KaxClusterSilentTrackNumber, el ) )
{
kcstn_ptr->ReadData( es.I_O() );
// find the track
for (size_t i=0; i<tracks.size(); i++)
{
if ( tracks[i]->i_number == static_cast<uint32>( *kcstn_ptr ) )
{
tracks[i]->b_silent = true;
break;
}
}
break;
}
#if LIBMATROSKA_VERSION >= 0x010401
else if( MKV_CHECKED_PTR_DECL ( kdp_ptr, KaxDiscardPadding, el ) )
case 1:
{
kdp_ptr->ReadData( es.I_O() );
if ( *pi_duration < static_cast<int64>( *kdp_ptr ) )
*pi_duration = 0;
else
*pi_duration -= static_cast<int64>( *kdp_ptr );
EbmlTypeDispatcher const * dispatcher = dispatchers[i_level - 1];
dispatcher->send( el, BlockGetHandler_l1::Payload( payload ) );
}
#endif
break;
default:
msg_Err( &sys.demuxer, "invalid level = %d", i_level );
return VLC_EGENERIC;
}
}
catch(...)
catch (int ret_code)
{
return ret_code;
}
catch (...)
{
msg_Err( &sys.demuxer, "Error while reading %s... upping level", typeid(*el).name());
ep->Up();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment