+}
+
+void *event_thread_t::EventThread(void *data)
+{
+ static_cast<event_thread_t*>(data)->EventThread();
+ return NULL;
+}
+
+
+demux_sys_t::~demux_sys_t()
+{
+ CleanUi();
+ size_t i;
+ for ( i=0; i<streams.size(); i++ )
+ delete streams[i];
+ for ( i=0; i<opened_segments.size(); i++ )
+ delete opened_segments[i];
+ for ( i=0; i<used_segments.size(); i++ )
+ delete used_segments[i];
+ for ( i=0; i<stored_attachments.size(); i++ )
+ delete stored_attachments[i];
+ if( meta ) vlc_meta_Delete( meta );
+
+ while( titles.size() )
+ { vlc_input_title_Delete( titles.back() ); titles.pop_back();}
+
+ vlc_mutex_destroy( &lock_demuxer );
+}
+
+
+matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial )
+{
+ int i_upper_lvl = 0;
+ EbmlElement *p_l0, *p_l1, *p_l2;
+ bool b_keep_stream = false, b_keep_segment = false;
+
+ /* verify the EBML Header... it shouldn't be bigger than 1kB */
+ p_l0 = p_estream->FindNextID(EBML_INFO(EbmlHead), 1024);
+ if (p_l0 == NULL)
+ {
+ msg_Err( p_demux, "No EBML header found" );
+ return NULL;
+ }
+
+ /* verify we can read this Segment */
+ try
+ {
+ p_l0->Read(*p_estream, EBML_CLASS_CONTEXT(EbmlHead), i_upper_lvl, p_l0, true);
+ }
+ catch(...)
+ {
+ msg_Err(p_demux, "EBML Header Read failed");
+ return NULL;
+ }
+
+ EDocType doc_type = GetChild<EDocType>(*static_cast<EbmlHead*>(p_l0));
+ if (std::string(doc_type) != "matroska" && std::string(doc_type) != "webm" )
+ {
+ msg_Err( p_demux, "Not a Matroska file : DocType = %s ", std::string(doc_type).c_str());
+ return NULL;
+ }
+
+ EDocTypeReadVersion doc_read_version = GetChild<EDocTypeReadVersion>(*static_cast<EbmlHead*>(p_l0));
+ if (uint64(doc_read_version) > 2)
+ {
+ msg_Err( p_demux, "matroska file needs version %"PRId64" but only versions 1 & 2 supported", uint64(doc_read_version));
+ return NULL;
+ }
+
+ delete p_l0;
+
+
+ // find all segments in this file
+ p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), UINT64_MAX);
+ if (p_l0 == NULL)
+ {
+ return NULL;
+ }
+
+ matroska_stream_c *p_stream1 = new matroska_stream_c();
+
+ while (p_l0 != 0)
+ {
+ if ( MKV_IS_ID( p_l0, KaxSegment) )
+ {
+ EbmlParser *ep;
+ matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
+
+ ep = new EbmlParser(p_estream, p_l0, &demuxer );
+ p_segment1->ep = ep;
+ p_segment1->segment = (KaxSegment*)p_l0;
+
+ while ((p_l1 = ep->Get()))
+ {
+ if (MKV_IS_ID(p_l1, KaxInfo))
+ {
+ // find the families of this segment
+ KaxInfo *p_info = static_cast<KaxInfo*>(p_l1);
+ b_keep_segment = b_initial;
+ if( unlikely( p_info->GetSize() >= SIZE_MAX ) )
+ {
+ msg_Err( p_demux, "KaxInfo too big aborting" );
+ break;
+ }
+ try
+ {
+ p_info->Read(*p_estream, EBML_CLASS_CONTEXT(KaxInfo), i_upper_lvl, p_l2, true);
+ }
+ catch (...)
+ {
+ msg_Err( p_demux, "KaxInfo found but corrupted");
+ break;
+ }
+ for( size_t i = 0; i < p_info->ListSize(); i++ )
+ {
+ EbmlElement *l = (*p_info)[i];
+
+ if( MKV_IS_ID( l, KaxSegmentUID ) )
+ {
+ KaxSegmentUID *p_uid = static_cast<KaxSegmentUID*>(l);
+ b_keep_segment = (FindSegment( *p_uid ) == NULL);
+ delete p_segment1->p_segment_uid;
+ p_segment1->p_segment_uid = new KaxSegmentUID(*p_uid);
+ if ( !b_keep_segment )
+ break; // this segment is already known
+ }
+ else if( MKV_IS_ID( l, KaxPrevUID ) )
+ {
+ p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) );
+ p_segment1->b_ref_external_segments = true;
+ }
+ else if( MKV_IS_ID( l, KaxNextUID ) )
+ {
+ p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) );
+ p_segment1->b_ref_external_segments = true;
+ }
+ else if( MKV_IS_ID( l, KaxSegmentFamily ) )
+ {
+ KaxSegmentFamily *p_fam = new KaxSegmentFamily( *static_cast<KaxSegmentFamily*>(l) );
+ p_segment1->families.push_back( p_fam );
+ }
+ }
+ if( b_keep_segment || !p_segment1->p_segment_uid )
+ opened_segments.push_back( p_segment1 );
+ break;
+ }
+ }
+ if ( b_keep_segment || !p_segment1->p_segment_uid )
+ {
+ b_keep_stream = true;
+ p_stream1->segments.push_back( p_segment1 );
+ }
+ else
+ {
+ p_segment1->segment = NULL;
+ delete p_segment1;
+ }
+ }
+ if (p_l0->IsFiniteSize() )
+ {
+ p_l0->SkipData(*p_estream, KaxMatroska_Context);
+ p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), UINT64_MAX);
+ }
+ else
+ {
+ p_l0 = NULL;
+ }
+ }
+
+ if ( !b_keep_stream )
+ {
+ delete p_stream1;
+ p_stream1 = NULL;
+ }
+
+ return p_stream1;
+}
+
+void demux_sys_t::InitUi()
+{
+ msg_Dbg( &demuxer, "Starting the UI Hook" );
+
+ /* FIXME hack hack hack hack FIXME */
+ /* Get p_input and create variable */
+ p_input = demux_GetParentInput( &demuxer );
+ if( p_input )
+ {
+ var_Create( p_input, "x-start", VLC_VAR_INTEGER );
+ var_Create( p_input, "y-start", VLC_VAR_INTEGER );
+ var_Create( p_input, "x-end", VLC_VAR_INTEGER );
+ var_Create( p_input, "y-end", VLC_VAR_INTEGER );
+ var_Create( p_input, "color", VLC_VAR_ADDRESS );
+ var_Create( p_input, "menu-palette", VLC_VAR_ADDRESS );
+ var_Create( p_input, "highlight", VLC_VAR_BOOL );
+ }
+
+ /* Now create our event thread catcher */
+ p_ev = new event_thread_t(&demuxer);
+}
+
+void demux_sys_t::CleanUi()
+{
+ delete p_ev;
+ p_ev = NULL;
+
+ if( p_input )
+ {
+ var_Destroy( p_input, "highlight" );
+ var_Destroy( p_input, "x-start" );
+ var_Destroy( p_input, "x-end" );
+ var_Destroy( p_input, "y-start" );
+ var_Destroy( p_input, "y-end" );
+ var_Destroy( p_input, "color" );
+ var_Destroy( p_input, "menu-palette" );
+
+ vlc_object_release( p_input );
+ }
+
+ msg_Dbg( &demuxer, "Stopping the UI Hook" );