FS-11189 add avcodec settings
This commit is contained in:
parent
0ad867f3dd
commit
18bcc4ddff
|
@ -0,0 +1,144 @@
|
|||
<configuration name="avcodec.conf" description="AVCodec Config">
|
||||
<settings>
|
||||
<!-- max bitrate the system support, truncate if over limit -->
|
||||
<!-- <param name="max-bitrate" value="5mb"/> -->
|
||||
|
||||
<!-- <param name="rtp-slice-size" value="1200"/> -->
|
||||
|
||||
<!-- minimum time to generate a new key frame in ms /> -->
|
||||
<!-- <param name="key-frame-min-freq" value="250"/> -->
|
||||
|
||||
<!-- integer of cpus, or 'auto', or 'cpu/<divisor>/<max> -->
|
||||
<param name="dec-threads" value="cpu/2/4"/>
|
||||
<param name="enc-threads" value="cpu/2/4"/>
|
||||
<param name="h263-profile" value="H263"/>
|
||||
<param name="h263+-profile" value="H263+"/>
|
||||
<param name="h264-profile" value="H264"/>
|
||||
<param name="h265-profile" value="H265"/>
|
||||
</settings>
|
||||
|
||||
<profiles>
|
||||
<profile name="H263">
|
||||
</profile>
|
||||
|
||||
<profile name="H263+">
|
||||
</profile>
|
||||
|
||||
<profile name="H264">
|
||||
<!-- <param name="dec-threads" value="cpu/2/4"/> -->
|
||||
<!-- <param name="enc-threads" value="1"/> -->
|
||||
|
||||
<!-- <param name="profile" value="2"/> -->
|
||||
<!-- <param name="level" value="41"/> -->
|
||||
<!-- <param name="timebase" value="1/90"/> -->
|
||||
|
||||
<!--
|
||||
|
||||
#define AV_CODEC_FLAG_UNALIGNED (1 << 0)
|
||||
#define AV_CODEC_FLAG_QSCALE (1 << 1)
|
||||
#define AV_CODEC_FLAG_4MV (1 << 2)
|
||||
#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3)
|
||||
#define AV_CODEC_FLAG_QPEL (1 << 4)
|
||||
#define AV_CODEC_FLAG_PASS1 (1 << 9)
|
||||
#define AV_CODEC_FLAG_PASS2 (1 << 10)
|
||||
#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11)
|
||||
#define AV_CODEC_FLAG_GRAY (1 << 13)
|
||||
#define AV_CODEC_FLAG_PSNR (1 << 15)
|
||||
#define AV_CODEC_FLAG_TRUNCATED (1 << 16)
|
||||
#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18)
|
||||
#define AV_CODEC_FLAG_LOW_DELAY (1 << 19)
|
||||
#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
|
||||
#define AV_CODEC_FLAG_BITEXACT (1 << 23)
|
||||
#define AV_CODEC_FLAG_AC_PRED (1 << 24)
|
||||
#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29)
|
||||
#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31)
|
||||
|
||||
-->
|
||||
|
||||
<param name="flags" value="LOOP_FILTER|PSNR"/>
|
||||
|
||||
<!--
|
||||
#define FF_CMP_SAD 0
|
||||
#define FF_CMP_SSE 1
|
||||
#define FF_CMP_SATD 2
|
||||
#define FF_CMP_DCT 3
|
||||
#define FF_CMP_PSNR 4
|
||||
#define FF_CMP_BIT 5
|
||||
#define FF_CMP_RD 6
|
||||
#define FF_CMP_ZERO 7
|
||||
#define FF_CMP_VSAD 8
|
||||
#define FF_CMP_VSSE 9
|
||||
#define FF_CMP_NSSE 10
|
||||
#define FF_CMP_W53 11
|
||||
#define FF_CMP_W97 12
|
||||
#define FF_CMP_DCTMAX 13
|
||||
#define FF_CMP_DCT264 14
|
||||
#define FF_CMP_MEDIAN_SAD 15
|
||||
#define FF_CMP_CHROMA 256
|
||||
-->
|
||||
|
||||
<!-- <param name="me-cmp" value="1"/> -->
|
||||
<!-- <param name="me-range" value="16"/> -->
|
||||
<!-- <param name="max-b-frames" value="3"/> -->
|
||||
<!-- <param name="refs" value="3"/> -->
|
||||
<!-- <param name="gop-size" value="250"/> -->
|
||||
<!-- <param name="keyint-min" value="25"/> -->
|
||||
<!-- <param name="i-quant-factor" value="0.71"/> -->
|
||||
<!-- <param name="b-quant-factor" value="0.76923078"/> -->
|
||||
<!-- <param name="qcompress" value="0.6"/> -->
|
||||
<!-- <param name="qmin" value="10"/> -->
|
||||
<!-- <param name="qmax" value="51"/> -->
|
||||
<!-- <param name="max-qdiff" value="4"/> -->
|
||||
|
||||
<!--
|
||||
enum AVColorSpace {
|
||||
AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
|
||||
AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
|
||||
AVCOL_SPC_UNSPECIFIED = 2,
|
||||
AVCOL_SPC_RESERVED = 3,
|
||||
AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
|
||||
AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
|
||||
AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
|
||||
AVCOL_SPC_SMPTE240M = 7, ///< functionally identical to above
|
||||
AVCOL_SPC_YCGCO = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
|
||||
AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO,
|
||||
AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system
|
||||
AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system
|
||||
AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x
|
||||
AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system
|
||||
AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system
|
||||
AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp
|
||||
AVCOL_SPC_NB ///< Not part of ABI
|
||||
};
|
||||
-->
|
||||
<param name="colorspace" value="0"/>
|
||||
|
||||
<!--
|
||||
enum AVColorRange {
|
||||
AVCOL_RANGE_UNSPECIFIED = 0,
|
||||
AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges
|
||||
AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges
|
||||
AVCOL_RANGE_NB ///< Not part of ABI
|
||||
};
|
||||
-->
|
||||
<param name="color-range" value="2"/>
|
||||
|
||||
<!-- x264 private -->
|
||||
<param name="x264-preset" value="veryfast"/>
|
||||
<param name="x264-intra-refresh" value="1"/>
|
||||
<param name="x264-tune" value="animation+zerolatency"/>
|
||||
<!-- <param name="x264-sc-threshold" value="40"/> -->
|
||||
<!-- <param name="x264-b-strategy" value="1"/> -->
|
||||
<!-- <param name="x264-crf" value="18"/> -->
|
||||
|
||||
</profile>
|
||||
|
||||
<profile name="H265">
|
||||
</profile>
|
||||
</profiles>
|
||||
</configuration>
|
||||
|
||||
<configuration name="avformat.conf" description="AVFormat Config">
|
||||
<settings>
|
||||
</settings>
|
||||
</configuration>
|
|
@ -38,10 +38,12 @@
|
|||
#include <libavutil/opt.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
|
||||
#define SLICE_SIZE SWITCH_DEFAULT_VIDEO_SIZE
|
||||
int SLICE_SIZE = SWITCH_DEFAULT_VIDEO_SIZE;
|
||||
|
||||
#define H264_NALU_BUFFER_SIZE 65536
|
||||
#define MAX_NALUS 128
|
||||
#define MAX_NALUS 256
|
||||
#define H263_MODE_B // else Mode A only
|
||||
#define KEY_FRAME_MIN_FREQ 250000
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_avcodec_load);
|
||||
|
||||
|
@ -194,6 +196,55 @@ typedef struct h264_codec_context_s {
|
|||
|
||||
static uint8_t ff_input_buffer_padding[FF_INPUT_BUFFER_PADDING_SIZE] = { 0 };
|
||||
|
||||
#define MAX_CODECS 4
|
||||
|
||||
typedef struct avcodec_profile_s {
|
||||
char name[20];
|
||||
int decoder_thread_count;
|
||||
AVCodecContext ctx;
|
||||
struct {
|
||||
char preset[20];
|
||||
char tune[64];
|
||||
int intra_refresh;
|
||||
int sc_threshold;
|
||||
int b_strategy;
|
||||
int crf;
|
||||
} x264;
|
||||
} avcodec_profile_t;
|
||||
|
||||
struct avcodec_globals {
|
||||
int debug;
|
||||
uint32_t max_bitrate;
|
||||
uint32_t rtp_slice_size;
|
||||
uint32_t key_frame_min_freq;
|
||||
|
||||
avcodec_profile_t profiles[MAX_CODECS];
|
||||
};
|
||||
|
||||
struct avcodec_globals avcodec_globals = { 0 };
|
||||
|
||||
char *CODEC_MAPS[] = {
|
||||
"H263",
|
||||
"H263+",
|
||||
"H264",
|
||||
"H265",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int get_codec_index(const char *cstr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
if (!strcasecmp(cstr, CODEC_MAPS[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static switch_status_t buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *frame)
|
||||
{
|
||||
uint8_t nalu_type = 0;
|
||||
|
@ -827,9 +878,8 @@ static switch_status_t consume_nalu(h264_codec_context_t *context, switch_frame_
|
|||
|
||||
static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t width, uint32_t height)
|
||||
{
|
||||
int sane = 0;
|
||||
int threads = switch_core_cpu_count();
|
||||
int fps = 15;
|
||||
avcodec_profile_t *profile = NULL;
|
||||
|
||||
#ifdef NVENC_SUPPORT
|
||||
if (!context->encoder) {
|
||||
|
@ -860,6 +910,18 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (context->av_codec_id == AV_CODEC_ID_H263) {
|
||||
profile = &avcodec_globals.profiles[get_codec_index("H263")];
|
||||
} else if (context->av_codec_id == AV_CODEC_ID_H263P) {
|
||||
profile = &avcodec_globals.profiles[get_codec_index("H263+")];
|
||||
} else if (context->av_codec_id == AV_CODEC_ID_H264) {
|
||||
profile = &avcodec_globals.profiles[get_codec_index("H264")];
|
||||
} else if (context->av_codec_id == AV_CODEC_ID_H265) {
|
||||
profile = &avcodec_globals.profiles[get_codec_index("H265")];
|
||||
}
|
||||
|
||||
if (!profile) return SWITCH_STATUS_FALSE;
|
||||
|
||||
if (context->encoder_ctx) {
|
||||
if (avcodec_is_open(context->encoder_ctx)) {
|
||||
avcodec_close(context->encoder_ctx);
|
||||
|
@ -896,15 +958,11 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
|
|||
context->bandwidth = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 1, fps);
|
||||
}
|
||||
|
||||
sane = switch_calc_bitrate(1920, 1080, 3, 60);
|
||||
|
||||
if (context->bandwidth > sane) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "BITRATE TRUNCATED TO %d\n", sane);
|
||||
context->bandwidth = sane;
|
||||
if (context->bandwidth > avcodec_globals.max_bitrate) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "BITRATE TRUNCATED TO %d\n", avcodec_globals.max_bitrate);
|
||||
context->bandwidth = avcodec_globals.max_bitrate;
|
||||
}
|
||||
|
||||
if (threads > 4) threads = 4;
|
||||
|
||||
context->bandwidth *= 3;
|
||||
|
||||
fps = context->codec_settings.video.fps;
|
||||
|
@ -921,11 +979,10 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
|
|||
|
||||
context->encoder_ctx->width = context->codec_settings.video.width;
|
||||
context->encoder_ctx->height = context->codec_settings.video.height;
|
||||
/* frames per second */
|
||||
context->encoder_ctx->time_base = (AVRational){1, 90};
|
||||
context->encoder_ctx->max_b_frames = 0;
|
||||
context->encoder_ctx->max_b_frames = profile->ctx.max_b_frames;
|
||||
context->encoder_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
context->encoder_ctx->thread_count = threads;
|
||||
context->encoder_ctx->thread_count = profile->ctx.thread_count;
|
||||
|
||||
if (context->av_codec_id == AV_CODEC_ID_H263 || context->av_codec_id == AV_CODEC_ID_H263P) {
|
||||
#ifndef H263_MODE_B
|
||||
|
@ -946,44 +1003,38 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
|||
context->encoder_ctx->opaque = context;
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "mb_info", SLICE_SIZE - 8, 0);
|
||||
} else if (context->av_codec_id == AV_CODEC_ID_H264) {
|
||||
context->encoder_ctx->profile = FF_PROFILE_H264_BASELINE;
|
||||
context->encoder_ctx->level = 31;
|
||||
context->encoder_ctx->profile = profile->ctx.profile;
|
||||
context->encoder_ctx->level = profile->ctx.level;
|
||||
|
||||
if (context->hw_encoder) {
|
||||
av_opt_set(context->encoder_ctx->priv_data, "preset", "llhp", 0);
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "2pass", 1, 0);
|
||||
} else {
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "intra-refresh", 1, 0);
|
||||
av_opt_set(context->encoder_ctx->priv_data, "preset", "veryfast", 0);
|
||||
av_opt_set(context->encoder_ctx->priv_data, "tune", "animation+zerolatency", 0);
|
||||
av_opt_set(context->encoder_ctx->priv_data, "profile", "baseline", 0);
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "intra-refresh", profile->x264.intra_refresh, 0);
|
||||
av_opt_set(context->encoder_ctx->priv_data, "preset", profile->x264.preset, 0);
|
||||
av_opt_set(context->encoder_ctx->priv_data, "tune", profile->x264.tune, 0);
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "slice-max-size", SLICE_SIZE, 0);
|
||||
|
||||
|
||||
context->encoder_ctx->colorspace = AVCOL_SPC_RGB;
|
||||
context->encoder_ctx->color_range = AVCOL_RANGE_JPEG;
|
||||
context->encoder_ctx->colorspace = profile->ctx.colorspace;
|
||||
context->encoder_ctx->color_range = profile->ctx.color_range;
|
||||
|
||||
/*
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "sc_threshold", 40, 0);
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "b_strategy", 1, 0);
|
||||
av_opt_set_int(context->encoder_ctx->priv_data, "crf", 18, 0);
|
||||
if (profile->x264.sc_threshold > 0) av_opt_set_int(context->encoder_ctx->priv_data, "sc_threshold", profile->x264.sc_threshold, 0);
|
||||
if (profile->x264.b_strategy > 0)av_opt_set_int(context->encoder_ctx->priv_data, "b_strategy", profile->x264.b_strategy, 0);
|
||||
if (profile->x264.crf > 0)av_opt_set_int(context->encoder_ctx->priv_data, "crf", profile->x264.crf, 0);
|
||||
|
||||
// libx264-medium.ffpreset preset
|
||||
|
||||
context->encoder_ctx->flags|=CODEC_FLAG_LOOP_FILTER; // flags=+loop
|
||||
context->encoder_ctx->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1
|
||||
context->encoder_ctx->me_range = 21; // me_range=16
|
||||
context->encoder_ctx->max_b_frames = 3; // bf=3
|
||||
//context->encoder_ctx->refs = 3; // refs=3
|
||||
context->encoder_ctx->gop_size = 250; // g=250
|
||||
context->encoder_ctx->keyint_min = 25; // keyint_min=25
|
||||
context->encoder_ctx->i_quant_factor = 0.71; // i_qfactor=0.71
|
||||
context->encoder_ctx->b_quant_factor = 0.76923078; // Qscale difference between P-frames and B-frames.
|
||||
context->encoder_ctx->qcompress = 0;//0.6; // qcomp=0.6
|
||||
context->encoder_ctx->qmin = 10; // qmin=10
|
||||
context->encoder_ctx->qmax = 51; // qmax=51
|
||||
context->encoder_ctx->max_qdiff = 4; // qdiff=4
|
||||
*/
|
||||
context->encoder_ctx->flags |= profile->ctx.flags; // CODEC_FLAG_LOOP_FILTER; // flags=+loop
|
||||
if (profile->ctx.me_cmp >= 0) context->encoder_ctx->me_cmp = profile->ctx.me_cmp; // cmp=+chroma, where CHROMA = 1
|
||||
if (profile->ctx.me_range >= 0) context->encoder_ctx->me_range = profile->ctx.me_range;
|
||||
if (profile->ctx.max_b_frames >= 0) context->encoder_ctx->max_b_frames = profile->ctx.max_b_frames;
|
||||
if (profile->ctx.refs >= 0) context->encoder_ctx->refs = profile->ctx.refs;
|
||||
if (profile->ctx.gop_size >= 0) context->encoder_ctx->gop_size = profile->ctx.gop_size;
|
||||
if (profile->ctx.keyint_min >= 0) context->encoder_ctx->keyint_min = profile->ctx.keyint_min;
|
||||
if (profile->ctx.i_quant_factor >= 0) context->encoder_ctx->i_quant_factor = profile->ctx.i_quant_factor;
|
||||
if (profile->ctx.b_quant_factor >= 0) context->encoder_ctx->b_quant_factor = profile->ctx.b_quant_factor;
|
||||
if (profile->ctx.qcompress >= 0) context->encoder_ctx->qcompress = profile->ctx.qcompress;
|
||||
if (profile->ctx.qmin >= 0) context->encoder_ctx->qmin = profile->ctx.qmin;
|
||||
if (profile->ctx.qmax >= 0) context->encoder_ctx->qmax = profile->ctx.qmax;
|
||||
if (profile->ctx.max_qdiff >= 0) context->encoder_ctx->max_qdiff = profile->ctx.max_qdiff;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -999,7 +1050,7 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
|
|||
{
|
||||
int encoding, decoding;
|
||||
h264_codec_context_t *context = NULL;
|
||||
int threads = switch_core_cpu_count();
|
||||
avcodec_profile_t *profile = NULL;
|
||||
|
||||
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
|
||||
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
|
||||
|
@ -1022,12 +1073,17 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
|
|||
|
||||
if (!strcmp(codec->implementation->iananame, "H263")) {
|
||||
context->av_codec_id = AV_CODEC_ID_H263;
|
||||
profile = &avcodec_globals.profiles[get_codec_index("H263")];
|
||||
} else if (!strcmp(codec->implementation->iananame, "H263-1998")) {
|
||||
context->av_codec_id = AV_CODEC_ID_H263P;
|
||||
profile = &avcodec_globals.profiles[get_codec_index("H263+")];
|
||||
} else {
|
||||
context->av_codec_id = AV_CODEC_ID_H264;
|
||||
profile = &avcodec_globals.profiles[get_codec_index("H264")];
|
||||
}
|
||||
|
||||
switch_assert(profile);
|
||||
|
||||
if (decoding) {
|
||||
context->decoder = avcodec_find_decoder(context->av_codec_id);
|
||||
|
||||
|
@ -1042,11 +1098,9 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
|
|||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "codec: id=%d %s\n", context->decoder->id, context->decoder->long_name);
|
||||
|
||||
if (threads > 4) threads = 4;
|
||||
|
||||
context->decoder_ctx = avcodec_alloc_context3(context->decoder);
|
||||
//context->decoder_ctx->thread_count = threads;
|
||||
context->decoder_ctx->thread_count = profile->decoder_thread_count;
|
||||
if (avcodec_open2(context->decoder_ctx, context->decoder, NULL) < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error openning codec\n");
|
||||
goto error;
|
||||
|
@ -1247,6 +1301,10 @@ GCC_DIAG_ON(deprecated-declarations)
|
|||
while (!(*p++)) ; /* eat the sync bytes, what ever 0 0 1 or 0 0 0 1 */
|
||||
context->nalus[i].start = p;
|
||||
context->nalus[i].eat = p;
|
||||
|
||||
if (mod_av_globals.debug && (*p & 0x1f) == 7) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "KEY FRAME GENERATED\n");
|
||||
}
|
||||
} else {
|
||||
context->nalus[i].len = p - context->nalus[i].start;
|
||||
while (!(*p++)) ; /* eat the sync bytes, what ever 0 0 1 or 0 0 0 1 */
|
||||
|
@ -1558,10 +1616,302 @@ void show_codecs(switch_stream_handle_t *stream)
|
|||
av_free(codecs);
|
||||
}
|
||||
|
||||
#define UINTVAL(v) (v > 0 ? v : 0);
|
||||
|
||||
static void load_config()
|
||||
{
|
||||
switch_xml_t cfg = NULL, xml = NULL;
|
||||
int i;
|
||||
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H263")].name, "H263");
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H263+")].name, "H263+");
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H264")].name, "H264");
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H265")].name, "H265");
|
||||
|
||||
for (i = 0; i < MAX_CODECS; i++) {
|
||||
avcodec_profile_t *profile = &avcodec_globals.profiles[i];
|
||||
|
||||
profile->ctx.colorspace = AVCOL_SPC_RGB;
|
||||
profile->ctx.color_range = AVCOL_RANGE_JPEG;
|
||||
profile->ctx.flags = 0;
|
||||
profile->ctx.me_cmp = -1;
|
||||
profile->ctx.me_range = -1;
|
||||
profile->ctx.max_b_frames = -1;
|
||||
profile->ctx.refs = -1;
|
||||
profile->ctx.gop_size = -1;
|
||||
profile->ctx.keyint_min = -1;
|
||||
profile->ctx.i_quant_factor = -1;
|
||||
profile->ctx.b_quant_factor = -1;
|
||||
profile->ctx.qcompress = -1;
|
||||
profile->ctx.qmin = -1;
|
||||
profile->ctx.qmax = -1;
|
||||
profile->ctx.max_qdiff = -1;
|
||||
|
||||
profile->x264.sc_threshold = 0;
|
||||
profile->x264.b_strategy = 0;
|
||||
profile->x264.crf = 0;
|
||||
|
||||
if (!strcasecmp(CODEC_MAPS[i], "H264")) {
|
||||
profile->ctx.profile = FF_PROFILE_H264_BASELINE;
|
||||
profile->ctx.level = 41;
|
||||
}
|
||||
}
|
||||
|
||||
avcodec_globals.max_bitrate = 0;
|
||||
|
||||
xml = switch_xml_open_cfg("avcodec.conf", &cfg, NULL);
|
||||
|
||||
if (xml) {
|
||||
switch_xml_t settings = switch_xml_child(cfg, "settings");
|
||||
switch_xml_t profiles = switch_xml_child(cfg, "profiles");
|
||||
|
||||
if (settings) {
|
||||
switch_xml_t param;
|
||||
|
||||
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
|
||||
const char *name = switch_xml_attr(param, "name");
|
||||
const char *value = switch_xml_attr(param, "value");
|
||||
|
||||
if (zstr(name) || zstr(value)) continue;
|
||||
|
||||
if (!strcmp(name, "max-bitrate")) {
|
||||
avcodec_globals.max_bitrate = switch_parse_bandwidth_string(value);
|
||||
} else if (!strcmp(name, "rtp-slice-size")) {
|
||||
int val = atoi(value);
|
||||
avcodec_globals.rtp_slice_size = UINTVAL(val);
|
||||
} else if (!strcmp(name, "key-frame-min-freq")) {
|
||||
int val = atoi(value);
|
||||
avcodec_globals.key_frame_min_freq = UINTVAL(val);
|
||||
avcodec_globals.key_frame_min_freq *= 1000;
|
||||
} else if (!strcmp(name, "dec-threads")) {
|
||||
int i;
|
||||
uint threads = switch_parse_cpu_string(value);
|
||||
|
||||
for (i = 0; i < MAX_CODECS; i++) {
|
||||
avcodec_globals.profiles[i].decoder_thread_count = threads;
|
||||
}
|
||||
} else if (!strcmp(name, "enc-threads")) {
|
||||
int i;
|
||||
uint threads = switch_parse_cpu_string(value);
|
||||
|
||||
for (i = 0; i < MAX_CODECS; i++) {
|
||||
avcodec_globals.profiles[i].ctx.thread_count = threads;
|
||||
}
|
||||
} else if (!strcasecmp(name, "h263-profile")) {
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H263")].name, value);
|
||||
} else if (!strcasecmp(name, "h263+-profile")) {
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H263+")].name, value);
|
||||
} else if (!strcasecmp(name, "h264-profile")) {
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H264")].name, value);
|
||||
} else if (!strcasecmp(name, "h265-profile")) {
|
||||
switch_set_string(avcodec_globals.profiles[get_codec_index("H265")].name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (profiles) {
|
||||
switch_xml_t profile = switch_xml_child(profiles, "profile");
|
||||
|
||||
for (; profile; profile = profile->next) {
|
||||
switch_xml_t param = NULL;
|
||||
const char *profile_name = switch_xml_attr(profile, "name");
|
||||
avcodec_profile_t *aprofile = NULL;
|
||||
AVCodecContext *ctx = NULL;
|
||||
int i;
|
||||
|
||||
if (zstr(profile_name)) continue;
|
||||
|
||||
for (i = 0; i < MAX_CODECS; i++) {
|
||||
if (!strcmp(profile_name, avcodec_globals.profiles[i].name)) {
|
||||
aprofile = &avcodec_globals.profiles[i];
|
||||
ctx = &aprofile->ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx) continue;
|
||||
|
||||
for (param = switch_xml_child(profile, "param"); param; param = param->next) {
|
||||
const char *name = switch_xml_attr(param, "name");
|
||||
const char *value = switch_xml_attr(param, "value");
|
||||
int val;
|
||||
|
||||
if (zstr(name) || zstr(value)) continue;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: %s = %s\n", profile_name, name, value);
|
||||
|
||||
val = atoi(value);
|
||||
|
||||
if (!strcmp(name, "dec-threads")) {
|
||||
aprofile->decoder_thread_count = switch_parse_cpu_string(value);
|
||||
} else if (!strcmp(name, "enc-threads")) {
|
||||
ctx->thread_count = switch_parse_cpu_string(value);
|
||||
} else if (!strcmp(name, "profile")) {
|
||||
ctx->profile = UINTVAL(val);
|
||||
|
||||
if (ctx->profile == 0 && !strcasecmp(CODEC_MAPS[i], "H264")) {
|
||||
if (!strcasecmp(value, "baseline")) {
|
||||
ctx->profile = FF_PROFILE_H264_BASELINE;
|
||||
} else if (!strcasecmp(value, "main")) {
|
||||
ctx->profile = FF_PROFILE_H264_MAIN;
|
||||
} else if (!strcasecmp(value, "high")) {
|
||||
ctx->profile = FF_PROFILE_H264_HIGH;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(name, "level")) {
|
||||
ctx->level = UINTVAL(val);
|
||||
} else if (!strcmp(name, "timebase")) {
|
||||
int num = 0;
|
||||
int den = 0;
|
||||
char *slash = strchr(value, '/');
|
||||
|
||||
num = UINTVAL(val);
|
||||
|
||||
if (slash) {
|
||||
slash++;
|
||||
den = atoi(slash);
|
||||
|
||||
if (den < 0) den = 0;
|
||||
}
|
||||
|
||||
if (num && den) {
|
||||
ctx->time_base.num = num;
|
||||
ctx->time_base.den = den;
|
||||
}
|
||||
} else if (!strcmp(name, "preset")) {
|
||||
switch_set_string(aprofile->x264.preset, value);
|
||||
} else if (!strcmp(name, "flags")) {
|
||||
char *s = strdup(value);
|
||||
int flags = 0;
|
||||
|
||||
if (s) {
|
||||
int argc;
|
||||
char *argv[20];
|
||||
int i;
|
||||
|
||||
argc = switch_separate_string(s, '|', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!strcasecmp(argv[i], "UNALIGNED")) {
|
||||
flags |= AV_CODEC_FLAG_UNALIGNED;
|
||||
} else if (!strcasecmp(argv[i], "QSCALE")) {
|
||||
flags |= AV_CODEC_FLAG_QSCALE;
|
||||
} else if (!strcasecmp(argv[i], "QSCALE")) {
|
||||
flags |= AV_CODEC_FLAG_QSCALE;
|
||||
} else if (!strcasecmp(argv[i], "4MV")) {
|
||||
flags |= AV_CODEC_FLAG_4MV;
|
||||
} else if (!strcasecmp(argv[i], "CORRUPT")) {
|
||||
flags |= AV_CODEC_FLAG_OUTPUT_CORRUPT;
|
||||
} else if (!strcasecmp(argv[i], "QPEL")) {
|
||||
flags |= AV_CODEC_FLAG_QPEL;
|
||||
} else if (!strcasecmp(argv[i], "PASS1")) {
|
||||
flags |= AV_CODEC_FLAG_PASS1;
|
||||
} else if (!strcasecmp(argv[i], "PASS2")) {
|
||||
flags |= AV_CODEC_FLAG_PASS2;
|
||||
} else if (!strcasecmp(argv[i], "FILTER")) {
|
||||
flags |= AV_CODEC_FLAG_LOOP_FILTER;
|
||||
} else if (!strcasecmp(argv[i], "GRAY")) {
|
||||
flags |= AV_CODEC_FLAG_GRAY;
|
||||
} else if (!strcasecmp(argv[i], "PSNR")) {
|
||||
flags |= AV_CODEC_FLAG_PSNR;
|
||||
} else if (!strcasecmp(argv[i], "TRUNCATED")) {
|
||||
flags |= AV_CODEC_FLAG_TRUNCATED;
|
||||
} else if (!strcasecmp(argv[i], "INTERLACED_DCT")) {
|
||||
flags |= AV_CODEC_FLAG_INTERLACED_DCT;
|
||||
} else if (!strcasecmp(argv[i], "LOW_DELAY")) {
|
||||
flags |= AV_CODEC_FLAG_LOW_DELAY;
|
||||
} else if (!strcasecmp(argv[i], "HEADER")) {
|
||||
flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
} else if (!strcasecmp(argv[i], "BITEXACT")) {
|
||||
flags |= AV_CODEC_FLAG_BITEXACT;
|
||||
} else if (!strcasecmp(argv[i], "AC_PRED")) {
|
||||
flags |= AV_CODEC_FLAG_AC_PRED;
|
||||
} else if (!strcasecmp(argv[i], "INTERLACED_ME")) {
|
||||
flags |= AV_CODEC_FLAG_INTERLACED_ME;
|
||||
} else if (!strcasecmp(argv[i], "CLOSED_GOP")) {
|
||||
flags |= AV_CODEC_FLAG_CLOSED_GOP;
|
||||
}
|
||||
}
|
||||
|
||||
free(s);
|
||||
ctx->flags = flags;
|
||||
}
|
||||
} else if (!strcmp(name, "me-cmp")) {
|
||||
ctx->me_cmp = UINTVAL(val);
|
||||
} else if (!strcmp(name, "me-range")) {
|
||||
ctx->me_range = UINTVAL(val);
|
||||
} else if (!strcmp(name, "max-b-frames")) {
|
||||
ctx->max_b_frames = UINTVAL(val);
|
||||
} else if (!strcmp(name, "refs")) {
|
||||
ctx->refs = UINTVAL(val);
|
||||
} else if (!strcmp(name, "gop-size")) {
|
||||
ctx->gop_size = UINTVAL(val);
|
||||
} else if (!strcmp(name, "keyint-min")) {
|
||||
ctx->keyint_min = UINTVAL(val);
|
||||
} else if (!strcmp(name, "i-quant-factor")) {
|
||||
ctx->i_quant_factor = UINTVAL(val);
|
||||
} else if (!strcmp(name, "b-quant-factor")) {
|
||||
ctx->b_quant_factor = UINTVAL(val);
|
||||
} else if (!strcmp(name, "qcompress")) {
|
||||
ctx->qcompress = UINTVAL(val);
|
||||
} else if (!strcmp(name, "qmin")) {
|
||||
ctx->qmin = UINTVAL(val);
|
||||
} else if (!strcmp(name, "qmax")) {
|
||||
ctx->qmax = UINTVAL(val);
|
||||
} else if (!strcmp(name, "max-qdiff")) {
|
||||
ctx->max_qdiff = UINTVAL(val);
|
||||
} else if (!strcmp(name, "colorspace")) {
|
||||
ctx->colorspace = UINTVAL(val);
|
||||
|
||||
if (ctx->colorspace > AVCOL_SPC_NB) {
|
||||
ctx->colorspace = AVCOL_SPC_RGB;
|
||||
}
|
||||
} else if (!strcmp(name, "color-range")) {
|
||||
ctx->color_range = UINTVAL(val);
|
||||
|
||||
if (ctx->color_range > AVCOL_RANGE_NB) {
|
||||
ctx->color_range = 0;
|
||||
}
|
||||
} else if (!strcmp(name, "x264-preset")) {
|
||||
switch_set_string(aprofile->x264.preset, value);
|
||||
} else if (!strcmp(name, "x264-tune")) {
|
||||
switch_set_string(aprofile->x264.tune, value);
|
||||
} else if (!strcmp(name, "x264-sc-threshold")) {
|
||||
aprofile->x264.sc_threshold = UINTVAL(val);
|
||||
} else if (!strcmp(name, "x264-b-strategy")) {
|
||||
aprofile->x264.b_strategy = UINTVAL(val);
|
||||
} else if (!strcmp(name, "x264-crf")) {
|
||||
aprofile->x264.crf = UINTVAL(val);
|
||||
}
|
||||
} // for param
|
||||
} // for profile
|
||||
} // profiles
|
||||
|
||||
switch_xml_free(xml);
|
||||
} // xml
|
||||
|
||||
if (avcodec_globals.max_bitrate <= 0) {
|
||||
avcodec_globals.max_bitrate = switch_calc_bitrate(1920, 1080, 5, 60);
|
||||
}
|
||||
|
||||
if (avcodec_globals.rtp_slice_size < 500 || avcodec_globals.rtp_slice_size > 1500) {
|
||||
avcodec_globals.rtp_slice_size = SWITCH_DEFAULT_VIDEO_SIZE;
|
||||
}
|
||||
|
||||
SLICE_SIZE = avcodec_globals.rtp_slice_size;
|
||||
|
||||
if (avcodec_globals.key_frame_min_freq < 10000 || avcodec_globals.key_frame_min_freq > 3 * 1000000) {
|
||||
avcodec_globals.key_frame_min_freq = KEY_FRAME_MIN_FREQ;
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_avcodec_load)
|
||||
{
|
||||
switch_codec_interface_t *codec_interface;
|
||||
|
||||
memset(&avcodec_globals, 0, sizeof(struct avcodec_globals));
|
||||
load_config();
|
||||
|
||||
SWITCH_ADD_CODEC(codec_interface, "H264 Video");
|
||||
switch_core_codec_add_video_implementation(pool, codec_interface, 99, "H264", NULL,
|
||||
switch_h264_init, switch_h264_encode, switch_h264_decode, switch_h264_control, switch_h264_destroy);
|
||||
|
|
Loading…
Reference in New Issue