]> git.sesse.net Git - vlc/blobdiff - src/input/es_out.c
* modules/packetizer/mpeg4audio.c, modules/packetizer/mpegvideo.c: compilation fix.
[vlc] / src / input / es_out.c
index 1055bbd1e0a800c5805527511bb9e7ad03af0c77..c7e925ff1f92c92349bf7dc760422d5308fdb762 100644 (file)
@@ -2,7 +2,7 @@
  * es_out.c: Es Out handler for input.
  *****************************************************************************
  * Copyright (C) 2003-2004 VideoLAN
- * $Id: es_out.c,v 1.14 2004/01/06 12:02:06 zorglub Exp $
+ * $Id: es_out.c,v 1.25 2004/01/31 20:21:47 fenrir Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -32,6 +32,7 @@
 
 #include "vlc_playlist.h"
 #include "codecs.h"
+#include "iso_lang.h"
 
 /*****************************************************************************
  * Local prototypes
@@ -77,10 +78,14 @@ static int          EsOutSend   ( es_out_t *, es_out_id_t *, block_t * );
 static void         EsOutDel    ( es_out_t *, es_out_id_t * );
 static int          EsOutControl( es_out_t *, int i_query, va_list );
 
+static char *LanguageGetName( const char *psz_code );
 
-/*****************************************************************************
- * input_EsOutNew:
- *****************************************************************************/
+/**
+ * Create a new es_out structure
+ *
+ * \param p_input The related input thread
+ * \return the new es_out_t
+ */
 es_out_t *input_EsOutNew( input_thread_t *p_input )
 {
     es_out_t     *out = malloc( sizeof( es_out_t ) );
@@ -121,9 +126,12 @@ es_out_t *input_EsOutNew( input_thread_t *p_input )
     return out;
 }
 
-/*****************************************************************************
- * input_EsOutDelete:
- *****************************************************************************/
+/**
+ * Deletes an es_out structure
+ *
+ * \param out  the es_out structure to destroy
+ * \return nothing
+ */
 void input_EsOutDelete( es_out_t *out )
 {
     es_out_sys_t *p_sys = out->p_sys;
@@ -141,10 +149,52 @@ void input_EsOutDelete( es_out_t *out )
     free( out );
 }
 
-/*****************************************************************************
- * EsOutSelect: Select an ES given the current mode
+/**
+ * Add a program
+ *
+ * \param out the es_out
+ * \param i_group ...
+ * \return a program descriptor for the new program
+ */
+static pgrm_descriptor_t *EsOutAddProgram( es_out_t *out, int i_group )
+{
+    input_thread_t    *p_input = out->p_sys->p_input;
+    pgrm_descriptor_t *p_prgm;
+    es_descriptor_t   *p_pmt;
+
+    /* FIXME we should use a object variable but a lot of place in src/input
+     * have to be changed */
+    int               i_select = config_GetInt( p_input, "program" );
+
+    /* create it */
+    p_prgm = input_AddProgram( p_input, 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 stupid, nevertheless it is needed for
+     * the old ts demuxer */
+    p_pmt = input_AddES( p_input, p_prgm, 0, UNKNOWN_ES, NULL, 0 );
+    p_pmt->i_fourcc = VLC_FOURCC( 'n', 'u', 'l', 'l' );
+
+    /* Select i_select or the first by default */
+    if( p_input->stream.p_selected_program == NULL &&
+        ( i_select <= 0 || i_select == i_group ) )
+    {
+        p_input->stream.p_selected_program = p_prgm;
+    }
+
+    return p_prgm;
+}
+
+/**
+ * Select an ES given the current mode
  * XXX: you need to take a the lock before (stream.stream_lock)
- *****************************************************************************/
+ *
+ * \param out The es_out structure
+ * \param es es_out_id structure
+ * \param b_force ...
+ * \return nothing
+ */
 static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
 {
     es_out_sys_t      *p_sys = out->p_sys;
@@ -152,19 +202,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 &&
@@ -225,9 +285,13 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
     }
 }
 
-/*****************************************************************************
- * EsOutAdd:
- *****************************************************************************/
+/**
+ * Add an es_out
+ *
+ * \param out the es_out to add
+ * \param fmt the es_format of the es_out
+ * \return an es_out id
+ */
 static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
 {
     es_out_sys_t      *p_sys = out->p_sys;
@@ -235,8 +299,9 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
     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[sizeof( "Stream " ) + 10];
+    char              psz_cat[sizeof( _("Stream ") ) + 10];
     input_info_category_t *p_cat;
+    char              *psz_description;
 
     vlc_mutex_lock( &p_input->stream.stream_lock );
     if( fmt->i_group >= 0 )
@@ -246,23 +311,22 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
 
         if( p_prgm == NULL )
         {
-            /* create it */
-            p_prgm = input_AddProgram( p_input, fmt->i_group, 0 );
-
-            /* Select the first by default */
-            if( p_input->stream.p_selected_program == NULL )
-            {
-                p_input->stream.p_selected_program = p_prgm;
-            }
+            /* Create it */
+            p_prgm = EsOutAddProgram( out, fmt->i_group );
         }
     }
+    if( fmt->i_id < 0 )
+    {
+        fmt->i_id = out->p_sys->i_id - 1;
+    }
 
+    psz_description = LanguageGetName( fmt->psz_language );
     es->p_es = input_AddES( p_input,
                             p_prgm,
-                            out->p_sys->i_id,
+                            fmt->i_id + 1,
                             fmt->i_cat,
-                            fmt->psz_language, 0 );
-    es->p_es->i_stream_id = out->p_sys->i_id;
+                            psz_description, 0 );
+    es->p_es->i_stream_id = fmt->i_id;
     es->p_es->i_fourcc = fmt->i_codec;
 
     switch( fmt->i_cat )
@@ -343,86 +407,78 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
         ( p_playlist = (playlist_t *)vlc_object_find( p_input,
                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ) ) )
     {
-        /* Add information */
+        char *psz_type;
         switch( fmt->i_cat )
         {
             case AUDIO_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, _("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") );
+                psz_type = _("Audio");
+                break;
+            case VIDEO_ES:
+                psz_type = _("Video");
+                break;
+            case SPU_ES:
+                psz_type = _("Subtitle");
+                break;
+            default:
+                psz_type = NULL;
+                break;
+        }
+        if( psz_type )
+        {
+            input_AddInfo( p_cat, _("Type"), psz_type );
+            playlist_AddInfo( p_playlist, -1, psz_cat, _("Type"), psz_type );
+        }
+        input_AddInfo( p_cat, _("Codec"), "%.4s", (char*)&fmt->i_codec );
+        playlist_AddInfo( p_playlist, -1, psz_cat, _("Codec"),
+                          "%.4s",(char*)&fmt->i_codec );
+        if( *psz_description )
+        {
+            input_AddInfo( p_cat, _("Language"), psz_description );
+            playlist_AddInfo( p_playlist, -1, psz_cat, _("Language"),
+                              "%s", psz_description );
+        }
+        if( fmt->psz_description && *fmt->psz_description )
+        {
+            input_AddInfo( p_cat, _("Description"), "%s", fmt->psz_description );
+            playlist_AddInfo( p_playlist, -1, psz_cat, _("Description"),
+                              "%s", fmt->psz_description );
+        }
 
+        /* Add information */
+        switch( fmt->i_cat )
+        {
+            case AUDIO_ES:
                 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 );
+                    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->audio.i_rate > 0 )
                 {
-                    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 );
+                    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 )
+                if( fmt->audio.i_bitspersample > 0 )
                 {
-                    input_AddInfo( p_cat, _("Bitrate"), _("%d bps"),
-                                   fmt->i_bitrate );
-                    playlist_AddInfo( p_playlist, -1, psz_cat,
-                                    _("Bitrate"), _("%d bps"),
-                                     fmt->i_bitrate );
+                    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 );
                 }
-                if( fmt->audio.i_bitspersample )
+                if( fmt->i_bitrate > 0 )
                 {
-                    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 );
+                    input_AddInfo( p_cat, _("Bitrate"),
+                                   _("%d bps"), fmt->i_bitrate );
+                    playlist_AddInfo( p_playlist, -1, psz_cat, _("Bitrate"),
+                                      _("%d bps"), fmt->i_bitrate );
                 }
                 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 );
 
+            case VIDEO_ES:
                 if( fmt->video.i_width > 0 && fmt->video.i_height > 0 )
                 {
                     input_AddInfo( p_cat, _("Resolution"), "%dx%d",
@@ -443,22 +499,16 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
                                        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 );
     }
+    free( psz_description );
+
+    es_format_Copy( &es->p_es->fmt, fmt );
 
     /* Apply mode
      * XXX change that when we do group too */
@@ -466,11 +516,8 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
     {
         EsOutSelect( out, es, VLC_FALSE );
     }
-
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
-    es->p_es->fmt = *fmt;
-
     TAB_APPEND( out->p_sys->i_es, out->p_sys->es, es );
     p_sys->i_id++;  /* always incremented */
     switch( fmt->i_cat )
@@ -489,28 +536,36 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
     return es;
 }
 
-/*****************************************************************************
- * EsOutSend:
- *****************************************************************************/
+/**
+ * Send a block for the given es_out
+ *
+ * \param out the es_out to send from
+ * \param es the es_out_id
+ * \param p_block the data block to send
+ */
 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 );
         }
     }
 
@@ -580,16 +635,19 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
     free( es );
 }
 
-/*****************************************************************************
- * EsOutControl:
- *****************************************************************************/
+/**
+ * Control query handler
+ *
+ * \param out the es_out to control
+ * \param i_query A es_out query as defined in include/ninput.h
+ * \param args a variable list of arguments for the query
+ * \return VLC_SUCCESS or an error code
+ */
 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;
 
@@ -699,14 +757,29 @@ 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 );
+                if( p_prgm == NULL )
+                {
+                    /* we create the requested program */
+                    p_prgm = EsOutAddProgram( out, 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 * 9 / 100);
             }
@@ -715,11 +788,9 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
         }
 
         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;
@@ -729,3 +800,46 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
             return VLC_EGENERIC;
     }
 }
+
+/****************************************************************************
+ * LanguageGetName: try to expend iso639 into plain name
+ ****************************************************************************/
+static char *LanguageGetName( const char *psz_code )
+{
+    const iso639_lang_t *pl;
+
+    if( psz_code == NULL )
+    {
+        return strdup( "" );
+    }
+
+    if( strlen( psz_code ) == 2 )
+    {
+        pl = GetLang_1( psz_code );
+    }
+    else if( strlen( psz_code ) == 3 )
+    {
+        pl = GetLang_2B( psz_code );
+        if( !strcmp( pl->psz_iso639_1, "??" ) )
+        {
+            pl = GetLang_2T( psz_code );
+        }
+    }
+    else
+    {
+        return strdup( psz_code );
+    }
+
+    if( !strcmp( pl->psz_iso639_1, "??" ) )
+    {
+       return strdup( psz_code );
+    }
+    else
+    {
+        if( *pl->psz_native_name )
+        {
+            return strdup( pl->psz_native_name );
+        }
+        return strdup( pl->psz_eng_name );
+    }
+}