Newer
Older
} else if (!strcasecmp(cmd, "AudioSampleRate")) {
get_arg(arg, sizeof(arg), &p);
} else if (!strcasecmp(cmd, "AudioQuality")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
} else if (!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 {
fprintf(stderr, "%s:%d: Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n",
filename, line_num, arg);
errors++;
}
}
Philip Gladstone
committed
} else if (!strcasecmp(cmd, "Debug")) {
if (stream) {
get_arg(arg, sizeof(arg), &p);
video_enc.debug = strtol(arg,0,0);
}
} else if (!strcasecmp(cmd, "Strict")) {
if (stream) {
get_arg(arg, sizeof(arg), &p);
video_enc.strict_std_compliance = atoi(arg);
}
Henning Haaland Kulander
committed
} else if (!strcasecmp(cmd, "VideoBufferSize")) {
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 (!strcasecmp(cmd, "VideoBitRateTolerance")) {
if (stream) {
get_arg(arg, sizeof(arg), &p);
video_enc.bit_rate_tolerance = atoi(arg) * 1000;
}
} else if (!strcasecmp(cmd, "VideoBitRate")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.bit_rate = atoi(arg) * 1000;
}
} else if (!strcasecmp(cmd, "VideoSize")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
av_parse_video_frame_size(&video_enc.width, &video_enc.height, arg);
if ((video_enc.width % 16) != 0 ||
(video_enc.height % 16) != 0) {
fprintf(stderr, "%s:%d: Image size must be a multiple of 16\n",
filename, line_num);
errors++;
}
}
} else if (!strcasecmp(cmd, "VideoFrameRate")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.time_base.num= DEFAULT_FRAME_RATE_BASE;
video_enc.time_base.den = (int)(strtod(arg, NULL) * video_enc.time_base.num);
}
} else if (!strcasecmp(cmd, "VideoGopSize")) {
get_arg(arg, sizeof(arg), &p);
video_enc.gop_size = atoi(arg);
} else if (!strcasecmp(cmd, "VideoIntraOnly")) {
} else if (!strcasecmp(cmd, "VideoHighQuality")) {
video_enc.mb_decision = FF_MB_DECISION_BITS;
Philip Gladstone
committed
} else if (!strcasecmp(cmd, "Video4MotionVector")) {
if (stream) {
video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
Philip Gladstone
committed
video_enc.flags |= CODEC_FLAG_4MV;
}
} else if (!strcasecmp(cmd, "VideoTag")) {
get_arg(arg, sizeof(arg), &p);
if ((strlen(arg) == 4) && stream)
video_enc.codec_tag = ff_get_fourcc(arg);
} else if (!strcasecmp(cmd, "BitExact")) {
video_enc.flags |= CODEC_FLAG_BITEXACT;
} else if (!strcasecmp(cmd, "DctFastint")) {
video_enc.dct_algo = FF_DCT_FASTINT;
} else if (!strcasecmp(cmd, "IdctSimple")) {
video_enc.idct_algo = FF_IDCT_SIMPLE;
} else if (!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 (!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) {
fprintf(stderr, "%s:%d: VideoQDiff out of range\n",
filename, line_num);
errors++;
}
}
} else if (!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) {
fprintf(stderr, "%s:%d: VideoQMax out of range\n",
filename, line_num);
errors++;
}
}
} else if (!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) {
fprintf(stderr, "%s:%d: VideoQMin out of range\n",
filename, line_num);
errors++;
}
}
D Richard Felker III
committed
} else if (!strcasecmp(cmd, "LumaElim")) {
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.luma_elim_threshold = atoi(arg);
} else if (!strcasecmp(cmd, "ChromaElim")) {
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.chroma_elim_threshold = atoi(arg);
} else if (!strcasecmp(cmd, "LumiMask")) {
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.lumi_masking = atof(arg);
} else if (!strcasecmp(cmd, "DarkMask")) {
get_arg(arg, sizeof(arg), &p);
D Richard Felker III
committed
video_enc.dark_masking = atof(arg);
} else if (!strcasecmp(cmd, "NoVideo")) {
video_id = CODEC_ID_NONE;
} else if (!strcasecmp(cmd, "NoAudio")) {
audio_id = CODEC_ID_NONE;
} else if (!strcasecmp(cmd, "ACL")) {
IPAddressACL acl;
get_arg(arg, sizeof(arg), &p);
if (strcasecmp(arg, "allow") == 0)
acl.action = IP_ALLOW;
else if (strcasecmp(arg, "deny") == 0)
acl.action = IP_DENY;
fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
filename, line_num, arg);
errors++;
}
get_arg(arg, sizeof(arg), &p);
if (resolve_host(&acl.first, arg) != 0) {
fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
filename, line_num, arg);
errors++;
acl.last = acl.first;
get_arg(arg, sizeof(arg), &p);
if (arg[0]) {
if (resolve_host(&acl.last, arg) != 0) {
fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
filename, line_num, arg);
errors++;
}
}
if (!errors) {
IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
IPAddressACL **naclp = 0;
*nacl = acl;
naclp = &stream->acl;
naclp = &feed->acl;
fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
filename, line_num);
errors++;
}
if (naclp) {
while (*naclp)
naclp = &(*naclp)->next;
*naclp = nacl;
}
}
Fabrice Bellard
committed
} else if (!strcasecmp(cmd, "RTSPOption")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
av_freep(&stream->rtsp_option);
Fabrice Bellard
committed
}
Fabrice Bellard
committed
} else if (!strcasecmp(cmd, "MulticastAddress")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
Alex Beregszaszi
committed
if (resolve_host(&stream->multicast_ip, arg) != 0) {
fprintf(stderr, "%s:%d: Invalid host/IP address: %s\n",
Fabrice Bellard
committed
filename, line_num, arg);
errors++;
}
stream->is_multicast = 1;
stream->loop = 1; /* default is looping */
Fabrice Bellard
committed
}
} else if (!strcasecmp(cmd, "MulticastPort")) {
get_arg(arg, sizeof(arg), &p);
Fabrice Bellard
committed
stream->multicast_port = atoi(arg);
} else if (!strcasecmp(cmd, "MulticastTTL")) {
get_arg(arg, sizeof(arg), &p);
stream->multicast_ttl = atoi(arg);
} else if (!strcasecmp(cmd, "NoLoop")) {
stream->loop = 0;
} else if (!strcasecmp(cmd, "</Stream>")) {
if (!stream) {
fprintf(stderr, "%s:%d: No corresponding <Stream> for </Stream>\n",
filename, line_num);
errors++;
}
if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
if (audio_id != CODEC_ID_NONE) {
audio_enc.codec_type = CODEC_TYPE_AUDIO;
audio_enc.codec_id = audio_id;
add_codec(stream, &audio_enc);
}
if (video_id != CODEC_ID_NONE) {
video_enc.codec_type = CODEC_TYPE_VIDEO;
video_enc.codec_id = video_id;
add_codec(stream, &video_enc);
}
}
stream = NULL;
} else if (!strcasecmp(cmd, "<Redirect")) {
/*********************************************/
char *q;
if (stream || feed || redirect) {
fprintf(stderr, "%s:%d: Already in a tag\n",
filename, line_num);
errors++;
} 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 (!strcasecmp(cmd, "URL")) {
get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
} else if (!strcasecmp(cmd, "</Redirect>")) {
if (!redirect) {
fprintf(stderr, "%s:%d: No corresponding <Redirect> for </Redirect>\n",
filename, line_num);
errors++;
}
if (!redirect->feed_filename[0]) {
fprintf(stderr, "%s:%d: No URL found for <Redirect>\n",
filename, line_num);
errors++;
}
redirect = NULL;
Fabrice Bellard
committed
} else if (!strcasecmp(cmd, "LoadModule")) {
get_arg(arg, sizeof(arg), &p);
#ifdef HAVE_DLOPEN
Fabrice Bellard
committed
load_module(arg);
fprintf(stderr, "%s:%d: Module support not compiled into this version: '%s'\n",
filename, line_num, arg);
errors++;
#endif
fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n",
filename, line_num, cmd);
errors++;
}
}
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;
}
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
static void opt_show_license(void)
{
show_license();
exit(0);
}
static void opt_debug()
{
ffserver_debug = 1;
ffserver_daemon = 0;
}
static void opt_show_help(void)
{
printf("usage: ffserver [options]\n"
"Hyper fast multi format Audio/Video streaming server\n");
printf("\n");
show_help_options(options, "Main options:\n", 0, 0);
exit(0);
}
static const OptionDef options[] = {
{ "h", 0, {(void*)opt_show_help}, "show help" },
{ "L", 0, {(void*)opt_show_license}, "show license" },
{ "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 },
};
av_register_all();
show_banner(program_name, program_birth_year);
my_program_dir = getcwd(0, 0);
Fabrice Bellard
committed
ffserver_daemon = 1;
parse_options(argc, argv, options, NULL);
putenv("http_proxy"); /* Kill the http_proxy */
av_init_random(av_gettime() + (getpid() << 16), &random_state);
Fabrice Bellard
committed
/* address on which the server will handle HTTP connections */
my_http_addr.sin_family = AF_INET;
my_http_addr.sin_port = htons (8080);
my_http_addr.sin_addr.s_addr = htonl (INADDR_ANY);
/* address on which the server will handle RTSP connections */
my_rtsp_addr.sin_family = AF_INET;
my_rtsp_addr.sin_port = htons (5454);
my_rtsp_addr.sin_addr.s_addr = htonl (INADDR_ANY);
max_bandwidth = 1000;
memset(&sigact, 0, sizeof(sigact));
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);
}
Fabrice Bellard
committed
build_file_streams();
compute_bandwidth();
Fabrice Bellard
committed
/* put the process in background and detach it from its TTY */
if (ffserver_daemon) {
int pid;
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
} else if (pid > 0) {
/* parent : exit */
exit(0);
} else {
/* child */
setsid();
chdir("/");
close(0);
open("/dev/null", O_RDWR);
close(1);
dup(0);
}
close(2);
Fabrice Bellard
committed
dup(0);
}
}
/* signal init */
signal(SIGPIPE, SIG_IGN);
/* open log file if needed */
if (logfilename[0] != '\0') {
if (!strcmp(logfilename, "-"))
logfile = stdout;
else
logfile = fopen(logfilename, "a");
Fabrice Bellard
committed
if (http_server() < 0) {
fprintf(stderr, "Could not start server\n");