Newer
Older
line_num, "Invalid %s: %s", cmd, arg);
if (av_dict_set(&config->video_conf, cmd, arg, 0) < 0)
goto nomem;
} else if (!av_strcasecmp(cmd, "DarkMask")) {
ffserver_get_arg(arg, sizeof(arg), p);
ffserver_set_float_param(NULL, arg, 0, -FLT_MAX, FLT_MAX, config,
line_num, "Invalid %s: %s", cmd, arg);
if (av_dict_set(&config->video_conf, cmd, arg, 0) < 0)
goto nomem;
} else if (!av_strcasecmp(cmd, "NoVideo")) {
config->video_id = AV_CODEC_ID_NONE;
} else if (!av_strcasecmp(cmd, "NoAudio")) {
config->audio_id = AV_CODEC_ID_NONE;
} else if (!av_strcasecmp(cmd, "ACL")) {
ffserver_parse_acl_row(stream, NULL, NULL, *p, config->filename,
line_num);
} else if (!av_strcasecmp(cmd, "DynamicACL")) {
ffserver_get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), p);
} else if (!av_strcasecmp(cmd, "RTSPOption")) {
ffserver_get_arg(arg, sizeof(arg), p);
av_freep(&stream->rtsp_option);
stream->rtsp_option = av_strdup(arg);
} else if (!av_strcasecmp(cmd, "MulticastAddress")) {
ffserver_get_arg(arg, sizeof(arg), p);
if (resolve_host(&stream->multicast_ip, arg))
ERROR("Invalid host/IP address: %s\n", arg);
stream->is_multicast = 1;
stream->loop = 1; /* default is looping */
} else if (!av_strcasecmp(cmd, "MulticastPort")) {
ffserver_get_arg(arg, sizeof(arg), p);
ffserver_set_int_param(&val, arg, 0, 1, 65535, config, line_num,
"Invalid MulticastPort: %s\n", arg);
} else if (!av_strcasecmp(cmd, "MulticastTTL")) {
ffserver_get_arg(arg, sizeof(arg), p);
ffserver_set_int_param(&val, arg, 0, INT_MIN, INT_MAX, config,
line_num, "Invalid MulticastTTL: %s\n", arg);
} else if (!av_strcasecmp(cmd, "NoLoop")) {
stream->loop = 0;
} else if (!av_strcasecmp(cmd, "</Stream>")) {
if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm")) {
if (config->audio_id != AV_CODEC_ID_NONE) {
AVCodecContext *audio_enc = avcodec_alloc_context3(avcodec_find_encoder(config->audio_id));
if (config->audio_preset &&
ffserver_opt_preset(arg, audio_enc, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_ENCODING_PARAM,
NULL, NULL) < 0)
ERROR("Could not apply preset '%s'\n", arg);
ffserver_apply_stream_config(audio_enc, config->audio_conf,
&config->audio_opts);
add_codec(stream, audio_enc);
}
if (config->video_id != AV_CODEC_ID_NONE) {
AVCodecContext *video_enc = avcodec_alloc_context3(avcodec_find_encoder(config->video_id));
if (config->video_preset &&
ffserver_opt_preset(arg, video_enc, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_ENCODING_PARAM,
NULL, NULL) < 0)
ERROR("Could not apply preset '%s'\n", arg);
ffserver_apply_stream_config(video_enc, config->video_conf,
&config->video_opts);
add_codec(stream, video_enc);
av_dict_free(&config->video_opts);
av_dict_free(&config->video_conf);
av_dict_free(&config->audio_opts);
av_dict_free(&config->audio_conf);
av_freep(&config->video_preset);
av_freep(&config->audio_preset);
avcodec_free_context(&config->dummy_ctx);
*pstream = NULL;
} else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) {
ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename),
p);
} else {
ERROR("Invalid entry '%s' inside <Stream></Stream>\n", cmd);
}
return 0;
nomem:
av_log(NULL, AV_LOG_ERROR, "Out of memory. Aborting.\n");
av_dict_free(&config->video_opts);
av_dict_free(&config->video_conf);
av_dict_free(&config->audio_opts);
av_dict_free(&config->audio_conf);
av_freep(&config->video_preset);
av_freep(&config->audio_preset);
avcodec_free_context(&config->dummy_ctx);
return AVERROR(ENOMEM);
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
}
static int ffserver_parse_config_redirect(FFServerConfig *config, const char *cmd, const char **p,
int line_num, FFServerStream **predirect)
{
FFServerStream *redirect;
av_assert0(predirect);
redirect = *predirect;
if (!av_strcasecmp(cmd, "<Redirect")) {
char *q;
redirect = av_mallocz(sizeof(FFServerStream));
if (!redirect)
return AVERROR(ENOMEM);
ffserver_get_arg(redirect->filename, sizeof(redirect->filename), p);
q = strrchr(redirect->filename, '>');
if (*q)
*q = '\0';
redirect->stream_type = STREAM_TYPE_REDIRECT;
*predirect = redirect;
return 0;
}
av_assert0(redirect);
if (!av_strcasecmp(cmd, "URL")) {
ffserver_get_arg(redirect->feed_filename,
sizeof(redirect->feed_filename), p);
} else if (!av_strcasecmp(cmd, "</Redirect>")) {
if (!redirect->feed_filename[0])
ERROR("No URL found for <Redirect>\n");
*predirect = NULL;
} else {
ERROR("Invalid entry '%s' inside <Redirect></Redirect>\n", cmd);
}
return 0;
}
int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config)
{
FILE *f;
char line[1024];
char cmd[64];
const char *p;
int line_num = 0;
FFServerStream **last_stream, *stream = NULL, *redirect = NULL;
FFServerStream **last_feed, *feed = NULL;
int ret = 0;
av_assert0(config);
f = fopen(filename, "r");
if (!f) {
ret = AVERROR(errno);
av_log(NULL, AV_LOG_ERROR,
"Could not open the configuration file '%s'\n", filename);
return ret;
}
config->first_stream = NULL;
last_stream = &config->first_stream;
config->first_feed = NULL;
last_feed = &config->first_feed;
config->errors = config->warnings = 0;
for(;;) {
if (fgets(line, sizeof(line), f) == NULL)
break;
line_num++;
p = line;
while (av_isspace(*p))
p++;
if (*p == '\0' || *p == '#')
continue;
ffserver_get_arg(cmd, sizeof(cmd), &p);
if (feed || !av_strcasecmp(cmd, "<Feed")) {
int opening = !av_strcasecmp(cmd, "<Feed");
if (opening && (stream || feed || redirect)) {
ERROR("Already in a tag\n");
} else {
if ((ret = ffserver_parse_config_feed(config, cmd, &p, line_num, &feed)) < 0)
if (opening) {
/* add in stream list */
*last_stream = feed;
last_stream = &feed->next;
/* add in feed list */
*last_feed = feed;
last_feed = &feed->next_feed;
} else if (stream || !av_strcasecmp(cmd, "<Stream")) {
int opening = !av_strcasecmp(cmd, "<Stream");
if (opening && (stream || feed || redirect)) {
ERROR("Already in a tag\n");
} else {
if ((ret = ffserver_parse_config_stream(config, cmd, &p, line_num, &stream)) < 0)
break;
if (opening) {
/* add in stream list */
*last_stream = stream;
last_stream = &stream->next;
} else if (redirect || !av_strcasecmp(cmd, "<Redirect")) {
int opening = !av_strcasecmp(cmd, "<Redirect");
if (opening && (stream || feed || redirect))
ERROR("Already in a tag\n");
else {
if ((ret = ffserver_parse_config_redirect(config, cmd, &p, line_num, &redirect)) < 0)
break;
if (opening) {
/* add in stream list */
*last_stream = redirect;
last_stream = &redirect->next;
}
}
} else {
ffserver_parse_config_global(config, cmd, &p, line_num);
}
}
fclose(f);
if (ret < 0)
return ret;
if (config->errors)
return AVERROR(EINVAL);
else
return 0;
}
#undef ERROR
#undef WARNING