|
|
|
@ -132,7 +132,8 @@ void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream* feed, |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), &p); |
|
|
|
|
|
|
|
|
|
if (resolve_host(&acl.first, arg)) { |
|
|
|
|
fprintf(stderr, "%s:%d: ACL refers to invalid host or IP address '%s'\n", |
|
|
|
|
fprintf(stderr, |
|
|
|
|
"%s:%d: ACL refers to invalid host or IP address '%s'\n", |
|
|
|
|
filename, line_num, arg); |
|
|
|
|
errors++; |
|
|
|
|
} else |
|
|
|
@ -196,7 +197,8 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
|
|
|
|
av_opt_set_dict2(av, opts, AV_OPT_SEARCH_CHILDREN); |
|
|
|
|
if (av_dict_count(*opts)) |
|
|
|
|
av_log(NULL, AV_LOG_WARNING, |
|
|
|
|
"Something is wrong, %d options are not set!\n", av_dict_count(*opts)); |
|
|
|
|
"Something is wrong, %d options are not set!\n", |
|
|
|
|
av_dict_count(*opts)); |
|
|
|
|
|
|
|
|
|
if (config->stream_use_defaults) { |
|
|
|
|
//TODO: reident
|
|
|
|
@ -262,8 +264,8 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
|
|
|
|
if (!av_dict_get(recommended, "rc_eq", NULL, 0)) { |
|
|
|
|
av->rc_eq = av_strdup("tex^qComp"); |
|
|
|
|
av_dict_set(&recommended, "rc_eq", "tex^qComp", 0); |
|
|
|
|
WARNING("Setting default value for video rate control equation = %s. " |
|
|
|
|
"Use NoDefaults to disable it.\n", |
|
|
|
|
WARNING("Setting default value for video rate control equation = " |
|
|
|
|
"%s. Use NoDefaults to disable it.\n", |
|
|
|
|
av->rc_eq); |
|
|
|
|
} |
|
|
|
|
if (!av_dict_get(recommended, "maxrate", NULL, 0)) { |
|
|
|
@ -289,16 +291,19 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
|
|
|
|
switch(av->codec_type) { |
|
|
|
|
case AVMEDIA_TYPE_AUDIO: |
|
|
|
|
if (av->bit_rate == 0) |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, "audio bit rate is not set\n"); |
|
|
|
|
report_config_error(config->filename, config->line_num, |
|
|
|
|
AV_LOG_ERROR, &config->errors, |
|
|
|
|
"audio bit rate is not set\n"); |
|
|
|
|
if (av->sample_rate == 0) |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, "audio sample rate is not set\n"); |
|
|
|
|
report_config_error(config->filename, config->line_num, |
|
|
|
|
AV_LOG_ERROR, &config->errors, |
|
|
|
|
"audio sample rate is not set\n"); |
|
|
|
|
break; |
|
|
|
|
case AVMEDIA_TYPE_VIDEO: |
|
|
|
|
if (av->width == 0 || av->height == 0) |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, "video size is not set\n"); |
|
|
|
|
report_config_error(config->filename, config->line_num, |
|
|
|
|
AV_LOG_ERROR, &config->errors, |
|
|
|
|
"video size is not set\n"); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
av_assert0(0); |
|
|
|
@ -315,13 +320,15 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
|
|
|
|
stream->streams[stream->nb_streams++] = st; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ffserver_set_codec(AVCodecContext *ctx, const char *codec_name, FFServerConfig *config) |
|
|
|
|
static int ffserver_set_codec(AVCodecContext *ctx, const char *codec_name, |
|
|
|
|
FFServerConfig *config) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
AVCodec *codec = avcodec_find_encoder_by_name(codec_name); |
|
|
|
|
if (!codec || codec->type != ctx->codec_type) { |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, "Invalid codec name: '%s'\n", codec_name); |
|
|
|
|
&config->errors, |
|
|
|
|
"Invalid codec name: '%s'\n", codec_name); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
if (ctx->codec_id == AV_CODEC_ID_NONE && !ctx->priv_data) { |
|
|
|
@ -330,8 +337,10 @@ static int ffserver_set_codec(AVCodecContext *ctx, const char *codec_name, FFSer |
|
|
|
|
ctx->codec = codec; |
|
|
|
|
} |
|
|
|
|
if (ctx->codec_id != codec->id) |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, &config->errors, |
|
|
|
|
"Inconsistent configuration: trying to set '%s' codec option, but '%s' codec is used previously\n", |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, |
|
|
|
|
"Inconsistent configuration: trying to set '%s' " |
|
|
|
|
"codec option, but '%s' codec is used previously\n", |
|
|
|
|
codec_name, avcodec_get_name(ctx->codec_id)); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -368,12 +377,13 @@ static int ffserver_opt_preset(const char *arg, int type, FFServerConfig *config |
|
|
|
|
continue; |
|
|
|
|
e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2; |
|
|
|
|
if(e){ |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "%s: Invalid syntax: '%s'\n", filename, line); |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "%s: Invalid syntax: '%s'\n", filename, |
|
|
|
|
line); |
|
|
|
|
ret = AVERROR(EINVAL); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if ((!strcmp(tmp, "acodec") && avctx->codec_type == AVMEDIA_TYPE_AUDIO) || |
|
|
|
|
!strcmp(tmp, "vcodec") && avctx->codec_type == AVMEDIA_TYPE_VIDEO) |
|
|
|
|
if (!strcmp(tmp, "acodec") && avctx->codec_type == AVMEDIA_TYPE_AUDIO || |
|
|
|
|
!strcmp(tmp, "vcodec") && avctx->codec_type == AVMEDIA_TYPE_VIDEO) |
|
|
|
|
{ |
|
|
|
|
if (ffserver_set_codec(avctx, tmp2, config) < 0) |
|
|
|
|
break; |
|
|
|
@ -390,7 +400,9 @@ static int ffserver_opt_preset(const char *arg, int type, FFServerConfig *config |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename, const char *mime_type) |
|
|
|
|
static AVOutputFormat *ffserver_guess_format(const char *short_name, |
|
|
|
|
const char *filename, |
|
|
|
|
const char *mime_type) |
|
|
|
|
{ |
|
|
|
|
AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type); |
|
|
|
|
|
|
|
|
@ -409,7 +421,9 @@ static AVOutputFormat *ffserver_guess_format(const char *short_name, const char |
|
|
|
|
return fmt; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void vreport_config_error(const char *filename, int line_num, int log_level, int *errors, const char *fmt, va_list vl) |
|
|
|
|
static void vreport_config_error(const char *filename, int line_num, |
|
|
|
|
int log_level, int *errors, const char *fmt, |
|
|
|
|
va_list vl) |
|
|
|
|
{ |
|
|
|
|
av_log(NULL, log_level, "%s:%d: ", filename, line_num); |
|
|
|
|
av_vlog(NULL, log_level, fmt, vl); |
|
|
|
@ -417,7 +431,9 @@ static void vreport_config_error(const char *filename, int line_num, int log_lev |
|
|
|
|
(*errors)++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void report_config_error(const char *filename, int line_num, int log_level, int *errors, const char *fmt, ...) |
|
|
|
|
static void report_config_error(const char *filename, int line_num, |
|
|
|
|
int log_level, int *errors, |
|
|
|
|
const char *fmt, ...) |
|
|
|
|
{ |
|
|
|
|
va_list vl; |
|
|
|
|
va_start(vl, fmt); |
|
|
|
@ -425,8 +441,9 @@ static void report_config_error(const char *filename, int line_num, int log_leve |
|
|
|
|
va_end(vl); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ffserver_set_int_param(int *dest, const char *value, int factor, int min, int max, |
|
|
|
|
FFServerConfig *config, const char *error_msg, ...) |
|
|
|
|
static int ffserver_set_int_param(int *dest, const char *value, int factor, |
|
|
|
|
int min, int max, FFServerConfig *config, |
|
|
|
|
const char *error_msg, ...) |
|
|
|
|
{ |
|
|
|
|
int tmp; |
|
|
|
|
char *tailp; |
|
|
|
@ -457,8 +474,10 @@ static int ffserver_set_int_param(int *dest, const char *value, int factor, int |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ffserver_set_float_param(float *dest, const char *value, float factor, float min, float max, |
|
|
|
|
FFServerConfig *config, const char *error_msg, ...) |
|
|
|
|
static int ffserver_set_float_param(float *dest, const char *value, |
|
|
|
|
float factor, float min, float max, |
|
|
|
|
FFServerConfig *config, |
|
|
|
|
const char *error_msg, ...) |
|
|
|
|
{ |
|
|
|
|
double tmp; |
|
|
|
|
char *tailp; |
|
|
|
@ -486,7 +505,8 @@ static int ffserver_set_float_param(float *dest, const char *value, float factor |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ffserver_save_avoption(const char *opt, const char *arg, int type, FFServerConfig *config) |
|
|
|
|
static int ffserver_save_avoption(const char *opt, const char *arg, int type, |
|
|
|
|
FFServerConfig *config) |
|
|
|
|
{ |
|
|
|
|
static int hinted = 0; |
|
|
|
|
int ret = 0; |
|
|
|
@ -537,31 +557,35 @@ static int ffserver_save_avoption(const char *opt, const char *arg, int type, FF |
|
|
|
|
option = opt; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
o = av_opt_find(ctx, option, NULL, type | AV_OPT_FLAG_ENCODING_PARAM, AV_OPT_SEARCH_CHILDREN); |
|
|
|
|
if (!o && (!strcmp(option, "time_base") || !strcmp(option, "pixel_format") || |
|
|
|
|
!strcmp(option, "video_size") || !strcmp(option, "codec_tag"))) |
|
|
|
|
o = av_opt_find(ctx, option, NULL, type | AV_OPT_FLAG_ENCODING_PARAM, |
|
|
|
|
AV_OPT_SEARCH_CHILDREN); |
|
|
|
|
if (!o && |
|
|
|
|
(!strcmp(option, "time_base") || !strcmp(option, "pixel_format") || |
|
|
|
|
!strcmp(option, "video_size") || !strcmp(option, "codec_tag"))) |
|
|
|
|
o = av_opt_find(ctx, option, NULL, 0, 0); |
|
|
|
|
if (!o) { |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, "Option not found: '%s'\n", opt); |
|
|
|
|
if (!hinted && ctx->codec_id == AV_CODEC_ID_NONE) { |
|
|
|
|
hinted = 1; |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, NULL, |
|
|
|
|
"If '%s' is a codec private option, then prefix it with codec name, " |
|
|
|
|
"for example '%s:%s %s' or define codec earlier.\n", |
|
|
|
|
opt, avcodec_get_name(guessed_codec_id) ,opt, arg); |
|
|
|
|
report_config_error(config->filename, config->line_num, |
|
|
|
|
AV_LOG_ERROR, NULL, "If '%s' is a codec private" |
|
|
|
|
"option, then prefix it with codec name, for " |
|
|
|
|
"example '%s:%s %s' or define codec earlier.\n", |
|
|
|
|
opt, avcodec_get_name(guessed_codec_id) ,opt, |
|
|
|
|
arg); |
|
|
|
|
} |
|
|
|
|
} else if ((ret = av_opt_set(ctx, option, arg, AV_OPT_SEARCH_CHILDREN)) < 0) { |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, "Invalid value for option %s (%s): %s\n", opt, |
|
|
|
|
arg, av_err2str(ret)); |
|
|
|
|
} else if ((e = av_dict_get(*dict, option, NULL, 0))) { |
|
|
|
|
if ((o->type == AV_OPT_TYPE_FLAGS) && arg && (arg[0] == '+' || arg[0] == '-')) |
|
|
|
|
if ((o->type == AV_OPT_TYPE_FLAGS) && arg && |
|
|
|
|
(arg[0] == '+' || arg[0] == '-')) |
|
|
|
|
return av_dict_set(dict, option, arg, AV_DICT_APPEND); |
|
|
|
|
report_config_error(config->filename, config->line_num, AV_LOG_ERROR, |
|
|
|
|
&config->errors, |
|
|
|
|
"Redeclaring value of option '%s'. Previous value was: '%s'.\n", |
|
|
|
|
opt, e->value); |
|
|
|
|
&config->errors, "Redeclaring value of option '%s'." |
|
|
|
|
"Previous value was: '%s'.\n", opt, e->value); |
|
|
|
|
} else if (av_dict_set(dict, option, arg, 0) < 0) { |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
@ -590,9 +614,11 @@ static int ffserver_parse_config_global(FFServerConfig *config, const char *cmd, |
|
|
|
|
if (val < 1024) |
|
|
|
|
WARNING("Trying to use IETF assigned system port: '%d'\n", val); |
|
|
|
|
config->http_addr.sin_port = htons(val); |
|
|
|
|
} else if (!av_strcasecmp(cmd, "HTTPBindAddress") || !av_strcasecmp(cmd, "BindAddress")) { |
|
|
|
|
} else if (!av_strcasecmp(cmd, "HTTPBindAddress") || |
|
|
|
|
!av_strcasecmp(cmd, "BindAddress")) { |
|
|
|
|
if (!av_strcasecmp(cmd, "BindAddress")) |
|
|
|
|
WARNING("BindAddress option is deprecated. Use HTTPBindAddress instead.\n"); |
|
|
|
|
WARNING("BindAddress option is deprecated. Use HTTPBindAddress " |
|
|
|
|
"instead.\n"); |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
if (resolve_host(&config->http_addr.sin_addr, arg)) |
|
|
|
|
ERROR("Invalid host/IP address: '%s'\n", arg); |
|
|
|
@ -612,17 +638,21 @@ static int ffserver_parse_config_global(FFServerConfig *config, const char *cmd, |
|
|
|
|
ffserver_set_int_param(&val, arg, 0, 1, 65535, config, |
|
|
|
|
"Invalid MaxHTTPConnections: %s\n", arg); |
|
|
|
|
config->nb_max_http_connections = val; |
|
|
|
|
if (config->nb_max_connections > config->nb_max_http_connections) |
|
|
|
|
ERROR("Inconsistent configuration: MaxClients(%d) > MaxHTTPConnections(%d)\n", |
|
|
|
|
config->nb_max_connections, config->nb_max_http_connections); |
|
|
|
|
if (config->nb_max_connections > config->nb_max_http_connections) { |
|
|
|
|
ERROR("Inconsistent configuration: MaxClients(%d) > " |
|
|
|
|
"MaxHTTPConnections(%d)\n", config->nb_max_connections, |
|
|
|
|
config->nb_max_http_connections); |
|
|
|
|
} |
|
|
|
|
} else if (!av_strcasecmp(cmd, "MaxClients")) { |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
ffserver_set_int_param(&val, arg, 0, 1, 65535, config, |
|
|
|
|
"Invalid MaxClients: '%s'\n", arg); |
|
|
|
|
config->nb_max_connections = val; |
|
|
|
|
if (config->nb_max_connections > config->nb_max_http_connections) |
|
|
|
|
ERROR("Inconsistent configuration: MaxClients(%d) > MaxHTTPConnections(%d)\n", |
|
|
|
|
config->nb_max_connections, config->nb_max_http_connections); |
|
|
|
|
if (config->nb_max_connections > config->nb_max_http_connections) { |
|
|
|
|
ERROR("Inconsistent configuration: MaxClients(%d) > " |
|
|
|
|
"MaxHTTPConnections(%d)\n", config->nb_max_connections, |
|
|
|
|
config->nb_max_http_connections); |
|
|
|
|
} |
|
|
|
|
} else if (!av_strcasecmp(cmd, "MaxBandwidth")) { |
|
|
|
|
int64_t llval; |
|
|
|
|
char *tailp; |
|
|
|
@ -634,8 +664,10 @@ static int ffserver_parse_config_global(FFServerConfig *config, const char *cmd, |
|
|
|
|
else |
|
|
|
|
config->max_bandwidth = llval; |
|
|
|
|
} else if (!av_strcasecmp(cmd, "CustomLog")) { |
|
|
|
|
if (!config->debug) |
|
|
|
|
ffserver_get_arg(config->logfilename, sizeof(config->logfilename), p); |
|
|
|
|
if (!config->debug) { |
|
|
|
|
ffserver_get_arg(config->logfilename, sizeof(config->logfilename), |
|
|
|
|
p); |
|
|
|
|
} |
|
|
|
|
} else if (!av_strcasecmp(cmd, "LoadModule")) { |
|
|
|
|
ERROR("Loadable modules are no longer supported\n"); |
|
|
|
|
} else if (!av_strcasecmp(cmd, "NoDefaults")) { |
|
|
|
@ -699,15 +731,16 @@ static int ffserver_parse_config_feed(FFServerConfig *config, const char *cmd, c |
|
|
|
|
|
|
|
|
|
feed->child_argv[i] = |
|
|
|
|
av_asprintf("http://%s:%d/%s", |
|
|
|
|
(config->http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" : |
|
|
|
|
inet_ntoa(config->http_addr.sin_addr), ntohs(config->http_addr.sin_port), |
|
|
|
|
feed->filename); |
|
|
|
|
(config->http_addr.sin_addr.s_addr == INADDR_ANY) ? |
|
|
|
|
"127.0.0.1" : inet_ntoa(config->http_addr.sin_addr), |
|
|
|
|
ntohs(config->http_addr.sin_port), feed->filename); |
|
|
|
|
if (!feed->child_argv[i]) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} else if (!av_strcasecmp(cmd, "ACL")) { |
|
|
|
|
ffserver_parse_acl_row(NULL, feed, NULL, *p, config->filename, |
|
|
|
|
config->line_num); |
|
|
|
|
} else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) { |
|
|
|
|
} else if (!av_strcasecmp(cmd, "File") || |
|
|
|
|
!av_strcasecmp(cmd, "ReadOnlyFile")) { |
|
|
|
|
ffserver_get_arg(feed->feed_filename, sizeof(feed->feed_filename), p); |
|
|
|
|
feed->readonly = !av_strcasecmp(cmd, "ReadOnlyFile"); |
|
|
|
|
} else if (!av_strcasecmp(cmd, "Truncate")) { |
|
|
|
@ -742,9 +775,10 @@ static int ffserver_parse_config_feed(FFServerConfig *config, const char *cmd, c |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
feed->feed_max_size = (int64_t)fsize; |
|
|
|
|
if (feed->feed_max_size < FFM_PACKET_SIZE*4) |
|
|
|
|
if (feed->feed_max_size < FFM_PACKET_SIZE*4) { |
|
|
|
|
ERROR("Feed max file size is too small. Must be at least %d.\n", |
|
|
|
|
FFM_PACKET_SIZE*4); |
|
|
|
|
FFM_PACKET_SIZE*4); |
|
|
|
|
} |
|
|
|
|
} else if (!av_strcasecmp(cmd, "</Feed>")) { |
|
|
|
|
*pfeed = NULL; |
|
|
|
|
} else { |
|
|
|
@ -883,7 +917,8 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
ffserver_set_float_param(&f, arg, 1000, -FLT_MAX, FLT_MAX, config, |
|
|
|
|
"Invalid %s: '%s'\n", cmd, arg); |
|
|
|
|
if (ffserver_save_avoption_int("ab", (int64_t)lrintf(f), AV_OPT_FLAG_AUDIO_PARAM, config) < 0) |
|
|
|
|
if (ffserver_save_avoption_int("ab", (int64_t)lrintf(f), |
|
|
|
|
AV_OPT_FLAG_AUDIO_PARAM, config) < 0) |
|
|
|
|
goto nomem; |
|
|
|
|
} else if (!av_strcasecmp(cmd, "AudioChannels")) { |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
@ -909,7 +944,7 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
} |
|
|
|
|
} else |
|
|
|
|
ERROR("Incorrect format for VideoBitRateRange. It should be " |
|
|
|
|
"<min>-<max>: '%s'.\n", arg); |
|
|
|
|
"<min>-<max>: '%s'.\n", arg); |
|
|
|
|
} else if (!av_strcasecmp(cmd, "Debug")) { |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
if (ffserver_save_avoption("debug", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0 || |
|
|
|
@ -929,13 +964,13 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
} else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) { |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
ffserver_set_int_param(&val, arg, 1000, INT_MIN, INT_MAX, config, |
|
|
|
|
"Invalid %s: '%s'", cmd, arg); |
|
|
|
|
"Invalid %s: '%s'", cmd, arg); |
|
|
|
|
if (ffserver_save_avoption_int("bt", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) |
|
|
|
|
goto nomem; |
|
|
|
|
} else if (!av_strcasecmp(cmd, "VideoBitRate")) { |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
ffserver_set_int_param(&val, arg, 1000, INT_MIN, INT_MAX, config, |
|
|
|
|
"Invalid %s: '%s'", cmd, arg); |
|
|
|
|
"Invalid %s: '%s'", cmd, arg); |
|
|
|
|
if (ffserver_save_avoption_int("b", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) |
|
|
|
|
goto nomem; |
|
|
|
|
} else if (!av_strcasecmp(cmd, "VideoSize")) { |
|
|
|
@ -983,9 +1018,11 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
ffserver_get_arg(arg2, sizeof(arg2), p); |
|
|
|
|
if (!av_strcasecmp(cmd, "AVOptionVideo")) |
|
|
|
|
ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_VIDEO_PARAM, config); |
|
|
|
|
ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_VIDEO_PARAM, |
|
|
|
|
config); |
|
|
|
|
else |
|
|
|
|
ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_AUDIO_PARAM, config); |
|
|
|
|
ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_AUDIO_PARAM, |
|
|
|
|
config); |
|
|
|
|
if (ret < 0) |
|
|
|
|
goto nomem; |
|
|
|
|
} else if (!av_strcasecmp(cmd, "AVPresetVideo") || |
|
|
|
@ -998,7 +1035,8 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
} else if (!av_strcasecmp(cmd, "VideoTag")) { |
|
|
|
|
ffserver_get_arg(arg, sizeof(arg), p); |
|
|
|
|
if (strlen(arg) == 4 && |
|
|
|
|
ffserver_save_avoption_int("codec_tag", MKTAG(arg[0], arg[1], arg[2], arg[3]), |
|
|
|
|
ffserver_save_avoption_int("codec_tag", |
|
|
|
|
MKTAG(arg[0], arg[1], arg[2], arg[3]), |
|
|
|
|
AV_OPT_FLAG_VIDEO_PARAM, config) < 0) |
|
|
|
|
goto nomem; |
|
|
|
|
} else if (!av_strcasecmp(cmd, "BitExact")) { |
|
|
|
@ -1074,13 +1112,15 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm")) { |
|
|
|
|
if (config->dummy_actx->codec_id == AV_CODEC_ID_NONE) |
|
|
|
|
config->dummy_actx->codec_id = config->guessed_audio_codec_id; |
|
|
|
|
if (!config->no_audio && config->dummy_actx->codec_id != AV_CODEC_ID_NONE) { |
|
|
|
|
if (!config->no_audio && |
|
|
|
|
config->dummy_actx->codec_id != AV_CODEC_ID_NONE) { |
|
|
|
|
AVCodecContext *audio_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_actx->codec_id)); |
|
|
|
|
add_codec(stream, audio_enc, config); |
|
|
|
|
} |
|
|
|
|
if (config->dummy_vctx->codec_id == AV_CODEC_ID_NONE) |
|
|
|
|
config->dummy_vctx->codec_id = config->guessed_video_codec_id; |
|
|
|
|
if (!config->no_video && config->dummy_vctx->codec_id != AV_CODEC_ID_NONE) { |
|
|
|
|
if (!config->no_video && |
|
|
|
|
config->dummy_vctx->codec_id != AV_CODEC_ID_NONE) { |
|
|
|
|
AVCodecContext *video_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_vctx->codec_id)); |
|
|
|
|
add_codec(stream, video_enc, config); |
|
|
|
|
} |
|
|
|
@ -1090,7 +1130,8 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
avcodec_free_context(&config->dummy_vctx); |
|
|
|
|
avcodec_free_context(&config->dummy_actx); |
|
|
|
|
*pstream = NULL; |
|
|
|
|
} else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) { |
|
|
|
|
} else if (!av_strcasecmp(cmd, "File") || |
|
|
|
|
!av_strcasecmp(cmd, "ReadOnlyFile")) { |
|
|
|
|
ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename), |
|
|
|
|
p); |
|
|
|
|
} else if (!av_strcasecmp(cmd, "UseDefaults")) { |
|
|
|
@ -1114,7 +1155,8 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ffserver_parse_config_redirect(FFServerConfig *config, const char *cmd, const char **p, |
|
|
|
|
static int ffserver_parse_config_redirect(FFServerConfig *config, |
|
|
|
|
const char *cmd, const char **p, |
|
|
|
|
FFServerStream **predirect) |
|
|
|
|
{ |
|
|
|
|
FFServerStream *redirect; |
|
|
|
|