Browse Source
Signed-off-by: Thomas Guillem <thomas@gllm.fr> Signed-off-by: Hugo Beauzée-Luyssen <hugo@beauzee.fr>pull/83/head
committed by
Thomas Guillem
5 changed files with 385 additions and 272 deletions
@ -0,0 +1,285 @@ |
|||
/*****************************************************************************
|
|||
* renderer_common.cpp : renderer helper functions |
|||
***************************************************************************** |
|||
* Copyright © 2014-2018 VideoLAN |
|||
* |
|||
* Authors: Adrien Maglo <magsoft@videolan.org> |
|||
* Jean-Baptiste Kempf <jb@videolan.org> |
|||
* Steve Lhomme <robux4@videolabs.io> |
|||
* Shaleen Jain <shaleen@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 |
|||
@ -0,0 +1,85 @@ |
|||
/*****************************************************************************
|
|||
* renderer_common.hpp : renderer helper functions |
|||
***************************************************************************** |
|||
* Copyright © 2014-2018 VideoLAN |
|||
* |
|||
* Authors: Adrien Maglo <magsoft@videolan.org> |
|||
* Jean-Baptiste Kempf <jb@videolan.org> |
|||
* Steve Lhomme <robux4@videolabs.io> |
|||
* Shaleen Jain <shaleen@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 */ |
|||
Loading…
Reference in new issue