This source file includes following definitions.
- dc_str_to_resolution
- dc_create_configuration
- dc_read_configuration
- parse_time
- dc_read_switch_config
- dc_cmd_data_init
- dc_cmd_data_destroy
- on_dc_log
- dc_parse_command
#include "cmd_data.h"
#define DASHCAST_CHECK_NEXT_ARG \
i++; \
if (i >= argc) { \
fprintf(stderr, "%s: %s", command_error, argv[i]); \
fprintf(stderr, "%s", command_usage); \
return -1; \
}
int dc_str_to_resolution(char *str, int *width, int *height)
{
char *token = strtok(str, "x");
if (!token) {
GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot parse resolution string.\n"));
return -1;
}
*width = atoi(token);
token = strtok(NULL, " ");
if (!token) {
GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot parse resolution string.\n"));
return -1;
}
*height = atoi(token);
return 0;
}
#define DEFAULT_VIDEO_BITRATE 1000000
#define DEFAULT_VIDEO_FRAMERATE 25
#define DEFAULT_VIDEO_WIDTH 640
#define DEFAULT_VIDEO_HEIGHT 480
#define DEFAULT_VIDEO_CODEC "libx264"
#define DEFAULT_AUDIO_BITRATE 192000
#define DEFAULT_AUDIO_SAMPLERATE 44100
#define DEFAULT_AUDIO_CHANNELS 2
#define DEFAULT_AUDIO_CODEC "aac"
static void dc_create_configuration(CmdData *cmd_data)
{
u32 i;
GF_Config *conf = cmd_data->conf;
u32 sec_count = gf_cfg_get_section_count(conf);
if (!sec_count) {
gf_cfg_set_key(conf, "v1", "type", "video");
gf_cfg_set_key(conf, "a1", "type", "audio");
sec_count = gf_cfg_get_section_count(conf);
}
for (i=0; i<sec_count; i++) {
char value[GF_MAX_PATH];
const char *section_name = gf_cfg_get_section_name(conf, i);
const char *section_type = gf_cfg_get_key(conf, section_name, "type");
if (strcmp(section_type, "video") == 0) {
if (!gf_cfg_get_key(conf, section_name, "bitrate")) {
if (cmd_data->video_data_conf.bitrate == -1)
cmd_data->video_data_conf.bitrate = DEFAULT_VIDEO_BITRATE;
snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.bitrate);
gf_cfg_set_key(conf, section_name, "bitrate", value);
}
if (!gf_cfg_get_key(conf, section_name, "framerate")) {
if (cmd_data->video_data_conf.framerate == -1)
cmd_data->video_data_conf.framerate = DEFAULT_VIDEO_FRAMERATE;
snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.framerate);
gf_cfg_set_key(conf, section_name, "framerate", value);
}
if (!gf_cfg_get_key(conf, section_name, "width")) {
if (cmd_data->video_data_conf.width == -1)
cmd_data->video_data_conf.width = DEFAULT_VIDEO_WIDTH;
snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.width);
gf_cfg_set_key(conf, section_name, "width", value);
}
if (!gf_cfg_get_key(conf, section_name, "height")) {
if (cmd_data->video_data_conf.height == -1)
cmd_data->video_data_conf.height = DEFAULT_VIDEO_HEIGHT;
snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.height);
gf_cfg_set_key(conf, section_name, "height", value);
}
if (!gf_cfg_get_key(conf, section_name, "crop_x")) {
if (cmd_data->video_data_conf.crop_x == -1)
cmd_data->video_data_conf.crop_x = 0;
snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.crop_x);
gf_cfg_set_key(conf, section_name, "crop_x", value);
}
if (!gf_cfg_get_key(conf, section_name, "low_delay")) {
gf_cfg_set_key(conf, section_name, "low_delay", cmd_data->video_data_conf.low_delay ? "yes" : "no");
}
if (!gf_cfg_get_key(conf, section_name, "crop_y")) {
if (cmd_data->video_data_conf.crop_y == -1)
cmd_data->video_data_conf.crop_y = 0;
snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.crop_y);
gf_cfg_set_key(conf, section_name, "crop_y", value);
}
if (!gf_cfg_get_key(conf, section_name, "codec"))
gf_cfg_set_key(conf, section_name, "codec", DEFAULT_VIDEO_CODEC);
}
if (strcmp(section_type, "audio") == 0) {
if (!gf_cfg_get_key(conf, section_name, "bitrate")) {
if (cmd_data->audio_data_conf.bitrate == -1)
cmd_data->audio_data_conf.bitrate = DEFAULT_AUDIO_BITRATE;
snprintf(value, sizeof(value), "%d", cmd_data->audio_data_conf.bitrate);
gf_cfg_set_key(conf, section_name, "bitrate", value);
}
if (!gf_cfg_get_key(conf, section_name, "samplerate")) {
if (cmd_data->audio_data_conf.samplerate == -1)
cmd_data->audio_data_conf.samplerate = DEFAULT_AUDIO_SAMPLERATE;
snprintf(value, sizeof(value), "%d", cmd_data->audio_data_conf.samplerate);
gf_cfg_set_key(conf, section_name, "samplerate", value);
}
if (!gf_cfg_get_key(conf, section_name, "channels")) {
if (cmd_data->audio_data_conf.channels == -1)
cmd_data->audio_data_conf.channels = DEFAULT_AUDIO_CHANNELS;
snprintf(value, sizeof(value), "%d", cmd_data->audio_data_conf.channels);
gf_cfg_set_key(conf, section_name, "channels", value);
}
if (!gf_cfg_get_key(conf, section_name, "codec")) {
if (strlen(cmd_data->audio_data_conf.codec))
gf_cfg_set_key(conf, section_name, "codec", cmd_data->audio_data_conf.codec);
else
gf_cfg_set_key(conf, section_name, "codec", DEFAULT_AUDIO_CODEC);
}
}
}
}
int dc_read_configuration(CmdData *cmd_data)
{
const char *opt;
u32 i;
GF_Config *conf = cmd_data->conf;
u32 sec_count = gf_cfg_get_section_count(conf);
for (i=0; i<sec_count; i++) {
const char *section_name = gf_cfg_get_section_name(conf, i);
const char *section_type = gf_cfg_get_key(conf, section_name, "type");
if (strcmp(section_type, "video") == 0) {
VideoDataConf *video_data_conf;
GF_SAFEALLOC(video_data_conf, VideoDataConf);
strcpy(video_data_conf->filename, section_name);
opt = gf_cfg_get_key(conf, section_name, "codec");
if (!opt) opt = DEFAULT_VIDEO_CODEC;
strcpy(video_data_conf->codec, opt);
opt = gf_cfg_get_key(conf, section_name, "bitrate");
video_data_conf->bitrate = opt ? atoi(opt) : DEFAULT_VIDEO_BITRATE;
opt = gf_cfg_get_key(conf, section_name, "framerate");
video_data_conf->framerate = opt ? atoi(opt) : DEFAULT_VIDEO_FRAMERATE;
opt = gf_cfg_get_key(conf, section_name, "height");
video_data_conf->height = opt ? atoi(opt) : DEFAULT_VIDEO_HEIGHT;
opt = gf_cfg_get_key(conf, section_name, "width");
video_data_conf->width = opt ? atoi(opt) : DEFAULT_VIDEO_WIDTH;
opt = gf_cfg_get_key(conf, section_name, "crop_x");
video_data_conf->crop_x = opt ? atoi(opt) : 0;
opt = gf_cfg_get_key(conf, section_name, "crop_y");
video_data_conf->crop_x = opt ? atoi(opt) : 0;
opt = gf_cfg_get_key(conf, section_name, "low_delay");
video_data_conf->low_delay = (opt && !strcmp(opt, "yes")) ? 1 : 0;
opt = gf_cfg_get_key(conf, section_name, "custom");
if (opt) {
if (strlen(opt) >= GF_MAX_PATH)
fprintf(stderr, "Warning: video custom opt is too long. Truncating.\n");
strncpy(video_data_conf->custom, opt, GF_MAX_PATH-1);
}
gf_list_add(cmd_data->video_lst, (void *) video_data_conf);
}
else if (strcmp(section_type, "audio") == 0)
{
AudioDataConf *audio_data_conf;
GF_SAFEALLOC(audio_data_conf, AudioDataConf);
strcpy(audio_data_conf->filename, section_name);
opt = gf_cfg_get_key(conf, section_name, "codec");
if (!opt) opt = DEFAULT_AUDIO_CODEC;
strcpy(audio_data_conf->codec, opt);
opt = gf_cfg_get_key(conf, section_name, "bitrate");
audio_data_conf->bitrate = opt ? atoi(opt) : DEFAULT_AUDIO_BITRATE;
opt = gf_cfg_get_key(conf, section_name, "samplerate");
audio_data_conf->samplerate = opt ? atoi(opt) : DEFAULT_AUDIO_SAMPLERATE;
opt = gf_cfg_get_key(conf, section_name, "channels");
audio_data_conf->channels = opt ? atoi(opt) : DEFAULT_AUDIO_CHANNELS;
opt = gf_cfg_get_key(conf, section_name, "custom");
if (opt) {
if (strlen(opt) >= GF_MAX_PATH)
fprintf(stderr, "Warning: audio custom opt is too long. Truncating.\n");
strncpy(audio_data_conf->custom, opt, GF_MAX_PATH-1);
}
gf_list_add(cmd_data->audio_lst, (void *) audio_data_conf);
} else {
fprintf(stderr, "Configuration file: type %s is not supported.\n", section_type);
}
}
fprintf(stdout, "\33[34m\33[1m");
fprintf(stdout, "Configurations:\n");
for (i=0; i<gf_list_count(cmd_data->video_lst); i++) {
VideoDataConf *video_data_conf = (VideoDataConf*)gf_list_get(cmd_data->video_lst, i);
fprintf(stdout, " id:%s\tres:%dx%d\tvbr:%d\n", video_data_conf->filename,
video_data_conf->width, video_data_conf->height,
video_data_conf->bitrate);
}
for (i=0; i<gf_list_count(cmd_data->audio_lst); i++) {
AudioDataConf *audio_data_conf = (AudioDataConf*)gf_list_get(cmd_data->audio_lst, i);
fprintf(stdout, " id:%s\tabr:%d\n", audio_data_conf->filename, audio_data_conf->bitrate);
}
fprintf(stdout, "\33[0m");
fflush(stdout);
return 0;
}
static Bool parse_time(const char* str_time, struct tm *tm_time)
{
if (!tm_time)
return GF_FALSE;
#if defined(__GNUC__)
strptime(str_time, "%Y-%m-%d %H:%M:%S", tm_time);
#elif defined(WIN32)
assert(0);
#else
#error
#endif
return GF_TRUE;
}
int dc_read_switch_config(CmdData *cmd_data)
{
u32 i;
int src_number;
char start_time[4096], end_time[4096];
time_t now_t = time(NULL);
struct tm start_tm = *localtime(&now_t);
struct tm end_tm = *localtime(&now_t);
GF_Config *conf = cmd_data->switch_conf;
u32 sec_count = gf_cfg_get_section_count(conf);
dc_task_init(&cmd_data->task_list);
if (sec_count == 0) {
return 0;
}
for (i = 0; i < sec_count; i++) {
const char *section_name = gf_cfg_get_section_name(conf, i);
const char *section_type = gf_cfg_get_key(conf, section_name, "type");
if (strcmp(section_type, "video") == 0) {
VideoDataConf *video_data_conf = (VideoDataConf*)gf_malloc(sizeof(VideoDataConf));
strcpy(video_data_conf->source_id, section_name);
strcpy(video_data_conf->filename, gf_cfg_get_key(conf, section_name, "source"));
strcpy(start_time, gf_cfg_get_key(conf, section_name, "start"));
parse_time(start_time, &start_tm);
video_data_conf->start_time = mktime(&start_tm);
strcpy(end_time, gf_cfg_get_key(conf, section_name, "end"));
parse_time(end_time, &end_tm);
video_data_conf->end_time = mktime(&end_tm);
gf_list_add(cmd_data->vsrc, (void *) video_data_conf);
src_number = gf_list_count(cmd_data->vsrc);
dc_task_add(&cmd_data->task_list, src_number, video_data_conf->source_id, video_data_conf->start_time, video_data_conf->end_time);
}
else if (strcmp(section_type, "audio") == 0)
{
AudioDataConf *audio_data_conf = (AudioDataConf*)gf_malloc(sizeof(AudioDataConf));
strcpy(audio_data_conf->source_id, section_name);
strcpy(audio_data_conf->filename, gf_cfg_get_key(conf, section_name, "source"));
strcpy(start_time, gf_cfg_get_key(conf, section_name, "start"));
parse_time(start_time, &start_tm);
audio_data_conf->start_time = mktime(&start_tm);
strcpy(end_time, gf_cfg_get_key(conf, section_name, "end"));
parse_time(end_time, &end_tm);
audio_data_conf->end_time = mktime(&end_tm);
gf_list_add(cmd_data->asrc, (void *) audio_data_conf);
} else {
fprintf(stdout, "Switch source configuration file: type %s is not supported.\n", section_type);
}
}
fprintf(stdout, "\33[34m\33[1m");
fprintf(stdout, "Sources:\n");
for (i=0; i<gf_list_count(cmd_data->vsrc); i++) {
VideoDataConf *video_data_conf = (VideoDataConf*)gf_list_get(cmd_data->vsrc, i);
strftime(start_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&video_data_conf->start_time));
strftime(end_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&video_data_conf->end_time));
fprintf(stdout, " id:%s\tsource:%s\tstart:%s\tend:%s\n", video_data_conf->source_id, video_data_conf->filename, start_time, end_time);
}
for (i=0; i<gf_list_count(cmd_data->asrc); i++) {
AudioDataConf *audio_data_conf = (AudioDataConf*)gf_list_get(cmd_data->asrc, i);
strftime(start_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&audio_data_conf->start_time));
strftime(end_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&audio_data_conf->end_time));
fprintf(stdout, " id:%s\tsource:%s\tstart:%s\tend:%s\n", audio_data_conf->source_id, audio_data_conf->filename, start_time, end_time);
}
fprintf(stdout, "\33[0m");
fflush(stdout);
return 0;
}
void dc_cmd_data_init(CmdData *cmd_data)
{
memset(cmd_data, 0, sizeof(CmdData));
dc_audio_data_set_default(&cmd_data->audio_data_conf);
dc_video_data_set_default(&cmd_data->video_data_conf);
cmd_data->mode = ON_DEMAND;
cmd_data->ast_offset = -1;
cmd_data->min_buffer_time = -1;
cmd_data->minimum_update_period = -1;
cmd_data->use_source_timing = GF_TRUE;
cmd_data->audio_lst = gf_list_new();
cmd_data->video_lst = gf_list_new();
cmd_data->asrc = gf_list_new();
cmd_data->vsrc = gf_list_new();
}
void dc_cmd_data_destroy(CmdData *cmd_data)
{
while (gf_list_count(cmd_data->audio_lst)) {
AudioDataConf *audio_data_conf = (AudioDataConf*)gf_list_last(cmd_data->audio_lst);
gf_list_rem_last(cmd_data->audio_lst);
gf_free(audio_data_conf);
}
gf_list_del(cmd_data->audio_lst);
while (gf_list_count(cmd_data->video_lst)) {
VideoDataConf *video_data_conf = (VideoDataConf*)gf_list_last(cmd_data->video_lst);
gf_list_rem_last(cmd_data->video_lst);
gf_free(video_data_conf);
}
gf_list_del(cmd_data->video_lst);
gf_list_del(cmd_data->asrc);
gf_list_del(cmd_data->vsrc);
gf_cfg_del(cmd_data->conf);
gf_cfg_del(cmd_data->switch_conf);
if (cmd_data->logfile)
gf_fclose(cmd_data->logfile);
dc_task_destroy(&cmd_data->task_list);
gf_sys_close();
}
static void on_dc_log(void *cbk, GF_LOG_Level ll, GF_LOG_Tool lm, const char *av_fmt_ctx, va_list list)
{
FILE *logs = (FILE*)cbk;
vfprintf(logs, av_fmt_ctx, list);
fflush(logs);
}
int dc_parse_command(int argc, char **argv, CmdData *cmd_data)
{
GF_MemTrackerType mem_track = GF_MemTrackerNone;
int i;
const char *command_usage =
"Usage: DashCast [options]\n"
"GPAC version " GPAC_FULL_VERSION"\n"
"\n"
"General options:\n"
" -log-file filename set output log file. Also works with -lf\n"
" -logs LOGS set log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@levelX\n"
#ifdef GPAC_MEMORY_TRACKING
" -mem-track enable the memory tracker\n"
" -mem-track-stack enable the memory tracker with stack dumping\n"
#endif
" -conf filename set the configuration file name (default: dashcast.conf)\n"
" -switch-source filename set the configuration file name for source switching\n"
"\n"
"Live options:\n"
" -live system is live and input is a camera\n"
" -live-media system is live and input is a media file\n"
" -no-loop system does not loop on the input media file when live\n"
" -dynamic-ast changes segment availability start time at each MPD generation (old behaviour but not allowed in most profiles)\n"
" -insert-utc inserts UTC clock at the start of each segment\n"
" -no-rewrite Do not rewrite the MPD as a static one at the end of the live session\n"
"\n"
"Source options:\n"
" -npts use frame counting for timestamps (not error-free) instead of source timing (default)\n"
" -av string set the source name for a multiplexed audio and video input\n"
" - if this option is present, neither '-a' nor '-v' shall be present\n"
"* Video options:\n"
" -v string set the source name for a video input\n"
" - if input is from a webcam, use \"/dev/video[x]\" \n"
" where x is the video device number\n"
" - if input is the screen video, use \":0.0+[x],[y]\" \n"
" which captures from upper-left at x,y\n"
" - if input is from stdin, use \"pipe:\"\n"
" -vf string set the input video format\n"
#ifdef WIN32
" - to capture from a directshow device, set dshow\n"
#else
" - to capture from a webcam, set video4linux2\n"
" - to capture the screen, set x11grab\n"
" -v4l2f inv4l2f inv4l2f is the input format for webcam acquisition\n"
" - it can be mjpeg, yuyv422, etc.\n"
#endif
" -pixf FMT set the input pixel format\n"
" -vfr N force the input video framerate\n"
" -vres WxH force the video resolution (e.g. 640x480)\n"
" -vcrop XxY crop the source video from X pixels left and Y pixels top. Must be used with -vres.\n"
" -demux-buffer SIZE sets demux buffer size to SIZE.\n"
"* Audio options:\n"
" -a string set the source name for an audio input\n"
" - if input is from microphone, use \"plughw:[x],[y]\"\n"
" where x is the card number and y is the device number\n"
" -af string set the input audio format\n"
"\n"
"Output options:\n"
"* Video encoding options:\n"
" -vcodec string set the output video codec (default: h264)\n"
#if 0
" -vb int set the output video bitrate (in bits)\n"
#endif
" -vcustom string send custom parameters directly to the video encoder\n"
" -gdr use Gradual Decoder Refresh feature for video encoding (h264 codec only)\n"
" -gop specify GOP size in frames - default is framerate (1 sec gop)\n"
" -low-delay specify that low delay settings should be used (no B-frames, fast encoding)\n"
"* Audio encoding options:\n"
" -acodec string set the output audio codec (default: aac)\n"
#if 0
" -ab int set the output audio bitrate in bits (default: 192000)\n"
" -as int set the sample rate (default: 44100)\n"
" -ach int set the number of output audio channels (default: 2)\n"
#endif
" -acustom string send custom parameters directly to the audio encoder\n"
"\n"
"DASH options:\n"
" -seg-dur dur:int set the segment duration in millisecond (default value: 1000)\n"
" -frag dur:int set the fragment duration in millisecond (default value: 1000) (same as -frag-dur)\n"
" -seg-marker marker:4cc add a marker box named marker at the end of DASH segment\n"
" -out outdir:str outdir is the output data directory (default: output)\n"
" -mpd mpdname:str mpdname is the MPD file name (default: dashcast.mpd)\n"
" -ast-offset dur:int dur is the MPD availabilityStartTime shift in milliseconds (default value: 0)\n"
" -mpd-refresh dur:int dur is the MPD minimumUpdatePeriod in seconds\n"
" -time-shift dur:int dur is the MPD TimeShiftBufferDepth in seconds\n"
" - the default value is 10. Specify -1 to keep all files.\n"
" -min-buffer dur:float dur is the MPD minBufferTime in seconds (default value: 1.0)\n"
" -base-url baseurl:str baseurl is the MPD BaseURL\n"
"\n"
"\n"
"Examples:\n"
"\n"
" DashCast -av test.avi -live-media\n"
" DashCast -a test_audio.mp3 -v test_audio.mp4 -live-media\n"
#ifdef WIN32
" DashCast -vf dshow -vres 1280x720 -vfr 24 -v video=\"screen-capture-recorder\" -live (please install http://screencapturer.sf.net/)\n"
" DashCast -vf dshow -vres 1280x720 -vfr 24 -v video=\"YOUR-WEBCAM\" -pixf yuv420p -live (see https://trac.ffmpeg.org/wiki/DirectShow)\n"
#elif defined(__DARWIN) || defined(__APPLE__)
" DashCast -vf avfoundation -vres 1280x720 -v \"FaceTime HD Camera\" -vfr 25 -live\n"
" DashCast -vf avfoundation -vres 1280x720 -v \"Capture screen 0\" -vfr 25 -live\n"
#else
" DashCast -vf video4linux2 -vres 1280x720 -vfr 24 -v4l2f mjpeg -v /dev/video0 -af alsa -a plughw:1,0 -live\n"
" DashCast -vf x11grab -vres 800x600 -vfr 25 -v :0.0 -live\n"
#endif
"\n";
const char *command_error = "\33[31mUnknown option or missing mandatory argument.\33[0m\n";
if (argc == 1) {
fprintf(stderr, "%s", command_usage);
return -2;
}
#ifdef GPAC_MEMORY_TRACKING
i = 1;
while (i < argc) {
if (strcmp(argv[i], "-mem-track") == 0) {
mem_track = GF_MemTrackerSimple;
break;
}
else if (strcmp(argv[i], "-mem-track-stack") == 0) {
mem_track = GF_MemTrackerBackTrace;
break;
}
i++;
}
#endif
gf_sys_init(mem_track);
gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING);
if (mem_track) {
gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_INFO);
}
dc_cmd_data_init(cmd_data);
cmd_data->mem_track = mem_track;
i = 1;
while (i < argc) {
if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-av") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strcmp(argv[i - 1], "-a") == 0 || strcmp(argv[i - 1], "-av") == 0) {
if (strcmp(cmd_data->audio_data_conf.filename, "") != 0) {
fprintf(stderr, "Audio source has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strcpy(cmd_data->audio_data_conf.filename, argv[i]);
}
if (strcmp(argv[i - 1], "-v") == 0 || strcmp(argv[i - 1], "-av") == 0) {
if (strcmp(cmd_data->video_data_conf.filename, "") != 0) {
fprintf(stderr, "Video source has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strcpy(cmd_data->video_data_conf.filename, argv[i]);
}
i++;
} else if (strcmp(argv[i], "-af") == 0 || strcmp(argv[i], "-vf") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strcmp(argv[i - 1], "-af") == 0) {
if (strcmp(cmd_data->audio_data_conf.format, "") != 0) {
fprintf(stderr, "Audio format has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strcpy(cmd_data->audio_data_conf.format, argv[i]);
}
if (strcmp(argv[i - 1], "-vf") == 0) {
if (strcmp(cmd_data->video_data_conf.format, "") != 0) {
fprintf(stderr, "Video format has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strcpy(cmd_data->video_data_conf.format, argv[i]);
}
i++;
} else if (strcmp(argv[i], "-pixf") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strcmp(cmd_data->video_data_conf.pixel_format, "") != 0) {
fprintf(stderr, "Input pixel format has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strcpy(cmd_data->video_data_conf.pixel_format, argv[i]);
i++;
} else if (strcmp(argv[i], "-vfr") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->video_data_conf.framerate != -1) {
fprintf(stderr, "Video framerate has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->video_data_conf.framerate = atoi(argv[i]);
i++;
} else if (strcmp(argv[i], "-vres") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->video_data_conf.height != -1 && cmd_data->video_data_conf.width != -1) {
fprintf(stderr, "Video resolution has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
dc_str_to_resolution(argv[i], &cmd_data->video_data_conf.width, &cmd_data->video_data_conf.height);
i++;
} else if (strcmp(argv[i], "-vcrop") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->video_data_conf.crop_x && cmd_data->video_data_conf.crop_y) {
fprintf(stderr, "Video crop has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
dc_str_to_resolution(argv[i], &cmd_data->video_data_conf.crop_x, &cmd_data->video_data_conf.crop_y);
i++;
} else if (strcmp(argv[i], "-vcodec") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strcmp(cmd_data->video_data_conf.codec, "") != 0) {
fprintf(stderr, "Video codec has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strncpy(cmd_data->video_data_conf.codec, argv[i], GF_MAX_PATH-1);
i++;
} else if (strcmp(argv[i], "-vcustom") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strlen(cmd_data->video_data_conf.custom)) {
fprintf(stderr, "Video custom has already been specified: appending\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
if (strlen(argv[i]) >= GF_MAX_PATH)
fprintf(stderr, "Warning: video custom is too long. Truncating.\n");
strncpy(cmd_data->video_data_conf.custom, argv[i], GF_MAX_PATH-1);
i++;
} else if (strcmp(argv[i], "-acodec") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strcmp(cmd_data->audio_data_conf.codec, "") != 0) {
fprintf(stderr, "Audio codec has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strncpy(cmd_data->audio_data_conf.codec, argv[i], GF_MAX_PATH-1);
i++;
} else if (strcmp(argv[i], "-acustom") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strlen(cmd_data->audio_data_conf.custom)) {
fprintf(stderr, "Audio custom has already been specified: appending\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
if (strlen(argv[i]) >= GF_MAX_PATH)
fprintf(stderr, "Warning: audio custom is too long. Truncating.\n");
strncpy(cmd_data->audio_data_conf.custom, argv[i], GF_MAX_PATH-1);
i++;
} else if (strcmp(argv[i], "-conf") == 0) {
DASHCAST_CHECK_NEXT_ARG
cmd_data->conf = gf_cfg_force_new(NULL, argv[i]);
i++;
} else if (strcmp(argv[i], "-switch-source") == 0) {
DASHCAST_CHECK_NEXT_ARG
cmd_data->switch_conf = gf_cfg_force_new(NULL, argv[i]);
i++;
} else if (strcmp(argv[i], "-out") == 0) {
DASHCAST_CHECK_NEXT_ARG
strcpy(cmd_data->out_dir, argv[i]);
i++;
#ifndef WIN32
} else if (strcmp(argv[i], "-v4l2f") == 0) {
DASHCAST_CHECK_NEXT_ARG
strcpy(cmd_data->video_data_conf.v4l2f, argv[i]);
i++;
#endif
} else if (strcmp(argv[i], "-seg-marker") == 0) {
char *m;
DASHCAST_CHECK_NEXT_ARG
m = argv[i];
if (strlen(m) == 4) {
cmd_data->seg_marker = GF_4CC(m[0], m[1], m[2], m[3]);
} else {
fprintf(stderr, "Invalid marker box name specified: %s\n", m);
return -1;
}
i++;
} else if (strcmp(argv[i], "-mpd") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strcmp(cmd_data->mpd_filename, "") != 0) {
fprintf(stderr, "MPD file has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strncpy(cmd_data->mpd_filename, argv[i], GF_MAX_PATH-1);
i++;
} else if (strcmp(argv[i], "-seg-dur") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->seg_dur != 0) {
fprintf(stderr, "Segment duration has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->seg_dur = atoi(argv[i]);
i++;
} else if ((strcmp(argv[i], "-frag-dur") == 0) || (strcmp(argv[i], "-frag") == 0)) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->frag_dur != 0) {
fprintf(stderr, "Fragment duration has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->frag_dur = atoi(argv[i]);
i++;
} else if (strcmp(argv[i], "-ast-offset") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->ast_offset != -1) {
fprintf(stderr, "AvailabilityStartTime offset has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->ast_offset = atoi(argv[i]);
i++;
} else if (strcmp(argv[i], "-mpd-refresh") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->minimum_update_period != -1) {
fprintf(stderr, "minimumUpdatePeriod (mpd-refresh) has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->minimum_update_period = atoi(argv[i]);
i++;
} else if (strcmp(argv[i], "-time-shift") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->time_shift != 0) {
fprintf(stderr, "TimeShiftBufferDepth has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->time_shift = atoi(argv[i]);
i++;
} else if (strcmp(argv[i], "-gop") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->gop_size != 0) {
fprintf(stderr, "GOP size has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->gop_size = atoi(argv[i]);
i++;
} else if (strcmp(argv[i], "-min-buffer") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (cmd_data->min_buffer_time != -1) {
fprintf(stderr, "Min Buffer Time has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
cmd_data->min_buffer_time = (float)atof(argv[i]);
i++;
} else if (strcmp(argv[i], "-demux-buffer") == 0) {
DASHCAST_CHECK_NEXT_ARG
cmd_data->video_data_conf.demux_buffer_size = (int)atoi(argv[i]);
i++;
} else if (strcmp(argv[i], "-base-url") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (strcmp(cmd_data->base_url, "") != 0) {
fprintf(stderr, "BaseURL has already been specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
strncpy(cmd_data->base_url, argv[i], GF_MAX_PATH-1);
i++;
} else if (strcmp(argv[i], "-low-delay") == 0) {
cmd_data->video_data_conf.low_delay = 1;
i++;
} else if (strcmp(argv[i], "-live") == 0) {
cmd_data->mode = LIVE_CAMERA;
i++;
} else if (strcmp(argv[i], "-npts") == 0) {
cmd_data->use_source_timing = GF_FALSE;
i++;
} else if (strcmp(argv[i], "-live-media") == 0) {
cmd_data->mode = LIVE_MEDIA;
i++;
} else if (strcmp(argv[i], "-no-loop") == 0) {
cmd_data->no_loop = 1;
i++;
} else if (strcmp(argv[i], "-insert-utc") == 0) {
cmd_data->insert_utc = 1;
i++;
} else if (strcmp(argv[i], "-no-rewrite") == 0) {
cmd_data->no_mpd_rewrite = 1;
i++;
} else if (strcmp(argv[i], "-dynamic-ast") == 0) {
cmd_data->use_dynamic_ast = 1;
i++;
} else if (strcmp(argv[i], "-send-message") == 0) {
cmd_data->send_message = 1;
i++;
} else if (strcmp(argv[i], "-logs") == 0) {
DASHCAST_CHECK_NEXT_ARG
if (gf_log_set_tools_levels(argv[i]) != GF_OK) {
fprintf(stderr, "Invalid log format %s", argv[i]);
return 1;
}
i++;
} else if (!strcmp(argv[i], "-mem-track") || !strcmp(argv[i], "-mem-track-stack") ) {
i++;
#ifndef GPAC_MEMORY_TRACKING
GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("WARNING - GPAC not compiled with Memory Tracker - ignoring \"%s\"\n", argv[i]));
#endif
} else if (!strcmp(argv[i], "-lf") || !strcmp(argv[i], "-log-file")) {
DASHCAST_CHECK_NEXT_ARG
cmd_data->logfile = gf_fopen(argv[i], "wt");
gf_log_set_callback(cmd_data->logfile, on_dc_log);
i++;
} else if (strcmp(argv[i], "-gdr") == 0) {
if ( (i+1 <= argc) && (argv[i+1][0] != '-')) {
DASHCAST_CHECK_NEXT_ARG
cmd_data->gdr = atoi(argv[i]);
} else {
cmd_data->gdr = 8;
}
i++;
} else {
fprintf(stderr, "%s: %s", command_error, argv[i]);
fprintf(stderr, "%s", command_usage);
return -1;
}
}
if (strcmp(cmd_data->mpd_filename, "") == 0) {
strcpy(cmd_data->mpd_filename, "dashcast.mpd");
}
if (strcmp(cmd_data->out_dir, "") == 0) {
struct stat status;
strcpy(cmd_data->out_dir, "output");
if (stat(cmd_data->out_dir, &status) != 0) {
gf_mkdir(cmd_data->out_dir);
}
}
if (strcmp(cmd_data->video_data_conf.filename, "") == 0 && strcmp(cmd_data->audio_data_conf.filename, "") == 0) {
fprintf(stderr, "Audio/Video source must be specified.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
if (cmd_data->seg_dur == 0) {
cmd_data->seg_dur = 1000;
}
if (cmd_data->frag_dur == 0) {
cmd_data->frag_dur = cmd_data->seg_dur;
}
if (cmd_data->ast_offset == -1) {
cmd_data->ast_offset = 0;
}
if (cmd_data->mode == ON_DEMAND)
cmd_data->time_shift = -1;
else {
if (cmd_data->time_shift == 0) {
cmd_data->time_shift = 10;
}
}
if (cmd_data->min_buffer_time == -1) {
cmd_data->min_buffer_time = 1.0;
}
if ((cmd_data->minimum_update_period == -1) && (cmd_data->mode == LIVE_CAMERA)) {
fprintf(stderr, "MPD refresh time not set in live - defaulting to segment duration\n");
cmd_data->minimum_update_period = cmd_data->seg_dur / 1000;
}
if (cmd_data->video_data_conf.crop_x || cmd_data->video_data_conf.crop_y) {
if (cmd_data->video_data_conf.width == -1 && cmd_data->video_data_conf.height == -1) {
fprintf(stderr, "You cannot use '-vcrop' without '-vres'. Please check usage.\n");
fprintf(stderr, "%s", command_usage);
return -1;
}
}
fprintf(stdout, "\33[34m\33[1m");
fprintf(stdout, "Options:\n");
fprintf(stdout, " video source: %s\n", cmd_data->video_data_conf.filename);
if (strcmp(cmd_data->video_data_conf.format, "") != 0) {
fprintf(stdout, " video format: %s\n", cmd_data->video_data_conf.format);
}
#ifndef WIN32
if (strcmp(cmd_data->video_data_conf.v4l2f, "") != 0) {
fprintf(stdout, " v4l2 format: %s\n", cmd_data->video_data_conf.v4l2f);
}
#endif
if (cmd_data->video_data_conf.framerate != -1) {
fprintf(stdout, " video framerate: %d\n", cmd_data->video_data_conf.framerate);
}
if (cmd_data->video_data_conf.height != -1 && cmd_data->video_data_conf.width != -1) {
fprintf(stdout, " video resolution: %dx%d\n", cmd_data->video_data_conf.width, cmd_data->video_data_conf.height);
}
if (cmd_data->video_data_conf.crop_x != -1 && cmd_data->video_data_conf.crop_y != -1) {
fprintf(stdout, " video crop: %dx%d\n", cmd_data->video_data_conf.crop_x, cmd_data->video_data_conf.crop_y);
}
fprintf(stdout, " audio source: %s\n", cmd_data->audio_data_conf.filename);
if (strcmp(cmd_data->audio_data_conf.format, "") != 0) {
fprintf(stdout, " audio format: %s\n", cmd_data->audio_data_conf.format);
}
fprintf(stdout, "\33[0m");
fflush(stdout);
if (!cmd_data->conf) {
cmd_data->conf = gf_cfg_force_new(NULL, "dashcast.conf");
dc_create_configuration(cmd_data);
}
dc_read_configuration(cmd_data);
if (!cmd_data->switch_conf) {
cmd_data->switch_conf = gf_cfg_force_new(NULL, "switch.conf");
}
dc_read_switch_config(cmd_data);
return 0;
}