Newer
Older
if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
codec ? codec->name : NULL))) {
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
fprintf(stderr, "File for preset '%s' not found\n", arg);
return 1;
}
while(!feof(f)){
int e= fscanf(f, "%999[^\n]\n", line) - 1;
if(line[0] == '#' && !e)
continue;
e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
if(e){
fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
ret = 1;
break;
}
if(!strcmp(tmp, "acodec")){
*audio_id = opt_audio_codec(tmp2);
}else if(!strcmp(tmp, "vcodec")){
*video_id = opt_video_codec(tmp2);
}else if(!strcmp(tmp, "scodec")){
/* opt_subtitle_codec(tmp2); */
}else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
ret = 1;
break;
}
}
fclose(f);
return ret;
}
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);
if (fmt) {
AVOutputFormat *stream_fmt;
char stream_format_name[64];
snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
if (stream_fmt)
fmt = stream_fmt;
}
return fmt;
}
static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
{
va_list vl;
va_start(vl, fmt);
fprintf(stderr, "%s:%d: ", filename, line_num);
vfprintf(stderr, fmt, vl);
va_end(vl);
(*errors)++;
}
static int parse_ffconfig(const char *filename)
{
FILE *f;
char line[1024];
char cmd[64];
char arg[1024];
const char *p;
int val, errors, line_num;
FFStream **last_stream, *stream, *redirect;
FFStream **last_feed, *feed, *s;
enum AVCodecID audio_id, video_id;
f = fopen(filename, "r");
if (!f) {
perror(filename);
return -1;
}
errors = 0;
line_num = 0;
first_stream = NULL;
last_stream = &first_stream;
first_feed = NULL;
last_feed = &first_feed;
stream = NULL;
feed = NULL;
audio_id = AV_CODEC_ID_NONE;
video_id = AV_CODEC_ID_NONE;
#define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
for(;;) {
if (fgets(line, sizeof(line), f) == NULL)
break;
line_num++;
p = line;
p++;
if (*p == '\0' || *p == '#')
continue;
get_arg(cmd, sizeof(cmd), &p);
if (!av_strcasecmp(cmd, "Port")) {
val = atoi(arg);
if (val < 1 || val > 65536) {
ERROR("Invalid_port: %s\n", arg);
}
my_http_addr.sin_port = htons(val);
} else if (!av_strcasecmp(cmd, "BindAddress")) {
Alex Beregszaszi
committed
if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
Fabrice Bellard
committed
}
} else if (!av_strcasecmp(cmd, "NoDaemon")) {
// do nothing here, its the default now
} else if (!av_strcasecmp(cmd, "RTSPPort")) {
Fabrice Bellard
committed
get_arg(arg, sizeof(arg), &p);
val = atoi(arg);
if (val < 1 || val > 65536) {
ERROR("%s:%d: Invalid port: %s\n", arg);
}
my_rtsp_addr.sin_port = htons(atoi(arg));
} else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
Fabrice Bellard
committed
get_arg(arg, sizeof(arg), &p);
Alex Beregszaszi
committed
if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
ERROR("Invalid host/IP address: %s\n", arg);
} else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
get_arg(arg, sizeof(arg), &p);
val = atoi(arg);
if (val < 1 || val > 65536) {
ERROR("Invalid MaxHTTPConnections: %s\n", arg);
}
nb_max_http_connections = val;
} else if (!av_strcasecmp(cmd, "MaxClients")) {
if (val < 1 || val > nb_max_http_connections) {
ERROR("Invalid MaxClients: %s\n", arg);
} else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
int64_t llval;
get_arg(arg, sizeof(arg), &p);
llval = atoll(arg);
if (llval < 10 || llval > 10000000) {
ERROR("Invalid MaxBandwidth: %s\n", arg);
max_bandwidth = llval;
} else if (!av_strcasecmp(cmd, "CustomLog")) {
if (!ffserver_debug)
get_arg(logfilename, sizeof(logfilename), &p);
} else if (!av_strcasecmp(cmd, "<Feed")) {
/*********************************************/
/* Feed related options */
char *q;
if (stream || feed) {
ERROR("Already in a tag\n");
} else {
feed = av_mallocz(sizeof(FFStream));
get_arg(feed->filename, sizeof(feed->filename), &p);
q = strrchr(feed->filename, '>');
if (*q)
*q = '\0';
for (s = first_feed; s; s = s->next) {
if (!strcmp(feed->filename, s->filename)) {
ERROR("Feed '%s' already registered\n", s->filename);
}
}
feed->fmt = av_guess_format("ffm", NULL, NULL);
/* defaut feed file */
snprintf(feed->feed_filename, sizeof(feed->feed_filename),
"/tmp/%s.ffm", feed->filename);
feed->feed_max_size = 5 * 1024 * 1024;
feed->is_feed = 1;
feed->feed = feed; /* self feeding :-) */
/* 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 (!av_strcasecmp(cmd, "Launch")) {
feed->child_argv = av_mallocz(64 * sizeof(char *));
Alex Beregszaszi
committed
for (i = 0; i < 62; i++) {
feed->child_argv[i] = av_asprintf("http://%s:%d/%s",
(my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
inet_ntoa(my_http_addr.sin_addr),
ntohs(my_http_addr.sin_port), feed->filename);
} else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
Philip Gladstone
committed
if (feed) {
get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
feed->readonly = 1;
} else if (stream) {
get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
}
} else if (!av_strcasecmp(cmd, "File")) {
if (feed) {
get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
} else if (!av_strcasecmp(cmd, "Truncate")) {
if (feed) {
get_arg(arg, sizeof(arg), &p);
feed->truncate = strtod(arg, NULL);
}
} else if (!av_strcasecmp(cmd, "FileMaxSize")) {
double fsize;
get_arg(arg, sizeof(arg), &p);
p1 = arg;
switch(toupper(*p1)) {
case 'K':
fsize *= 1024;
break;
case 'M':
fsize *= 1024 * 1024;
break;
case 'G':
fsize *= 1024 * 1024 * 1024;
break;
}
feed->feed_max_size = (int64_t)fsize;
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);
} else if (!av_strcasecmp(cmd, "</Feed>")) {
ERROR("No corresponding <Feed> for </Feed>\n");
} else if (!av_strcasecmp(cmd, "<Stream")) {
/*********************************************/
/* Stream related options */
char *q;
if (stream || feed) {
ERROR("Already in a tag\n");
FFStream *s;
stream = av_mallocz(sizeof(FFStream));
get_arg(stream->filename, sizeof(stream->filename), &p);
q = strrchr(stream->filename, '>');
for (s = first_stream; s; s = s->next) {
if (!strcmp(stream->filename, s->filename)) {
ERROR("Stream '%s' already registered\n", s->filename);
}
}
stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
avcodec_get_context_defaults3(&video_enc, NULL);
avcodec_get_context_defaults3(&audio_enc, NULL);
audio_id = AV_CODEC_ID_NONE;
video_id = AV_CODEC_ID_NONE;
if (stream->fmt) {
audio_id = stream->fmt->audio_codec;
video_id = stream->fmt->video_codec;
}
*last_stream = stream;
last_stream = &stream->next;
} else if (!av_strcasecmp(cmd, "Feed")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
FFStream *sfeed;
sfeed = first_feed;
while (sfeed != NULL) {
if (!strcmp(sfeed->filename, arg))
break;
sfeed = sfeed->next_feed;
}
ERROR("feed '%s' not defined\n", arg);
} else if (!av_strcasecmp(cmd, "Format")) {
if (!strcmp(arg, "status")) {
stream->stream_type = STREAM_TYPE_STATUS;
stream->fmt = NULL;
} else {
stream->stream_type = STREAM_TYPE_LIVE;
/* jpeg cannot be used here, so use single frame jpeg */
if (!strcmp(arg, "jpeg"))
strcpy(arg, "mjpeg");
stream->fmt = ffserver_guess_format(arg, NULL, NULL);
ERROR("Unknown Format: %s\n", arg);
}
}
if (stream->fmt) {
audio_id = stream->fmt->audio_codec;
video_id = stream->fmt->video_codec;
} else if (!av_strcasecmp(cmd, "InputFormat")) {
get_arg(arg, sizeof(arg), &p);
stream->ifmt = av_find_input_format(arg);
if (!stream->ifmt) {
ERROR("Unknown input format: %s\n", arg);
} else if (!av_strcasecmp(cmd, "FaviconURL")) {
if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
} else {
ERROR("FaviconURL only permitted for status streams\n");
} else if (!av_strcasecmp(cmd, "Author")) {
get_arg(stream->author, sizeof(stream->author), &p);
} else if (!av_strcasecmp(cmd, "Comment")) {
get_arg(stream->comment, sizeof(stream->comment), &p);
} else if (!av_strcasecmp(cmd, "Copyright")) {
get_arg(stream->copyright, sizeof(stream->copyright), &p);
} else if (!av_strcasecmp(cmd, "Title")) {
get_arg(stream->title, sizeof(stream->title), &p);
} else if (!av_strcasecmp(cmd, "Preroll")) {
get_arg(arg, sizeof(arg), &p);
stream->prebuffer = atof(arg) * 1000;
} else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
Philip Gladstone
committed
stream->send_on_key = 1;
} else if (!av_strcasecmp(cmd, "AudioCodec")) {
Philip Gladstone
committed
get_arg(arg, sizeof(arg), &p);
audio_id = opt_audio_codec(arg);
if (audio_id == AV_CODEC_ID_NONE) {
ERROR("Unknown AudioCodec: %s\n", arg);
Philip Gladstone
committed
}
} else if (!av_strcasecmp(cmd, "VideoCodec")) {
Philip Gladstone
committed
get_arg(arg, sizeof(arg), &p);
video_id = opt_video_codec(arg);
if (video_id == AV_CODEC_ID_NONE) {
ERROR("Unknown VideoCodec: %s\n", arg);
Philip Gladstone
committed
}
} else if (!av_strcasecmp(cmd, "MaxTime")) {
get_arg(arg, sizeof(arg), &p);
stream->max_time = atof(arg) * 1000;
} else if (!av_strcasecmp(cmd, "AudioBitRate")) {
audio_enc.bit_rate = lrintf(atof(arg) * 1000);
} else if (!av_strcasecmp(cmd, "AudioChannels")) {
} else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
} else if (!av_strcasecmp(cmd, "AudioQuality")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
} else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
if (stream) {
int minrate, maxrate;
get_arg(arg, sizeof(arg), &p);
if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
video_enc.rc_min_rate = minrate * 1000;
video_enc.rc_max_rate = maxrate * 1000;
} else {
ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
} else if (!av_strcasecmp(cmd, "Debug")) {
Philip Gladstone
committed
if (stream) {
get_arg(arg, sizeof(arg), &p);
video_enc.debug = strtol(arg,0,0);
}
} else if (!av_strcasecmp(cmd, "Strict")) {
Philip Gladstone
committed
if (stream) {
get_arg(arg, sizeof(arg), &p);
video_enc.strict_std_compliance = atoi(arg);
}
} else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
Henning Haaland Kulander
committed
if (stream) {
get_arg(arg, sizeof(arg), &p);
Philip Gladstone
committed
video_enc.rc_buffer_size = atoi(arg) * 8*1024;
Henning Haaland Kulander
committed
}
} else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
if (stream) {
get_arg(arg, sizeof(arg), &p);
video_enc.bit_rate_tolerance = atoi(arg) * 1000;
}
} else if (!av_strcasecmp(cmd, "VideoBitRate")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.bit_rate = atoi(arg) * 1000;
}
} else if (!av_strcasecmp(cmd, "VideoSize")) {
av_parse_video_size(&video_enc.width, &video_enc.height, arg);
if ((video_enc.width % 16) != 0 ||
(video_enc.height % 16) != 0) {
ERROR("Image size must be a multiple of 16\n");
} else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
if (av_parse_video_rate(&frame_rate, arg) < 0) {
ERROR("Incorrect frame rate: %s\n", arg);
} else {
video_enc.time_base.num = frame_rate.den;
video_enc.time_base.den = frame_rate.num;
}
} else if (!av_strcasecmp(cmd, "VideoGopSize")) {
} else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
} else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
video_enc.mb_decision = FF_MB_DECISION_BITS;
} else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
Philip Gladstone
committed
if (stream) {
video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
Philip Gladstone
committed
video_enc.flags |= CODEC_FLAG_4MV;
}
} else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
!av_strcasecmp(cmd, "AVOptionAudio")) {
char arg2[1024];
AVCodecContext *avctx;
int type;
get_arg(arg, sizeof(arg), &p);
get_arg(arg2, sizeof(arg2), &p);
if (!av_strcasecmp(cmd, "AVOptionVideo")) {
avctx = &video_enc;
type = AV_OPT_FLAG_VIDEO_PARAM;
} else {
avctx = &audio_enc;
type = AV_OPT_FLAG_AUDIO_PARAM;
}
Michael Niedermayer
committed
if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
ERROR("AVOption error: %s %s\n", arg, arg2);
} else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
!av_strcasecmp(cmd, "AVPresetAudio")) {
AVCodecContext *avctx;
int type;
get_arg(arg, sizeof(arg), &p);
if (!av_strcasecmp(cmd, "AVPresetVideo")) {
avctx = &video_enc;
video_enc.codec_id = video_id;
type = AV_OPT_FLAG_VIDEO_PARAM;
} else {
avctx = &audio_enc;
audio_enc.codec_id = audio_id;
type = AV_OPT_FLAG_AUDIO_PARAM;
}
if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
ERROR("AVPreset error: %s\n", arg);
}
} else if (!av_strcasecmp(cmd, "VideoTag")) {
get_arg(arg, sizeof(arg), &p);
if ((strlen(arg) == 4) && stream)
video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
} else if (!av_strcasecmp(cmd, "BitExact")) {
video_enc.flags |= CODEC_FLAG_BITEXACT;
} else if (!av_strcasecmp(cmd, "DctFastint")) {
video_enc.dct_algo = FF_DCT_FASTINT;
} else if (!av_strcasecmp(cmd, "IdctSimple")) {
video_enc.idct_algo = FF_IDCT_SIMPLE;
} else if (!av_strcasecmp(cmd, "Qscale")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.flags |= CODEC_FLAG_QSCALE;
video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
}
} else if (!av_strcasecmp(cmd, "VideoQDiff")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.max_qdiff = atoi(arg);
if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
ERROR("VideoQDiff out of range\n");
} else if (!av_strcasecmp(cmd, "VideoQMax")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.qmax = atoi(arg);
if (video_enc.qmax < 1 || video_enc.qmax > 31) {
ERROR("VideoQMax out of range\n");
} else if (!av_strcasecmp(cmd, "VideoQMin")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.qmin = atoi(arg);
if (video_enc.qmin < 1 || video_enc.qmin > 31) {
ERROR("VideoQMin out of range\n");
} else if (!av_strcasecmp(cmd, "LumaElim")) {
D Richard Felker III
committed
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.luma_elim_threshold = atoi(arg);
} else if (!av_strcasecmp(cmd, "ChromaElim")) {
D Richard Felker III
committed
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.chroma_elim_threshold = atoi(arg);
} else if (!av_strcasecmp(cmd, "LumiMask")) {
D Richard Felker III
committed
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.lumi_masking = atof(arg);
} else if (!av_strcasecmp(cmd, "DarkMask")) {
D Richard Felker III
committed
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.dark_masking = atof(arg);
} else if (!av_strcasecmp(cmd, "NoVideo")) {
} else if (!av_strcasecmp(cmd, "NoAudio")) {
} else if (!av_strcasecmp(cmd, "ACL")) {
parse_acl_row(stream, feed, NULL, p, filename, line_num);
} else if (!av_strcasecmp(cmd, "DynamicACL")) {
if (stream) {
get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
}
} else if (!av_strcasecmp(cmd, "RTSPOption")) {
Fabrice Bellard
committed
get_arg(arg, sizeof(arg), &p);
if (stream) {
av_freep(&stream->rtsp_option);
Fabrice Bellard
committed
}
} else if (!av_strcasecmp(cmd, "MulticastAddress")) {
Fabrice Bellard
committed
get_arg(arg, sizeof(arg), &p);
if (stream) {
Alex Beregszaszi
committed
if (resolve_host(&stream->multicast_ip, arg) != 0) {
ERROR("Invalid host/IP address: %s\n", arg);
Fabrice Bellard
committed
}
stream->is_multicast = 1;
stream->loop = 1; /* default is looping */
Fabrice Bellard
committed
}
} else if (!av_strcasecmp(cmd, "MulticastPort")) {
Fabrice Bellard
committed
get_arg(arg, sizeof(arg), &p);
Fabrice Bellard
committed
stream->multicast_port = atoi(arg);
} else if (!av_strcasecmp(cmd, "MulticastTTL")) {
get_arg(arg, sizeof(arg), &p);
stream->multicast_ttl = atoi(arg);
} else if (!av_strcasecmp(cmd, "NoLoop")) {
stream->loop = 0;
} else if (!av_strcasecmp(cmd, "</Stream>")) {
ERROR("No corresponding <Stream> for </Stream>\n");
if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
if (audio_id != AV_CODEC_ID_NONE) {
audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
audio_enc.codec_id = audio_id;
add_codec(stream, &audio_enc);
}
if (video_id != AV_CODEC_ID_NONE) {
video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
video_enc.codec_id = video_id;
add_codec(stream, &video_enc);
}
} else if (!av_strcasecmp(cmd, "<Redirect")) {
/*********************************************/
char *q;
if (stream || feed || redirect) {
ERROR("Already in a tag\n");
} else {
redirect = av_mallocz(sizeof(FFStream));
*last_stream = redirect;
last_stream = &redirect->next;
get_arg(redirect->filename, sizeof(redirect->filename), &p);
q = strrchr(redirect->filename, '>');
if (*q)
*q = '\0';
redirect->stream_type = STREAM_TYPE_REDIRECT;
}
} else if (!av_strcasecmp(cmd, "URL")) {
get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
} else if (!av_strcasecmp(cmd, "</Redirect>")) {
ERROR("No corresponding <Redirect> for </Redirect>\n");
ERROR("No URL found for <Redirect>\n");
} else if (!av_strcasecmp(cmd, "LoadModule")) {
Fabrice Bellard
committed
get_arg(arg, sizeof(arg), &p);
Fabrice Bellard
committed
load_module(arg);
ERROR("Module support not compiled into this version: '%s'\n", arg);
ERROR("Incorrect keyword: '%s'\n", cmd);
#undef ERROR
fclose(f);
if (errors)
return -1;
else
return 0;
}
static void handle_child_exit(int sig)
{
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
FFStream *feed;
for (feed = first_feed; feed; feed = feed->next) {
if (feed->pid == pid) {
int uptime = time(0) - feed->pid_start;
feed->pid = 0;
fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
/* Turn off any more restarts */
feed->child_argv = 0;
}
}
}
need_to_start_children = 1;
}
static void opt_debug(void)
logfilename[0] = '-';
void show_help_default(const char *opt, const char *arg)
printf("usage: ffserver [options]\n"
"Hyper fast multi format Audio/Video streaming server\n");
printf("\n");
show_help_options(options, "Main options:", 0, 0, 0);
}
static const OptionDef options[] = {
#include "cmdutils_common_opts.h"
{ "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
{ "d", 0, {(void*)opt_debug}, "enable debug mode" },
{ "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
{ NULL },
};
struct sigaction sigact = { { 0 } };
parse_loglevel(argc, argv, options);
av_register_all();
avformat_network_init();
show_banner(argc, argv, options);
parse_options(NULL, argc, argv, options, NULL);
Stefano Sabatini
committed
unsetenv("http_proxy"); /* Kill the http_proxy */
Martin Storsjö
committed
av_lfg_init(&random_state, av_get_random_seed());
sigact.sa_handler = handle_child_exit;
sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
sigaction(SIGCHLD, &sigact, 0);
if (parse_ffconfig(config_filename) < 0) {
fprintf(stderr, "Incorrect config file - exiting.\n");
exit(1);
}
/* open log file if needed */
if (logfilename[0] != '\0') {
if (!strcmp(logfilename, "-"))
else
logfile = fopen(logfilename, "a");
av_log_set_callback(http_av_log);
}
Fabrice Bellard
committed
build_file_streams();
compute_bandwidth();
Fabrice Bellard
committed
if (http_server() < 0) {
http_log("Could not start server\n");