|
|
|
@ -178,13 +178,15 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
|
|
|
|
FFServerConfig *config) |
|
|
|
|
{ |
|
|
|
|
AVStream *st; |
|
|
|
|
AVDictionary **opts; |
|
|
|
|
AVDictionary **opts, *recommended = NULL; |
|
|
|
|
char *enc_config; |
|
|
|
|
|
|
|
|
|
if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams)) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
opts = av->codec_type == AVMEDIA_TYPE_AUDIO ? |
|
|
|
|
&config->audio_opts : &config->video_opts; |
|
|
|
|
av_dict_copy(&recommended, *opts, 0); |
|
|
|
|
av_opt_set_dict2(av->priv_data, opts, AV_OPT_SEARCH_CHILDREN); |
|
|
|
|
av_opt_set_dict2(av, opts, AV_OPT_SEARCH_CHILDREN); |
|
|
|
|
if (av_dict_count(*opts)) |
|
|
|
@ -196,63 +198,99 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
|
|
|
|
/* compute default parameters */ |
|
|
|
|
switch(av->codec_type) { |
|
|
|
|
case AVMEDIA_TYPE_AUDIO: |
|
|
|
|
if (av->bit_rate == 0) |
|
|
|
|
if (av->bit_rate == 0) { |
|
|
|
|
av->bit_rate = 64000; |
|
|
|
|
if (av->sample_rate == 0) |
|
|
|
|
av_dict_set_int(&recommended, "ab", av->bit_rate, 0); |
|
|
|
|
} |
|
|
|
|
if (av->sample_rate == 0) { |
|
|
|
|
av->sample_rate = 22050; |
|
|
|
|
if (av->channels == 0) |
|
|
|
|
av_dict_set_int(&recommended, "ar", av->sample_rate, 0); |
|
|
|
|
} |
|
|
|
|
if (av->channels == 0) { |
|
|
|
|
av->channels = 1; |
|
|
|
|
av_dict_set_int(&recommended, "ac", av->channels, 0); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case AVMEDIA_TYPE_VIDEO: |
|
|
|
|
if (av->bit_rate == 0) |
|
|
|
|
if (av->bit_rate == 0) { |
|
|
|
|
av->bit_rate = 64000; |
|
|
|
|
av_dict_set_int(&recommended, "b", av->bit_rate, 0); |
|
|
|
|
} |
|
|
|
|
if (av->time_base.num == 0){ |
|
|
|
|
av->time_base.den = 5; |
|
|
|
|
av->time_base.num = 1; |
|
|
|
|
av_dict_set(&recommended, "time_base", "1/5", 0); |
|
|
|
|
} |
|
|
|
|
if (av->width == 0 || av->height == 0) { |
|
|
|
|
av->width = 160; |
|
|
|
|
av->height = 128; |
|
|
|
|
av_dict_set(&recommended, "video_size", "160x128", 0); |
|
|
|
|
} |
|
|
|
|
/* Bitrate tolerance is less for streaming */ |
|
|
|
|
if (av->bit_rate_tolerance == 0) |
|
|
|
|
if (av->bit_rate_tolerance == 0) { |
|
|
|
|
av->bit_rate_tolerance = FFMAX(av->bit_rate / 4, |
|
|
|
|
(int64_t)av->bit_rate*av->time_base.num/av->time_base.den); |
|
|
|
|
if (av->qmin == 0) |
|
|
|
|
av_dict_set_int(&recommended, "bt", av->bit_rate_tolerance, 0); |
|
|
|
|
} |
|
|
|
|
if (av->qmin == 0) { |
|
|
|
|
av->qmin = 3; |
|
|
|
|
if (av->qmax == 0) |
|
|
|
|
av_dict_set_int(&recommended, "qmin", av->qmin, 0); |
|
|
|
|
} |
|
|
|
|
if (av->qmax == 0) { |
|
|
|
|
av->qmax = 31; |
|
|
|
|
if (av->max_qdiff == 0) |
|
|
|
|
av_dict_set_int(&recommended, "qmax", av->qmax, 0); |
|
|
|
|
} |
|
|
|
|
if (av->max_qdiff == 0) { |
|
|
|
|
av->max_qdiff = 3; |
|
|
|
|
av_dict_set_int(&recommended, "qdiff", av->max_qdiff, 0); |
|
|
|
|
} |
|
|
|
|
/*FIXME: 0.5 is a default for these two, it is a dead code */ |
|
|
|
|
av->qcompress = 0.5; |
|
|
|
|
av_dict_set(&recommended, "qcomp", "0.5", 0); |
|
|
|
|
av->qblur = 0.5; |
|
|
|
|
av_dict_set(&recommended, "qblur", "0.5", 0); |
|
|
|
|
|
|
|
|
|
if (!av->nsse_weight) |
|
|
|
|
if (!av->nsse_weight) { |
|
|
|
|
av->nsse_weight = 8; |
|
|
|
|
av_dict_set_int(&recommended, "nssew", av->nsse_weight, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av->frame_skip_cmp = FF_CMP_DCTMAX; |
|
|
|
|
if (!av->me_method) |
|
|
|
|
av_dict_set_int(&recommended, "skipcmp", FF_CMP_DCTMAX, 0); |
|
|
|
|
if (!av->me_method) { |
|
|
|
|
av->me_method = ME_EPZS; |
|
|
|
|
av_dict_set_int(&recommended, "me_method", ME_EPZS, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* FIXME: rc_buffer_aggressivity and rc_eq are deprecated */ |
|
|
|
|
av->rc_buffer_aggressivity = 1.0; |
|
|
|
|
av_dict_set(&recommended, "rc_buf_aggressivity", "1.0", 0); |
|
|
|
|
|
|
|
|
|
if (!av->rc_eq) |
|
|
|
|
if (!av->rc_eq) { |
|
|
|
|
av->rc_eq = av_strdup("tex^qComp"); |
|
|
|
|
if (!av->i_quant_factor) |
|
|
|
|
av_dict_set(&recommended, "rc_eq", "tex^qComp", 0); |
|
|
|
|
} |
|
|
|
|
if (!av->i_quant_factor) { |
|
|
|
|
av->i_quant_factor = -0.8; |
|
|
|
|
if (!av->b_quant_factor) |
|
|
|
|
av_dict_set(&recommended, "i_qfactor", "-0.8", 0); |
|
|
|
|
} |
|
|
|
|
if (!av->b_quant_factor) { |
|
|
|
|
av->b_quant_factor = 1.25; |
|
|
|
|
if (!av->b_quant_offset) |
|
|
|
|
av_dict_set(&recommended, "b_qfactor", "1.25", 0); |
|
|
|
|
} |
|
|
|
|
if (!av->b_quant_offset) { |
|
|
|
|
av->b_quant_offset = 1.25; |
|
|
|
|
if (!av->rc_max_rate) |
|
|
|
|
av_dict_set(&recommended, "b_qoffset", "1.25", 0); |
|
|
|
|
} |
|
|
|
|
if (!av->rc_max_rate) { |
|
|
|
|
av->rc_max_rate = av->bit_rate * 2; |
|
|
|
|
av_dict_set_int(&recommended, "maxrate", av->rc_max_rate, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (av->rc_max_rate && !av->rc_buffer_size) { |
|
|
|
|
av->rc_buffer_size = av->rc_max_rate; |
|
|
|
|
av_dict_set_int(&recommended, "bufsize", av->rc_buffer_size, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
abort(); |
|
|
|
@ -280,6 +318,9 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
|
|
|
|
st = av_mallocz(sizeof(AVStream)); |
|
|
|
|
if (!st) |
|
|
|
|
return; |
|
|
|
|
av_dict_get_string(recommended, &enc_config, '=', ','); |
|
|
|
|
av_dict_free(&recommended); |
|
|
|
|
av_stream_set_recommended_encoder_configuration(st, enc_config); |
|
|
|
|
st->codec = av; |
|
|
|
|
stream->streams[stream->nb_streams++] = st; |
|
|
|
|
} |
|
|
|
|