[vlc-devel] [PATCH] Add x265 params support to VLC streaming module
Mahesh
mahesh at multicorewareinc.com
Wed Jun 8 13:55:55 CEST 2016
---
modules/codec/Makefile.am | 4 +-
modules/codec/x265.c | 1072 +++++++++++++++++---
.../gui/qt/components/sout/profile_selector.cpp | 20 +-
3 files changed, 975 insertions(+), 121 deletions(-)
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index c0f8d32..94ceaf2 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -450,10 +450,10 @@ endif
### X26x encoders ###
libx265_plugin_la_SOURCES = codec/x265.c
-libx265_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
+libx265_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DMODULE_NAME_IS_x265
libx265_plugin_la_CFLAGS = $(AM_CFLAGS) $(CFLAGS_x265)
libx265_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_x265) -rpath '$(codecdir)'
-libx265_plugin_la_LIBADD = $(LIBS_x265)
+libx265_plugin_la_LIBADD = $(LIBS_x265) $(LIBM)
EXTRA_LTLIBRARIES += libx265_plugin.la
codec_LTLIBRARIES += $(LTLIBx265)
diff --git a/modules/codec/x265.c b/modules/codec/x265.c
index 2fac637..0b76b3f 100644
--- a/modules/codec/x265.c
+++ b/modules/codec/x265.c
@@ -4,6 +4,8 @@
* Copyright (C) 2013 Rafaël Carré
*
* Authors: Rafaël Carré <funman at videolanorg>
+ * Mahesh Pittala <mahesh at multicorewareinc.com>
+ * Gopi Akisetty <gopi.satykrishna at multicorewareinc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +25,7 @@
/*****************************************************************************
* Preamble
*****************************************************************************/
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -30,47 +33,966 @@
#define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
#include <vlc_common.h>
#include <vlc_plugin.h>
-#include <vlc_threads.h>
#include <vlc_sout.h>
#include <vlc_codec.h>
+#include <vlc_charset.h>
+#include <vlc_cpu.h>
+#include <math.h>
+#include <stdio.h>
+#ifdef PTW32_STATIC_LIB
+#include <pthread.h>
+#endif
+#include <assert.h>
#include <x265.h>
+#ifdef MODULE_NAME_IS_x265
+#define SOUT_CFG_PREFIX "sout-x265-"
+#endif
+
+#define INT_MAX 2147483647
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
-static int Open (vlc_object_t *);
-static void Close(vlc_object_t *);
+static int Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
+static void x265_log( void *, int i_level, const char *psz, va_list );
+
+#define LONGTEXT N_( "Please go through x265 readthedocs for full " \
+ "information - https://x265.readthedocs.org/en/default/cli.html " )
+
+/* Frame-type options */
+
+#define KEYINT_TEXT N_("Max intra period in frames")
+
+#define MIN_KEYINT_TEXT N_("Minimum GOP size")
+
+#define OPENGOP_TEXT N_("Enable open GOP, allow I-slices to be non-IDR")
+
+#define SCENE_TEXT N_("Extra I-frames aggressivity")
+
+#define BFRAMES_TEXT N_("Maxinum number of consecutive B-frames")
+
+#define B_ADAPT_TEXT N_("Set the level of effort in determining B frame " \
+ "placement")
+
+#define B_BIAS_TEXT N_("Bias towards B frames in slicetype decision")
+
+#define BPYRAMID_TEXT N_("Use B-frames as references, when possible")
+
+#define REF_TEXT N_("Max number of L0 references to be allowed")
+
+#define FILTER_TEXT N_("Loop filter AlphaC0 and Beta parameters alpha:beta")
+
+#define LEVEL_TEXT N_("HEVC level")
+
+#define PROFILE_TEXT N_("HEVC profile")
+
+#define INTERLACED_TEXT N_("Interlaced mode")
+
+#define INTRAREFRESH_TEXT N_("Enables Periodic Intra Refresh(PIR) instead of" \
+ "keyframe insertion")
+
+#define REPEATHEADERS_TEXT N_("If enabled, x265 will emit VPS, SPS, and PPS " \
+ "headers with every keyframe")
+
+/* Ratecontrol */
+
+#define QP_TEXT N_("Set QP")
+
+#define CRF_TEXT N_("Quality-controlled variable bitrate")
+
+#define BITRATE_TEXT N_("Bitrate")
+
+#define VBV_MAXRATE_TEXT N_("Max local bitrate")
+
+#define VBV_BUFSIZE_TEXT N_("VBV buffer")
+
+#define VBV_INIT_TEXT N_("Initial VBV buffer occupancy")
+
+#define AQ_MODE_TEXT N_("Adaptive Quantization operating mode")
+
+#define AQ_STRENGTH_TEXT N_("Adjust the strength of the adaptive " \
+ "quantization offsets")
+
+#define IPRATIO_TEXT N_("QP factor between I and P")
+
+#define PBRATIO_TEXT N_("QP factor between P and B")
+
+#define CHROMAB_QP_OFFSET_TEXT N_("Offset of Cb chroma QP from the luma " \
+ "QP selected by rate control")
+
+#define CHROMAR_QP_OFFSET_TEXT N_("Offset of Cr chroma QP from the luma " \
+ "QP selected by rate contro")
+
+#define PASS_TEXT N_("Enable multi-pass rate control mode")
+
+#define QCOMP_TEXT N_("qComp sets the quantizer curve compression factor")
+
+#define CPLXBLUR_TEXT N_("Reduce fluctuations in QP")
+
+#define QBLUR_TEXT N_("temporally blur complexity")
+
+/* Analysis */
+
+#define WEIGHTB_TEXT N_("Enable weighted prediction in B slices")
+
+#define WEIGHTP_TEXT N_("Enable weighted prediction in P slices")
+
+
+#define ME_TEXT N_("Integer pixel motion estimation method")
+
+#define MERANGE_TEXT N_("Maximum motion vector search range")
+
+#define PSY_RD_TEXT N_("Strength of psychovisual optimization")
+
+#define SUBME_TEXT N_("Amount of subpel refinement to perform")
+
+#define NRINTRA_TEXT N_("Noise reduction")
+
+#define NRINTER_TEXT N_("Noise reduction")
+
+#define TSKIPFAST_TEXT N_("Only evaluate transform skip for NxN intra " \
+ "predictions (4x4 blocks)")
+
+#define CTU_TEXT N_("Maximum CU size (width and height)")
+
+#define MINCUSIZE_TEXT N_("Minimum CU size (width and height)")
+
+#define RCLOOKAHEAD_TEXT N_("Number of frames for slice-type decision" \
+ "lookahead")
+
+#define LIMITREFS_TEXT N_("limit the references analyzed")
+
+#define RECT_TEXT N_("Enable analysis of rectangular motion partitions" \
+ "Nx2N and 2NxN")
+
+#define AMP_TEXT N_("Enable analysis of asymmetric motion partitions " \
+ "(75/25 splits, four directions)")
+
+#define LIMITMODES_TEXT N_("limit-modes will limit modes analyzed for " \
+ "each CU using cost metrics from the 4 sub-CUs")
+
+#define MAXMERGE_TEXT N_("Maximum number of neighbor (spatial and temporal)" \
+ "candidate blocks")
+
+#define EARLYSKIP_TEXT N_("Measure 2Nx2N merge candidates first, if no" \
+ "residual is found, additional modes at that depth are not analysed")
+
+#define FASTINTRA_TEXT N_("Perform an initial scan of every fifth intra")
+
+#define BINTRA_TEXT N_("Evaluation of intra modes in B slices")
+
+#define SAO_TEXT N_("Toggle Sample Adaptive Offset loop filter")
+
+#define SIGNHIDE_TEXT N_("Hide sign bit of one coeff per TU (rdo)")
+
+#define CUTREE_TEXT N_("Enable the use of lookaheads lowres motion" \
+ "vector fields")
+
+#define RD_TEXT N_("Level of RDO in mode decision")
+
+#define RDOQLEVEL_TEXT N_("amount of rate-distortion analysis to use within" \
+ "quantization")
+
+#define TUINTRA_TEXT N_("Limits the number of extra recursion depth which" \
+ "can be attempted for intra coded units")
+
+#define TUINTER_TEXT N_("Limits the number of extra recursion depth which" \
+ "can be attempted for inter coded units")
+
+#define QPSTEP_TEXT N_("The maximum single adjustment in QP allowed")
+
+#define PSYRDOQ_TEXT N_("Influence rate distortion optimized quantization by" \
+ "favoring higher energy in the reconstructed image")
+
+#define FRAMETHREADS_TEXT N_("Number of concurrently encoded frames")
+
+#define PMODE_TEXT N_("Parallel mode decision, or distributed mode analysis")
+
+#define PME_TEXT N_("Parallel motion estimation")
+
+#define QGSIZE_TEXT N_("Minimum CU size at which QP can be adjusted")
+
+
+/* Input/Output */
+
+#define ASM_TEXT N_("CPU optimizations")
+
+#define PSNR_TEXT N_("PSNR computation")
+
+#define SSIM_TEXT N_("SSIM computation")
+
+#define AUD_TEXT N_("Access unit delimiters")
+
+#define LOOKAHEAD_SLICES_TEXT N_("Use multiple worker threads to measure the estimated cost " \
+ "of each frame within the lookahead")
+
+#define HRD_TEXT N_("HRD-timing information")
+
+#define TUNE_TEXT N_("Default tune setting used" )
+
+#define PRESET_TEXT N_("Default preset setting used" )
+
+
+static const char *const enc_me_list[] =
+ { "dia", "hex", "umh", "star", "full" };
+static const char *const enc_me_list_text[] =
+ { N_("dia"), N_("hex"), N_("umh"), N_("star"), N_("full") };
vlc_module_begin ()
- set_description(N_("H.265/HEVC encoder (x265)"))
- set_capability("encoder", 200)
- set_callbacks(Open, Close)
- set_category(CAT_INPUT)
- set_subcategory(SUBCAT_INPUT_VCODEC)
+
+#ifdef MODULE_NAME_IS_x265
+ set_description( N_("H.265/HEVC encoder (x265)"))
+ set_capability( "encoder", 200 )
+ set_callbacks( Open, Close )
+ set_category( CAT_INPUT )
+ set_subcategory( SUBCAT_INPUT_VCODEC )
+#endif
+/* Frame-type options */
+
+ add_integer( SOUT_CFG_PREFIX "keyint", 250, KEYINT_TEXT,
+ LONGTEXT, false )
+
+ add_integer( SOUT_CFG_PREFIX "min-keyint", 25, MIN_KEYINT_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "open-gop", true, OPENGOP_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "scenecut", 40, SCENE_TEXT,
+ LONGTEXT, true )
+ change_integer_range( -1, 100 )
+
+ add_integer( SOUT_CFG_PREFIX "bframes", 4, BFRAMES_TEXT,
+ LONGTEXT, true )
+ change_integer_range( 0, 16 )
+
+ add_integer( SOUT_CFG_PREFIX "b-adapt", 2, B_ADAPT_TEXT,
+ LONGTEXT, true )
+ change_integer_range( 0, 2 )
+
+ add_integer( SOUT_CFG_PREFIX "bframe-bias", 0, B_BIAS_TEXT,
+ LONGTEXT, true )
+ change_integer_range( -100, 100 )
+
+ add_bool( SOUT_CFG_PREFIX "b-pyramid", true, BPYRAMID_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "b-pyramid", true, BPYRAMID_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "ref", 3, REF_TEXT,
+ LONGTEXT, true )
+ change_integer_range( 1, 16 )
+
+ add_string( SOUT_CFG_PREFIX "deblock", "0:0", FILTER_TEXT,
+ LONGTEXT, true )
+
+ add_float( SOUT_CFG_PREFIX "psy-rd", 1.0, PSY_RD_TEXT,
+ LONGTEXT, true )
+
+ add_string( SOUT_CFG_PREFIX "level-idc", "0", LEVEL_TEXT,
+ LONGTEXT, false )
+
+ add_string( SOUT_CFG_PREFIX "profile", "main", PROFILE_TEXT,
+ LONGTEXT, false )
+ vlc_config_set (VLC_CONFIG_LIST,
+ (sizeof(x265_profile_names) / sizeof (char*)) - 1,
+ x265_profile_names, x265_profile_names);
+
+ add_bool( SOUT_CFG_PREFIX "interlace", false, INTERLACED_TEXT, LONGTEXT,
+ true )
+
+ add_bool( SOUT_CFG_PREFIX "hrd", false, HRD_TEXT, LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "repeat-headers", false, REPEATHEADERS_TEXT,
+ LONGTEXT, true )
+
+
+
+/* Ratecontrol */
+
+ add_integer( SOUT_CFG_PREFIX "qp", 0, QP_TEXT, LONGTEXT,
+ true )
+ change_integer_range( 0, 51 ) /* QP 0 -> lossless encoding */
+
+ add_integer( SOUT_CFG_PREFIX "bitrate", 0, BITRATE_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "crf", 28, CRF_TEXT,
+ LONGTEXT, true )
+ change_integer_range( 0, 51 )
+
+ add_integer( SOUT_CFG_PREFIX "vbv-maxrate", 0, VBV_MAXRATE_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "vbv-bufsize", 0, VBV_BUFSIZE_TEXT,
+ LONGTEXT, true )
+
+ add_float( SOUT_CFG_PREFIX "vbv-init", 0.9, VBV_INIT_TEXT,
+ LONGTEXT, true )
+ change_float_range( 0, 1 )
+
+ add_integer( SOUT_CFG_PREFIX "cbqpoffs", 0, CHROMAB_QP_OFFSET_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "crqpoffs", 0, CHROMAR_QP_OFFSET_TEXT,
+ LONGTEXT, true )
+
+ add_float( SOUT_CFG_PREFIX "ipratio", 1.40, IPRATIO_TEXT,
+ LONGTEXT, true )
+ change_float_range( 1, 2 )
+
+ add_float( SOUT_CFG_PREFIX "pbratio", 1.30, PBRATIO_TEXT,
+ LONGTEXT, true )
+ change_float_range( 1, 2 )
+
+ add_integer( SOUT_CFG_PREFIX "pass", 0, PASS_TEXT,
+ LONGTEXT, false )
+ change_integer_range( 0, 3 )
+
+ add_float( SOUT_CFG_PREFIX "qcomp", 0.60, QCOMP_TEXT,
+ LONGTEXT, true )
+ change_float_range( 0, 1 )
+
+ add_integer( SOUT_CFG_PREFIX "aq-mode", X265_AQ_VARIANCE, AQ_MODE_TEXT,
+ LONGTEXT, true )
+ change_integer_range( 0, 3)
+
+ add_float( SOUT_CFG_PREFIX "aq-strength", 1.0, AQ_STRENGTH_TEXT,
+ LONGTEXT, true )
+
+ add_float( SOUT_CFG_PREFIX "cplxblur", 20.0, CPLXBLUR_TEXT,
+ LONGTEXT, true )
+
+ add_float( SOUT_CFG_PREFIX "qblur", 0.5, QBLUR_TEXT,
+ LONGTEXT, true )
+
+/* Analysis */
+
+
+ add_bool( SOUT_CFG_PREFIX "weightb", false, WEIGHTB_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "tskip-fast", false, TSKIPFAST_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "tskip-fast", false, TSKIPFAST_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "weightp", true, WEIGHTP_TEXT,
+ LONGTEXT, true )
+
+ add_string( SOUT_CFG_PREFIX "me", "hex", ME_TEXT,
+ LONGTEXT, true )
+ change_string_list( enc_me_list, enc_me_list_text )
+
+ add_integer( SOUT_CFG_PREFIX "merange", 57, MERANGE_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "subme", 2, SUBME_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "lookahead-slices", 0, LOOKAHEAD_SLICES_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "intra-refresh", false, INTRAREFRESH_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "nr-intra", 0, NRINTRA_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "nr-inter", 0, NRINTER_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "ctu", 64, CTU_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "min-cu-size", 8, MINCUSIZE_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "rc-lookahead", 20, RCLOOKAHEAD_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "limit-refs", 3, LIMITREFS_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "rect", false, RECT_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "amp", false, AMP_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "limit-modes", false, LIMITMODES_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "max-merge", 2, MAXMERGE_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "early-skip", false, EARLYSKIP_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "fast-intra", false, FASTINTRA_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "b-intra", false, BINTRA_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "sao", true, SAO_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "signhide", true, SIGNHIDE_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "cutree", true, CUTREE_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "rd", 3, RD_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "rdoq-level", 0, RDOQLEVEL_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "tu-intra", 1, TUINTRA_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "tu-inter", 1, TUINTER_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "qpstep", 4, QPSTEP_TEXT,
+ LONGTEXT, true )
+
+ add_float( SOUT_CFG_PREFIX "psy-rdoq", 0.0, PSYRDOQ_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "frame-threads", 0, FRAMETHREADS_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "pmode", false, PMODE_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "pme", false, PME_TEXT,
+ LONGTEXT, true )
+
+ add_integer( SOUT_CFG_PREFIX "qg-size", 32, QGSIZE_TEXT,
+ LONGTEXT, true )
+
+
+/* Input/Output */
+
+ add_bool( SOUT_CFG_PREFIX "asm", true, ASM_TEXT,
+ LONGTEXT, true )
+
+ //x265 psnr = 1 (default). disable PSNR computation for speed.
+ add_bool( SOUT_CFG_PREFIX "psnr", false, PSNR_TEXT,
+ LONGTEXT, true )
+
+ /* x265 ssim = 1 (default). disable SSIM computation for speed. */
+ add_bool( SOUT_CFG_PREFIX "ssim", false, SSIM_TEXT,
+ LONGTEXT, true )
+
+ add_bool( SOUT_CFG_PREFIX "aud", false, AUD_TEXT,
+ LONGTEXT, true )
+
+ add_string( SOUT_CFG_PREFIX "preset", NULL , PRESET_TEXT , PRESET_TEXT, false )
+ vlc_config_set (VLC_CONFIG_LIST,
+ (sizeof(x265_preset_names) / sizeof (char*)) - 1,
+ x265_preset_names, x265_preset_names);
+
+ add_string( SOUT_CFG_PREFIX "tune", NULL , TUNE_TEXT, TUNE_TEXT, false )
+ vlc_config_set (VLC_CONFIG_LIST,
+ (sizeof(x265_tune_names) / sizeof (char*)) - 1,
+ x265_tune_names, x265_tune_names);
+
vlc_module_end ()
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static const char *const ppsz_sout_options[] = {
+ "aud", "bframes", "b-pyramid", "b-adapt", "bframe-bias", "cbqpoffs",
+ "crqpoffs", "cplxblur", "crf", "deblock", "interlace", "ipratio", "keyint",
+ "level-idc", "me", "merange", "min-keyint", "pass", "pbratio", "psnr",
+ "qblur", "qp", "qcomp", "ref", "scenecut", "ssim", "subme", "vbv-bufsize",
+ "vbv-init", "vbv-maxrate", "weightb", "weightp", "aq-mode", "aq-strength",
+ "psy-rd", "profile", "lookahead-slices", "intra-refresh", "hrd", "tune",
+ "preset", "open-gop", "bitrate", "nr-intra", "nr-inter", "tskip-fast",
+ "repeat-headers", "ctu", "min-cu-size", "rc-lookahead", "limit-refs",
+ "rect", "amp", "limit-modes", "max-merge", "early-skip", "fast-intra",
+ "b-intra", "sao", "signhide", "cutree", "rd", "rdoq-level",
+ "tu-intra", "tu-inter", "tune", "qpstep", "psy-rdoq", "frame-threads",
+ "pmode", "pme", "qg-size",
+ NULL
+};
+
+static block_t *Encode( encoder_t *, picture_t * );
+
struct encoder_sys_t
{
x265_encoder *h;
x265_param param;
-
mtime_t i_initial_delay;
-
- mtime_t dts;
- mtime_t initial_date;
+ char *psz_stat_name;
+ int i_sei_size;
+ uint32_t i_colorspace;
+ uint8_t *p_sei;
+
+ mtime_t dts;
+ mtime_t initial_date;
#ifndef NDEBUG
mtime_t start;
+#endif
+
+};
+
+#ifdef PTW32_STATIC_LIB
+static vlc_mutex_t pthread_win32_mutex = VLC_STATIC_MUTEX;
+static int pthread_win32_count = 0;
#endif
+
+/*****************************************************************************
+ * Open: probe the encoder
+ *****************************************************************************/
+static int Open ( vlc_object_t *p_this )
+{
+ encoder_t *p_enc = (encoder_t *)p_this;
+ encoder_sys_t *p_sys;
+ int i_val, j_val;
+ char *psz_val;
+ int i_qmin = 0, i_qmax = 0;
+ x265_nal *nal;
+ int i, i_nal;
+ bool fullrange = false;
+ if( p_enc->fmt_out.i_codec != VLC_CODEC_HEVC && !p_enc->b_force )
+ {
+ return VLC_EGENERIC;
+ }
+
+ config_ChainParse( p_enc, SOUT_CFG_PREFIX, ppsz_sout_options, p_enc->p_cfg );
+
+ p_enc->fmt_out.i_cat = VIDEO_ES;
+
+ p_enc->fmt_out.i_codec = VLC_CODEC_HEVC;
+
+ p_enc->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) );
+ if( !p_sys )
+ return VLC_ENOMEM;
+
+ p_enc->fmt_in.i_codec = VLC_CODEC_I420;
+ p_sys->i_colorspace = X265_CSP_I420;
+
+ p_enc->pf_encode_video = Encode;
+ p_enc->pf_encode_audio = NULL;
+ p_sys->i_initial_delay = 0;
+ p_sys->psz_stat_name = NULL;
+ p_sys->i_sei_size = 0;
+ p_sys->p_sei = NULL;
+
+ char *psz_preset = var_GetString( p_enc, SOUT_CFG_PREFIX "preset" );
+ char *psz_tune = var_GetString( p_enc, SOUT_CFG_PREFIX "tune" );
+ if( *psz_preset == '\0' )
+ {
+ free(psz_preset);
+ psz_preset = NULL;
+ }
+
+ x265_param_default_preset( &p_sys->param, psz_preset, psz_tune );
+
+ free( psz_preset );
+ free( psz_tune );
+ p_sys->param.internalCsp = p_sys->i_colorspace;
+
+ if( fabs(var_GetFloat( p_enc, SOUT_CFG_PREFIX "qcomp" ) - 0.60) > 0.005 )
+ p_sys->param.rc.qCompress = var_GetFloat( p_enc, SOUT_CFG_PREFIX "qcomp" );
+
+ /* transcode-default bitrate is 0,
+ * set more to ABR if user specifies bitrate */
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "bitrate" );
+ j_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "qp" );
+ if( i_val > 0 || p_enc->fmt_out.i_bitrate > 0)
+ {
+ p_sys->param.rc.bitrate = ((i_val > 0) ? i_val : p_enc->fmt_out.i_bitrate/1000);
+ p_sys->param.rc.rateControlMode = X265_RC_ABR;
+ }
+ else if( j_val > 0)
+ {
+ if( j_val > 0 && j_val <= 51 )
+ {
+ p_sys->param.rc.qp = j_val;
+ p_sys->param.rc.rateControlMode = X265_RC_CQP;
+ }
+ }
+ else /* Set default to CRF */
+ {
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "crf" );
+ if( i_val > 0 && i_val <= 51 )
+ {
+ p_sys->param.rc.rfConstant = i_val;
+ p_sys->param.rc.rateControlMode = X265_RC_CRF;
+ }
+ }
+
+ p_sys->param.rc.vbvBufferInit = var_GetFloat( p_enc,
+ SOUT_CFG_PREFIX "vbv-init" );
+ p_sys->param.rc.vbvBufferSize = var_GetInteger( p_enc,
+ SOUT_CFG_PREFIX "vbv-bufsize" );
+
+ /* max bitrate = average bitrate -> CBR */
+ p_sys->param.rc.vbvMaxBitrate = var_GetInteger( p_enc, SOUT_CFG_PREFIX "vbv-maxrate" );
+ if( p_sys->param.rc.vbvMaxBitrate && p_sys->param.rc.rateControlMode != X265_RC_ABR )
+ p_enc->fmt_out.i_bitrate = p_sys->param.rc.vbvMaxBitrate * 1000;
+
+ psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "deblock" );
+ if( psz_val )
+ {
+ if( atoi( psz_val ) != 0 )
+ {
+ char *p = strchr( psz_val, ':' );
+ p_sys->param.deblockingFilterTCOffset = atoi( psz_val );
+ p_sys->param.deblockingFilterBetaOffset = p ?
+ atoi( p+1 ) : p_sys->param.deblockingFilterTCOffset;
+ }
+ free( psz_val );
+ }
+ p_sys->param.psyRd = var_GetFloat( p_enc, SOUT_CFG_PREFIX "psy-rd" );
+
+ psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "level-idc" );
+ if( psz_val )
+ {
+ if( us_atof (psz_val) < 6 && us_atof (psz_val) > 0 )
+ p_sys->param.levelIdc = (int) (10 * us_atof (psz_val)
+ + .5);
+ else if( atoi(psz_val) >= 10 && atoi(psz_val) <= 51 )
+ p_sys->param.levelIdc = atoi (psz_val);
+ free( psz_val );
+ }
+
+ p_sys->param.interlaceMode = var_GetBool( p_enc, SOUT_CFG_PREFIX "interlace" );
+
+ if( fabs(var_GetFloat( p_enc, SOUT_CFG_PREFIX "ipratio" ) - 1.4) > 0.005 )
+ p_sys->param.rc.ipFactor = var_GetFloat( p_enc, SOUT_CFG_PREFIX "ipratio" );
+
+ if( fabs(var_GetFloat( p_enc, SOUT_CFG_PREFIX "pbratio" ) - 1.3 ) > 0.005 )
+ p_sys->param.rc.pbFactor = var_GetFloat( p_enc, SOUT_CFG_PREFIX "pbratio" );
+
+ p_sys->param.rc.complexityBlur = var_GetFloat( p_enc, SOUT_CFG_PREFIX "cplxblur" );
+
+ p_sys->param.rc.qblur = var_GetFloat( p_enc, SOUT_CFG_PREFIX "qblur" );
+
+ if( var_GetInteger( p_enc, SOUT_CFG_PREFIX "aq-mode" ) != X265_AQ_VARIANCE )
+ p_sys->param.rc.aqMode = var_GetInteger( p_enc, SOUT_CFG_PREFIX "aq-mode" );
+
+ if( fabs( var_GetFloat( p_enc, SOUT_CFG_PREFIX "aq-strength" ) - 1.0) > 0.005 )
+ p_sys->param.rc.aqStrength = var_GetFloat( p_enc, SOUT_CFG_PREFIX "aq-strength" );
+
+
+ if( var_GetBool( p_enc, SOUT_CFG_PREFIX "aud" ) )
+ p_sys->param.bEnableAccessUnitDelimiters = true;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "keyint" );
+ if( i_val > -1 && i_val < INT_MAX )
+ {
+ p_sys->param.keyframeMax = i_val;
+ }
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "min-keyint" );
+ if( i_val > 0 && i_val != 25 ) p_sys->param.keyframeMin = i_val;
+
+ if (var_GetBool( p_enc, SOUT_CFG_PREFIX "open-gop" ))
+ p_sys->param.bOpenGOP = true;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "bframes" );
+ if( i_val >= 0 && i_val <= 16 && i_val != 3 )
+ p_sys->param.bframes = i_val;
+
+ p_sys->param.bIntraRefresh = var_GetBool( p_enc, SOUT_CFG_PREFIX "intra-refresh" );
+
+ if (var_GetBool( p_enc, SOUT_CFG_PREFIX "b-pyramid" ))
+ p_sys->param.bBPyramid = true;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "ref" );
+ if( i_val > 0 && i_val <= 16 && i_val != 3 )
+ p_sys->param.maxNumReferences = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "scenecut" );
+ if( i_val >= -1 && i_val <= 100 && i_val != 40 )
+ p_sys->param.scenecutThreshold = i_val;
+
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "subme" );
+ if( i_val >= 1 && i_val != 7 )
+ p_sys->param.subpelRefine = i_val;
+
+
+ if (var_GetBool( p_enc, SOUT_CFG_PREFIX "hrd"))
+ p_sys->param.bEmitHRDSEI = true;
+
+
+ psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "me" );
+ if( psz_val && strcmp( psz_val, "hex" ) )
+ {
+ if( !strcmp( psz_val, "dia" ) )
+ {
+ p_sys->param.searchMethod = X265_DIA_SEARCH;
+ }
+ else if( !strcmp( psz_val, "umh" ) )
+ {
+ p_sys->param.searchMethod = X265_UMH_SEARCH;
+ }
+ else if( !strcmp( psz_val, "star" ) )
+ {
+ p_sys->param.searchMethod = X265_STAR_SEARCH;
+ }
+ else if( !strcmp( psz_val, "full" ) )
+ {
+ p_sys->param.searchMethod = X265_FULL_SEARCH;
+ }
+ }
+ free( psz_val );
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "merange" );
+ if( i_val >= 0 && i_val <= 64 && i_val != 16 )
+ p_sys->param.searchRange = i_val;
+
+ p_sys->param.bEnablePsnr = var_GetBool( p_enc, SOUT_CFG_PREFIX "psnr" );
+
+ p_sys->param.bEnableSsim = var_GetBool( p_enc, SOUT_CFG_PREFIX "ssim" );
+
+ if(var_GetBool( p_enc, SOUT_CFG_PREFIX "weightb" ) )
+ p_sys->param.bEnableWeightedBiPred = true;
+
+ if( var_GetBool( p_enc, SOUT_CFG_PREFIX "weightp" ) )
+ p_sys->param.bEnableWeightedPred = true;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "b-adapt" );
+ if( i_val != 1 )
+ p_sys->param.bFrameAdaptive = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "bframe-bias" );
+ if( i_val >= -100 && i_val <= 100 && i_val != 0)
+ p_sys->param.bFrameBias = i_val;
+
+ p_sys->param.cbQpOffset = var_GetInteger( p_enc,
+ SOUT_CFG_PREFIX "cbqpoffs" );
+
+ p_sys->param.crQpOffset = var_GetInteger( p_enc,
+ SOUT_CFG_PREFIX "crqpoffs" );
+
+
+ if( var_GetBool( p_enc, SOUT_CFG_PREFIX "tskip-fast" ) )
+ p_sys->param.bEnableTSkipFast = true;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "nr-inter" );
+ if( i_val > 0 && i_val <= 2000 )
+ p_sys->param.noiseReductionInter = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "nr-intra" );
+ if( i_val > 0 && i_val <= 2000 )
+ p_sys->param.noiseReductionIntra = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "ctu" );
+ if( i_val == 16 || i_val == 32 || i_val == 64 )
+ p_sys->param.maxCUSize = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "min-cu-size" );
+ if( i_val == 8 || i_val == 16 || i_val == 32 || i_val == 64 )
+ p_sys->param.minCUSize = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "rc-lookahead" );
+ if( i_val >= 0 && i_val <= 250 )
+ p_sys->param.lookaheadDepth = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "limit-refs" );
+ if( i_val == 0 || i_val == 1 || i_val == 2 || i_val == 3 )
+ p_sys->param.limitReferences = i_val;
+
+ p_sys->param.bEnableRectInter = var_GetBool( p_enc, SOUT_CFG_PREFIX "rect" );
+
+ p_sys->param.bEnableAMP = var_GetBool( p_enc, SOUT_CFG_PREFIX "amp" );
+
+ p_sys->param.limitModes = var_GetBool( p_enc, SOUT_CFG_PREFIX "limit-modes" );
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "max-merge" );
+ if( i_val >= 1 && i_val <= 5 )
+ p_sys->param.maxNumMergeCand = i_val;
+
+ p_sys->param.bEnableEarlySkip = var_GetBool( p_enc, SOUT_CFG_PREFIX "early-skip" );
+
+ p_sys->param.bEnableFastIntra = var_GetBool( p_enc, SOUT_CFG_PREFIX "fast-intra" );
+
+ p_sys->param.bIntraInBFrames = var_GetBool( p_enc, SOUT_CFG_PREFIX "b-intra" );
+
+ p_sys->param.bEnableSAO = var_GetBool( p_enc, SOUT_CFG_PREFIX "sao" );
+
+ p_sys->param.bEnableSignHiding = var_GetBool( p_enc, SOUT_CFG_PREFIX "signhide" );
+
+ p_sys->param.rc.cuTree = var_GetBool( p_enc, SOUT_CFG_PREFIX "cutree" );
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "rd" );
+ if( i_val >= 1 && i_val <= 6 )
+ p_sys->param.rdLevel = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "rdoq-level" );
+ if( i_val == 0 || i_val == 1 || i_val == 2 )
+ p_sys->param.rdoqLevel = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "tu-intra" );
+ if( i_val >= 1 && i_val <= 4 )
+ p_sys->param.tuQTMaxIntraDepth = i_val;
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "tu-inter" );
+ if( i_val >= 1 && i_val <= 4 )
+ p_sys->param.tuQTMaxInterDepth = i_val;
+
+ p_sys->param.rc.qpStep = var_GetInteger( p_enc, SOUT_CFG_PREFIX "qpstep" );
+
+ p_sys->param.psyRdoq = var_GetFloat( p_enc, SOUT_CFG_PREFIX "psy-rdoq" );
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "frame-threads" );
+ if( i_val >= 1 && i_val <= 16 )
+ p_sys->param.frameNumThreads = i_val;
+
+ p_sys->param.bDistributeModeAnalysis = var_GetBool( p_enc, SOUT_CFG_PREFIX "pmode" );
+
+ p_sys->param.bDistributeMotionEstimation = var_GetBool( p_enc, SOUT_CFG_PREFIX "pme" );
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "qg-size" );
+ if( i_val == 16 || i_val == 32 || i_val == 64)
+ p_sys->param.rc.qgSize = i_val;
+
+ if( var_GetBool( p_enc, SOUT_CFG_PREFIX "asm" ) )
+ p_sys->param.cpuid = 1;
+
+ /* Check slice-options */
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "lookahead-slices" );
+ if( i_val > 0 )
+ p_sys->param.lookaheadSlices = i_val;
+
+ /* Check if user has given some profile (baseline,main,high) to limit
+ * settings, and apply those*/
+ psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "profile" );
+ if( psz_val && *psz_val )
+ x265_param_apply_profile( &p_sys->param, psz_val );
+ free( psz_val );
+
+ i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "pass" );
+ if( i_val > 0 && i_val <= 3 )
+ {
+ p_sys->param.rc.bStatWrite = i_val & 1;
+ p_sys->param.rc.bStatRead = i_val & 2;
+ }
+
+
+ /* We need to initialize pthreadw32 before we open the encoder,
+ but only once for the whole application. Since pthreadw32
+ doesn't keep a refcount, do it ourselves. */
+#ifdef PTW32_STATIC_LIB
+ vlc_mutex_lock( &pthread_win32_mutex );
+
+ if( pthread_win32_count == 0 )
+ {
+ if( !pthread_win32_process_attach_np() || !pthread_win32_thread_attach_np() )
+ {
+ msg_Warn( p_enc, "pthread Win32 Initialization failed" );
+ vlc_mutex_unlock( &pthread_win32_mutex );
+ return VLC_EGENERIC;
+ }
+ }
+
+ pthread_win32_count++;
+ vlc_mutex_unlock( &pthread_win32_mutex );
+#endif
+
+ if (var_GetBool( p_enc, SOUT_CFG_PREFIX "repeat-headers" ))
+ p_sys->param.bRepeatHeaders = true;
+
+ p_sys->param.fpsNum = p_enc->fmt_in.video.i_frame_rate;
+ p_sys->param.fpsDenom = p_enc->fmt_in.video.i_frame_rate_base;
+ if (!p_sys->param.fpsNum)
+ {
+ p_sys->param.fpsNum = 25;
+ p_sys->param.fpsDenom = 1;
+ }
+ p_sys->param.sourceWidth = p_enc->fmt_in.video.i_visible_width;
+ p_sys->param.sourceHeight = p_enc->fmt_in.video.i_visible_height;
+
+ /* Open the encoder */
+ p_sys->h = x265_encoder_open( &p_sys->param );
+ if( p_sys->h == NULL )
+ {
+ msg_Err( p_enc, "cannot open x265 encoder" );
+ Close( VLC_OBJECT(p_enc) );
+ return VLC_EGENERIC;
+ }
+
+ if (x265_encoder_headers(p_sys->h, &nal, &i_nal) < 0) {
+ msg_Err(p_enc, "cannot get x265 headers");
+ Close(VLC_OBJECT(p_enc));
+ return VLC_EGENERIC;
+ }
+
+ size_t i_extra = 0;
+ for (uint32_t i = 0; i < i_nal; i++)
+ i_extra += nal[i].sizeBytes;
+
+ p_enc->fmt_out.i_extra = i_extra;
+
+ uint8_t *p_extra = p_enc->fmt_out.p_extra = malloc(i_extra);
+ if (!p_extra) {
+ Close(VLC_OBJECT(p_enc));
+ return VLC_ENOMEM;
+ }
+
+ for (uint32_t i = 0; i < i_nal; i++) {
+ memcpy(p_extra, nal[i].payload, nal[i].sizeBytes);
+ p_extra += nal[i].sizeBytes;
+ }
+
+ p_sys->dts = 0;
+ p_sys->initial_date = 0;
+ p_sys->i_initial_delay = 0;
+
+ p_enc->pf_encode_video = Encode;
+ p_enc->pf_encode_audio = NULL;
+ return VLC_SUCCESS;
+}
+
+/****************************************************************************
+ * Logging
+ ****************************************************************************/
+static void x265_log( void *data, int i_level, const char *psz, va_list args)
+{
+ encoder_t *p_enc = (encoder_t *)data;
+
+ switch( i_level )
+ {
+ case X265_LOG_ERROR:
+ i_level = VLC_MSG_ERR;
+ break;
+ case X265_LOG_WARNING:
+ i_level = VLC_MSG_WARN;
+ break;
+ case X265_LOG_INFO:
+ i_level = VLC_MSG_INFO;
+ break;
+ case X265_LOG_DEBUG:
+ default:
+ i_level = VLC_MSG_DBG;
+ }
+
+ msg_GenericVa( p_enc, i_level, psz, args );
};
+/****************************************************************************
+ * Encode:
+ ****************************************************************************/
static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
{
encoder_sys_t *p_sys = p_enc->p_sys;
x265_picture pic;
-
x265_picture_init(&p_sys->param, &pic);
-
if (likely(p_pict)) {
pic.pts = p_pict->date;
if (unlikely(p_sys->initial_date == 0)) {
@@ -85,12 +1007,11 @@ static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
pic.stride[i] = p_pict->p[i].i_pitch;
}
}
-
x265_nal *nal;
uint32_t i_nal = 0;
x265_encoder_encode(p_sys->h, &nal, &i_nal,
likely(p_pict) ? &pic : NULL, &pic);
-
+
if (!i_nal)
return NULL;
@@ -136,112 +1057,35 @@ static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
return p_block;
}
-static int Open (vlc_object_t *p_this)
+/*****************************************************************************
+ * CloseEncoder: x265 encoder destruction
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
- encoder_sys_t *p_sys;
-
- if (p_enc->fmt_out.i_codec != VLC_CODEC_HEVC && !p_enc->b_force)
- return VLC_EGENERIC;
-
- p_enc->fmt_out.i_cat = VIDEO_ES;
- p_enc->fmt_out.i_codec = VLC_CODEC_HEVC;
- p_enc->p_sys = p_sys = malloc(sizeof(encoder_sys_t));
- if (!p_sys)
- return VLC_ENOMEM;
-
- p_enc->fmt_in.i_codec = VLC_CODEC_I420;
-
- x265_param *param = &p_sys->param;
- x265_param_default(param);
-
- param->frameNumThreads = vlc_GetCPUCount();
- param->bEnableWavefront = 0; // buggy in x265, use frame threading for now
- param->maxCUSize = 16; /* use smaller macroblock */
-
-#if X265_BUILD >= 6
- param->fpsNum = p_enc->fmt_in.video.i_frame_rate;
- param->fpsDenom = p_enc->fmt_in.video.i_frame_rate_base;
- if (!param->fpsNum) {
- param->fpsNum = 25;
- param->fpsDenom = 1;
- }
-#else
- if (p_enc->fmt_in.video.i_frame_rate_base) {
- param->frameRate = p_enc->fmt_in.video.i_frame_rate /
- p_enc->fmt_in.video.i_frame_rate_base;
- } else {
- param->frameRate = 25;
- }
-#endif
- param->sourceWidth = p_enc->fmt_in.video.i_visible_width;
- param->sourceHeight = p_enc->fmt_in.video.i_visible_height;
-
- if (param->sourceWidth & (param->maxCUSize - 1)) {
- msg_Err(p_enc, "Width (%d) must be a multiple of %d",
- param->sourceWidth, param->maxCUSize);
- free(p_sys);
- return VLC_EGENERIC;
- }
- if (param->sourceHeight & 7) {
- msg_Err(p_enc, "Height (%d) must be a multiple of 8", param->sourceHeight);
- free(p_sys);
- return VLC_EGENERIC;
- }
-
- if (p_enc->fmt_out.i_bitrate > 0) {
- param->rc.bitrate = p_enc->fmt_out.i_bitrate / 1000;
- param->rc.rateControlMode = X265_RC_ABR;
- }
+ encoder_sys_t *p_sys = p_enc->p_sys;
- p_sys->h = x265_encoder_open(param);
- if (p_sys->h == NULL) {
- msg_Err(p_enc, "cannot open x265 encoder");
- free(p_sys);
- return VLC_EGENERIC;
- }
+ free( p_sys->psz_stat_name );
+ free( p_sys->p_sei );
- x265_nal *nal;
- uint32_t i_nal;
- if (x265_encoder_headers(p_sys->h, &nal, &i_nal) < 0) {
- msg_Err(p_enc, "cannot get x265 headers");
- Close(VLC_OBJECT(p_enc));
- return VLC_EGENERIC;
+ if( p_sys->h )
+ {
+ x265_encoder_close( p_sys->h );
}
- size_t i_extra = 0;
- for (uint32_t i = 0; i < i_nal; i++)
- i_extra += nal[i].sizeBytes;
-
- p_enc->fmt_out.i_extra = i_extra;
+#ifdef PTW32_STATIC_LIB
+ vlc_mutex_lock( &pthread_win32_mutex );
+ pthread_win32_count--;
- uint8_t *p_extra = p_enc->fmt_out.p_extra = malloc(i_extra);
- if (!p_extra) {
- Close(VLC_OBJECT(p_enc));
- return VLC_ENOMEM;
- }
-
- for (uint32_t i = 0; i < i_nal; i++) {
- memcpy(p_extra, nal[i].payload, nal[i].sizeBytes);
- p_extra += nal[i].sizeBytes;
+ if( pthread_win32_count == 0 )
+ {
+ pthread_win32_thread_detach_np();
+ pthread_win32_process_detach_np();
+ msg_Dbg( p_enc, "pthread-win32 deinitialized" );
}
- p_sys->dts = 0;
- p_sys->initial_date = 0;
- p_sys->i_initial_delay = 0;
-
- p_enc->pf_encode_video = Encode;
- p_enc->pf_encode_audio = NULL;
-
- return VLC_SUCCESS;
-}
-
-static void Close(vlc_object_t *p_this)
-{
- encoder_t *p_enc = (encoder_t *)p_this;
- encoder_sys_t *p_sys = p_enc->p_sys;
-
- x265_encoder_close(p_sys->h);
+ vlc_mutex_unlock( &pthread_win32_mutex );
+#endif
- free(p_sys);
+ free( p_sys );
}
diff --git a/modules/gui/qt/components/sout/profile_selector.cpp b/modules/gui/qt/components/sout/profile_selector.cpp
index cfb1882..2fe35c5 100644
--- a/modules/gui/qt/components/sout/profile_selector.cpp
+++ b/modules/gui/qt/components/sout/profile_selector.cpp
@@ -257,8 +257,9 @@ void VLCProfileSelector::updateOptions( int i )
if ( !value.isEmpty() )
{
+ QString encoder;
smrl.option( "vcodec", value );
-
+ encoder = value;
HASHPICK( "vcodec", "bitrate" );
if ( value.toInt() > 0 )
{
@@ -272,7 +273,7 @@ void VLCProfileSelector::updateOptions( int i )
smrl.option( "vfilter", valuesList.join( ":" ) );
}
- /*if ( codec is h264 )*/
+
{
/* special handling */
QStringList codecoptions;
@@ -285,9 +286,18 @@ void VLCProfileSelector::updateOptions( int i )
if( !value.isEmpty() )
codecoptions << QUrl::fromPercentEncoding( value.toLatin1() );
- if ( codecoptions.count() )
- smrl.option( "venc",
- QString("x264{%1}").arg( codecoptions.join(",") ) );
+ if ( encoder == "hevc" )
+ {
+ if ( codecoptions.count() )
+ smrl.option( "venc",
+ QString("x265{%1}").arg( codecoptions.join(",") ) );
+ }
+ else
+ {
+ if ( codecoptions.count() )
+ smrl.option( "venc",
+ QString("x264{%1}").arg( codecoptions.join(",") ) );
+ }
}
HASHPICK( "vcodec", "framerate" );
--
1.8.3.1
More information about the vlc-devel
mailing list