]> 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 85d567dbcd4ccc8cf47f8499fd857753db871f05..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.4 2003/11/27 12:22:15 fenrir 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"
 
 /*****************************************************************************
@@ -44,6 +45,7 @@ struct es_out_id_t
 struct es_out_sys_t
 {
     input_thread_t *p_input;
+    vlc_bool_t      b_pcr_set;
 
     /* all es */
     int         i_id;
@@ -92,6 +94,7 @@ es_out_t *input_EsOutNew( input_thread_t *p_input )
     out->p_sys      = p_sys;
 
     p_sys->p_input = p_input;
+    p_sys->b_pcr_set = VLC_FALSE;
 
     p_sys->b_active = VLC_FALSE;
     p_sys->i_mode   = ES_OUT_MODE_AUTO;
@@ -149,30 +152,45 @@ 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 && p_sys->p_es_audio->p_es->fmt.i_priority >= es->p_es->fmt.i_priority )
+            if( p_sys->p_es_audio &&
+                p_sys->p_es_audio->p_es->fmt.i_priority >=
+                    es->p_es->fmt.i_priority )
             {
                 return;
             }
-            i_wanted  = p_sys->i_audio_last >= 0 ? p_sys->i_audio_last : es->i_channel;
+            i_wanted  = p_sys->i_audio_last >= 0 ?
+                            p_sys->i_audio_last : es->i_channel;
         }
         else if( i_cat == SPU_ES )
         {
-            if( p_sys->p_es_sub && p_sys->p_es_sub->p_es->fmt.i_priority >= es->p_es->fmt.i_priority )
+            if( p_sys->p_es_sub &&
+                p_sys->p_es_sub->p_es->fmt.i_priority >=
+                    es->p_es->fmt.i_priority )
             {
                 return;
             }
@@ -223,10 +241,11 @@ 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;
-    char              psz_cat[strlen( "Stream " ) + 10];
+    char              psz_cat[sizeof( "Stream " ) + 10];
     input_info_category_t *p_cat;
 
     vlc_mutex_lock( &p_input->stream.stream_lock );
@@ -240,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 )
             {
@@ -329,65 +354,128 @@ 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 )
         {
             case AUDIO_ES:
-                input_AddInfo( p_cat, _("Type"), _("Audio") );
+                if( fmt->psz_description )
+                {
+                    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",
+                                   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",
+                    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",
+                    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",
+                                   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 )
@@ -422,8 +510,34 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
  *****************************************************************************/
 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 )
+    {
+        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 && p_pgrm )
+        {
+            p_block->i_dts =
+                input_ClockGetTS( p_input, p_pgrm, p_block->i_dts * 9 / 100 );
+        }
+        if( p_block->i_pts > 0 && p_pgrm )
+        {
+            p_block->i_pts =
+                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 );
     }
@@ -432,6 +546,7 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
         block_Release( p_block );
     }
     vlc_mutex_unlock( &out->p_sys->p_input->stream.stream_lock );
+
     return VLC_SUCCESS;
 }
 
@@ -476,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 );
@@ -541,7 +660,8 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
 
         case ES_OUT_SET_MODE:
             i = (int) va_arg( args, int );
-            if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL || i == ES_OUT_MODE_AUTO )
+            if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL ||
+                i == ES_OUT_MODE_AUTO )
             {
                 vlc_value_t val;
 
@@ -596,12 +716,42 @@ 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;
+
+            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_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:
+            for( i = 0; i < p_sys->p_input->stream.i_pgrm_number; i++ )
+            {
+                p_sys->p_input->stream.pp_programs[i]->i_synchro_state = SYNCHRO_REINIT;
+            }
+            p_sys->b_pcr_set = VLC_TRUE;
+            return VLC_SUCCESS;
+
         default:
             msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
             return VLC_EGENERIC;
     }
 }
-
-
-
-