Added initial uncrypted blu-ray support.
[vlc.git] / modules / access / bd / bd.c
1 /*****************************************************************************
2  * bd.c: BluRay Disc support (uncrypted)
3  *****************************************************************************
4  * Copyright (C) 2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #ifdef HAVE_SYS_STAT_H
33 #   include <sys/stat.h>
34 #endif
35 #include <limits.h>
36
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
39 #include <vlc_input.h>
40 #include <vlc_access.h>
41 #include <vlc_demux.h>
42 #include <vlc_charset.h>
43 #include <vlc_bits.h>
44 #include <assert.h>
45
46 #include "mpls.h"
47 #include "clpi.h"
48
49 /*****************************************************************************
50  * Module descriptor
51  *****************************************************************************/
52 #define CACHING_TEXT N_("Caching value in ms")
53 #define CACHING_LONGTEXT N_( \
54     "Caching value for BDs. This "\
55     "value should be set in milliseconds." )
56
57 static int  Open ( vlc_object_t * );
58 static void Close( vlc_object_t * );
59
60 vlc_module_begin ()
61     set_shortname( N_("BD") )
62     set_description( N_("BD Input") )
63     set_category( CAT_INPUT )
64     set_subcategory( SUBCAT_INPUT_ACCESS )
65     add_integer( "bd-caching", DEFAULT_PTS_DELAY / 1000, NULL,
66         CACHING_TEXT, CACHING_LONGTEXT, true );
67     set_capability( "access_demux", 60 )
68     add_shortcut( "bd" )
69     set_callbacks( Open, Close )
70 vlc_module_end ()
71
72 /*****************************************************************************
73  * Documentation
74  * I have used:
75  *  - http://www.stebbins.biz/source/bdtools.tgz
76  *  - hdcookbook java code
77  *  - BDInfo source code
78  *****************************************************************************/
79
80 /*****************************************************************************
81  * Local prototypes
82  *****************************************************************************/
83 struct demux_sys_t
84 {
85     char *psz_base;
86
87     /* */
88     int       i_mpls;
89     bd_mpls_t **pp_mpls;
90
91     /* */
92     int       i_clpi;
93     bd_clpi_t **pp_clpi;
94
95     /* */
96     int             i_title;
97     input_title_t   **pp_title;
98
99     /* */
100     es_out_t        *p_out;
101
102     /* Current state */
103     const bd_clpi_t *p_clpi;
104     int             i_clpi_ep;
105     stream_t        *p_parser;
106     stream_t        *p_m2ts;
107     int             i_play_item;
108     int             i_packet;
109     int             i_packet_start;
110     int             i_packet_stop;
111     int             i_packet_headers;
112     int64_t         i_atc_initial;
113     int64_t         i_atc_current;
114     int64_t         i_atc_wrap;
115     int64_t         i_atc_last;
116 };
117
118 static int Control( demux_t *, int, va_list );
119 static int Demux( demux_t * );
120
121 static char *FindPathBase( const char * );
122
123 static int LoadPlaylist( demux_t * );
124 static int LoadClip( demux_t * );
125
126 static void ReorderPlaylist( demux_t * );
127
128 static void InitTitles( demux_t * );
129 static int  SetTitle( demux_t *, int );
130 static int  SetChapter( demux_t *, int );
131 static int64_t GetTime( demux_t * );
132 static double  GetPosition( demux_t * );
133 static int     SetTime( demux_t *, int64_t );
134 static int     SetPosition( demux_t *, double );
135
136 static int SetPlayItem( demux_t *p_demux, int i_mpls, int i_play_item );
137 static void ClosePlayItem( demux_t * );
138
139 /* */
140 static int64_t GetClpiPacket( demux_t *p_demux, int *pi_ep, const bd_mpls_clpi_t *p_mpls_clpi, int64_t i_time /* in 45kHz */ );
141
142 static es_out_t *EsOutNew( demux_t *p_demux );
143
144 //#define BD_DEBUG
145
146 /*****************************************************************************
147  * Open:
148  *****************************************************************************/
149 static int Open( vlc_object_t *p_this )
150 {
151     demux_t     *p_demux = (demux_t*)p_this;
152     demux_sys_t *p_sys;
153
154     if( *p_demux->psz_access && strcmp( p_demux->psz_access, "bd" ) )
155         return VLC_EGENERIC;
156
157     /* */
158     char *psz_base = FindPathBase( p_demux->psz_path );
159     if( !psz_base )
160         return VLC_EGENERIC;
161
162     msg_Dbg( p_demux, "Using path '%s'", psz_base );
163
164     /* Fill p_demux field */
165     p_demux->p_sys = p_sys = malloc( sizeof(*p_sys) );
166     if( !p_sys )
167         return VLC_EGENERIC;
168     p_sys->psz_base = psz_base;
169     TAB_INIT( p_sys->i_mpls, p_sys->pp_mpls );
170     TAB_INIT( p_sys->i_clpi, p_sys->pp_clpi );
171     TAB_INIT( p_sys->i_title, p_sys->pp_title );
172     p_demux->info.i_title = -1;
173     p_sys->p_clpi = NULL;
174     p_sys->i_clpi_ep = -1;
175     p_sys->p_parser = NULL;
176     p_sys->p_m2ts = NULL;
177     p_sys->i_play_item = -1;
178     p_sys->i_packet = -1;
179     p_sys->i_packet_start = -1;
180     p_sys->i_packet_stop = -1;
181     p_sys->i_packet_headers = -1;
182     p_sys->p_out = EsOutNew( p_demux );
183     if( !p_sys->p_out )
184         goto error;
185
186     p_demux->pf_control = Control;
187     p_demux->pf_demux = Demux;
188
189     /* Load all clip/playlist files */
190     LoadClip( p_demux );
191     LoadPlaylist( p_demux );
192
193     /* Reorder playlist to have the most significant first
194      * (as we don't have menu support, no idea how to find the main title */
195     ReorderPlaylist( p_demux );
196
197     /* Setup variables (for TS demuxer) */
198     var_Create( p_demux, "ts-es-id-pid", VLC_VAR_BOOL );
199     var_SetBool( p_demux, "ts-es-id-pid", true );
200
201     /* */
202     InitTitles( p_demux );
203     if( SetTitle( p_demux, 0 ) )
204         goto error;
205
206     return VLC_SUCCESS;
207
208 error:
209     Close( VLC_OBJECT(p_demux) );
210     return VLC_EGENERIC;
211 }
212
213 /*****************************************************************************
214  * Close:
215  *****************************************************************************/
216 static void Close( vlc_object_t *p_this )
217 {
218     demux_t     *p_demux = (demux_t*)p_this;
219     demux_sys_t *p_sys = p_demux->p_sys;
220
221     /* */
222     ClosePlayItem( p_demux );
223
224     /* */
225     es_out_Delete( p_sys->p_out );
226
227     /* Titles */
228     for( int i = 0; i < p_sys->i_title; i++ )
229         vlc_input_title_Delete( p_sys->pp_title[i] );
230     TAB_CLEAN( p_sys->i_title, p_sys->pp_title );
231
232     /* CLPI */
233     for( int i = 0; i < p_sys->i_clpi; i++ )
234     {
235         bd_clpi_t *p_clpi = p_sys->pp_clpi[i];
236
237         bd_clpi_Clean( p_clpi );
238         free( p_clpi );
239     }
240     TAB_CLEAN( p_sys->i_clpi, p_sys->pp_clpi );
241
242     /* MPLS */
243     for( int i = 0; i < p_sys->i_mpls; i++ )
244     {
245         bd_mpls_t *p_mpls = p_sys->pp_mpls[i];
246
247         bd_mpls_Clean( p_mpls );
248         free( p_mpls );
249     }
250     TAB_CLEAN( p_sys->i_mpls, p_sys->pp_mpls );
251
252     free( p_sys->psz_base );
253     free( p_sys );
254 }
255
256 /*****************************************************************************
257  * Control:
258  *****************************************************************************/
259 static int Control( demux_t *p_demux, int i_query, va_list args )
260 {
261     demux_sys_t *p_sys = p_demux->p_sys;
262
263     switch( i_query )
264     {
265     case DEMUX_GET_TIME:
266     {
267         int64_t *pi_time = (int64_t*)va_arg( args, int64_t * );
268         *pi_time = GetTime( p_demux );
269         return VLC_SUCCESS;;
270     }
271
272     case DEMUX_GET_POSITION:
273     {
274         double *pf_position = (double*)va_arg( args, double * );
275         *pf_position = GetPosition( p_demux );
276         return VLC_SUCCESS;
277     }
278
279     case DEMUX_SET_TIME:
280     {
281         int64_t i_time = (int64_t)va_arg( args, int64_t );
282         return SetTime( p_demux, i_time );
283     }
284     case DEMUX_SET_POSITION:
285     {
286         double f_position = (double)va_arg( args, double );
287         return SetPosition( p_demux, f_position );
288     }
289
290     case DEMUX_GET_LENGTH:
291     {
292         int64_t *pi_length = (int64_t*)va_arg( args, int64_t * );
293         *pi_length = p_sys->pp_title[p_demux->info.i_title]->i_length;
294         return VLC_SUCCESS;
295     }
296
297     /* Special for access_demux */
298     case DEMUX_CAN_PAUSE:
299     case DEMUX_CAN_SEEK:
300     case DEMUX_CAN_CONTROL_PACE:
301     {
302         bool *pb_bool = (bool*)va_arg( args, bool * );
303         *pb_bool = true;
304         return VLC_SUCCESS;
305     }
306
307     case DEMUX_SET_PAUSE_STATE:
308         return VLC_SUCCESS;
309
310     case DEMUX_GET_TITLE_INFO:
311     {
312         input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
313         int *pi_int    = (int*)va_arg( args, int* );
314         int *pi_title_offset = (int*)va_arg( args, int* );
315         int *pi_chapter_offset = (int*)va_arg( args, int* );
316
317         /* */
318         *pi_title_offset = 0;
319         *pi_chapter_offset = 0;
320
321         /* Duplicate title infos */
322         *pi_int = p_sys->i_title;
323         *ppp_title = calloc( p_sys->i_title, sizeof(input_title_t **) );
324         for( int i = 0; i < p_sys->i_title; i++ )
325             (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->pp_title[i] );
326
327         return VLC_SUCCESS;
328     }
329
330     case DEMUX_SET_TITLE:
331     {
332         int i_title = (int)va_arg( args, int );
333
334         if( SetTitle( p_demux, i_title ) )
335             return VLC_EGENERIC;
336         return VLC_SUCCESS;
337     }
338     case DEMUX_SET_SEEKPOINT:
339     {
340         int i_chapter = (int)va_arg( args, int );
341
342         if( SetChapter( p_demux, i_chapter ) )
343             return VLC_EGENERIC;
344         return VLC_SUCCESS;
345     }
346
347     case DEMUX_GET_PTS_DELAY:
348     {
349         int64_t *pi_delay = (int64_t*)va_arg( args, int64_t * );
350         *pi_delay = var_GetInteger( p_demux, "bd-caching" ) * INT64_C(1000);
351         return VLC_SUCCESS;
352     }
353
354     case DEMUX_GET_META:
355
356     default:
357         return VLC_EGENERIC;
358     }
359 }
360
361 /*****************************************************************************
362  * Demux:
363  *****************************************************************************/
364 #define BD_TS_PACKET_HEADER (4)
365 #define BD_TS_PACKET_SIZE (192)
366 static int Demux( demux_t *p_demux )
367 {
368     demux_sys_t *p_sys = p_demux->p_sys;
369     if( !p_sys->p_m2ts )
370         return -1;
371
372     /* */
373     if( p_sys->i_packet == p_sys->i_packet_start )
374     {
375         stream_Seek( p_sys->p_m2ts, 0 );
376
377         block_t *p_block = stream_Block( p_sys->p_m2ts,
378                                          p_sys->i_packet_headers * (int64_t)BD_TS_PACKET_SIZE + BD_TS_PACKET_HEADER );
379         if( p_block )
380         {
381             p_block->i_buffer -= BD_TS_PACKET_HEADER;
382             p_block->p_buffer += BD_TS_PACKET_HEADER;
383             stream_DemuxSend( p_sys->p_parser, p_block );
384         }
385
386         stream_Seek( p_sys->p_m2ts, p_sys->i_packet_start * (int64_t)BD_TS_PACKET_SIZE );
387     }
388
389     /* */
390     const int i_packets = __MIN( 5, p_sys->i_packet_stop - p_sys->i_packet );
391     if( i_packets <= 0 )
392     {
393         const int i_title = p_demux->info.i_title;
394         const bd_mpls_t *p_mpls = p_sys->pp_mpls[i_title];
395
396         if( p_sys->i_play_item < p_mpls->i_play_item )
397         {
398             if( !SetPlayItem( p_demux, i_title, p_sys->i_play_item + 1 ) )
399                 return 1;
400             msg_Warn( p_demux, "Failed to switch to the next play item" );
401         }
402
403         /* */
404         if( SetTitle( p_demux, i_title + 1 ) )
405             return 0; /* EOF */
406         return 1;
407     }
408
409     /* XXX
410      * we ensure that the TS packet start at the begining of the buffer,
411      * it ensure proper TS parsing */
412     block_t *p_block = block_New( p_demux, i_packets * BD_TS_PACKET_SIZE + BD_TS_PACKET_HEADER );
413     if( !p_block )
414         return -1;
415
416     const int i_read = stream_Read( p_sys->p_m2ts, p_block->p_buffer, p_block->i_buffer - BD_TS_PACKET_HEADER );
417     if( i_read <= 0 )
418     {
419         msg_Err( p_demux, "Error reading current title" );
420         return -1;
421     }
422
423     if( i_read > 4 )
424     {
425         const int64_t i_atc = GetDWBE( p_block->p_buffer ) & ( (1 << 30) - 1 );
426
427         if( i_atc < p_sys->i_atc_last )
428             p_sys->i_atc_wrap += 1 << 30;
429         p_sys->i_atc_last = i_atc;
430
431         if( p_sys->i_atc_initial < 0 )
432             p_sys->i_atc_initial = i_atc + p_sys->i_atc_wrap;
433
434         p_sys->i_atc_current = i_atc + p_sys->i_atc_wrap;
435     }
436
437     p_block->i_buffer = i_read;
438     p_block->p_buffer += BD_TS_PACKET_HEADER;
439     stream_DemuxSend( p_sys->p_parser, p_block );
440
441     p_sys->i_packet += i_read / BD_TS_PACKET_SIZE;
442
443     /* Update EP */
444     if( p_sys->p_clpi->i_ep_map > 0 )
445     {
446         const int i_old_clpi_ep = p_sys->i_clpi_ep;
447
448         const bd_clpi_ep_map_t *p_ep_map = &p_sys->p_clpi->p_ep_map[0];
449         for( ; p_sys->i_clpi_ep+1 < p_ep_map->i_ep; p_sys->i_clpi_ep++ )
450         {
451             const bd_clpi_ep_t *p_ep = &p_ep_map->p_ep[p_sys->i_clpi_ep+1];
452
453             if( p_ep->i_packet > p_sys->i_packet )
454                 break;
455         }
456         if( i_old_clpi_ep != p_sys->i_clpi_ep )
457         {
458             /* We have changed of EP */
459             p_sys->i_atc_initial = p_sys->i_atc_current; /* FIXME not exact */
460
461             /* Update seekpoint */
462             const input_title_t *p_title = p_sys->pp_title[p_demux->info.i_title];
463             const int64_t i_time = GetTime( p_demux );
464
465             for( ; p_demux->info.i_seekpoint+1 < p_title->i_seekpoint; p_demux->info.i_seekpoint++ )
466             {
467                 const seekpoint_t *p_seekpoint = p_title->seekpoint[p_demux->info.i_seekpoint+1];
468                 if( p_seekpoint->i_time_offset >  i_time )
469                     break;
470                 p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
471             }
472         }
473     }
474     return 1;
475 }
476
477 /*****************************************************************************
478  *
479  *****************************************************************************/
480 #define BD_45KHZ INT64_C(45000)
481 static void InitTitles( demux_t *p_demux )
482 {
483     demux_sys_t *p_sys = p_demux->p_sys;
484
485     /* */
486     for( int i = 0; i < p_sys->i_mpls; i++ )
487     {
488         const bd_mpls_t *p_mpls = p_sys->pp_mpls[i];
489
490         input_title_t *t = vlc_input_title_New();
491         if( !t )
492             break;
493
494         /* */
495         t->i_length = 0;
496         for( int j = 0; j < p_mpls->i_play_item; j++ )
497         {
498             const bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[j];
499
500             t->i_length += ( p_item->i_out_time - p_item->i_in_time ) * CLOCK_FREQ / BD_45KHZ;
501         }
502
503 #ifdef BD_DEBUG
504         {
505         char psz_length[MSTRTIME_MAX_SIZE];
506         msg_Warn( p_demux, "TITLE[%d] %s", i, secstotimestr( psz_length, t->i_length / CLOCK_FREQ ) );
507         }
508 #endif
509
510         /* Seekpoint */
511         for( int j = 0; j < p_mpls->i_mark; j++ )
512         {
513             bd_mpls_mark_t *p_mark = &p_mpls->p_mark[j];
514
515             if( p_mark->i_type == BD_MPLS_MARK_TYPE_BOOKMARK &&
516                 p_mark->i_play_item_id >= 0 && p_mark->i_play_item_id < p_mpls->i_play_item )
517             {
518                 seekpoint_t *s = vlc_seekpoint_New();
519                 if( !s )
520                     break;
521
522                 for( int k = 0; k <= p_mark->i_play_item_id; k++ )
523                 {
524                     const bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[k];
525                     int64_t i_out_time;
526
527                     if( k == p_mark->i_play_item_id )
528                         i_out_time = p_mark->i_time;
529                     else
530                         i_out_time = p_item->i_out_time;
531                     s->i_time_offset += ( i_out_time - p_item->i_in_time ) * CLOCK_FREQ / BD_45KHZ;
532                 }
533 #ifdef BD_DEBUG
534                 {
535                 char psz_time[MSTRTIME_MAX_SIZE];
536                 msg_Warn( p_demux, "    SEEKPOINT[%d] %s", j, secstotimestr( psz_time, s->i_time_offset / CLOCK_FREQ ) );
537                 }
538 #endif
539                 TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
540             }
541         }
542         if( t->i_seekpoint <= 0 )
543         {
544             seekpoint_t *s = vlc_seekpoint_New();
545             if( s )
546                 TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
547         }
548
549         TAB_APPEND( p_sys->i_title, p_sys->pp_title, t );
550     }
551 }
552 static int SetTitle( demux_t *p_demux, int i_title )
553 {
554     demux_sys_t *p_sys = p_demux->p_sys;
555
556     if( i_title < 0 || i_title >= p_sys->i_title )
557         return VLC_EGENERIC;
558
559
560     if( SetPlayItem( p_demux, i_title, 0 ) )
561         return VLC_EGENERIC;
562
563     /* */
564     p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
565     p_demux->info.i_title = i_title;
566     p_demux->info.i_seekpoint = 0;
567
568     return VLC_SUCCESS;
569 }
570 static int SetChapter( demux_t *p_demux, int i_chapter )
571 {
572     demux_sys_t *p_sys = p_demux->p_sys;
573     const int i_title = p_demux->info.i_title;
574     const input_title_t *p_title = p_sys->pp_title[i_title];
575
576     if( i_chapter < 0 || i_chapter > p_title->i_seekpoint )
577         return VLC_EGENERIC;
578
579     if( SetTime( p_demux, p_title->seekpoint[i_chapter]->i_time_offset ) )
580         return VLC_EGENERIC;
581
582     return VLC_SUCCESS;
583 }
584 static int SetPlayItem( demux_t *p_demux, int i_mpls, int i_play_item )
585 {
586     demux_sys_t *p_sys = p_demux->p_sys;
587
588     /* FIXME TODO do not reopen everything when avoidable
589      * XXX becarefull that then the es_out wrapper need some sort of
590      * locking !!! */
591
592     /* */
593     const bool b_same_mpls = i_mpls == p_demux->info.i_title;
594     const bool b_same_play_item = b_same_mpls &&
595                                   i_play_item == p_sys->i_play_item;
596
597     /* */
598     const bd_mpls_t *p_mpls = p_sys->pp_mpls[i_mpls];
599
600     /* */
601     if( i_play_item < 0 || i_play_item >= p_mpls->i_play_item )
602         return VLC_EGENERIC;
603
604     const bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[i_play_item];
605     const bd_mpls_clpi_t *p_mpls_clpi = &p_item->clpi;
606
607     const bd_clpi_t *p_clpi = NULL;
608     for( int i_clpi = 0; i_clpi < p_sys->i_clpi && !p_clpi; i_clpi++ )
609     {
610         if( p_sys->pp_clpi[i_clpi]->i_id == p_mpls_clpi->i_id )
611             p_clpi = p_sys->pp_clpi[i_clpi];
612     }
613
614     const bool b_same_clpi = b_same_mpls && p_sys->p_clpi->i_id == p_clpi->i_id;
615     stream_t *p_m2ts = NULL;
616     if( !b_same_clpi )
617     {
618         char *psz_m2ts;
619         if( asprintf( &psz_m2ts, "%s/STREAM/%05d.m2ts", p_sys->psz_base, p_mpls_clpi->i_id ) < 0 )
620             return VLC_EGENERIC;
621
622         p_m2ts = stream_UrlNew( p_demux, psz_m2ts );
623         if( !p_m2ts )
624         {
625             msg_Err( p_demux, "Failed to open %s", psz_m2ts );
626             free( psz_m2ts );
627             return VLC_EGENERIC;
628         }
629         free( psz_m2ts );
630     }
631
632     /* TODO avoid reopenning the parser when unneeded.
633      * - b_same_play_item is too strict, we should check the play_items connection.
634      * - a way to completely flush the demuxer is also needed !
635      */
636     const bool b_same_parser = b_same_play_item && false;
637     stream_t *p_parser = stream_DemuxNew( p_demux, "ts", p_sys->p_out );
638     if( !p_parser )
639     {
640         msg_Err( p_demux, "Failed to create TS demuxer" );
641         if( p_m2ts )
642             stream_Delete( p_m2ts );
643         return VLC_EGENERIC;
644     }
645
646     /* */
647     if( !p_m2ts )
648     {
649         msg_Dbg( p_demux, "Reusing stream file" );
650         p_m2ts = p_sys->p_m2ts;
651         p_sys->p_m2ts = NULL;
652     }
653
654     /* */
655     ClosePlayItem( p_demux );
656
657     /* */
658     p_sys->p_clpi = p_clpi;
659     p_sys->p_parser = p_parser;
660     p_sys->p_m2ts = p_m2ts;
661     p_sys->i_play_item = i_play_item;
662
663     p_sys->i_packet_start = GetClpiPacket( p_demux, &p_sys->i_clpi_ep, p_mpls_clpi, p_item->i_in_time );
664     if( p_sys->i_packet_start < 0 )
665     {
666         p_sys->i_packet_start = 0;
667         p_sys->i_clpi_ep = 0;
668     }
669
670     p_sys->i_packet_stop = GetClpiPacket( p_demux, NULL, p_mpls_clpi, p_item->i_out_time );
671     if( p_sys->i_packet_stop < 0 )
672         p_sys->i_packet_stop = stream_Size( p_m2ts ) / BD_TS_PACKET_SIZE;
673     p_sys->i_packet = p_sys->i_packet_start;
674
675     /* This is a hack to detect the number of packet to send before any data
676      * to have the PAT/PMT. I have no idea if it is the right, but seems to work.
677      * I used a limits of 10 packets, sufficient if it is really only headers */
678     p_sys->i_packet_headers = 0;
679     if( p_clpi->i_ep_map > 0 )
680     {
681         const bd_clpi_ep_map_t *p_ep_map = &p_clpi->p_ep_map[0];
682         if( p_ep_map->i_ep > 0 )
683             p_sys->i_packet_headers = __MIN( p_ep_map->p_ep[0].i_packet, 10 );
684     }
685
686     p_sys->i_atc_initial = -1;
687     p_sys->i_atc_current = -1;
688     p_sys->i_atc_last    = -1;
689     p_sys->i_atc_wrap    = 0;
690
691     return VLC_SUCCESS;
692 }
693 static void ClosePlayItem( demux_t *p_demux )
694 {
695     demux_sys_t *p_sys = p_demux->p_sys;
696
697     if( p_sys->p_m2ts )
698         stream_Delete( p_sys->p_m2ts );
699     if( p_sys->p_parser )
700         stream_Delete( p_sys->p_parser );
701
702     es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
703 }
704
705 static int64_t GetClpiPacket( demux_t *p_demux, int *pi_ep, const bd_mpls_clpi_t *p_mpls_clpi, int64_t i_time /* in 45kHz */ )
706 {
707     demux_sys_t *p_sys = p_demux->p_sys;
708
709     const bd_clpi_t *p_clpi = p_sys->p_clpi;
710     assert( p_clpi );
711
712     if( p_clpi->i_ep_map <= 0 )
713         return -1;
714     const bd_clpi_ep_map_t *p_ep_map = &p_clpi->p_ep_map[0];
715
716     if( p_mpls_clpi->i_stc_id < 0 || p_mpls_clpi->i_stc_id >= p_clpi->i_stc )
717         return -1;
718
719     const bd_clpi_stc_t *p_stc = &p_clpi->p_stc[p_mpls_clpi->i_stc_id];
720 #if 0
721     /* Not sure it is right */
722     if( i_time < p_stc->i_start || i_time > p_stc->i_end )
723         return -1;
724 #endif
725
726     const int64_t i_packet = p_stc->i_packet;
727     int i_ep;
728     for( i_ep = 0; i_ep < p_ep_map->i_ep; i_ep++ )
729     {
730         if( p_ep_map->p_ep[i_ep].i_packet >= i_packet )
731             break;
732     }
733     if( i_ep >= p_ep_map->i_ep )
734         return -1;
735
736     for( ; i_ep < p_ep_map->i_ep; i_ep++ )
737     {
738         const bd_clpi_ep_t *p_ep = &p_ep_map->p_ep[i_ep];
739         const bd_clpi_ep_t *p_ep_next = &p_ep_map->p_ep[i_ep+1];
740
741         if( i_ep+1 < p_ep_map->i_ep && p_ep_next->i_pts / 2 > i_time )
742             break;
743         if( p_ep->i_pts / 2 >= i_time )
744             break;
745     }
746     if( i_ep >= p_ep_map->i_ep )
747         return -1;
748
749     /* */
750     if( pi_ep )
751         *pi_ep = i_ep;
752     return p_ep_map->p_ep[i_ep].i_packet;
753 }
754
755 /**
756  * Retreive the current time using current EP + ATC delta
757  */
758 static int64_t GetTime( demux_t *p_demux )
759 {
760     demux_sys_t *p_sys = p_demux->p_sys;
761     const int i_mpls = p_demux->info.i_title;
762
763     const bd_mpls_t *p_mpls = p_sys->pp_mpls[i_mpls];
764     const bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[p_sys->i_play_item];
765
766     const bd_clpi_t *p_clpi = p_sys->p_clpi;
767     if( !p_clpi || p_clpi->i_ep_map <= 0 )
768         return 0;
769
770     /* */
771     const bd_clpi_ep_map_t *p_ep_map = &p_clpi->p_ep_map[0];
772     if( p_sys->i_clpi_ep < 0 || p_sys->i_clpi_ep >= p_ep_map->i_ep )
773         return 0;
774
775     const bd_clpi_ep_t *p_ep = &p_ep_map->p_ep[p_sys->i_clpi_ep];
776     int64_t i_time = p_ep->i_pts / 2 - p_item->i_in_time +
777                      ( p_sys->i_atc_current - p_sys->i_atc_initial ) / 300 / 2;
778
779     for( int j = 0; j < p_sys->i_play_item; j++ )
780     {
781         const bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[j];
782         i_time += ( p_item->i_out_time - p_item->i_in_time );
783     }
784
785     return i_time * CLOCK_FREQ / BD_45KHZ;
786 }
787
788 static double GetPosition( demux_t *p_demux )
789 {
790     demux_sys_t *p_sys = p_demux->p_sys;
791
792     const int64_t i_time = GetTime( p_demux );
793     const input_title_t *p_title = p_sys->pp_title[p_demux->info.i_title];
794
795     if( p_title->i_length <= 0 )
796         return 0.0;
797
798     return (double)i_time / p_title->i_length;
799 }
800
801 static int SetTime( demux_t *p_demux, int64_t i_time )
802 {
803     demux_sys_t *p_sys = p_demux->p_sys;
804     const int i_mpls = p_demux->info.i_title;
805     const input_title_t *p_title = p_sys->pp_title[i_mpls];
806     const bd_mpls_t *p_mpls = p_sys->pp_mpls[i_mpls];
807
808     /* Find the play item */
809     int i_item;
810     int64_t i_play_item_time = 0;
811     for( i_item = 0; i_item < p_mpls->i_play_item; i_item++ )
812     {
813         const bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[i_item];
814         const int64_t i_duration = ( p_item->i_out_time - p_item->i_in_time ) * CLOCK_FREQ / BD_45KHZ;
815
816         if( i_time >= i_play_item_time && i_time < i_play_item_time + i_duration )
817             break;
818
819         i_play_item_time += i_duration;
820     }
821
822     if( i_item >= p_mpls->i_play_item )
823         return VLC_EGENERIC;
824
825     if( SetPlayItem( p_demux, i_mpls, i_item ) )
826         return VLC_EGENERIC;
827
828
829     /* Find the right entry point */
830     if( p_sys->p_clpi->i_ep_map <= 0 )
831         goto update;
832
833     const bd_clpi_ep_map_t *p_ep_map = &p_sys->p_clpi->p_ep_map[0];
834     if( p_ep_map->i_ep <= 0 )
835         goto update;
836
837     int64_t i_next_display_date = -1;
838     for( ; p_sys->i_clpi_ep+1 < p_ep_map->i_ep; p_sys->i_clpi_ep++ )
839     {
840         const bd_clpi_ep_t *p_next = &p_ep_map->p_ep[p_sys->i_clpi_ep+1];
841         const int64_t i_next_time = i_play_item_time + ( ( p_next->i_pts / 2 - p_mpls->p_play_item[i_item].i_in_time ) * CLOCK_FREQ / BD_45KHZ );
842
843         if( i_next_time > i_time )
844         {
845             const bd_clpi_ep_t *p_ep = &p_ep_map->p_ep[p_sys->i_clpi_ep];
846             const int64_t i_ep_time = i_play_item_time + ( ( p_ep->i_pts / 2 - p_mpls->p_play_item[i_item].i_in_time ) * CLOCK_FREQ / BD_45KHZ );
847
848
849             i_next_display_date = p_ep->i_pts * CLOCK_FREQ / 90000 + ( i_time - i_ep_time );
850             break;
851         }
852     }
853
854     const bd_clpi_ep_t *p_ep = &p_ep_map->p_ep[p_sys->i_clpi_ep];
855     p_sys->i_packet_start =
856     p_sys->i_packet       = p_ep->i_packet;
857
858     if( i_next_display_date >= 0 )
859         es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_next_display_date );
860
861 update:
862     /* Update seekpoint */
863     for( p_demux->info.i_seekpoint = 0; p_demux->info.i_seekpoint+1 < p_title->i_seekpoint; p_demux->info.i_seekpoint++ )
864     {
865         const seekpoint_t *p_seekpoint = p_title->seekpoint[p_demux->info.i_seekpoint+1];
866         if( p_seekpoint->i_time_offset >  i_time )
867             break;
868     }
869     p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
870     return VLC_SUCCESS;
871 }
872
873 static int SetPosition( demux_t *p_demux, double f_position )
874 {
875     demux_sys_t *p_sys = p_demux->p_sys;
876     const input_title_t *p_title = p_sys->pp_title[p_demux->info.i_title];
877
878     if( p_title->i_length <= 0 )
879         return VLC_EGENERIC;
880
881     return SetTime( p_demux, f_position * p_title->i_length );
882 }
883
884 /*****************************************************************************
885  * Mpls ordering
886  *****************************************************************************/
887 static int64_t GetMplsUniqueDuration( const bd_mpls_t *p_mpls )
888 {
889     int64_t i_length = 0;
890
891     for( int i = 0; i < p_mpls->i_play_item; i++ )
892     {
893         const bd_mpls_play_item_t *p_item0 = &p_mpls->p_play_item[i];
894         int j;
895         for( j = i+1; j < p_mpls->i_play_item; j++ )
896         {
897             const bd_mpls_play_item_t *p_item1 = &p_mpls->p_play_item[j];
898             if( p_item0->clpi.i_id == p_item1->clpi.i_id &&
899                 p_item0->clpi.i_stc_id == p_item1->clpi.i_stc_id &&
900                 p_item0->i_in_time == p_item1->i_in_time &&
901                 p_item0->i_out_time == p_item1->i_out_time )
902                 break;
903         }
904         if( j >= p_mpls->i_play_item )
905             i_length += p_item0->i_out_time - p_item0->i_in_time;
906     }
907     return i_length;
908 }
909 static int SortMpls( void **pp_a, void **pp_b )
910 {
911     const int64_t i_length_a = GetMplsUniqueDuration( *pp_a );
912     const int64_t i_length_b = GetMplsUniqueDuration( *pp_b );
913
914     if( i_length_a == i_length_b )
915         return 0;
916     return i_length_a < i_length_b ? 1 : -1;
917 }
918
919 static void ReorderPlaylist( demux_t *p_demux )
920 {
921     demux_sys_t *p_sys = p_demux->p_sys;
922     qsort( p_sys->pp_mpls, p_sys->i_mpls, sizeof(*p_sys->pp_mpls), SortMpls );
923 }
924 /*****************************************************************************
925  * Helpers:
926  *****************************************************************************/
927 /* */
928 static char *FindPathBase( const char *psz_path )
929 {
930     struct stat s;
931     char *psz_tmp;
932
933     /* */
934     char *psz_base = strdup( psz_path );
935     if( !psz_base )
936         return NULL;
937
938     /* */
939     while( *psz_base && psz_base[strlen(psz_base)-1] == '/' )
940         psz_base[strlen(psz_base)-1] = '\0';
941
942     /* */
943     if( utf8_stat( psz_base, &s ) || !S_ISDIR( s.st_mode ) )
944         goto error;
945
946     /* Check BDMV */
947     if( asprintf( &psz_tmp, "%s/BDMV", psz_base ) < 0 )
948         goto error;
949     if( !utf8_stat( psz_tmp, &s ) && S_ISDIR( s.st_mode ) )
950     {
951         free( psz_base );
952         psz_base = psz_tmp;
953     }
954     else
955     {
956         free( psz_tmp );
957     }
958
959     /* Check presence of mandatory files */
960     for( int i = 0;; i++ )
961     {
962         static const char *ppsz_name[] = {
963             "index.bdmv",
964             "MovieObject.bdmv",
965             NULL
966         };
967         if( !ppsz_name[i] )
968             break;
969
970         if( asprintf( &psz_tmp, "%s/%s", psz_base, ppsz_name[i] ) < 0 )
971             goto error;
972
973         bool b_ok = utf8_stat( psz_tmp, &s ) == 0 && S_ISREG( s.st_mode );
974
975         free( psz_tmp );
976         if( !b_ok )
977             goto error;
978     }
979
980     return psz_base;
981
982 error:
983     free( psz_base );
984     return NULL;
985 }
986
987 /* */
988 static block_t *LoadBlock( demux_t *p_demux, const char *psz_name )
989 {
990     stream_t *s = stream_UrlNew( p_demux, psz_name );
991     if( !s )
992         return NULL;
993
994     const int64_t i_size = stream_Size( s );
995     block_t *p_block = NULL;
996
997     if( i_size > 0 && i_size < INT_MAX )
998         p_block = stream_Block( s, i_size );
999
1000     stream_Delete( s );
1001
1002     return p_block;
1003 }
1004
1005 /* */
1006 static int FilterMpls( const char *psz_name )
1007 {
1008     return strlen( psz_name ) == strlen( "xxxxx.mpls" ) &&
1009            !strcmp( &psz_name[5], ".mpls" );
1010 }
1011
1012 static void LoadMpls( demux_t *p_demux, const char *psz_name, int i_id )
1013 {
1014     demux_sys_t *p_sys = p_demux->p_sys;
1015
1016 #if defined(BD_DEBUG)
1017     msg_Err( p_demux, "Loading %s", psz_name );
1018 #endif
1019
1020     block_t *p_block = LoadBlock( p_demux, psz_name );
1021     if( !p_block )
1022         goto error;
1023
1024     /* */
1025     bd_mpls_t *p_mpls = malloc( sizeof(*p_mpls) );
1026     if( !p_mpls )
1027         goto error;
1028
1029     /* */
1030     bs_t s;
1031     bs_init( &s, p_block->p_buffer, p_block->i_buffer );
1032
1033     if( bd_mpls_Parse( p_mpls, &s, i_id ) )
1034         goto error;
1035
1036 #if defined(BD_DEBUG)
1037     msg_Err( p_demux, "MPLS: id=%d", p_mpls->i_id );
1038     msg_Err( p_demux, "MPLS: play_item=%d sub_path=%d",
1039              p_mpls->i_play_item, p_mpls->i_sub_path );
1040
1041     for( int i = 0; i < p_mpls->i_play_item; i++ )
1042     {
1043         bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[i];
1044
1045         msg_Err( p_demux, "PLAY_ITEM[%d] connection=%d in=%d out=%d still=%d(%d)",
1046                  i, p_item->i_connection,
1047                  (int)p_item->i_in_time, (int)p_item->i_out_time,
1048                  p_item->i_still, p_item->i_still_time );
1049         msg_Err( p_demux, "     clpi_default: id=%d stc_id=%d",
1050                  p_item->clpi.i_id, p_item->clpi.i_stc_id );
1051         for( int j = 0; j < p_item->i_clpi; j++ )
1052             msg_Err( p_demux, "     clpi[%d]: id=%d stc_id=%d",
1053                      j, p_item->p_clpi[j].i_id, p_item->p_clpi[j].i_stc_id );
1054         for( int j = 0; j < p_item->i_stream; j++ )
1055             msg_Err( p_demux, "     stream[%d]: type=%d class=%d stream_type=0x%x lang=%s charset=%d",
1056                      j,
1057                      p_item->p_stream[j].i_type,
1058                      p_item->p_stream[j].i_class,
1059                      p_item->p_stream[j].i_stream_type,
1060                      p_item->p_stream[j].psz_language,
1061                      p_item->p_stream[j].i_charset );
1062     }
1063
1064     for( int i = 0; i < p_mpls->i_sub_path; i++ )
1065     {
1066         bd_mpls_sub_path_t *p_sub = &p_mpls->p_sub_path[i];
1067
1068         msg_Err( p_demux, "SUB_PATH[%d] type=%d repeat=%d item=%d",
1069                  i, p_sub->i_type, p_sub->b_repeat, p_sub->i_item );
1070     }
1071
1072     for( int i = 0; i < p_mpls->i_mark; i++ )
1073     {
1074         bd_mpls_mark_t *p_mark = &p_mpls->p_mark[i];
1075
1076         msg_Err( p_demux, "M[%d] t=%d play_item_id=%d time=%d entry_es_pid=%d",
1077                  i, p_mark->i_type, p_mark->i_play_item_id, (int)p_mark->i_time, p_mark->i_entry_es_pid );
1078     }
1079 #endif
1080
1081     /* */
1082     TAB_APPEND( p_sys->i_mpls, p_sys->pp_mpls, p_mpls );
1083
1084     /* */
1085     block_Release( p_block );
1086     return;
1087
1088 error:
1089     msg_Err( p_demux, "Failed loading %s", psz_name );
1090     if( p_block )
1091         block_Release( p_block );
1092 }
1093
1094 /* */
1095 static int FilterClpi( const char *psz_name )
1096 {
1097     return strlen( psz_name ) == strlen( "xxxxx.clpi" ) &&
1098            !strcmp( &psz_name[5], ".clpi" );
1099 }
1100
1101 static void LoadClpi( demux_t *p_demux, const char *psz_name, int i_id )
1102 {
1103     demux_sys_t *p_sys = p_demux->p_sys;
1104
1105 #if defined(BD_DEBUG)
1106     msg_Err( p_demux, "Loading %s", psz_name );
1107 #endif
1108
1109     block_t *p_block = LoadBlock( p_demux, psz_name );
1110     if( !p_block )
1111         goto error;
1112
1113     /* */
1114     bd_clpi_t *p_clpi = malloc( sizeof(*p_clpi) );
1115     if( !p_clpi )
1116         goto error;
1117
1118     /* */
1119     bs_t s;
1120     bs_init( &s, p_block->p_buffer, p_block->i_buffer );
1121
1122     if( bd_clpi_Parse( p_clpi, &s, i_id ) )
1123         goto error;
1124
1125 #if defined(BD_DEBUG)
1126     msg_Err( p_demux, "CLPI: id=%d", p_clpi->i_id );
1127     msg_Err( p_demux, "CLPI: STC=%d", p_clpi->i_stc );
1128     for( int i = 0; i < p_clpi->i_stc; i++ )
1129         msg_Err( p_demux, "   STC[%d] pcr_pid=%d packet=%d start=%d end=%d",
1130                  i, p_clpi->p_stc[i].i_pcr_pid, (int)p_clpi->p_stc[i].i_packet,
1131                  (int)p_clpi->p_stc[i].i_start, (int)p_clpi->p_stc[i].i_end );
1132     msg_Err( p_demux, "CLPI: Stream=%d", p_clpi->i_stream );
1133     for( int i = 0; i < p_clpi->i_stream; i++ )
1134         msg_Err( p_demux, "   Stream[%d] pid=%d type=0x%x",
1135                  i, p_clpi->p_stream[i].i_pid, p_clpi->p_stream[i].i_type );
1136     msg_Err( p_demux, "CLPI: Ep Map=%d", p_clpi->i_ep_map );
1137     for( int i = 0; i < p_clpi->i_ep_map; i++ )
1138     {
1139         const bd_clpi_ep_map_t *p_ep_map = &p_clpi->p_ep_map[i];
1140         msg_Err( p_demux, "   Ep Map[%d] pid=%d type=0x%x entry_point=%d",
1141                  i, p_ep_map->i_pid, p_ep_map->i_type, p_ep_map->i_ep );
1142         for( int j = 0; j < p_ep_map->i_ep; j++ )
1143         {
1144             msg_Err( p_demux, "      Ep[%d] packet=%d pts=%d",
1145                      j, (int)p_ep_map->p_ep[j].i_packet, (int)p_ep_map->p_ep[j].i_pts );
1146         }
1147     }
1148 #endif
1149
1150     /* */
1151     TAB_APPEND( p_sys->i_clpi, p_sys->pp_clpi, p_clpi );
1152
1153     /* */
1154     block_Release( p_block );
1155     return;
1156
1157 error:
1158     msg_Err( p_demux, "Failed loading %s", psz_name );
1159     if( p_block )
1160         block_Release( p_block );
1161 }
1162
1163 /* */
1164 static int ScanSort( const char **ppsz_a, const char **ppsz_b )
1165 {
1166     return strcmp( *ppsz_a, *ppsz_b );
1167 }
1168
1169 static int Load( demux_t *p_demux,
1170                  const char *psz_dir,
1171                  int (*pf_filter)( const char * ),
1172                  void (*pf_load)( demux_t *p_demux, const char *psz_name, int i_id ) )
1173 {
1174     char *psz_playlist;
1175     if( asprintf( &psz_playlist, "%s/%s", p_demux->p_sys->psz_base, psz_dir ) < 0 )
1176         return VLC_EGENERIC;
1177
1178     char **ppsz_list;
1179
1180     int i_list = utf8_scandir( psz_playlist, &ppsz_list, pf_filter, ScanSort );
1181
1182     for( int i = 0; i < i_list; i++ )
1183     {
1184         char *psz_file = ppsz_list[i];
1185         if( !psz_file )
1186             break;
1187
1188         char *psz_name;
1189         if( asprintf( &psz_name, "%s/%s/%s", p_demux->p_sys->psz_base, psz_dir, psz_file ) >= 0)
1190         {
1191             const int i_id = strtol( psz_file, NULL, 10 );
1192             pf_load( p_demux, psz_name, i_id );
1193             free( psz_name );
1194         }
1195         free( psz_file );
1196     }
1197     free( ppsz_list );
1198
1199     free( psz_playlist );
1200     return VLC_SUCCESS;
1201 }
1202
1203 static int LoadPlaylist( demux_t *p_demux )
1204 {
1205     return Load( p_demux, "PLAYLIST", FilterMpls, LoadMpls );
1206 }
1207 static int LoadClip( demux_t *p_demux )
1208 {
1209     return Load( p_demux, "CLIPINF", FilterClpi, LoadClpi );
1210 }
1211
1212 /* */
1213 struct es_out_sys_t
1214 {
1215     demux_t *p_demux;
1216 };
1217
1218 static es_out_id_t *EsOutAdd( es_out_t *p_out, const es_format_t *p_fmt )
1219 {
1220     demux_t *p_demux = p_out->p_sys->p_demux;
1221     const bd_mpls_t *p_mpls = p_demux->p_sys->pp_mpls[p_demux->info.i_title];
1222     const bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[p_demux->p_sys->i_play_item];
1223
1224     es_format_t fmt;
1225
1226     es_format_Copy( &fmt, p_fmt );
1227     fmt.i_priority = -2;
1228
1229     for( int i = 0; i < p_item->i_stream; i++ )
1230     {
1231         const bd_mpls_stream_t *p_stream = &p_item->p_stream[i];
1232         if( p_stream->i_type != BD_MPLS_STREAM_TYPE_PLAY_ITEM ||
1233             p_stream->play_item.i_pid != fmt.i_id )
1234             continue;
1235
1236         /* TODO improved priority for higher quality stream ?
1237          * if so, extending stream attributes parsing might be a good idea
1238          */
1239         fmt.i_priority = 0;
1240
1241 #if 0
1242         /* Useless, and beside not sure it is the right thing to do */
1243         free( fmt.psz_description );
1244         switch( p_stream->i_class )
1245         {
1246         case BD_MPLS_STREAM_CLASS_SECONDARY_AUDIO:
1247             fmt.psz_description = strdup( "Secondary audio" );
1248             break;
1249         default:
1250             fmt.psz_description = NULL;
1251             break;
1252         }
1253 #endif
1254
1255         //msg_Err( p_demux, "Found ref for stream pid %d", fmt.i_id );
1256         if( *p_stream->psz_language && ( !fmt.psz_language || *fmt.psz_language == '\0' ) )
1257         {
1258             free( fmt.psz_language );
1259             fmt.psz_language = strdup( p_stream->psz_language );
1260         }
1261         switch( p_stream->i_charset )
1262         {
1263         /* TODO add all values */
1264         default:
1265             break;
1266         }
1267         break;
1268     }
1269     if( fmt.i_priority < 0 )
1270         msg_Dbg( p_demux, "Hidding one stream (pid=%d)", fmt.i_id );
1271
1272     /* */
1273     es_out_id_t *p_es = es_out_Add( p_demux->out, &fmt );
1274
1275     es_format_Clean( &fmt );
1276     return p_es;
1277 }
1278 static int EsOutSend( es_out_t *p_out, es_out_id_t *p_es, block_t *p_block )
1279 {
1280     return es_out_Send( p_out->p_sys->p_demux->out, p_es, p_block );
1281 }
1282 static void EsOutDel( es_out_t *p_out, es_out_id_t *p_es )
1283 {
1284     es_out_Del( p_out->p_sys->p_demux->out, p_es );
1285 }
1286 static int EsOutControl( es_out_t *p_out, int i_query, va_list args )
1287 {
1288     return es_out_vaControl( p_out->p_sys->p_demux->out, i_query, args );
1289 }
1290 static void EsOutDestroy( es_out_t *p_out )
1291 {
1292     free( p_out->p_sys );
1293     free( p_out );
1294 }
1295
1296 static es_out_t *EsOutNew( demux_t *p_demux )
1297 {
1298     es_out_t *p_out = malloc( sizeof(*p_out) );
1299     es_out_sys_t *p_sys;
1300
1301     if( !p_out )
1302         return NULL;
1303
1304     p_out->pf_add     = EsOutAdd;
1305     p_out->pf_send    = EsOutSend;
1306     p_out->pf_del     = EsOutDel;
1307     p_out->pf_control = EsOutControl;
1308     p_out->pf_destroy = EsOutDestroy;
1309     p_out->b_sout = false;
1310
1311     p_out->p_sys = p_sys = malloc( sizeof(*p_sys) );
1312     if( !p_sys )
1313     {
1314         free( p_out );
1315         return NULL;
1316     }
1317     p_sys->p_demux = p_demux;
1318
1319     return p_out;
1320 }
1321