[vlc-commits] transcode: refactor audio

Francois Cartegnie git at videolan.org
Mon Jul 9 16:15:32 CEST 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Jun 26 23:20:18 2018 +0200| [1f6c01737fcf528ca35dfa69c4d50d5d9fe733a6] | committer: Francois Cartegnie

transcode: refactor audio

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=1f6c01737fcf528ca35dfa69c4d50d5d9fe733a6
---

 modules/stream_out/transcode/audio.c     | 286 ++++++++++++++++++-------------
 modules/stream_out/transcode/transcode.h |   2 +-
 2 files changed, 165 insertions(+), 123 deletions(-)

diff --git a/modules/stream_out/transcode/audio.c b/modules/stream_out/transcode/audio.c
index dbe2fb012b..958dcd2204 100644
--- a/modules/stream_out/transcode/audio.c
+++ b/modules/stream_out/transcode/audio.c
@@ -75,9 +75,9 @@ static int audio_update_format( decoder_t *p_dec )
     return ( p_dec->fmt_out.audio.i_bitspersample > 0 ) ? 0 : -1;
 }
 
-static int transcode_audio_initialize_filters( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
-                                               sout_stream_sys_t *p_sys )
+static int transcode_audio_filters_init( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
 {
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
     /* Load user specified audio filters */
     /* XXX: These variable names come kinda out of nowhere... */
     var_Create( p_stream, "audio-time-stretch", VLC_VAR_BOOL );
@@ -88,21 +88,40 @@ static int transcode_audio_initialize_filters( sout_stream_t *p_stream, sout_str
                                       &id->p_encoder->fmt_in.audio, NULL, NULL );
     var_Destroy( p_stream, "audio-filter" );
     var_Destroy( p_stream, "audio-time-stretch" );
-    if( id->p_af_chain == NULL )
+    return ( id->p_af_chain != NULL ) ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
+static int transcode_audio_encoder_open( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
+{
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+    id->p_encoder->p_module = module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
+    /* p_sys->i_acodec = 0 if there isn't acodec defined */
+    if( !id->p_encoder->p_module )
     {
-        msg_Err( p_stream, "Unable to initialize audio filters" );
+        msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). "
+                           "Take a look few lines earlier to see possible reason.",
+                           p_sys->psz_aenc ? p_sys->psz_aenc : "any",
+                           (char *)&p_sys->i_acodec );
+        return VLC_EGENERIC;
+    }
+
+    id->downstream_id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
+    if ( !id->downstream_id )
+    {
+        msg_Err( p_stream, "cannot add this stream" );
         module_unneed( id->p_encoder, id->p_encoder->p_module );
         id->p_encoder->p_module = NULL;
-        module_unneed( id->p_decoder, id->p_decoder->p_module );
-        id->p_decoder->p_module = NULL;
         return VLC_EGENERIC;
     }
-    id->fmt_audio.i_rate = id->audio_dec_out.i_rate;
-    id->fmt_audio.i_physical_channels = id->audio_dec_out.i_physical_channels;
+
+    id->p_encoder->fmt_out.i_codec =
+            vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
+
     return VLC_SUCCESS;
 }
 
-static int transcode_audio_initialize_encoder( sout_stream_id_sys_t *id, sout_stream_t *p_stream )
+static int transcode_audio_encoder_configure( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
     audio_format_t *p_enc_in = &id->p_encoder->fmt_in.audio;
@@ -110,12 +129,14 @@ static int transcode_audio_initialize_encoder( sout_stream_id_sys_t *id, sout_st
 
     /* Complete destination format */
     id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
+    id->p_encoder->fmt_out.audio.i_format = p_sys->i_acodec;
     id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
     p_enc_out->i_rate = p_sys->i_sample_rate ? p_sys->i_sample_rate
                                              : id->audio_dec_out.i_rate;
     p_enc_out->i_bitspersample = id->audio_dec_out.i_bitspersample;
     p_enc_out->i_channels = p_sys->i_channels ? p_sys->i_channels
                                               : id->audio_dec_out.i_channels;
+    aout_FormatPrepare( p_enc_out );
     assert(p_enc_out->i_channels > 0);
     if( p_enc_out->i_channels >= ARRAY_SIZE(pi_channels_maps) )
         p_enc_out->i_channels = ARRAY_SIZE(pi_channels_maps) - 1;
@@ -131,22 +152,6 @@ static int transcode_audio_initialize_encoder( sout_stream_id_sys_t *id, sout_st
     aout_FormatPrepare( p_enc_in );
 
     id->p_encoder->p_cfg = p_sys->p_audio_cfg;
-    id->p_encoder->p_module =
-        module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
-    /* p_sys->i_acodec = 0 if there isn't acodec defined */
-    if( !id->p_encoder->p_module && p_sys->i_acodec )
-    {
-        msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). "
-                           "Take a look few lines earlier to see possible reason.",
-                 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
-                 (char *)&p_sys->i_acodec );
-        module_unneed( id->p_decoder, id->p_decoder->p_module );
-        id->p_decoder->p_module = NULL;
-        return VLC_EGENERIC;
-    }
-
-    id->p_encoder->fmt_out.i_codec =
-        vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
 
     /* Fix input format */
     p_enc_in->i_format = id->p_encoder->fmt_in.i_codec;
@@ -157,9 +162,81 @@ static int transcode_audio_initialize_encoder( sout_stream_id_sys_t *id, sout_st
     }
     aout_FormatPrepare( p_enc_in );
 
+    id->fmt_input_audio.i_rate = id->audio_dec_out.i_rate;
+    id->fmt_input_audio.i_physical_channels = id->audio_dec_out.i_physical_channels;
+
     return VLC_SUCCESS;
 }
 
+static int transcode_audio_encoder_test( sout_stream_t *p_stream,
+                                         const audio_format_t *p_dec_in,
+                                         const audio_format_t *p_dec_out,
+                                         vlc_fourcc_t i_codec_in,
+                                         config_chain_t *p_cfg,
+                                         const es_format_t *p_enc_fmtout,
+                                         es_format_t *p_enc_wanted_in )
+{
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+    encoder_t *p_encoder = sout_EncoderCreate( p_stream );
+    if( !p_encoder )
+        return VLC_EGENERIC;
+
+    p_encoder->p_cfg = p_cfg;
+
+    es_format_Init( &p_encoder->fmt_in, AUDIO_ES, i_codec_in );
+    p_encoder->fmt_in.audio = *p_dec_out;
+    es_format_Init( &p_encoder->fmt_out, AUDIO_ES, 0 );
+    es_format_Copy( &p_encoder->fmt_out, p_enc_fmtout );
+
+    audio_format_t *p_afmt_out = &p_encoder->fmt_out.audio;
+
+    p_encoder->fmt_in.audio.i_format = i_codec_in;
+    p_encoder->fmt_out.i_codec = p_afmt_out->i_format =  p_sys->i_acodec;
+    p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
+
+    p_afmt_out->i_rate = FIRSTVALID( p_sys->i_sample_rate, p_dec_out->i_rate, p_dec_in->i_rate );
+    p_afmt_out->i_channels = p_sys->i_channels ? p_sys->i_channels
+                                               : p_dec_out->i_channels;
+    if( p_afmt_out->i_channels == 0 )
+    {
+        p_afmt_out->i_channels = 2;
+        p_afmt_out->i_physical_channels = AOUT_CHANS_STEREO;
+    }
+    else
+    {
+        if( p_afmt_out->i_physical_channels )
+            p_afmt_out->i_physical_channels = p_afmt_out->i_physical_channels;
+        else
+            p_afmt_out->i_physical_channels = p_dec_out->i_physical_channels;
+    }
+    aout_FormatPrepare( p_afmt_out );
+
+    module_t *p_module = module_need( p_encoder, "encoder", p_sys->psz_aenc, true );
+    if( !p_module )
+    {
+        msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s). "
+                           "Take a look few lines earlier to see possible reason.",
+                           p_sys->psz_aenc ? p_sys->psz_aenc : "any",
+                           (char *)&p_sys->i_acodec );
+    }
+    else
+    {
+        /* Close the encoder.
+         * We'll open it only when we have the first frame. */
+        module_unneed( p_encoder, p_module );
+    }
+
+    /* copy our requested format */
+    es_format_Copy( p_enc_wanted_in, &p_encoder->fmt_in );
+
+    es_format_Clean( &p_encoder->fmt_in );
+    es_format_Clean( &p_encoder->fmt_out );
+
+    vlc_object_release( p_encoder );
+
+    return p_module != NULL ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
 static void decoder_queue_audio( decoder_t *p_dec, block_t *p_audio )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
@@ -212,43 +289,51 @@ static int transcode_audio_new( sout_stream_t *p_stream,
     }
 
     vlc_mutex_lock(&id->fifo.lock);
+
+    id->audio_dec_out = id->p_decoder->fmt_out.audio;
     /* The decoder fmt_out can be uninitialized here (since it can initialized
      * asynchronously). Fix audio_dec_out with default values in that case.
      * This should be enough to initialize the encoder for the first time (it
      * will be reloaded when all informations from the decoder are available).
      * */
-    id->audio_dec_out = id->p_decoder->fmt_out.audio;
-    id->audio_dec_out.i_format = id->p_decoder->fmt_out.i_codec;
-    if (id->audio_dec_out.i_format == 0)
-        id->audio_dec_out.i_format = VLC_CODEC_FL32;
-    if (id->audio_dec_out.i_rate == 0)
-    {
-        id->audio_dec_out.i_rate = id->p_decoder->fmt_in.audio.i_rate;
-        if (id->audio_dec_out.i_rate == 0)
-            id->audio_dec_out.i_rate = 48000;
-    }
-    if (id->audio_dec_out.i_physical_channels == 0)
-    {
-        id->audio_dec_out.i_physical_channels = id->p_decoder->fmt_in.audio.i_physical_channels;
-        if (id->audio_dec_out.i_physical_channels == 0)
-            id->audio_dec_out.i_physical_channels = AOUT_CHANS_STEREO;
-    }
+    id->audio_dec_out.i_format = FIRSTVALID( id->audio_dec_out.i_format,
+                                             id->p_decoder->fmt_out.i_codec,
+                                             VLC_CODEC_FL32 );
+    id->audio_dec_out.i_rate = FIRSTVALID( id->audio_dec_out.i_rate,
+                                           id->p_decoder->fmt_in.audio.i_rate,
+                                           48000 );
+    id->audio_dec_out.i_physical_channels =
+            FIRSTVALID( id->audio_dec_out.i_physical_channels,
+                        id->p_decoder->fmt_in.audio.i_physical_channels,
+                        AOUT_CHANS_STEREO );
     aout_FormatPrepare( &id->audio_dec_out );
 
-    /*
-     * Open encoder
-     */
-    if( transcode_audio_initialize_encoder( id, p_stream ) == VLC_EGENERIC )
-    {
-        vlc_mutex_unlock(&id->fifo.lock);
-        return VLC_EGENERIC;
-    }
+    /* Initialization of encoder format structures */
+    es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
+                    id->p_decoder->fmt_out.i_codec );
+    /* Should be the same format until encoder loads */
+    es_format_Init( &id->encoder_tested_fmt_in, id->p_decoder->fmt_in.i_cat,
+                    id->p_decoder->fmt_out.i_codec );
 
-    if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys ) != VLC_SUCCESS ) )
+    /* The decoder fmt_out can be uninitialized here (since it can initialized
+     * asynchronously). Fix audio_dec_out with default values in that case.
+     * This should be enough to initialize the encoder for the first time (it
+     * will be reloaded when all informations from the decoder are available).
+     * */
+    if( transcode_audio_encoder_test( p_stream, &id->p_decoder->fmt_in.audio,
+                                                &id->audio_dec_out,
+                                                id->p_decoder->fmt_out.i_codec,
+                                                p_sys->p_audio_cfg,
+                                                &id->p_encoder->fmt_out,
+                                                &id->encoder_tested_fmt_in ) != VLC_SUCCESS )
     {
         vlc_mutex_unlock(&id->fifo.lock);
+        module_unneed( id->p_decoder, id->p_decoder->p_module );
+        id->p_decoder->p_module = NULL;
+        es_format_Clean( &id->encoder_tested_fmt_in );
         return VLC_EGENERIC;
     }
+
     vlc_mutex_unlock(&id->fifo.lock);
 
     return VLC_SUCCESS;
@@ -303,51 +388,44 @@ int transcode_audio_process( sout_stream_t *p_stream,
         }
 
         vlc_mutex_lock(&id->fifo.lock);
-        if( unlikely( !id->p_encoder->p_module ) )
+
+        if( p_audio_buf &&
+            ( unlikely(id->p_encoder->p_module == NULL) ||
+              id->audio_dec_out.i_rate != id->fmt_input_audio.i_rate ||
+              id->audio_dec_out.i_physical_channels != id->fmt_input_audio.i_physical_channels ) )
         {
-            if( transcode_audio_initialize_encoder( id, p_stream ) )
+            if( id->p_encoder->p_module == NULL )
             {
-                msg_Err( p_stream, "cannot create audio chain" );
-                vlc_mutex_unlock(&id->fifo.lock);
-                goto error;
+                transcode_audio_encoder_configure( p_stream, id );
             }
-            if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys ) != VLC_SUCCESS ) )
+            else
             {
-                vlc_mutex_unlock(&id->fifo.lock);
-                goto error;
-            }
-            date_Init( &id->next_input_pts, id->audio_dec_out.i_rate, 1 );
-            date_Set( &id->next_input_pts, p_audio_buf->i_pts );
-
-            if (!id->downstream_id)
-            {
-                id->downstream_id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
-                if (!id->downstream_id)
+                /* Check if audio format has changed, and filters need reinit */
+                msg_Info( p_stream, "Audio changed, trying to reinitialize filters" );
+                if( id->p_af_chain != NULL )
                 {
-                    vlc_mutex_unlock(&id->fifo.lock);
-                    goto error;
+                    aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
+                    id->p_af_chain = NULL;
                 }
             }
-        }
 
-        /* Check if audio format has changed, and filters need reinit */
-        if( unlikely( ( id->audio_dec_out.i_rate != id->fmt_audio.i_rate ) ||
-                      ( id->audio_dec_out.i_physical_channels != id->fmt_audio.i_physical_channels ) ) )
-        {
-            msg_Info( p_stream, "Audio changed, trying to reinitialize filters" );
-            if( id->p_af_chain != NULL )
-                aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
-
-            if( transcode_audio_initialize_filters( p_stream, id, p_sys ) != VLC_SUCCESS )
+            if( transcode_audio_filters_init( p_stream, id ) )
             {
                 vlc_mutex_unlock(&id->fifo.lock);
                 goto error;
             }
 
-            /* Set next_input_pts to run with new samplerate */
-            date_Init( &id->next_input_pts, id->fmt_audio.i_rate, 1 );
+            date_Init( &id->next_input_pts, id->audio_dec_out.i_rate, 1 );
             date_Set( &id->next_input_pts, p_audio_buf->i_pts );
+
+            if( id->p_encoder->p_module == NULL &&
+                transcode_audio_encoder_open( p_stream, id ) )
+            {
+                vlc_mutex_unlock(&id->fifo.lock);
+                goto error;
+            }
         }
+
         vlc_mutex_unlock(&id->fifo.lock);
 
         if( p_sys->b_master_sync )
@@ -394,16 +472,13 @@ error:
 
 end:
     /* Drain encoder */
-    if( unlikely( !id->b_error && in == NULL ) )
+    if( unlikely( !id->b_error && in == NULL ) && id->p_encoder->p_module )
     {
-        if( id->p_encoder->p_module )
-        {
-            block_t *p_block;
-            do {
-               p_block = id->p_encoder->pf_encode_audio(id->p_encoder, NULL );
-               block_ChainAppend( out, p_block );
-            } while( p_block );
-        }
+        block_t *p_block;
+        do {
+            p_block = id->p_encoder->pf_encode_audio(id->p_encoder, NULL );
+            block_ChainAppend( out, p_block );
+        } while( p_block );
     }
 
     return id->b_error ? VLC_EGENERIC : VLC_SUCCESS;
@@ -421,23 +496,6 @@ bool transcode_audio_add( sout_stream_t *p_stream, const es_format_t *p_fmt,
     id->fifo.audio.first = NULL;
     id->fifo.audio.last = &id->fifo.audio.first;
 
-    /* Complete destination format */
-    id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
-    id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
-        p_sys->i_sample_rate : p_fmt->audio.i_rate;
-    id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
-    id->p_encoder->fmt_out.audio.i_bitspersample =
-        p_fmt->audio.i_bitspersample;
-    id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
-        p_sys->i_channels : p_fmt->audio.i_channels;
-
-    if( id->p_encoder->fmt_out.audio.i_channels >= ARRAY_SIZE(pi_channels_maps) )
-        id->p_encoder->fmt_out.audio.i_channels = ARRAY_SIZE(pi_channels_maps) - 1;
-
-    id->p_encoder->fmt_in.audio.i_physical_channels =
-    id->p_encoder->fmt_out.audio.i_physical_channels =
-            pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
-
     /* Build decoder -> filter -> encoder chain */
     if( transcode_audio_new( p_stream, id ) == VLC_EGENERIC )
     {
@@ -448,21 +506,5 @@ bool transcode_audio_add( sout_stream_t *p_stream, const es_format_t *p_fmt,
     /* Open output stream */
     id->b_transcode = true;
 
-    /* Reinit encoder again later on, when all information from decoders
-     * is available. */
-    if( id->p_encoder->p_module )
-    {
-        module_unneed( id->p_encoder, id->p_encoder->p_module );
-        id->p_encoder->p_module = NULL;
-        if( id->p_encoder->fmt_out.p_extra )
-        {
-            free( id->p_encoder->fmt_out.p_extra );
-            id->p_encoder->fmt_out.p_extra = NULL;
-            id->p_encoder->fmt_out.i_extra = 0;
-        }
-        if( id->p_af_chain != NULL )
-            aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
-        id->p_af_chain = NULL;
-    }
     return true;
 }
diff --git a/modules/stream_out/transcode/transcode.h b/modules/stream_out/transcode/transcode.h
index 1053553468..4c0c67e462 100644
--- a/modules/stream_out/transcode/transcode.h
+++ b/modules/stream_out/transcode/transcode.h
@@ -156,7 +156,7 @@ struct sout_stream_id_sys_t
          struct
          {
              struct aout_filters    *p_af_chain; /**< Audio filters */
-             audio_format_t  fmt_audio;
+             audio_format_t  fmt_input_audio;
              audio_format_t  audio_dec_out; /* only rw from pf_aout_format_update() */
          };
 



More information about the vlc-commits mailing list