[vlc-commits] transcode: refactor video encoder setup/testing

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


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jun 22 11:16:27 2018 +0200| [2c546579c1c2a9ad72d37cac9dd052a3bba973d0] | committer: Francois Cartegnie

transcode: refactor video encoder setup/testing

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

 modules/stream_out/transcode/transcode.h |   2 +
 modules/stream_out/transcode/video.c     | 170 ++++++++++++++++++-------------
 2 files changed, 103 insertions(+), 69 deletions(-)

diff --git a/modules/stream_out/transcode/transcode.h b/modules/stream_out/transcode/transcode.h
index dd789e3fc4..baf9b099a1 100644
--- a/modules/stream_out/transcode/transcode.h
+++ b/modules/stream_out/transcode/transcode.h
@@ -4,6 +4,7 @@
 
 /*100ms is around the limit where people are noticing lipsync issues*/
 #define MASTER_SYNC_MAX_DRIFT VLC_TICK_FROM_MS(100)
+#define FIRSTVALID(a,b,c) ( a ? a : ( b ? b : c ) )
 
 typedef struct sout_stream_id_sys_t sout_stream_id_sys_t;
 
@@ -116,6 +117,7 @@ struct sout_stream_id_sys_t
     picture_fifo_t *pp_pics;
     vlc_sem_t       picture_pool_has_room;
     vlc_cond_t      cond;
+    es_format_t     encoder_tested_fmt_in;
 
 
     /* Sync */
diff --git a/modules/stream_out/transcode/video.c b/modules/stream_out/transcode/video.c
index c1e1aa80a5..ceb704e05c 100644
--- a/modules/stream_out/transcode/video.c
+++ b/modules/stream_out/transcode/video.c
@@ -82,6 +82,7 @@ static int video_update_format_decoder( decoder_t *p_dec )
     int chain_works = filter_chain_AppendConverter( test_chain, &p_dec->fmt_out,
                                   &id->p_encoder->fmt_in );
     filter_chain_Delete( test_chain );
+
     msg_Dbg( p_obj, "Filter chain testing done, input chroma %4.4s seems to be %s for transcode",
                      (char *)&p_dec->fmt_out.video.i_chroma,
                      chain_works == 0 ? "possible" : "not possible");
@@ -179,6 +180,71 @@ static picture_t *transcode_dequeue_all_pics( sout_stream_id_sys_t *id )
     return p_pics;
 }
 
+static int transcode_video_encoder_test( sout_stream_t *p_stream,
+                                         const es_format_t *p_dec_fmtin,
+                                         vlc_fourcc_t i_codec_in,
+                                         int i_threads,
+                                         const 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->i_threads = i_threads;
+    p_encoder->p_cfg = p_cfg;
+
+    es_format_Init( &p_encoder->fmt_in, VIDEO_ES, i_codec_in );
+    es_format_Copy( &p_encoder->fmt_out, p_enc_fmtout );
+
+    const video_format_t *p_dec_in = &p_dec_fmtin->video;
+    video_format_t *p_vfmt_in = &p_encoder->fmt_in.video;
+    video_format_t *p_vfmt_out = &p_encoder->fmt_out.video;
+
+    p_vfmt_in->i_chroma = i_codec_in;
+
+    /* The dimensions will be set properly later on.
+     * Just put sensible values so we can test an encoder is available. */
+    p_vfmt_in->i_width = FIRSTVALID( p_vfmt_out->i_width, p_dec_in->i_width, 16 ) & ~1;
+    p_vfmt_in->i_height = FIRSTVALID( p_vfmt_out->i_height, p_dec_in->i_height, 16 ) & ~1;
+    p_vfmt_in->i_visible_width = FIRSTVALID( p_vfmt_out->i_visible_width,
+                                             p_dec_in->i_visible_width, p_vfmt_in->i_width ) & ~1;
+    p_vfmt_in->i_visible_height = FIRSTVALID( p_vfmt_out->i_visible_height,
+                                              p_dec_in->i_visible_height, p_vfmt_in->i_height ) & ~1;
+    p_vfmt_in->i_frame_rate = ENC_FRAMERATE;
+    p_vfmt_in->i_frame_rate_base = ENC_FRAMERATE_BASE;
+
+    module_t *p_module = module_need( p_encoder, "encoder", p_sys->psz_venc, true );
+    if( !p_module )
+    {
+        msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s). "
+                           "Take a look few lines earlier to see possible reason.",
+                 p_sys->psz_venc ? p_sys->psz_venc : "any", (char *)&p_sys->i_vcodec );
+    }
+    else
+    {
+        /* Close the encoder.
+         * We'll open it only when we have the first frame. */
+        module_unneed( p_encoder, p_module );
+    }
+
+    if( likely(!p_encoder->fmt_in.video.i_chroma) ) /* always missing, and required by filter chain */
+        p_encoder->fmt_in.video.i_chroma = p_encoder->fmt_in.i_codec;
+
+    /* output 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 int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
@@ -219,59 +285,23 @@ static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_sys_t *i
     /* 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 );
-
-    /* The dimensions will be set properly later on.
-     * Just put sensible values so we can test an encoder is available. */
-    id->p_encoder->fmt_in.video.i_width =
-        id->p_encoder->fmt_out.video.i_width
-          ? id->p_encoder->fmt_out.video.i_width
-          : id->p_decoder->fmt_in.video.i_width
-            ? id->p_decoder->fmt_in.video.i_width : 16;
-    id->p_encoder->fmt_in.video.i_height =
-        id->p_encoder->fmt_out.video.i_height
-          ? id->p_encoder->fmt_out.video.i_height
-          : id->p_decoder->fmt_in.video.i_height
-            ? id->p_decoder->fmt_in.video.i_height : 16;
-    id->p_encoder->fmt_in.video.i_visible_width =
-        id->p_encoder->fmt_out.video.i_visible_width
-          ? id->p_encoder->fmt_out.video.i_visible_width
-          : id->p_decoder->fmt_in.video.i_visible_width
-            ? id->p_decoder->fmt_in.video.i_visible_width : id->p_encoder->fmt_in.video.i_width;
-    id->p_encoder->fmt_in.video.i_visible_height =
-        id->p_encoder->fmt_out.video.i_visible_height
-          ? id->p_encoder->fmt_out.video.i_visible_height
-          : id->p_decoder->fmt_in.video.i_visible_height
-            ? id->p_decoder->fmt_in.video.i_visible_height : id->p_encoder->fmt_in.video.i_height;
-    /* The same goes with frame rate. Some encoders need it to be initialized */
-    id->p_encoder->fmt_in.video.i_frame_rate = ENC_FRAMERATE;
-    id->p_encoder->fmt_in.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
+    /* 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 );
 
     id->p_encoder->i_threads = p_sys->i_threads;
     id->p_encoder->p_cfg = p_sys->p_video_cfg;
 
-    id->p_encoder->p_module =
-        module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
-    if( !id->p_encoder->p_module )
-    {
-        msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
-                 p_sys->psz_venc ? p_sys->psz_venc : "any",
-                 (char *)&p_sys->i_vcodec );
-        module_unneed( id->p_decoder, id->p_decoder->p_module );
-        id->p_decoder->p_module = 0;
+    if( transcode_video_encoder_test( p_stream, &id->p_decoder->fmt_in,
+                                                id->p_decoder->fmt_out.i_codec,
+                                                p_sys->i_threads,
+                                                p_sys->p_video_cfg,
+                                                &id->p_encoder->fmt_out,
+                                                &id->encoder_tested_fmt_in ) )
         return VLC_EGENERIC;
-    }
 
-    /* Close the encoder.
-     * We'll open it only when we have the first frame. */
-    module_unneed( id->p_encoder, id->p_encoder->p_module );
-    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;
-    }
-    id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
-    id->p_encoder->p_module = NULL;
+    /* Will use this format as encoder input for now */
+    es_format_Copy( &id->p_encoder->fmt_in, &id->encoder_tested_fmt_in );
 
     if( p_sys->i_threads <= 0 )
         return VLC_SUCCESS;
@@ -301,6 +331,7 @@ static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_sys_t *i
         id->p_decoder->p_module = NULL;
         return VLC_EGENERIC;
     }
+
     return VLC_SUCCESS;
 }
 
@@ -538,9 +569,9 @@ static void transcode_video_sar_apply( const video_format_t *p_src,
     }
 }
 
-static void transcode_video_encoder_init( sout_stream_t *p_stream,
-                                          sout_stream_id_sys_t *id,
-                                          picture_t *p_pic )
+static void transcode_video_encoder_configure( sout_stream_t *p_stream,
+                                               sout_stream_id_sys_t *id,
+                                               picture_t *p_pic )
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
     const video_format_t *p_src = filtered_video_format( id, p_pic );
@@ -549,6 +580,19 @@ static void transcode_video_encoder_init( sout_stream_t *p_stream,
     video_format_t *p_enc_in = &id->p_encoder->fmt_in.video;
     video_format_t *p_enc_out = &id->p_encoder->fmt_out.video;
 
+    /* Complete destination format */
+    id->p_encoder->fmt_out.i_codec = p_enc_out->i_chroma = p_sys->i_vcodec;
+    id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
+    p_enc_out->i_width = p_enc_out->i_visible_width  = p_sys->i_width & ~1;
+    p_enc_out->i_height = p_enc_out->i_visible_height = p_sys->i_height & ~1;
+    p_enc_out->i_sar_num = p_enc_out->i_sar_den = 0;
+    if( p_sys->fps_num )
+    {
+        p_enc_in->i_frame_rate = p_enc_out->i_frame_rate = p_sys->fps_num;
+        p_enc_in->i_frame_rate_base = p_enc_out->i_frame_rate_base = __MAX(p_sys->fps_den, 1);
+    }
+
+    /* Complete source format */
     p_enc_in->orientation = p_enc_out->orientation = p_dec_in->orientation;
     p_enc_in->i_chroma = id->p_encoder->fmt_in.i_codec;
 
@@ -650,6 +694,8 @@ void transcode_video_close( sout_stream_t *p_stream,
     if( id->p_encoder->p_module )
         module_unneed( id->p_encoder, id->p_encoder->p_module );
 
+    es_format_Clean( &id->encoder_tested_fmt_in );
+
     /* Close filters */
     if( id->p_f_chain )
         filter_chain_Delete( id->p_f_chain );
@@ -727,6 +773,9 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
     sout_stream_sys_t *p_sys = p_stream->p_sys;
     *out = NULL;
 
+    if( id->p_encoder->p_module == NULL && !id->p_encoder->fmt_in.i_codec )
+        es_format_Copy( &id->p_encoder->fmt_in, &id->encoder_tested_fmt_in );
+
     int ret = id->p_decoder->pf_decode( id->p_decoder, in );
     if( ret != VLCDEC_SUCCESS )
         return VLC_EGENERIC;
@@ -765,12 +814,7 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
                 filter_chain_Delete( id->p_uf_chain );
             id->p_uf_chain = NULL;
 
-            /* Reinitialize filters */
-            id->p_encoder->fmt_out.video.i_visible_width  = p_sys->i_width & ~1;
-            id->p_encoder->fmt_out.video.i_visible_height = p_sys->i_height & ~1;
-            id->p_encoder->fmt_out.video.i_sar_num = id->p_encoder->fmt_out.video.i_sar_den = 0;
-
-            transcode_video_encoder_init( p_stream, id, p_pic );
+            transcode_video_encoder_configure( p_stream, id, p_pic );
             transcode_video_filter_init( p_stream, id );
             if( conversion_video_filter_append( id, p_pic ) != VLC_SUCCESS )
                 goto error;
@@ -786,7 +830,7 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
                 filter_chain_Delete( id->p_uf_chain );
             id->p_f_chain = id->p_uf_chain = NULL;
 
-            transcode_video_encoder_init( p_stream, id, p_pic );
+            transcode_video_encoder_configure( p_stream, id, p_pic );
             transcode_video_filter_init( p_stream, id );
             if( conversion_video_filter_append( id, p_pic ) != VLC_SUCCESS )
                 goto error;
@@ -889,12 +933,6 @@ bool transcode_video_add( sout_stream_t *p_stream, const es_format_t *p_fmt,
     id->fifo.pic.first = NULL;
     id->fifo.pic.last = &id->fifo.pic.first;
 
-    /* Complete destination format */
-    id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
-    id->p_encoder->fmt_out.video.i_visible_width  = p_sys->i_width & ~1;
-    id->p_encoder->fmt_out.video.i_visible_height = p_sys->i_height & ~1;
-    id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
-
     /* Build decoder -> filter -> encoder chain */
     if( transcode_video_new( p_stream, id ) )
     {
@@ -906,12 +944,6 @@ bool transcode_video_add( sout_stream_t *p_stream, const es_format_t *p_fmt,
      * all the characteristics of the decoded stream yet */
     id->b_transcode = true;
 
-    if( p_sys->fps_num )
-    {
-        id->p_encoder->fmt_in.video.i_frame_rate = id->p_encoder->fmt_out.video.i_frame_rate = (p_sys->fps_num );
-        id->p_encoder->fmt_in.video.i_frame_rate_base = id->p_encoder->fmt_out.video.i_frame_rate_base = (p_sys->fps_den ? p_sys->fps_den : 1);
-    }
-
     return true;
 }
 



More information about the vlc-commits mailing list