[vlc-devel] [PATCH 1/4] chromecast: refactor out encoder option functions

Shaleen Jain shaleen at jain.sh
Wed Jan 9 16:10:37 CET 2019


---
 modules/stream_out/Makefile.am         |   2 +
 modules/stream_out/chromecast/cast.cpp | 284 ++----------------------
 modules/stream_out/renderer_common.cpp | 285 +++++++++++++++++++++++++
 modules/stream_out/renderer_common.hpp |  85 ++++++++
 po/POTFILES.in                         |   1 +
 5 files changed, 385 insertions(+), 272 deletions(-)
 create mode 100644 modules/stream_out/renderer_common.cpp
 create mode 100644 modules/stream_out/renderer_common.hpp

diff --git a/modules/stream_out/Makefile.am b/modules/stream_out/Makefile.am
index 6bfc38fff2..dfb262c467 100644
--- a/modules/stream_out/Makefile.am
+++ b/modules/stream_out/Makefile.am
@@ -107,6 +107,8 @@ libdemux_chromecast_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -Istream_out/chromecast
 
 libstream_out_chromecast_plugin_la_SOURCES = stream_out/chromecast/cast.cpp stream_out/chromecast/chromecast.h \
                                              stream_out/chromecast/cast_channel.proto \
+                                             stream_out/renderer_common.hpp \
+                                             stream_out/renderer_common.cpp \
                                              stream_out/chromecast/chromecast_common.h stream_out/chromecast/chromecast_ctrl.cpp \
                                              misc/webservices/json.h misc/webservices/json.c stream_out/chromecast/chromecast_communication.cpp
 nodist_libstream_out_chromecast_plugin_la_SOURCES = stream_out/chromecast/cast_channel.pb.cc
diff --git a/modules/stream_out/chromecast/cast.cpp b/modules/stream_out/chromecast/cast.cpp
index 7026eb1a95..5eaee3c4d7 100644
--- a/modules/stream_out/chromecast/cast.cpp
+++ b/modules/stream_out/chromecast/cast.cpp
@@ -30,6 +30,7 @@
 # include "config.h"
 #endif
 
+#include "../renderer_common.hpp"
 #include "chromecast.h"
 #include <vlc_dialog.h>
 
@@ -157,10 +158,7 @@ struct sout_stream_sys_t
     unsigned int                       spu_streams_count;
 
 private:
-    std::string GetVencOption( sout_stream_t *, vlc_fourcc_t *,
-                               const video_format_t *, int );
     std::string GetAcodecOption( sout_stream_t *, vlc_fourcc_t *, const audio_format_t *, int );
-    std::string GetVcodecOption( sout_stream_t *, vlc_fourcc_t *, const video_format_t *, int );
     bool UpdateOutput( sout_stream_t * );
 };
 
@@ -199,39 +197,6 @@ static const char *const ppsz_sout_options[] = {
 #define HTTP_PORT_TEXT N_("HTTP port")
 #define HTTP_PORT_LONGTEXT N_("This sets the HTTP port of the local server " \
                               "used to stream the media to the Chromecast.")
-#define PERF_TEXT N_( "Performance warning" )
-#define PERF_LONGTEXT N_( "Display a performance warning when transcoding" )
-#define AUDIO_PASSTHROUGH_TEXT N_( "Enable Audio passthrough" )
-#define AUDIO_PASSTHROUGH_LONGTEXT N_( "Disable if your receiver does not support Dolby®." )
-
-enum {
-    CONVERSION_QUALITY_HIGH = 0,
-    CONVERSION_QUALITY_MEDIUM = 1,
-    CONVERSION_QUALITY_LOW = 2,
-    CONVERSION_QUALITY_LOWCPU = 3,
-};
-
-#if defined (__ANDROID__) || defined (__arm__) || (defined (TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
-# define CONVERSION_QUALITY_DEFAULT CONVERSION_QUALITY_LOW
-#else
-# define CONVERSION_QUALITY_DEFAULT CONVERSION_QUALITY_MEDIUM
-#endif
-
-static const int conversion_quality_list[] = {
-    CONVERSION_QUALITY_HIGH,
-    CONVERSION_QUALITY_MEDIUM,
-    CONVERSION_QUALITY_LOW,
-    CONVERSION_QUALITY_LOWCPU,
-};
-static const char *const conversion_quality_list_text[] = {
-    N_( "High (high quality and high bandwidth)" ),
-    N_( "Medium (medium quality and medium bandwidth)" ),
-    N_( "Low (low quality and low bandwidth)" ),
-    N_( "Low CPU (low quality but high bandwidth)" ),
-};
-
-#define CONVERSION_QUALITY_TEXT N_( "Conversion quality" )
-#define CONVERSION_QUALITY_LONGTEXT N_( "Change this option to increase conversion speed or quality." )
 
 #define IP_ADDR_TEXT N_("IP Address")
 #define IP_ADDR_LONGTEXT N_("IP Address of the Chromecast.")
@@ -263,12 +228,7 @@ vlc_module_begin ()
     add_integer(SOUT_CFG_PREFIX "http-port", HTTP_PORT, HTTP_PORT_TEXT, HTTP_PORT_LONGTEXT, false)
     add_obsolete_string(SOUT_CFG_PREFIX "mux")
     add_obsolete_string(SOUT_CFG_PREFIX "mime")
-    add_integer(SOUT_CFG_PREFIX "show-perf-warning", 1, PERF_TEXT, PERF_LONGTEXT, true )
-        change_private()
-    add_bool(SOUT_CFG_PREFIX "audio-passthrough", false, AUDIO_PASSTHROUGH_TEXT, AUDIO_PASSTHROUGH_LONGTEXT, false )
-    add_integer(SOUT_CFG_PREFIX "conversion-quality", CONVERSION_QUALITY_DEFAULT,
-                CONVERSION_QUALITY_TEXT, CONVERSION_QUALITY_LONGTEXT, false );
-        change_integer_list(conversion_quality_list, conversion_quality_list_text)
+    add_renderer_opts(SOUT_CFG_PREFIX)
 
     add_submodule()
         /* sout proxy that start the cc input when all streams are loaded */
@@ -927,231 +887,6 @@ bool sout_stream_sys_t::transcodingCanFallback() const
     return transcoding_state != (TRANSCODING_VIDEO|TRANSCODING_AUDIO);
 }
 
-static std::string GetVencVPXOption( sout_stream_t * /* p_stream */,
-                                      const video_format_t * /* p_vid */,
-                                      int /* i_quality */ )
-{
-    return "venc=vpx{quality-mode=1}";
-}
-
-static std::string GetVencQSVH264Option( sout_stream_t * /* p_stream */,
-                                         const video_format_t * /* p_vid */,
-                                         int i_quality )
-{
-    std::stringstream ssout;
-    static const char video_target_usage_quality[]  = "quality";
-    static const char video_target_usage_balanced[] = "balanced";
-    static const char video_target_usage_speed[]    = "speed";
-    static const char video_bitrate_high[] = "vb=8000000";
-    static const char video_bitrate_low[]  = "vb=3000000";
-    const char *psz_video_target_usage;
-    const char *psz_video_bitrate;
-
-    switch ( i_quality )
-    {
-        case CONVERSION_QUALITY_HIGH:
-            psz_video_target_usage = video_target_usage_quality;
-            psz_video_bitrate = video_bitrate_high;
-            break;
-        case CONVERSION_QUALITY_MEDIUM:
-            psz_video_target_usage = video_target_usage_balanced;
-            psz_video_bitrate = video_bitrate_high;
-            break;
-        case CONVERSION_QUALITY_LOW:
-            psz_video_target_usage = video_target_usage_balanced;
-            psz_video_bitrate = video_bitrate_low;
-            break;
-        default:
-        case CONVERSION_QUALITY_LOWCPU:
-            psz_video_target_usage = video_target_usage_speed;
-            psz_video_bitrate = video_bitrate_low;
-            break;
-    }
-
-    ssout << "venc=qsv{target-usage=" << psz_video_target_usage <<
-             "}," << psz_video_bitrate;
-    return ssout.str();
-}
-
-static std::string GetVencX264Option( sout_stream_t * /* p_stream */,
-                                      const video_format_t *p_vid,
-                                      int i_quality )
-{
-    std::stringstream ssout;
-    static const char video_x264_preset_veryfast[] = "veryfast";
-    static const char video_x264_preset_ultrafast[] = "ultrafast";
-    const char *psz_video_x264_preset;
-    unsigned i_video_x264_crf_hd, i_video_x264_crf_720p;
-
-    switch ( i_quality )
-    {
-        case CONVERSION_QUALITY_HIGH:
-            i_video_x264_crf_hd = i_video_x264_crf_720p = 21;
-            psz_video_x264_preset = video_x264_preset_veryfast;
-            break;
-        case CONVERSION_QUALITY_MEDIUM:
-            i_video_x264_crf_hd = 23;
-            i_video_x264_crf_720p = 21;
-            psz_video_x264_preset = video_x264_preset_veryfast;
-            break;
-        case CONVERSION_QUALITY_LOW:
-            i_video_x264_crf_hd = i_video_x264_crf_720p = 23;
-            psz_video_x264_preset = video_x264_preset_veryfast;
-            break;
-        default:
-        case CONVERSION_QUALITY_LOWCPU:
-            i_video_x264_crf_hd = i_video_x264_crf_720p = 23;
-            psz_video_x264_preset = video_x264_preset_ultrafast;
-            break;
-    }
-
-    const bool b_hdres = p_vid->i_height == 0 || p_vid->i_height >= 800;
-    unsigned i_video_x264_crf = b_hdres ? i_video_x264_crf_hd : i_video_x264_crf_720p;
-
-    ssout << "venc=x264{preset=" << psz_video_x264_preset
-          << ",crf=" << i_video_x264_crf << "}";
-    return ssout.str();
-}
-
-#ifdef __APPLE__
-static std::string GetVencAvcodecVTOption( sout_stream_t * /* p_stream */,
-                                           const video_format_t * p_vid,
-                                           int i_quality )
-{
-    std::stringstream ssout;
-    ssout << "venc=avcodec{codec=h264_videotoolbox,options{realtime=1}}";
-    switch( i_quality )
-    {
-        /* Here, performances issues won't come from videotoolbox but from
-         * some old chromecast devices */
-
-        case CONVERSION_QUALITY_HIGH:
-            break;
-        case CONVERSION_QUALITY_MEDIUM:
-            ssout << ",vb=8000000";
-            break;
-        case CONVERSION_QUALITY_LOW:
-        case CONVERSION_QUALITY_LOWCPU:
-            ssout << ",vb=3000000";
-            break;
-    }
-
-    return ssout.str();
-}
-#endif
-
-static struct
-{
-    vlc_fourcc_t fcc;
-    std::string (*get_opt)( sout_stream_t *, const video_format_t *, int);
-} venc_opt_list[] = {
-#ifdef __APPLE__
-    { .fcc = VLC_CODEC_H264, .get_opt = GetVencAvcodecVTOption },
-#endif
-    { .fcc = VLC_CODEC_H264, .get_opt = GetVencQSVH264Option },
-    { .fcc = VLC_CODEC_H264, .get_opt = GetVencX264Option },
-    { .fcc = VLC_CODEC_VP8,  .get_opt = GetVencVPXOption },
-    { .fcc = VLC_CODEC_H264, .get_opt = NULL },
-};
-
-std::string
-sout_stream_sys_t::GetVencOption( sout_stream_t *p_stream, vlc_fourcc_t *p_codec_video,
-                                  const video_format_t *p_vid, int i_quality )
-{
-    for( size_t i = (venc_opt_idx == -1 ? 0 : venc_opt_idx);
-         i < ARRAY_SIZE(venc_opt_list); ++i )
-    {
-        std::stringstream ssout, ssvenc;
-        char fourcc[5];
-        ssvenc << "vcodec=";
-        vlc_fourcc_to_char( venc_opt_list[i].fcc, fourcc );
-        fourcc[4] = '\0';
-        ssvenc << fourcc << ',';
-
-        if( venc_opt_list[i].get_opt != NULL )
-            ssvenc << venc_opt_list[i].get_opt( p_stream, p_vid, i_quality ) << ',';
-
-        if( venc_opt_list[i].get_opt == NULL
-         || ( venc_opt_idx != -1 && (unsigned) venc_opt_idx == i) )
-        {
-            venc_opt_idx = i;
-            *p_codec_video = venc_opt_list[i].fcc;
-            return ssvenc.str();
-        }
-
-        /* Test if a module can encode with the specified options / fmt_video. */
-        ssout << "transcode{" << ssvenc.str() << "}:dummy";
-
-        sout_stream_t *p_sout_test =
-            sout_StreamChainNew( p_stream->p_sout, ssout.str().c_str(), NULL, NULL );
-
-        if( p_sout_test != NULL )
-        {
-            p_sout_test->obj.flags |= OBJECT_FLAGS_QUIET|OBJECT_FLAGS_NOINTERACT;
-
-            es_format_t fmt;
-            es_format_InitFromVideo( &fmt, p_vid );
-            fmt.i_codec = fmt.video.i_chroma = VLC_CODEC_I420;
-
-            /* Test the maximum size/fps we will encode */
-            fmt.video.i_visible_width = fmt.video.i_width = 1920;
-            fmt.video.i_visible_height = fmt.video.i_height = 1080;
-            fmt.video.i_frame_rate = 30;
-            fmt.video.i_frame_rate_base = 1;
-
-            void *id = sout_StreamIdAdd( p_sout_test, &fmt );
-
-            es_format_Clean( &fmt );
-            const bool success = id != NULL;
-
-            if( id )
-                sout_StreamIdDel( p_sout_test, id );
-            sout_StreamChainDelete( p_sout_test, NULL );
-
-            if( success )
-            {
-                venc_opt_idx = i;
-                *p_codec_video = venc_opt_list[i].fcc;
-                return ssvenc.str();
-            }
-        }
-    }
-    vlc_assert_unreachable();
-}
-
-std::string
-sout_stream_sys_t::GetVcodecOption( sout_stream_t *p_stream, vlc_fourcc_t *p_codec_video,
-                                    const video_format_t *p_vid, int i_quality )
-{
-    std::stringstream ssout;
-    static const char video_maxres_hd[] = "maxwidth=1920,maxheight=1080";
-    static const char video_maxres_720p[] = "maxwidth=1280,maxheight=720";
-
-    ssout << GetVencOption( p_stream, p_codec_video, p_vid, i_quality );
-
-    switch ( i_quality )
-    {
-        case CONVERSION_QUALITY_HIGH:
-        case CONVERSION_QUALITY_MEDIUM:
-            ssout << ( ( p_vid->i_width > 1920 ) ? "width=1920," : "" ) << video_maxres_hd << ',';
-            break;
-        default:
-            ssout << ( ( p_vid->i_width > 1280 ) ? "width=1280," : "" ) << video_maxres_720p << ',';
-    }
-
-    if( p_vid->i_frame_rate == 0 || p_vid->i_frame_rate_base == 0
-     || ( p_vid->i_frame_rate / p_vid->i_frame_rate_base ) > 30 )
-    {
-        /* Even force 24fps if the frame rate is unknown */
-        msg_Warn( p_stream, "lowering frame rate to 24fps" );
-        ssout << "fps=24,";
-    }
-
-    msg_Dbg( p_stream, "Converting video to %.4s", (const char*)p_codec_video );
-
-    return ssout.str();
-}
-
 std::string
 sout_stream_sys_t::GetAcodecOption( sout_stream_t *p_stream, vlc_fourcc_t *p_codec_audio,
                                     const audio_format_t *p_aud, int i_quality )
@@ -1291,7 +1026,7 @@ bool sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )
     if ( !canRemux )
     {
         if ( !perf_warning_shown && i_codec_video == 0 && p_original_video
-          && var_InheritInteger( p_stream, SOUT_CFG_PREFIX "show-perf-warning" ) )
+          && var_InheritInteger( p_stream, RENDERER_CFG_PREFIX "show-perf-warning" ) )
         {
             int res = vlc_dialog_wait_question( p_stream,
                           VLC_DIALOG_QUESTION_WARNING,
@@ -1304,7 +1039,7 @@ bool sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )
                  return false;
             perf_warning_shown = true;
             if ( res == 2 )
-                config_PutInt(SOUT_CFG_PREFIX "show-perf-warning", 0 );
+                config_PutInt(RENDERER_CFG_PREFIX "show-perf-warning", 0 );
         }
 
         const int i_quality = var_InheritInteger( p_stream, SOUT_CFG_PREFIX "conversion-quality" );
@@ -1319,9 +1054,14 @@ bool sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )
         }
         if ( i_codec_video == 0 && p_original_video )
         {
-            ssout << GetVcodecOption( p_stream, &i_codec_video,
-                                      &p_original_video->video, i_quality );
-            new_transcoding_state |= TRANSCODING_VIDEO;
+            try {
+                ssout << vlc_sout_renderer_GetVcodecOption( p_stream,
+                                        { VLC_CODEC_H264, VLC_CODEC_VP8 },
+                                        &p_original_video->video, i_quality );
+                new_transcoding_state |= TRANSCODING_VIDEO;
+            } catch(const std::exception& e) {
+                return false;
+            }
         }
         if ( p_original_spu )
             ssout << "soverlay,";
diff --git a/modules/stream_out/renderer_common.cpp b/modules/stream_out/renderer_common.cpp
new file mode 100644
index 0000000000..1555d7bb46
--- /dev/null
+++ b/modules/stream_out/renderer_common.cpp
@@ -0,0 +1,285 @@
+/*****************************************************************************
+ * renderer_common.cpp : renderer helper functions
+ *****************************************************************************
+ * Copyright © 2014-2018 VideoLAN
+ *
+ * Authors: Adrien Maglo <magsoft at videolan.org>
+ *          Jean-Baptiste Kempf <jb at videolan.org>
+ *          Steve Lhomme <robux4 at videolabs.io>
+ *          Shaleen Jain <shaleen at jain.sh>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <map>
+#include <sstream>
+
+#include "renderer_common.hpp"
+
+std::string
+GetVencOption( sout_stream_t *p_stream, vlc_fourcc_t *p_codec_video,
+        const video_format_t *p_vid, int i_quality );
+
+std::string GetVencVPXOption( sout_stream_t * /* p_stream */,
+                                      const video_format_t * /* p_vid */,
+                                      int /* i_quality */ );
+
+std::string GetVencQSVH264Option( sout_stream_t * /* p_stream */,
+                                         const video_format_t * /* p_vid */,
+                                         int i_quality );
+
+std::string GetVencX264Option( sout_stream_t * /* p_stream */,
+                                      const video_format_t *p_vid,
+                                      int i_quality );
+#ifdef __APPLE__
+std::string GetVencAvcodecVTOption( sout_stream_t * /* p_stream */,
+                                           const video_format_t * p_vid,
+                                           int i_quality );
+#endif
+
+struct venc_options
+{
+    std::string (*get_opt)( sout_stream_t *, const video_format_t *, int);
+};
+
+std::map<vlc_fourcc_t, std::vector<venc_options>> opts = {
+    {
+        VLC_CODEC_H264,
+        {
+        #ifdef __APPLE__
+            { GetVencAvcodecVTOption },
+        #endif
+            { GetVencQSVH264Option },
+            { GetVencX264Option },
+            { NULL },
+        }
+    },
+    {
+        VLC_CODEC_VP8,
+        {
+            { GetVencVPXOption }
+        }
+    },
+};
+
+std::string
+GetVencOption( sout_stream_t *p_stream, std::vector<vlc_fourcc_t> codecs,
+        const video_format_t *p_vid, int i_quality )
+{
+    for (vlc_fourcc_t codec : codecs) {
+        auto opt = opts.find(codec);
+        if (opt == opts.end())
+            break;
+        for (const auto& venc_opt : opt->second)
+        {
+            std::stringstream ssout, ssvenc;
+            char fourcc[5];
+            ssvenc << "vcodec=";
+            vlc_fourcc_to_char( codec, fourcc );
+            fourcc[4] = '\0';
+            ssvenc << fourcc << ',';
+
+            if( venc_opt.get_opt != NULL )
+                ssvenc << venc_opt.get_opt( p_stream, p_vid, i_quality ) << ',';
+
+            /* Test if a module can encode with the specified options / fmt_video. */
+            ssout << "transcode{" << ssvenc.str() << "}:dummy";
+
+            sout_stream_t *p_sout_test =
+                sout_StreamChainNew( p_stream->p_sout, ssout.str().c_str(), NULL, NULL );
+
+            if( p_sout_test != NULL )
+            {
+                p_sout_test->obj.flags |= OBJECT_FLAGS_QUIET|OBJECT_FLAGS_NOINTERACT;
+
+                es_format_t fmt;
+                es_format_InitFromVideo( &fmt, p_vid );
+                fmt.i_codec = fmt.video.i_chroma = VLC_CODEC_I420;
+
+                /* Test the maximum size/fps we will encode */
+                fmt.video.i_visible_width = fmt.video.i_width = 1920;
+                fmt.video.i_visible_height = fmt.video.i_height = 1080;
+                fmt.video.i_frame_rate = 30;
+                fmt.video.i_frame_rate_base = 1;
+
+                void *id = sout_StreamIdAdd( p_sout_test, &fmt );
+
+                es_format_Clean( &fmt );
+                const bool success = id != NULL;
+
+                if( id )
+                    sout_StreamIdDel( p_sout_test, id );
+                sout_StreamChainDelete( p_sout_test, NULL );
+
+                if( success )
+                {
+                    msg_Dbg( p_stream, "Converting video to %.4s", (const char*)&codec );
+                    return ssvenc.str();
+                }
+            }
+        }
+    }
+
+    throw std::domain_error("No configured encoder found");
+}
+
+std::string
+vlc_sout_renderer_GetVcodecOption(sout_stream_t *p_stream,
+        std::vector<vlc_fourcc_t> codecs, const video_format_t *p_vid, int i_quality)
+{
+    std::stringstream ssout;
+    static const char video_maxres_hd[] = "maxwidth=1920,maxheight=1080";
+    static const char video_maxres_720p[] = "maxwidth=1280,maxheight=720";
+
+    ssout << GetVencOption( p_stream, codecs, p_vid, i_quality );
+
+    switch ( i_quality )
+    {
+        case CONVERSION_QUALITY_HIGH:
+        case CONVERSION_QUALITY_MEDIUM:
+            ssout << ( ( p_vid->i_width > 1920 ) ? "width=1920," : "" ) << video_maxres_hd << ',';
+            break;
+        default:
+            ssout << ( ( p_vid->i_width > 1280 ) ? "width=1280," : "" ) << video_maxres_720p << ',';
+    }
+
+    if( p_vid->i_frame_rate == 0 || p_vid->i_frame_rate_base == 0
+     || ( p_vid->i_frame_rate / p_vid->i_frame_rate_base ) > 30 )
+    {
+        /* Even force 24fps if the frame rate is unknown */
+        msg_Warn( p_stream, "lowering frame rate to 24fps" );
+        ssout << "fps=24,";
+    }
+
+    return ssout.str();
+}
+
+std::string GetVencVPXOption( sout_stream_t * /* p_stream */,
+                                      const video_format_t * /* p_vid */,
+                                      int /* i_quality */ )
+{
+    return "venc=vpx{quality-mode=1}";
+}
+
+std::string GetVencQSVH264Option( sout_stream_t * /* p_stream */,
+                                         const video_format_t * /* p_vid */,
+                                         int i_quality )
+{
+    std::stringstream ssout;
+    static const char video_target_usage_quality[]  = "quality";
+    static const char video_target_usage_balanced[] = "balanced";
+    static const char video_target_usage_speed[]    = "speed";
+    static const char video_bitrate_high[] = "vb=8000000";
+    static const char video_bitrate_low[]  = "vb=3000000";
+    const char *psz_video_target_usage;
+    const char *psz_video_bitrate;
+
+    switch ( i_quality )
+    {
+        case CONVERSION_QUALITY_HIGH:
+            psz_video_target_usage = video_target_usage_quality;
+            psz_video_bitrate = video_bitrate_high;
+            break;
+        case CONVERSION_QUALITY_MEDIUM:
+            psz_video_target_usage = video_target_usage_balanced;
+            psz_video_bitrate = video_bitrate_high;
+            break;
+        case CONVERSION_QUALITY_LOW:
+            psz_video_target_usage = video_target_usage_balanced;
+            psz_video_bitrate = video_bitrate_low;
+            break;
+        default:
+        case CONVERSION_QUALITY_LOWCPU:
+            psz_video_target_usage = video_target_usage_speed;
+            psz_video_bitrate = video_bitrate_low;
+            break;
+    }
+
+    ssout << "venc=qsv{target-usage=" << psz_video_target_usage <<
+             "}," << psz_video_bitrate;
+    return ssout.str();
+}
+
+std::string GetVencX264Option( sout_stream_t * /* p_stream */,
+                                      const video_format_t *p_vid,
+                                      int i_quality )
+{
+    std::stringstream ssout;
+    static const char video_x264_preset_veryfast[] = "veryfast";
+    static const char video_x264_preset_ultrafast[] = "ultrafast";
+    const char *psz_video_x264_preset;
+    unsigned i_video_x264_crf_hd, i_video_x264_crf_720p;
+
+    switch ( i_quality )
+    {
+        case CONVERSION_QUALITY_HIGH:
+            i_video_x264_crf_hd = i_video_x264_crf_720p = 21;
+            psz_video_x264_preset = video_x264_preset_veryfast;
+            break;
+        case CONVERSION_QUALITY_MEDIUM:
+            i_video_x264_crf_hd = 23;
+            i_video_x264_crf_720p = 21;
+            psz_video_x264_preset = video_x264_preset_veryfast;
+            break;
+        case CONVERSION_QUALITY_LOW:
+            i_video_x264_crf_hd = i_video_x264_crf_720p = 23;
+            psz_video_x264_preset = video_x264_preset_veryfast;
+            break;
+        default:
+        case CONVERSION_QUALITY_LOWCPU:
+            i_video_x264_crf_hd = i_video_x264_crf_720p = 23;
+            psz_video_x264_preset = video_x264_preset_ultrafast;
+            break;
+    }
+
+    const bool b_hdres = p_vid->i_height == 0 || p_vid->i_height >= 800;
+    unsigned i_video_x264_crf = b_hdres ? i_video_x264_crf_hd : i_video_x264_crf_720p;
+
+    ssout << "venc=x264{preset=" << psz_video_x264_preset
+          << ",crf=" << i_video_x264_crf << "}";
+    return ssout.str();
+}
+
+#ifdef __APPLE__
+std::string GetVencAvcodecVTOption( sout_stream_t * /* p_stream */,
+                                           const video_format_t * p_vid,
+                                           int i_quality )
+{
+    std::stringstream ssout;
+    ssout << "venc=avcodec{codec=h264_videotoolbox,options{realtime=1}}";
+    switch( i_quality )
+    {
+        /* Here, performances issues won't come from videotoolbox but from
+         * some old chromecast devices */
+
+        case CONVERSION_QUALITY_HIGH:
+            break;
+        case CONVERSION_QUALITY_MEDIUM:
+            ssout << ",vb=8000000";
+            break;
+        case CONVERSION_QUALITY_LOW:
+        case CONVERSION_QUALITY_LOWCPU:
+            ssout << ",vb=3000000";
+            break;
+    }
+
+    return ssout.str();
+}
+#endif
diff --git a/modules/stream_out/renderer_common.hpp b/modules/stream_out/renderer_common.hpp
new file mode 100644
index 0000000000..7a440a6674
--- /dev/null
+++ b/modules/stream_out/renderer_common.hpp
@@ -0,0 +1,85 @@
+/*****************************************************************************
+ * renderer_common.hpp : renderer helper functions
+ *****************************************************************************
+ * Copyright © 2014-2018 VideoLAN
+ *
+ * Authors: Adrien Maglo <magsoft at videolan.org>
+ *          Jean-Baptiste Kempf <jb at videolan.org>
+ *          Steve Lhomme <robux4 at videolabs.io>
+ *          Shaleen Jain <shaleen at jain.sh>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef RENDERER_COMMON_H
+#define RENDERER_COMMON_H
+
+#include <string>
+#include <vector>
+
+#include <vlc_common.h>
+#include <vlc_sout.h>
+
+#define PERF_TEXT N_( "Performance warning" )
+#define PERF_LONGTEXT N_( "Display a performance warning when transcoding" )
+#define AUDIO_PASSTHROUGH_TEXT N_( "Enable Audio passthrough" )
+#define AUDIO_PASSTHROUGH_LONGTEXT N_( "Disable if your receiver does not support Dolby®." )
+#define CONVERSION_QUALITY_TEXT N_( "Conversion quality" )
+#define CONVERSION_QUALITY_LONGTEXT N_( "Change this option to increase conversion speed or quality." )
+
+#if defined (__ANDROID__) || defined (__arm__) || (defined (TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
+# define CONVERSION_QUALITY_DEFAULT CONVERSION_QUALITY_LOW
+#else
+# define CONVERSION_QUALITY_DEFAULT CONVERSION_QUALITY_MEDIUM
+#endif
+
+#define RENDERER_CFG_PREFIX "sout-renderer-"
+
+#define add_renderer_opts(prefix) \
+    add_integer(RENDERER_CFG_PREFIX "show-perf-warning", 1, \
+            PERF_TEXT, PERF_LONGTEXT, true ) \
+        change_private() \
+    add_bool(prefix "audio-passthrough", false, \
+            AUDIO_PASSTHROUGH_TEXT, AUDIO_PASSTHROUGH_LONGTEXT, false ) \
+    add_integer(prefix "conversion-quality", CONVERSION_QUALITY_DEFAULT, \
+                CONVERSION_QUALITY_TEXT, CONVERSION_QUALITY_LONGTEXT, false ); \
+        change_integer_list(conversion_quality_list, conversion_quality_list_text)
+
+static const char *const conversion_quality_list_text[] = {
+    N_( "High (high quality and high bandwidth)" ),
+    N_( "Medium (medium quality and medium bandwidth)" ),
+    N_( "Low (low quality and low bandwidth)" ),
+    N_( "Low CPU (low quality but high bandwidth)" ),
+};
+
+enum {
+    CONVERSION_QUALITY_HIGH = 0,
+    CONVERSION_QUALITY_MEDIUM = 1,
+    CONVERSION_QUALITY_LOW = 2,
+    CONVERSION_QUALITY_LOWCPU = 3,
+};
+
+static const int conversion_quality_list[] = {
+    CONVERSION_QUALITY_HIGH,
+    CONVERSION_QUALITY_MEDIUM,
+    CONVERSION_QUALITY_LOW,
+    CONVERSION_QUALITY_LOWCPU,
+};
+
+std::string
+vlc_sout_renderer_GetVcodecOption(sout_stream_t *p_stream,
+        std::vector<vlc_fourcc_t> codecs, const video_format_t *p_vid, int i_quality);
+
+#endif /* RENDERER_COMMON_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 85c3e001e1..98655a050b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1076,6 +1076,7 @@ modules/stream_out/es.c
 modules/stream_out/gather.c
 modules/stream_out/mosaic_bridge.c
 modules/stream_out/record.c
+modules/stream_out/renderer_common.hpp
 modules/stream_out/rtcp.c
 modules/stream_out/rtp.c
 modules/stream_out/rtpfmt.c
-- 
2.20.1


More information about the vlc-devel mailing list