2 /*****************************************************************************
3 * mkv.cpp : matroska demuxer
4 *****************************************************************************
5 * Copyright (C) 2003-2004 VLC authors and VideoLAN
8 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * Steve Lhomme <steve.lhomme@free.fr>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
27 #include "stream_io_callback.hpp"
28 #include "Ebml_parser.hpp"
32 event_thread_t::event_thread_t(demux_t
*p_demux
) : p_demux(p_demux
)
34 vlc_mutex_init( &lock
);
35 vlc_cond_init( &wait
);
38 event_thread_t::~event_thread_t()
41 vlc_cond_destroy( &wait
);
42 vlc_mutex_destroy( &lock
);
45 void event_thread_t::SetPci(const pci_t
*data
)
47 vlc_mutex_locker
l(&lock
);
51 #ifndef WORDS_BIGENDIAN
52 for( uint8_t button
= 1; button
<= pci_packet
.hli
.hl_gi
.btn_ns
; button
++) {
53 btni_t
*button_ptr
= &(pci_packet
.hli
.btnit
[button
-1]);
54 binary
*p_data
= (binary
*) button_ptr
;
56 uint16 i_x_start
= ((p_data
[0] & 0x3F) << 4 ) + ( p_data
[1] >> 4 );
57 uint16 i_x_end
= ((p_data
[1] & 0x03) << 8 ) + p_data
[2];
58 uint16 i_y_start
= ((p_data
[3] & 0x3F) << 4 ) + ( p_data
[4] >> 4 );
59 uint16 i_y_end
= ((p_data
[4] & 0x03) << 8 ) + p_data
[5];
60 button_ptr
->x_start
= i_x_start
;
61 button_ptr
->x_end
= i_x_end
;
62 button_ptr
->y_start
= i_y_start
;
63 button_ptr
->y_end
= i_y_end
;
66 for ( uint8_t i
= 0; i
<3; i
++ )
67 for ( uint8_t j
= 0; j
<2; j
++ )
68 pci_packet
.hli
.btn_colit
.btn_coli
[i
][j
] = U32_AT( &pci_packet
.hli
.btn_colit
.btn_coli
[i
][j
] );
73 is_running
= !vlc_clone( &thread
, EventThread
, this, VLC_THREAD_PRIORITY_LOW
);
76 void event_thread_t::ResetPci()
81 vlc_mutex_lock( &lock
);
83 vlc_cond_signal( &wait
);
84 vlc_mutex_unlock( &lock
);
86 vlc_join( thread
, NULL
);
89 int event_thread_t::EventMouse( vlc_object_t
*p_this
, char const *psz_var
,
90 vlc_value_t
, vlc_value_t
, void *p_data
)
92 event_thread_t
*p_ev
= (event_thread_t
*) p_data
;
93 vlc_mutex_lock( &p_ev
->lock
);
94 if( psz_var
[6] == 'c' )
96 p_ev
->b_clicked
= true;
97 msg_Dbg( p_this
, "Event Mouse: clicked");
99 else if( psz_var
[6] == 'm' )
100 p_ev
->b_moved
= true;
101 vlc_cond_signal( &p_ev
->wait
);
102 vlc_mutex_unlock( &p_ev
->lock
);
107 int event_thread_t::EventKey( vlc_object_t
*p_this
, char const *,
108 vlc_value_t
, vlc_value_t newval
, void *p_data
)
110 event_thread_t
*p_ev
= (event_thread_t
*) p_data
;
111 vlc_mutex_lock( &p_ev
->lock
);
112 p_ev
->i_key_action
= newval
.i_int
;
113 vlc_cond_signal( &p_ev
->wait
);
114 vlc_mutex_unlock( &p_ev
->lock
);
115 msg_Dbg( p_this
, "Event Key");
120 int event_thread_t::EventInput( vlc_object_t
*p_this
, char const *,
121 vlc_value_t
, vlc_value_t newval
, void *p_data
)
123 VLC_UNUSED( p_this
);
124 event_thread_t
*p_ev
= (event_thread_t
*) p_data
;
125 vlc_mutex_lock( &p_ev
->lock
);
126 if( newval
.i_int
== INPUT_EVENT_VOUT
)
128 p_ev
->b_vout
|= true;
129 vlc_cond_signal( &p_ev
->wait
);
131 vlc_mutex_unlock( &p_ev
->lock
);
136 void event_thread_t::EventThread()
138 demux_sys_t
*p_sys
= p_demux
->p_sys
;
139 vlc_object_t
*p_vout
= NULL
;
140 int canc
= vlc_savecancel ();
147 /* catch all key event */
148 var_AddCallback( p_demux
->obj
.libvlc
, "key-action", EventKey
, this );
149 /* catch input event */
150 var_AddCallback( p_demux
->p_input
, "intf-event", EventInput
, this );
155 vlc_mutex_lock( &lock
);
156 while( !b_abort
&& !i_key_action
&& !b_moved
&& !b_clicked
&& !b_vout
)
157 vlc_cond_wait( &wait
, &lock
);
161 vlc_mutex_unlock( &lock
);
168 msg_Dbg( p_demux
, "Handle Key Event");
170 pci_t
*pci
= &pci_packet
;
172 uint16 i_curr_button
= p_sys
->dvd_interpretor
.GetSPRM( 0x88 );
174 switch( i_key_action
)
176 case ACTIONID_NAV_LEFT
:
177 if ( i_curr_button
> 0 && i_curr_button
<= pci
->hli
.hl_gi
.btn_ns
)
179 btni_t
*p_button_ptr
= &(pci
->hli
.btnit
[i_curr_button
-1]);
180 if ( p_button_ptr
->left
> 0 && p_button_ptr
->left
<= pci
->hli
.hl_gi
.btn_ns
)
182 i_curr_button
= p_button_ptr
->left
;
183 p_sys
->dvd_interpretor
.SetSPRM( 0x88, i_curr_button
);
184 btni_t button_ptr
= pci
->hli
.btnit
[i_curr_button
-1];
185 if ( button_ptr
.auto_action_mode
)
187 vlc_mutex_unlock( &lock
);
188 vlc_mutex_lock( &p_sys
->lock_demuxer
);
190 // process the button action
191 p_sys
->dvd_interpretor
.Interpret( button_ptr
.cmd
.bytes
, 8 );
193 vlc_mutex_unlock( &p_sys
->lock_demuxer
);
194 vlc_mutex_lock( &lock
);
199 case ACTIONID_NAV_RIGHT
:
200 if ( i_curr_button
> 0 && i_curr_button
<= pci
->hli
.hl_gi
.btn_ns
)
202 btni_t
*p_button_ptr
= &(pci
->hli
.btnit
[i_curr_button
-1]);
203 if ( p_button_ptr
->right
> 0 && p_button_ptr
->right
<= pci
->hli
.hl_gi
.btn_ns
)
205 i_curr_button
= p_button_ptr
->right
;
206 p_sys
->dvd_interpretor
.SetSPRM( 0x88, i_curr_button
);
207 btni_t button_ptr
= pci
->hli
.btnit
[i_curr_button
-1];
208 if ( button_ptr
.auto_action_mode
)
210 vlc_mutex_unlock( &lock
);
211 vlc_mutex_lock( &p_sys
->lock_demuxer
);
213 // process the button action
214 p_sys
->dvd_interpretor
.Interpret( button_ptr
.cmd
.bytes
, 8 );
216 vlc_mutex_unlock( &p_sys
->lock_demuxer
);
217 vlc_mutex_lock( &lock
);
222 case ACTIONID_NAV_UP
:
223 if ( i_curr_button
> 0 && i_curr_button
<= pci
->hli
.hl_gi
.btn_ns
)
225 btni_t
*p_button_ptr
= &(pci
->hli
.btnit
[i_curr_button
-1]);
226 if ( p_button_ptr
->up
> 0 && p_button_ptr
->up
<= pci
->hli
.hl_gi
.btn_ns
)
228 i_curr_button
= p_button_ptr
->up
;
229 p_sys
->dvd_interpretor
.SetSPRM( 0x88, i_curr_button
);
230 btni_t button_ptr
= pci
->hli
.btnit
[i_curr_button
-1];
231 if ( button_ptr
.auto_action_mode
)
233 vlc_mutex_unlock( &lock
);
234 vlc_mutex_lock( &p_sys
->lock_demuxer
);
236 // process the button action
237 p_sys
->dvd_interpretor
.Interpret( button_ptr
.cmd
.bytes
, 8 );
239 vlc_mutex_unlock( &p_sys
->lock_demuxer
);
240 vlc_mutex_lock( &lock
);
245 case ACTIONID_NAV_DOWN
:
246 if ( i_curr_button
> 0 && i_curr_button
<= pci
->hli
.hl_gi
.btn_ns
)
248 btni_t
*p_button_ptr
= &(pci
->hli
.btnit
[i_curr_button
-1]);
249 if ( p_button_ptr
->down
> 0 && p_button_ptr
->down
<= pci
->hli
.hl_gi
.btn_ns
)
251 i_curr_button
= p_button_ptr
->down
;
252 p_sys
->dvd_interpretor
.SetSPRM( 0x88, i_curr_button
);
253 btni_t button_ptr
= pci
->hli
.btnit
[i_curr_button
-1];
254 if ( button_ptr
.auto_action_mode
)
256 vlc_mutex_unlock( &lock
);
257 vlc_mutex_lock( &p_sys
->lock_demuxer
);
259 // process the button action
260 p_sys
->dvd_interpretor
.Interpret( button_ptr
.cmd
.bytes
, 8 );
262 vlc_mutex_unlock( &p_sys
->lock_demuxer
);
263 vlc_mutex_lock( &lock
);
268 case ACTIONID_NAV_ACTIVATE
:
269 if ( i_curr_button
> 0 && i_curr_button
<= pci
->hli
.hl_gi
.btn_ns
)
271 btni_t button_ptr
= pci
->hli
.btnit
[i_curr_button
-1];
273 vlc_mutex_unlock( &lock
);
274 vlc_mutex_lock( &p_sys
->lock_demuxer
);
276 // process the button action
277 p_sys
->dvd_interpretor
.Interpret( button_ptr
.cmd
.bytes
, 8 );
279 vlc_mutex_unlock( &p_sys
->lock_demuxer
);
280 vlc_mutex_lock( &lock
);
290 if( p_vout
&& ( b_moved
|| b_clicked
) )
294 var_GetCoords( p_vout
, "mouse-moved", &x
, &y
);
295 pci_t
*pci
= &pci_packet
;
303 msg_Dbg( p_demux
, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x
, y
);
305 // get current button
307 dist
= 0x08000000; /* >> than (720*720)+(567*567); */
308 for(button
= 1; button
<= pci
->hli
.hl_gi
.btn_ns
; button
++)
310 btni_t
*button_ptr
= &(pci
->hli
.btnit
[button
-1]);
312 if(((unsigned)x
>= button_ptr
->x_start
)
313 && ((unsigned)x
<= button_ptr
->x_end
)
314 && ((unsigned)y
>= button_ptr
->y_start
)
315 && ((unsigned)y
<= button_ptr
->y_end
))
317 mx
= (button_ptr
->x_start
+ button_ptr
->x_end
)/2;
318 my
= (button_ptr
->y_start
+ button_ptr
->y_end
)/2;
321 d
= (dx
*dx
) + (dy
*dy
);
322 /* If the mouse is within the button and the mouse is closer
323 * to the center of this button then it is the best choice. */
333 btni_t button_ptr
= pci
->hli
.btnit
[best
-1];
334 uint16 i_curr_button
= p_sys
->dvd_interpretor
.GetSPRM( 0x88 );
336 msg_Dbg( &p_sys
->demuxer
, "Clicked button %d", best
);
337 vlc_mutex_unlock( &lock
);
338 vlc_mutex_lock( &p_sys
->lock_demuxer
);
340 // process the button action
341 p_sys
->dvd_interpretor
.SetSPRM( 0x88, best
);
342 p_sys
->dvd_interpretor
.Interpret( button_ptr
.cmd
.bytes
, 8 );
344 msg_Dbg( &p_sys
->demuxer
, "Processed button %d", best
);
347 if ( best
!= i_curr_button
)
351 if(button_ptr
.btn_coln
!= 0) {
352 i_palette
= pci
->hli
.btn_colit
.btn_coli
[button_ptr
.btn_coln
-1][1];
357 for( int i
= 0; i
< 4; i
++ )
359 uint32_t i_yuv
= 0xFF;//p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
360 uint8_t i_alpha
= (i_palette
>>(i
*4))&0x0f;
361 i_alpha
= i_alpha
== 0xf ? 0xff : i_alpha
<< 4;
363 p_sys
->palette
[i
][0] = (i_yuv
>> 16) & 0xff;
364 p_sys
->palette
[i
][1] = (i_yuv
>> 0) & 0xff;
365 p_sys
->palette
[i
][2] = (i_yuv
>> 8) & 0xff;
366 p_sys
->palette
[i
][3] = i_alpha
;
369 vlc_global_lock( VLC_HIGHLIGHT_MUTEX
);
370 var_SetInteger( p_demux
->p_input
, "x-start",
371 button_ptr
.x_start
);
372 var_SetInteger( p_demux
->p_input
, "x-end",
374 var_SetInteger( p_demux
->p_input
, "y-start",
375 button_ptr
.y_start
);
376 var_SetInteger( p_demux
->p_input
, "y-end",
378 var_SetAddress( p_demux
->p_input
, "menu-palette",
380 var_SetBool( p_demux
->p_input
, "highlight", true );
381 vlc_global_unlock( VLC_HIGHLIGHT_MUTEX
);
383 vlc_mutex_unlock( &p_sys
->lock_demuxer
);
384 vlc_mutex_lock( &lock
);
389 // dvdnav_mouse_select( NULL, pci, x, y );
397 vlc_mutex_unlock( &lock
);
399 /* Always check vout */
402 p_vout
= (vlc_object_t
*) input_GetVout(p_demux
->p_input
);
405 var_AddCallback( p_vout
, "mouse-moved", EventMouse
, this );
406 var_AddCallback( p_vout
, "mouse-clicked", EventMouse
, this );
411 /* Release callback */
414 var_DelCallback( p_vout
, "mouse-moved", EventMouse
, this );
415 var_DelCallback( p_vout
, "mouse-clicked", EventMouse
, this );
416 vlc_object_release( p_vout
);
418 var_DelCallback( p_demux
->p_input
, "intf-event", EventInput
, this );
419 var_DelCallback( p_demux
->obj
.libvlc
, "key-action", EventKey
, this );
421 vlc_restorecancel (canc
);
424 void *event_thread_t::EventThread(void *data
)
426 static_cast<event_thread_t
*>(data
)->EventThread();
431 demux_sys_t::~demux_sys_t()
435 for ( i
=0; i
<streams
.size(); i
++ )
437 for ( i
=0; i
<opened_segments
.size(); i
++ )
438 delete opened_segments
[i
];
439 for ( i
=0; i
<used_vsegments
.size(); i
++ )
440 delete used_vsegments
[i
];
441 for ( i
=0; i
<stored_attachments
.size(); i
++ )
442 delete stored_attachments
[i
];
443 if( meta
) vlc_meta_Delete( meta
);
445 while( titles
.size() )
446 { vlc_input_title_Delete( titles
.back() ); titles
.pop_back();}
448 vlc_mutex_destroy( &lock_demuxer
);
452 matroska_stream_c
*demux_sys_t::AnalyseAllSegmentsFound( demux_t
*p_demux
, EbmlStream
*p_estream
, bool b_initial
)
455 EbmlElement
*p_l0
, *p_l1
, *p_l2
;
456 bool b_keep_stream
= false, b_keep_segment
= false;
458 /* verify the EBML Header... it shouldn't be bigger than 1kB */
459 p_l0
= p_estream
->FindNextID(EBML_INFO(EbmlHead
), 1024);
462 msg_Err( p_demux
, "No EBML header found" );
466 /* verify we can read this Segment */
469 p_l0
->Read(*p_estream
, EBML_CLASS_CONTEXT(EbmlHead
), i_upper_lvl
, p_l0
, true);
473 msg_Err(p_demux
, "EBML Header Read failed");
477 EDocType doc_type
= GetChild
<EDocType
>(*static_cast<EbmlHead
*>(p_l0
));
478 if (std::string(doc_type
) != "matroska" && std::string(doc_type
) != "webm" )
480 msg_Err( p_demux
, "Not a Matroska file : DocType = %s ", std::string(doc_type
).c_str());
484 EDocTypeReadVersion doc_read_version
= GetChild
<EDocTypeReadVersion
>(*static_cast<EbmlHead
*>(p_l0
));
485 if (uint64(doc_read_version
) > 2)
487 msg_Err( p_demux
, "matroska file needs version %" PRId64
" but only versions 1 & 2 supported", uint64(doc_read_version
));
494 // find all segments in this file
495 p_l0
= p_estream
->FindNextID(EBML_INFO(KaxSegment
), UINT64_MAX
);
501 matroska_stream_c
*p_stream1
= new matroska_stream_c();
505 if ( MKV_IS_ID( p_l0
, KaxSegment
) )
508 matroska_segment_c
*p_segment1
= new matroska_segment_c( *this, *p_estream
);
510 ep
= new EbmlParser(p_estream
, p_l0
, &demuxer
,
511 var_InheritBool( &demuxer
, "mkv-use-dummy" ) );
513 p_segment1
->segment
= (KaxSegment
*)p_l0
;
515 while ((p_l1
= ep
->Get()))
517 if (MKV_IS_ID(p_l1
, KaxInfo
))
519 // find the families of this segment
520 KaxInfo
*p_info
= static_cast<KaxInfo
*>(p_l1
);
521 b_keep_segment
= b_initial
;
522 if( unlikely( p_info
->IsFiniteSize() && p_info
->GetSize() >= SIZE_MAX
) )
524 msg_Err( p_demux
, "KaxInfo too big aborting" );
529 p_info
->Read(*p_estream
, EBML_CLASS_CONTEXT(KaxInfo
), i_upper_lvl
, p_l2
, true);
533 msg_Err( p_demux
, "KaxInfo found but corrupted");
536 for( size_t i
= 0; i
< p_info
->ListSize(); i
++ )
538 EbmlElement
*l
= (*p_info
)[i
];
540 if( MKV_IS_ID( l
, KaxSegmentUID
) )
542 KaxSegmentUID
*p_uid
= static_cast<KaxSegmentUID
*>(l
);
543 b_keep_segment
= (FindSegment( *p_uid
) == NULL
);
544 delete p_segment1
->p_segment_uid
;
545 p_segment1
->p_segment_uid
= new KaxSegmentUID(*p_uid
);
546 if ( !b_keep_segment
)
547 break; // this segment is already known
549 else if( MKV_IS_ID( l
, KaxPrevUID
) )
551 p_segment1
->p_prev_segment_uid
= new KaxPrevUID( *static_cast<KaxPrevUID
*>(l
) );
552 p_segment1
->b_ref_external_segments
= true;
554 else if( MKV_IS_ID( l
, KaxNextUID
) )
556 p_segment1
->p_next_segment_uid
= new KaxNextUID( *static_cast<KaxNextUID
*>(l
) );
557 p_segment1
->b_ref_external_segments
= true;
559 else if( MKV_IS_ID( l
, KaxSegmentFamily
) )
561 KaxSegmentFamily
*p_fam
= new KaxSegmentFamily( *static_cast<KaxSegmentFamily
*>(l
) );
562 p_segment1
->families
.push_back( p_fam
);
565 if( b_keep_segment
|| !p_segment1
->p_segment_uid
)
566 opened_segments
.push_back( p_segment1
);
570 if ( b_keep_segment
|| !p_segment1
->p_segment_uid
)
572 b_keep_stream
= true;
573 p_stream1
->segments
.push_back( p_segment1
);
577 p_segment1
->segment
= NULL
;
581 if (p_l0
->IsFiniteSize() )
583 p_l0
->SkipData(*p_estream
, KaxMatroska_Context
);
584 p_l0
= p_estream
->FindNextID(EBML_INFO(KaxSegment
), UINT64_MAX
);
592 if ( !b_keep_stream
)
601 void demux_sys_t::InitUi()
603 msg_Dbg( &demuxer
, "Starting the UI Hook" );
605 /* FIXME hack hack hack hack FIXME */
606 /* Get p_input and create variable */
607 p_input
= demuxer
.p_input
;
610 var_Create( p_input
, "x-start", VLC_VAR_INTEGER
);
611 var_Create( p_input
, "y-start", VLC_VAR_INTEGER
);
612 var_Create( p_input
, "x-end", VLC_VAR_INTEGER
);
613 var_Create( p_input
, "y-end", VLC_VAR_INTEGER
);
614 var_Create( p_input
, "color", VLC_VAR_ADDRESS
);
615 var_Create( p_input
, "menu-palette", VLC_VAR_ADDRESS
);
616 var_Create( p_input
, "highlight", VLC_VAR_BOOL
);
619 /* Now create our event thread catcher */
620 p_ev
= new event_thread_t(&demuxer
);
623 void demux_sys_t::CleanUi()
630 var_Destroy( p_input
, "highlight" );
631 var_Destroy( p_input
, "x-start" );
632 var_Destroy( p_input
, "x-end" );
633 var_Destroy( p_input
, "y-start" );
634 var_Destroy( p_input
, "y-end" );
635 var_Destroy( p_input
, "color" );
636 var_Destroy( p_input
, "menu-palette" );
639 msg_Dbg( &demuxer
, "Stopping the UI Hook" );
642 void demux_sys_t::PreloadFamily( const matroska_segment_c
& of_segment
)
644 for (size_t i
=0; i
<opened_segments
.size(); i
++)
646 opened_segments
[i
]->PreloadFamily( of_segment
);
650 // preload all the linked segments for all preloaded segments
651 bool demux_sys_t::PreloadLinked()
654 virtual_segment_c
*p_vseg
;
656 if ( unlikely(opened_segments
.size() == 0) )
659 p_current_vsegment
= new (std::nothrow
) virtual_segment_c( *(opened_segments
[0]), opened_segments
);
660 if ( !p_current_vsegment
)
663 /* Set current chapter */
664 p_current_vsegment
->p_current_vchapter
= p_current_vsegment
->veditions
[p_current_vsegment
->i_current_edition
]->getChapterbyTimecode(0);
665 msg_Dbg( &demuxer
, "NEW START CHAPTER uid=%" PRId64
, p_current_vsegment
->p_current_vchapter
&& p_current_vsegment
->p_current_vchapter
->p_chapter
?
666 p_current_vsegment
->p_current_vchapter
->p_chapter
->i_uid
: 0 );
668 used_vsegments
.push_back( p_current_vsegment
);
670 for ( i
=1; i
< opened_segments
.size(); i
++ )
672 /* add segments from the same family to used_segments */
673 if ( opened_segments
[0]->SameFamily( *(opened_segments
[i
]) ) )
675 virtual_segment_c
*p_vsegment
= new (std::nothrow
) virtual_segment_c( *(opened_segments
[i
]), opened_segments
);
676 if ( likely(p_vsegment
!= NULL
) )
677 used_vsegments
.push_back( p_vsegment
);
681 // publish all editions of all usable segment
682 for ( i
=0; i
< used_vsegments
.size(); i
++ )
684 p_vseg
= used_vsegments
[i
];
685 if ( p_vseg
->Editions() != NULL
)
687 for ( j
=0; j
<p_vseg
->Editions()->size(); j
++ )
689 virtual_edition_c
* p_ved
= (*p_vseg
->Editions())[j
];
690 input_title_t
*p_title
= vlc_input_title_New();
693 // TODO use a name for each edition, let the TITLE deal with a codec name
694 if ( p_title
->psz_name
== NULL
)
696 if( p_ved
->GetMainName().length() )
697 p_title
->psz_name
= strdup( p_ved
->GetMainName().c_str() );
700 /* Check in tags if the edition has a name */
702 /* We use only the tags of the first segment as it contains the edition */
703 matroska_segment_c::tags_t
const& tags
= opened_segments
[0]->tags
;
704 uint64_t i_ed_uid
= 0;
705 if( p_ved
->p_edition
)
706 i_ed_uid
= (uint64_t) p_ved
->p_edition
->i_uid
;
708 for( size_t k
= 0; k
< tags
.size(); k
++ )
710 if( tags
[k
].i_tag_type
== EDITION_UID
&& tags
[k
].i_uid
== i_ed_uid
)
711 for( size_t l
= 0; l
< tags
[k
].simple_tags
.size(); l
++ )
713 SimpleTag
const& st
= tags
[k
].simple_tags
[l
];
714 if ( st
.tag_name
== "TITLE" )
716 msg_Dbg( &demuxer
, "Using title \"%s\" from tag for edition %" PRIu64
, st
.value
.c_str (), i_ed_uid
);
717 p_title
->psz_name
= strdup( st
.value
.c_str () );
723 if( !p_title
->psz_name
&&
724 asprintf(&(p_title
->psz_name
), "%s %d", "Segment", (int)ij
) == -1 )
725 p_title
->psz_name
= NULL
;
731 p_ved
->PublishChapters( *p_title
, i_chapters
, 0 );
733 // Input duration into i_length
734 p_title
->i_length
= p_ved
->i_duration
;
736 titles
.push_back( p_title
);
739 p_vseg
->i_sys_title
= p_vseg
->i_current_edition
;
742 // TODO decide which segment should be first used (VMG for DVD)
747 void demux_sys_t::FreeUnused()
750 for( i
= 0; i
< streams
.size(); i
++ )
753 struct matroska_stream_c
*p_s
= streams
[i
];
754 for( size_t j
= 0; j
< p_s
->segments
.size(); j
++ )
756 if( p_s
->segments
[j
]->b_preloaded
)
768 for( i
= 0; i
< opened_segments
.size(); i
++)
770 if( !opened_segments
[i
]->b_preloaded
)
772 delete opened_segments
[i
];
773 opened_segments
[i
] = NULL
;
778 bool demux_sys_t::PreparePlayback( virtual_segment_c
& new_vsegment
, mtime_t i_mk_date
)
780 if ( p_current_vsegment
!= &new_vsegment
)
782 if ( p_current_vsegment
->CurrentSegment() != NULL
)
783 p_current_vsegment
->CurrentSegment()->ESDestroy();
785 p_current_vsegment
= &new_vsegment
;
786 p_current_vsegment
->CurrentSegment()->ESCreate();
787 i_current_title
= p_current_vsegment
->i_sys_title
;
789 if( !p_current_vsegment
->CurrentSegment() )
791 if( !p_current_vsegment
->CurrentSegment()->b_cues
)
792 msg_Warn( &p_current_vsegment
->CurrentSegment()->sys
.demuxer
, "no cues/empty cues found->seek won't be precise" );
794 f_duration
= p_current_vsegment
->Duration();
796 /* add information */
797 p_current_vsegment
->CurrentSegment()->InformationCreate( );
798 p_current_vsegment
->CurrentSegment()->ESCreate( );
800 /* Seek to the beginning */
801 p_current_vsegment
->Seek(p_current_vsegment
->CurrentSegment()->sys
.demuxer
,
802 i_mk_date
, p_current_vsegment
->p_current_vchapter
);
807 void demux_sys_t::JumpTo( virtual_segment_c
& vsegment
, virtual_chapter_c
& vchapter
)
809 if ( !vchapter
.p_chapter
|| !vchapter
.p_chapter
->Enter( true ) )
811 // jump to the location in the found segment
812 vsegment
.Seek( demuxer
, vchapter
.i_mk_virtual_start_time
, &vchapter
);
816 matroska_segment_c
*demux_sys_t::FindSegment( const EbmlBinary
& uid
) const
818 for (size_t i
=0; i
<opened_segments
.size(); i
++)
820 if ( opened_segments
[i
]->p_segment_uid
&& *opened_segments
[i
]->p_segment_uid
== uid
)
821 return opened_segments
[i
];
826 virtual_chapter_c
*demux_sys_t::BrowseCodecPrivate( unsigned int codec_id
,
827 bool (*match
)(const chapter_codec_cmds_c
&data
, const void *p_cookie
, size_t i_cookie_size
),
828 const void *p_cookie
,
829 size_t i_cookie_size
,
830 virtual_segment_c
* &p_vsegment_found
)
832 virtual_chapter_c
*p_result
= NULL
;
833 for (size_t i
=0; i
<used_vsegments
.size(); i
++)
835 p_result
= used_vsegments
[i
]->BrowseCodecPrivate( codec_id
, match
, p_cookie
, i_cookie_size
);
836 if ( p_result
!= NULL
)
838 p_vsegment_found
= used_vsegments
[i
];
845 virtual_chapter_c
*demux_sys_t::FindChapter( int64_t i_find_uid
, virtual_segment_c
* & p_vsegment_found
)
847 virtual_chapter_c
*p_result
= NULL
;
848 for (size_t i
=0; i
<used_vsegments
.size(); i
++)
850 p_result
= used_vsegments
[i
]->FindChapter( i_find_uid
);
851 if ( p_result
!= NULL
)
853 p_vsegment_found
= used_vsegments
[i
];