FS-11189 add avcodec settings

This commit is contained in:
Seven Du 2018-06-20 19:00:22 +08:00 committed by Muteesa Fred
parent 0ad867f3dd
commit 18bcc4ddff
2 changed files with 541 additions and 47 deletions

View File

@ -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>

View File

@ -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);