]> git.sesse.net Git - vlc/blobdiff - src/input/es_out.c
* es_out.c: better support for multiple program. (bugfixes and a dirty
[vlc] / src / input / es_out.c
index 2fcea0b4dba23e253de872feea106577f99299db..7831b0e06d4e28099e65b34b610d310e5be7fbfd 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * es_out.c: Es Out handler for input.
  *****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: es_out.c,v 1.8 2003/12/07 17:17:04 gbazin Exp $
+ * Copyright (C) 2003-2004 VideoLAN
+ * $Id: es_out.c,v 1.17 2004/01/18 04:53:57 fenrir Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -30,6 +30,7 @@
 #include <vlc/input.h>
 #include <vlc/decoder.h>
 
+#include "vlc_playlist.h"
 #include "codecs.h"
 
 /*****************************************************************************
@@ -151,19 +152,29 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
 
     int i_cat = es->p_es->i_cat;
 
-    if( !p_sys->b_active || ( !b_force && es->p_es->fmt.i_priority < 0 ) )
+    if( !p_sys->b_active ||
+        ( !b_force && es->p_es->fmt.i_priority < 0 ) )
     {
         return;
     }
 
     if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
     {
-        input_SelectES( p_input, es->p_es );
+        if( !es->p_es->p_dec )
+        {
+            input_SelectES( p_input, es->p_es );
+        }
     }
     else if( p_sys->i_mode == ES_OUT_MODE_AUTO )
     {
         int i_wanted  = -1;
 
+        if( es->p_es->p_pgrm != NULL &&
+            es->p_es->p_pgrm != p_input->stream.p_selected_program )
+        {
+            return;
+        }
+
         if( i_cat == AUDIO_ES )
         {
             if( p_sys->p_es_audio &&
@@ -230,6 +241,7 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
 static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
 {
     es_out_sys_t      *p_sys = out->p_sys;
+    playlist_t        *p_playlist = NULL;
     input_thread_t    *p_input = p_sys->p_input;
     es_out_id_t       *es = malloc( sizeof( es_out_id_t ) );
     pgrm_descriptor_t *p_prgm = NULL;
@@ -247,6 +259,12 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
             /* create it */
             p_prgm = input_AddProgram( p_input, fmt->i_group, 0 );
 
+            /* XXX welcome to kludge, add a dummy es, if you want to understand
+             * why have a look at input_SetProgram. Basicaly, it assume the first
+             * es to be the PMT, how that is stupide, nevertheless it is needed for
+             * the old ts demuxer */
+            input_AddES( p_input, p_prgm, 0, UNKNOWN_ES, NULL, 0 );
+
             /* Select the first by default */
             if( p_input->stream.p_selected_program == NULL )
             {
@@ -336,7 +354,10 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
     }
 
     sprintf( psz_cat, _("Stream %d"), out->p_sys->i_id - 1 );
-    if( ( p_cat = input_InfoCategory( p_input, psz_cat ) ) )
+    /* Get a category and the playlist */
+    if( ( p_cat = input_InfoCategory( p_input, psz_cat ) ) &&
+        ( p_playlist = (playlist_t *)vlc_object_find( p_input,
+                       VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ) ) )
     {
         /* Add information */
         switch( fmt->i_cat )
@@ -344,72 +365,117 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
             case AUDIO_ES:
                 if( fmt->psz_description )
                 {
-                    input_AddInfo( p_cat, _("Description"), "%s", 
+                    input_AddInfo( p_cat, _("Description"), "%s",
                                    fmt->psz_description );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                     _("Description"), "%s",
+                                     fmt->psz_description );
                 }
                 input_AddInfo( p_cat, _("Codec"), "%.4s",
                                (char*)&fmt->i_codec );
+                playlist_AddInfo( p_playlist, -1, psz_cat,
+                                  _("Codec"),"%.4s",(char*)&fmt->i_codec );
+
                 input_AddInfo( p_cat, _("Type"), _("Audio") );
+                playlist_AddInfo( p_playlist, -1, psz_cat,
+                                 _("Type"), _("Audio") );
+
                 if( fmt->audio.i_channels > 0 )
                 {
                     input_AddInfo( p_cat, _("Channels"), "%d",
                                    fmt->audio.i_channels );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                      _("Channels"), "%d",                                                            fmt->audio.i_channels );
                 }
                 if( fmt->psz_language )
                 {
-                    input_AddInfo( p_cat, _("Language"), "%s", 
+                    input_AddInfo( p_cat, _("Language"), "%s",
                                    fmt->psz_language );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                     _("Language"), "%s",
+                                     fmt->psz_language );
                 }
                 if( fmt->audio.i_rate > 0 )
                 {
-                  input_AddInfo( p_cat, _("Sample Rate"), _("%d Hz"),
+                    input_AddInfo( p_cat, _("Sample rate"), _("%d Hz"),
                                    fmt->audio.i_rate );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                     _("Sample rate"), _("%d Hz"),
+                                      fmt->audio.i_rate );
                 }
                 if( fmt->i_bitrate > 0 )
                 {
-                  input_AddInfo( p_cat, _("Bitrate"), _("%d bps"), 
+                    input_AddInfo( p_cat, _("Bitrate"), _("%d bps"),
                                    fmt->i_bitrate );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                    _("Bitrate"), _("%d bps"),
+                                     fmt->i_bitrate );
                 }
                 if( fmt->audio.i_bitspersample )
                 {
-                    input_AddInfo( p_cat, _("Bits Per Sample"), "%d",
+                    input_AddInfo( p_cat, _("Bits per sample"), "%d",
                                    fmt->audio.i_bitspersample );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                     _("Bits per sample"), "%d",
+                                     fmt->audio.i_bitspersample );
                 }
                 break;
             case VIDEO_ES:
                 if( fmt->psz_description )
                 {
-                    input_AddInfo( p_cat, _("Description"), "%s", 
+                    input_AddInfo( p_cat, _("Description"), "%s",
                                    fmt->psz_description );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                     _("Description"), "%s",
+                                     fmt->psz_description );
                 }
                 input_AddInfo( p_cat, _("Type"), _("Video") );
+                playlist_AddInfo( p_playlist, -1, psz_cat,
+                                _("Type"), _("Video") );
+
                 input_AddInfo( p_cat, _("Codec"), "%.4s",
                                (char*)&fmt->i_codec );
+                playlist_AddInfo( p_playlist, -1, psz_cat,
+                                 _("Codec"), "%.4s",
+                                 (char*)&fmt->i_codec );
+
                 if( fmt->video.i_width > 0 && fmt->video.i_height > 0 )
                 {
                     input_AddInfo( p_cat, _("Resolution"), "%dx%d",
                                    fmt->video.i_width, fmt->video.i_height );
+                    playlist_AddInfo( p_playlist, -1, psz_cat,
+                                    _("Resolution"), "%dx%d",
+                                    fmt->video.i_width, fmt->video.i_height );
                 }
                 if( fmt->video.i_visible_width > 0 &&
                     fmt->video.i_visible_height > 0 )
                 {
-                    input_AddInfo( p_cat, _("Display Resolution"), "%dx%d",
+                    input_AddInfo( p_cat, _("Display resolution"), "%dx%d",
                                    fmt->video.i_visible_width,
                                    fmt->video.i_visible_height);
+                     playlist_AddInfo( p_playlist, -1, psz_cat,
+                                       _("Display resolution"), "%dx%d",
+                                       fmt->video.i_visible_width,
+                                       fmt->video.i_visible_height);
                 }
                 break;
             case SPU_ES:
                 input_AddInfo( p_cat, _("Type"), _("Subtitle") );
+                playlist_AddInfo( p_playlist, -1, psz_cat,
+                                   _("Type"), _("Subtitle") );
                 input_AddInfo( p_cat, _("Codec"), "%.4s",
                                (char*)&fmt->i_codec );
+                playlist_AddInfo( p_playlist, -1, psz_cat,
+                                 _("Codec"), "%.4s",
+                                 (char*)&fmt->i_codec );
                 break;
             default:
 
                 break;
         }
+        if( p_playlist ) vlc_object_release( p_playlist );
     }
 
-
     /* Apply mode
      * XXX change that when we do group too */
     if( 1 )
@@ -446,26 +512,32 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
 {
     es_out_sys_t *p_sys = out->p_sys;
 
-    if( p_sys->b_pcr_set && p_sys->p_input->stream.p_selected_program )
+    if( p_sys->b_pcr_set )
     {
-        input_thread_t *p_input = p_sys->p_input;
+        pgrm_descriptor_t *p_pgrm = es->p_es->p_pgrm;
+        input_thread_t    *p_input = p_sys->p_input;
+
+        if( p_pgrm == NULL )
+        {
+            p_pgrm = p_sys->p_input->stream.p_selected_program;
+        }
 
-        if( p_block->i_dts > 0 )
+        if( p_block->i_dts > 0 && p_pgrm )
         {
             p_block->i_dts =
-                input_ClockGetTS( p_input, p_input->stream.p_selected_program,
-                                  p_block->i_dts * 9 / 100 );
+                input_ClockGetTS( p_input, p_pgrm, p_block->i_dts * 9 / 100 );
         }
-        if( p_block->i_pts > 0 )
+        if( p_block->i_pts > 0 && p_pgrm )
         {
             p_block->i_pts =
-                input_ClockGetTS( p_input, p_input->stream.p_selected_program,
-                                  p_block->i_pts * 9 / 100 );
+                input_ClockGetTS( p_input, p_pgrm, p_block->i_pts * 9 / 100 );
         }
     }
 
     vlc_mutex_lock( &out->p_sys->p_input->stream.stream_lock );
-    if( es->p_es->p_dec )
+    p_block->i_rate = out->p_sys->p_input->stream.control.i_rate;
+    if( es->p_es->p_dec &&
+        (es->p_es->i_cat!=AUDIO_ES || !p_sys->p_input->stream.control.b_mute) )
     {
         input_DecodeBlock( es->p_es->p_dec, p_block );
     }
@@ -519,6 +591,10 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
     }
     input_DelES( p_sys->p_input, es->p_es );
 
+    if( p_sys->p_es_audio == es ) p_sys->p_es_audio = NULL;
+    if( p_sys->p_es_video == es ) p_sys->p_es_video = NULL;
+    if( p_sys->p_es_sub   == es ) p_sys->p_es_sub   = NULL;
+
     vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
 
     free( es );
@@ -532,8 +608,6 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
     es_out_sys_t *p_sys = out->p_sys;
     vlc_bool_t  b, *pb;
     int         i, *pi;
-    int         i_group;
-    int64_t     i_pcr;
 
     es_out_id_t *es;
 
@@ -643,27 +717,35 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
             return VLC_SUCCESS;
 
         case ES_OUT_SET_PCR:
+        case ES_OUT_SET_GROUP_PCR:
         {
             pgrm_descriptor_t *p_prgm = NULL;
+            int64_t           i_pcr;
 
-            i_group = (int)va_arg( args, int );
+            if( i_query == ES_OUT_SET_PCR )
+            {
+                p_prgm = p_sys->p_input->stream.p_selected_program;
+            }
+            else
+            {
+                int i_group = (int)va_arg( args, int );
+                p_prgm = input_FindProgram( p_sys->p_input, i_group );
+            }
             i_pcr   = (int64_t)va_arg( args, int64_t );
 
             /* search program */
-            if( ( p_prgm = input_FindProgram( p_sys->p_input, i_group ) ) )
+            if( p_prgm )
             {
-                input_ClockManageRef( p_sys->p_input, p_prgm, i_pcr );
+                input_ClockManageRef( p_sys->p_input, p_prgm, i_pcr * 9 / 100);
             }
             p_sys->b_pcr_set = VLC_TRUE;
             return VLC_SUCCESS;
         }
 
         case ES_OUT_RESET_PCR:
-            /* FIXME do it for all program */
-            if( p_sys->p_input->stream.p_selected_program )
+            for( i = 0; i < p_sys->p_input->stream.i_pgrm_number; i++ )
             {
-                p_sys->p_input->stream.p_selected_program->i_synchro_state =
-                    SYNCHRO_REINIT;
+                p_sys->p_input->stream.pp_programs[i]->i_synchro_state = SYNCHRO_REINIT;
             }
             p_sys->b_pcr_set = VLC_TRUE;
             return VLC_SUCCESS;