bd.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:39k
源码类别:

midi

开发平台:

Unix_Linux

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