mkv: remove unused variable callback parameters
[vlc.git] / modules / demux / mkv / demux.cpp
blob481aa0dce2028ff4f229cc6d714144909b7c9391
2 /*****************************************************************************
3 * mkv.cpp : matroska demuxer
4 *****************************************************************************
5 * Copyright (C) 2003-2004 VLC authors and VideoLAN
6 * $Id$
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 *****************************************************************************/
26 #include "demux.hpp"
27 #include "stream_io_callback.hpp"
28 #include "Ebml_parser.hpp"
30 #include <vlc_keys.h>
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 );
36 is_running = false;
38 event_thread_t::~event_thread_t()
40 ResetPci();
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);
49 pci_packet = *data;
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] );
69 #endif
70 if( !is_running )
72 b_abort = false;
73 is_running = !vlc_clone( &thread, EventThread, this, VLC_THREAD_PRIORITY_LOW );
76 void event_thread_t::ResetPci()
78 if( !is_running )
79 return;
81 vlc_mutex_lock( &lock );
82 b_abort = true;
83 vlc_cond_signal( &wait );
84 vlc_mutex_unlock( &lock );
86 vlc_join( thread, NULL );
87 is_running = false;
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 );
104 return VLC_SUCCESS;
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");
117 return VLC_SUCCESS;
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 );
133 return VLC_SUCCESS;
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 ();
142 b_moved = false;
143 b_clicked = false;
144 i_key_action = 0;
145 b_vout = true;
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 );
152 /* main loop */
153 for( ;; )
155 vlc_mutex_lock( &lock );
156 while( !b_abort && !i_key_action && !b_moved && !b_clicked && !b_vout)
157 vlc_cond_wait( &wait, &lock );
159 if( b_abort )
161 vlc_mutex_unlock( &lock );
162 break;
165 /* KEY part */
166 if( i_key_action )
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 );
198 break;
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 );
221 break;
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 );
244 break;
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 );
267 break;
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 );
282 break;
283 default:
284 break;
286 i_key_action = 0;
289 /* MOUSE part */
290 if( p_vout && ( b_moved || b_clicked ) )
292 int x, y;
294 var_GetCoords( p_vout, "mouse-moved", &x, &y );
295 pci_t *pci = &pci_packet;
297 if( b_clicked )
299 int32_t button;
300 int32_t best,dist,d;
301 int32_t mx,my,dx,dy;
303 msg_Dbg( p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
305 // get current button
306 best = 0;
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;
319 dx = mx - x;
320 dy = my - y;
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. */
324 if(d < dist) {
325 dist = d;
326 best = button;
331 if ( best != 0)
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 );
346 // select new button
347 if ( best != i_curr_button )
349 uint32_t i_palette;
351 if(button_ptr.btn_coln != 0) {
352 i_palette = pci->hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
353 } else {
354 i_palette = 0;
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",
373 button_ptr.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",
377 button_ptr.y_end );
378 var_SetAddress( p_demux->p_input, "menu-palette",
379 p_sys->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 );
387 else if( b_moved )
389 // dvdnav_mouse_select( NULL, pci, x, y );
392 b_moved = false;
393 b_clicked = false;
396 b_vout = false;
397 vlc_mutex_unlock( &lock );
399 /* Always check vout */
400 if( p_vout == NULL )
402 p_vout = (vlc_object_t*) input_GetVout(p_demux->p_input);
403 if( p_vout)
405 var_AddCallback( p_vout, "mouse-moved", EventMouse, this );
406 var_AddCallback( p_vout, "mouse-clicked", EventMouse, this );
411 /* Release callback */
412 if( p_vout )
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();
427 return NULL;
431 demux_sys_t::~demux_sys_t()
433 CleanUi();
434 size_t i;
435 for ( i=0; i<streams.size(); i++ )
436 delete streams[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 )
454 int i_upper_lvl = 0;
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);
460 if (p_l0 == NULL)
462 msg_Err( p_demux, "No EBML header found" );
463 return NULL;
466 /* verify we can read this Segment */
469 p_l0->Read(*p_estream, EBML_CLASS_CONTEXT(EbmlHead), i_upper_lvl, p_l0, true);
471 catch(...)
473 msg_Err(p_demux, "EBML Header Read failed");
474 return NULL;
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());
481 return NULL;
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));
488 return NULL;
491 delete p_l0;
494 // find all segments in this file
495 p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), UINT64_MAX);
496 if (p_l0 == NULL)
498 return NULL;
501 matroska_stream_c *p_stream1 = new matroska_stream_c();
503 while (p_l0 != 0)
505 if ( MKV_IS_ID( p_l0, KaxSegment) )
507 EbmlParser *ep;
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" ) );
512 p_segment1->ep = ep;
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" );
525 break;
529 p_info->Read(*p_estream, EBML_CLASS_CONTEXT(KaxInfo), i_upper_lvl, p_l2, true);
531 catch (...)
533 msg_Err( p_demux, "KaxInfo found but corrupted");
534 break;
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 );
567 break;
570 if ( b_keep_segment || !p_segment1->p_segment_uid )
572 b_keep_stream = true;
573 p_stream1->segments.push_back( p_segment1 );
575 else
577 p_segment1->segment = NULL;
578 delete p_segment1;
581 if (p_l0->IsFiniteSize() )
583 p_l0->SkipData(*p_estream, KaxMatroska_Context);
584 p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), UINT64_MAX);
586 else
588 p_l0 = NULL;
592 if ( !b_keep_stream )
594 delete p_stream1;
595 p_stream1 = NULL;
598 return p_stream1;
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;
608 if( 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()
625 delete p_ev;
626 p_ev = NULL;
628 if( p_input )
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()
653 size_t i, j, ij = 0;
654 virtual_segment_c *p_vseg;
656 if ( unlikely(opened_segments.size() == 0) )
657 return false;
659 p_current_vsegment = new (std::nothrow) virtual_segment_c( *(opened_segments[0]), opened_segments );
660 if ( !p_current_vsegment )
661 return false;
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();
691 int i_chapters;
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() );
698 else
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 () );
718 break;
723 if( !p_title->psz_name &&
724 asprintf(&(p_title->psz_name), "%s %d", "Segment", (int)ij) == -1 )
725 p_title->psz_name = NULL;
729 ij++;
730 i_chapters = 0;
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)
744 return true;
747 void demux_sys_t::FreeUnused()
749 size_t i;
750 for( i = 0; i < streams.size(); i++ )
752 bool used = false;
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 )
758 used = true;
759 break;
762 if( !used )
764 streams[i] = NULL;
765 delete p_s;
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() )
790 return false;
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 );
804 return true;
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];
823 return NULL;
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];
839 break;
842 return p_result;
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];
854 break;
857 return p_result;