PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/applications/dashcast/cmd_data.c

https://github.com/svettom/gpac
C | 865 lines | 717 code | 118 blank | 30 comment | 245 complexity | c773b525dcfd8213b9e5ce2d06e185f1 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. /*
  2. * GPAC - Multimedia Framework C SDK
  3. *
  4. * Authors: Arash Shafiei
  5. * Copyright (c) Telecom ParisTech 2000-2013
  6. * All rights reserved
  7. *
  8. * This file is part of GPAC / dashcast
  9. *
  10. * GPAC is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as published by
  12. * the Free Software Foundation; either version 2, or (at your option)
  13. * any later version.
  14. *
  15. * GPAC is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; see the file COPYING. If not, write to
  22. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  23. *
  24. */
  25. #include "cmd_data.h"
  26. int dc_str_to_resolution(char *str, int *width, int *height)
  27. {
  28. char *token = strtok(str, "x");
  29. if (!token) {
  30. fprintf(stderr, "Cannot parse resolution string.\n");
  31. return -1;
  32. }
  33. *width = atoi(token);
  34. token = strtok(NULL, " ");
  35. if (!token) {
  36. fprintf(stderr, "Cannot parse resolution string.\n");
  37. return -1;
  38. }
  39. *height = atoi(token);
  40. return 0;
  41. }
  42. #define DEFAULT_VIDEO_BITRATE 400000
  43. #define DEFAULT_VIDEO_FRAMERATE 25
  44. #define DEFAULT_VIDEO_WIDTH 640
  45. #define DEFAULT_VIDEO_HEIGHT 480
  46. #define DEFAULT_VIDEO_CODEC "libx264"
  47. #define DEFAULT_AUDIO_BITRATE 192000
  48. #define DEFAULT_AUDIO_SAMPLERATE 48000
  49. #define DEFAULT_AUDIO_CHANNELS 2
  50. #define DEFAULT_AUDIO_CODEC "mp2"
  51. static void dc_create_configuration(CmdData *cmd_data)
  52. {
  53. u32 i;
  54. GF_Config *conf = cmd_data->conf;
  55. u32 sec_count = gf_cfg_get_section_count(conf);
  56. if (!sec_count) {
  57. gf_cfg_set_key(conf, "v1", "type", "video");
  58. gf_cfg_set_key(conf, "a1", "type", "audio");
  59. sec_count = gf_cfg_get_section_count(conf);
  60. }
  61. for (i=0; i<sec_count; i++) {
  62. char value[GF_MAX_PATH];
  63. const char *section_name = gf_cfg_get_section_name(conf, i);
  64. const char *section_type = gf_cfg_get_key(conf, section_name, "type");
  65. if (strcmp(section_type, "video") == 0) {
  66. if (!gf_cfg_get_key(conf, section_name, "bitrate")) {
  67. if (cmd_data->video_data_conf.bitrate == -1)
  68. cmd_data->video_data_conf.bitrate = DEFAULT_VIDEO_BITRATE;
  69. snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.bitrate);
  70. gf_cfg_set_key(conf, section_name, "bitrate", value);
  71. }
  72. if (!gf_cfg_get_key(conf, section_name, "framerate")) {
  73. if (cmd_data->video_data_conf.framerate == -1)
  74. cmd_data->video_data_conf.framerate = DEFAULT_VIDEO_FRAMERATE;
  75. snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.framerate);
  76. gf_cfg_set_key(conf, section_name, "framerate", value);
  77. }
  78. if (!gf_cfg_get_key(conf, section_name, "width")) {
  79. if (cmd_data->video_data_conf.width == -1)
  80. cmd_data->video_data_conf.width = DEFAULT_VIDEO_WIDTH;
  81. snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.width);
  82. gf_cfg_set_key(conf, section_name, "width", value);
  83. }
  84. if (!gf_cfg_get_key(conf, section_name, "height")) {
  85. if (cmd_data->video_data_conf.height == -1)
  86. cmd_data->video_data_conf.height = DEFAULT_VIDEO_HEIGHT;
  87. snprintf(value, sizeof(value), "%d", cmd_data->video_data_conf.height);
  88. gf_cfg_set_key(conf, section_name, "height", value);
  89. }
  90. if (!gf_cfg_get_key(conf, section_name, "codec"))
  91. gf_cfg_set_key(conf, section_name, "codec", DEFAULT_VIDEO_CODEC);
  92. }
  93. if (strcmp(section_type, "audio") == 0) {
  94. if (!gf_cfg_get_key(conf, section_name, "bitrate")) {
  95. if (cmd_data->audio_data_conf.bitrate == -1)
  96. cmd_data->audio_data_conf.bitrate = DEFAULT_AUDIO_BITRATE;
  97. snprintf(value, sizeof(value), "%d", cmd_data->audio_data_conf.bitrate);
  98. gf_cfg_set_key(conf, section_name, "bitrate", value);
  99. }
  100. if (!gf_cfg_get_key(conf, section_name, "samplerate")) {
  101. if (cmd_data->audio_data_conf.samplerate == -1)
  102. cmd_data->audio_data_conf.samplerate = DEFAULT_AUDIO_SAMPLERATE;
  103. snprintf(value, sizeof(value), "%d", cmd_data->audio_data_conf.samplerate);
  104. gf_cfg_set_key(conf, section_name, "samplerate", value);
  105. }
  106. if (!gf_cfg_get_key(conf, section_name, "channels")) {
  107. if (cmd_data->audio_data_conf.channels == -1)
  108. cmd_data->audio_data_conf.channels = DEFAULT_AUDIO_CHANNELS;
  109. snprintf(value, sizeof(value), "%d", cmd_data->audio_data_conf.channels);
  110. gf_cfg_set_key(conf, section_name, "channels", value);
  111. }
  112. if (!gf_cfg_get_key(conf, section_name, "codec"))
  113. gf_cfg_set_key(conf, section_name, "codec", DEFAULT_AUDIO_CODEC);
  114. }
  115. }
  116. }
  117. int dc_read_configuration(CmdData *cmd_data)
  118. {
  119. const char *opt;
  120. u32 i;
  121. GF_Config *conf = cmd_data->conf;
  122. u32 sec_count = gf_cfg_get_section_count(conf);
  123. for (i=0; i<sec_count; i++) {
  124. const char *section_name = gf_cfg_get_section_name(conf, i);
  125. const char *section_type = gf_cfg_get_key(conf, section_name, "type");
  126. if (strcmp(section_type, "video") == 0) {
  127. VideoDataConf *video_data_conf;
  128. GF_SAFEALLOC(video_data_conf, VideoDataConf);
  129. strcpy(video_data_conf->filename, section_name);
  130. opt = gf_cfg_get_key(conf, section_name, "codec");
  131. if (!opt) opt = DEFAULT_VIDEO_CODEC;
  132. strcpy(video_data_conf->codec, opt);
  133. opt = gf_cfg_get_key(conf, section_name, "bitrate");
  134. video_data_conf->bitrate = opt ? atoi(opt) : DEFAULT_VIDEO_BITRATE;
  135. opt = gf_cfg_get_key(conf, section_name, "framerate");
  136. video_data_conf->framerate = opt ? atoi(opt) : DEFAULT_VIDEO_FRAMERATE;
  137. opt = gf_cfg_get_key(conf, section_name, "height");
  138. video_data_conf->height = opt ? atoi(opt) : DEFAULT_VIDEO_HEIGHT;
  139. opt = gf_cfg_get_key(conf, section_name, "width");
  140. video_data_conf->width = opt ? atoi(opt) : DEFAULT_VIDEO_WIDTH;
  141. opt = gf_cfg_get_key(conf, section_name, "custom");
  142. video_data_conf->custom = opt ? strdup(opt) : NULL;
  143. gf_list_add(cmd_data->video_lst, (void *) video_data_conf);
  144. }
  145. else if (strcmp(section_type, "audio") == 0)
  146. {
  147. AudioDataConf *audio_data_conf;
  148. GF_SAFEALLOC(audio_data_conf, AudioDataConf);
  149. strcpy(audio_data_conf->filename, section_name);
  150. opt = gf_cfg_get_key(conf, section_name, "codec");
  151. if (!opt) opt = DEFAULT_AUDIO_CODEC;
  152. strcpy(audio_data_conf->codec, opt);
  153. opt = gf_cfg_get_key(conf, section_name, "bitrate");
  154. audio_data_conf->bitrate = opt ? atoi(opt) : DEFAULT_AUDIO_BITRATE;
  155. opt = gf_cfg_get_key(conf, section_name, "samplerate");
  156. audio_data_conf->samplerate = opt ? atoi(opt) : DEFAULT_AUDIO_SAMPLERATE;
  157. opt = gf_cfg_get_key(conf, section_name, "channels");
  158. audio_data_conf->channels = opt ? atoi(opt) : DEFAULT_AUDIO_CHANNELS;
  159. opt = gf_cfg_get_key(conf, section_name, "custom");
  160. audio_data_conf->custom = opt ? strdup(opt) : NULL;
  161. gf_list_add(cmd_data->audio_lst, (void *) audio_data_conf);
  162. } else {
  163. fprintf(stdout, "Configuration file: type %s is not supported.\n", section_type);
  164. }
  165. }
  166. fprintf(stdout, "\33[34m\33[1m");
  167. fprintf(stdout, "Configurations:\n");
  168. for (i=0; i<gf_list_count(cmd_data->video_lst); i++) {
  169. VideoDataConf *video_data_conf = gf_list_get(cmd_data->video_lst, i);
  170. fprintf(stdout, " id:%s\tres:%dx%d\tvbr:%d\n", video_data_conf->filename,
  171. video_data_conf->width, video_data_conf->height,
  172. video_data_conf->bitrate/*, video_data_conf->framerate, video_data_conf->codec*/); }
  173. for (i=0; i<gf_list_count(cmd_data->audio_lst); i++) {
  174. AudioDataConf *audio_data_conf = gf_list_get(cmd_data->audio_lst, i);
  175. fprintf(stdout, " id:%s\tabr:%d\n", audio_data_conf->filename, audio_data_conf->bitrate/*, audio_data_conf->samplerate, audio_data_conf->channels,audio_data_conf->codec*/);
  176. }
  177. fprintf(stdout, "\33[0m");
  178. fflush(stdout);
  179. return 0;
  180. }
  181. /**
  182. * Parse time from a string to a struct tm.
  183. */
  184. static Bool parse_time(const char* str_time, struct tm *tm_time)
  185. {
  186. if (!tm_time)
  187. return GF_FALSE;
  188. #if defined(__GNUC__)
  189. strptime(str_time, "%Y-%m-%d %H:%M:%S", tm_time);
  190. #elif defined(WIN32)
  191. assert(0); //TODO
  192. #else
  193. #error
  194. #endif
  195. return GF_TRUE;
  196. }
  197. int dc_read_switch_config(CmdData *cmd_data)
  198. {
  199. u32 i;
  200. int src_number;
  201. char start_time[4096], end_time[4096];
  202. time_t now_t = time(NULL);
  203. struct tm start_tm = *localtime(&now_t);
  204. struct tm end_tm = *localtime(&now_t);
  205. GF_Config *conf = cmd_data->switch_conf;
  206. u32 sec_count = gf_cfg_get_section_count(conf);
  207. dc_task_init(&cmd_data->task_list);
  208. if (sec_count == 0) {
  209. return 0;
  210. }
  211. for (i = 0; i < sec_count; i++) {
  212. const char *section_name = gf_cfg_get_section_name(conf, i);
  213. const char *section_type = gf_cfg_get_key(conf, section_name, "type");
  214. if (strcmp(section_type, "video") == 0) {
  215. VideoDataConf *video_data_conf = gf_malloc(sizeof(VideoDataConf));
  216. strcpy(video_data_conf->source_id, section_name);
  217. strcpy(video_data_conf->filename, gf_cfg_get_key(conf, section_name, "source"));
  218. strcpy(start_time, gf_cfg_get_key(conf, section_name, "start"));
  219. parse_time(start_time, &start_tm);
  220. video_data_conf->start_time = mktime(&start_tm);
  221. strcpy(end_time, gf_cfg_get_key(conf, section_name, "end"));
  222. parse_time(end_time, &end_tm);
  223. video_data_conf->end_time = mktime(&end_tm);
  224. gf_list_add(cmd_data->vsrc, (void *) video_data_conf);
  225. src_number = gf_list_count(cmd_data->vsrc);
  226. dc_task_add(&cmd_data->task_list, src_number, video_data_conf->source_id, video_data_conf->start_time, video_data_conf->end_time);
  227. }
  228. else if (strcmp(section_type, "audio") == 0)
  229. {
  230. AudioDataConf *audio_data_conf = gf_malloc(sizeof(AudioDataConf));
  231. strcpy(audio_data_conf->source_id, section_name);
  232. strcpy(audio_data_conf->filename, gf_cfg_get_key(conf, section_name, "source"));
  233. strcpy(start_time, gf_cfg_get_key(conf, section_name, "start"));
  234. parse_time(start_time, &start_tm);
  235. audio_data_conf->start_time = mktime(&start_tm);
  236. strcpy(end_time, gf_cfg_get_key(conf, section_name, "end"));
  237. parse_time(end_time, &end_tm);
  238. audio_data_conf->end_time = mktime(&end_tm);
  239. gf_list_add(cmd_data->asrc, (void *) audio_data_conf);
  240. } else {
  241. fprintf(stdout, "Switch source configuration file: type %s is not supported.\n", section_type);
  242. }
  243. }
  244. fprintf(stdout, "\33[34m\33[1m");
  245. fprintf(stdout, "Sources:\n");
  246. for (i=0; i<gf_list_count(cmd_data->vsrc); i++) {
  247. VideoDataConf *video_data_conf = gf_list_get(cmd_data->vsrc, i);
  248. strftime(start_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&video_data_conf->start_time));
  249. strftime(end_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&video_data_conf->end_time));
  250. fprintf(stdout, " id:%s\tsource:%s\tstart:%s\tend:%s\n", video_data_conf->source_id, video_data_conf->filename, start_time, end_time);
  251. }
  252. for (i=0; i<gf_list_count(cmd_data->asrc); i++) {
  253. AudioDataConf *audio_data_conf = gf_list_get(cmd_data->asrc, i);
  254. strftime(start_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&audio_data_conf->start_time));
  255. strftime(end_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&audio_data_conf->end_time));
  256. fprintf(stdout, " id:%s\tsource:%s\tstart:%s\tend:%s\n", audio_data_conf->source_id, audio_data_conf->filename, start_time, end_time);
  257. }
  258. fprintf(stdout, "\33[0m");
  259. fflush(stdout);
  260. return 0;
  261. }
  262. void dc_cmd_data_init(CmdData *cmd_data)
  263. {
  264. memset(cmd_data, 0, sizeof(CmdData));
  265. dc_audio_data_set_default(&cmd_data->audio_data_conf);
  266. dc_video_data_set_default(&cmd_data->video_data_conf);
  267. cmd_data->mode = ON_DEMAND;
  268. cmd_data->ast_offset = -1;
  269. cmd_data->min_buffer_time = -1;
  270. cmd_data->use_source_timing = 1;
  271. cmd_data->audio_lst = gf_list_new();
  272. cmd_data->video_lst = gf_list_new();
  273. cmd_data->asrc = gf_list_new();
  274. cmd_data->vsrc = gf_list_new();
  275. }
  276. void dc_cmd_data_destroy(CmdData *cmd_data)
  277. {
  278. while (gf_list_count(cmd_data->audio_lst)) {
  279. AudioDataConf *audio_data_conf = gf_list_last(cmd_data->audio_lst);
  280. gf_list_rem_last(cmd_data->audio_lst);
  281. gf_free(audio_data_conf);
  282. }
  283. gf_list_del(cmd_data->audio_lst);
  284. while (gf_list_count(cmd_data->video_lst)) {
  285. VideoDataConf *video_data_conf = gf_list_last(cmd_data->video_lst);
  286. gf_list_rem_last(cmd_data->video_lst);
  287. gf_free(video_data_conf);
  288. }
  289. gf_list_del(cmd_data->video_lst);
  290. gf_list_del(cmd_data->asrc);
  291. gf_list_del(cmd_data->vsrc);
  292. gf_cfg_del(cmd_data->conf);
  293. gf_cfg_del(cmd_data->switch_conf);
  294. if (cmd_data->logfile)
  295. fclose(cmd_data->logfile);
  296. dc_task_destroy(&cmd_data->task_list);
  297. gf_sys_close();
  298. }
  299. static void on_dc_log(void *cbk, u32 ll, u32 lm, const char *fmt, va_list list)
  300. {
  301. FILE *logs = cbk;
  302. vfprintf(logs, fmt, list);
  303. fflush(logs);
  304. }
  305. int dc_parse_command(int argc, char **argv, CmdData *cmd_data)
  306. {
  307. Bool use_mem_track = GF_FALSE;
  308. int i;
  309. const char *command_usage =
  310. "Usage: DashCast [options]\n"
  311. "\n"
  312. "Options:\n"
  313. "\n"
  314. " -log-file file set output log file. Also works with -lf\n"
  315. " -logs LOGS set log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@levelX\n"
  316. " -a inasrc:str input audio source named inasrc\n"
  317. " - If input is from microphone, inasrc will be \"plughw:[x],[y]\"\n"
  318. " where x is the card number and y is the device number.\n"
  319. " -v invsrc:str input video source named invsrc\n"
  320. " - If input is from a webcam, invsrc will be \"/dev/video[x]\" \n"
  321. " where x is the video device number.\n"
  322. " - If input is the screen video, invsrc will be \":0.0+[x],[y]\" \n"
  323. " which captures from upper-left at x,y.\n"
  324. " - If input is from stdin, invsrc will be \"pipe:\".\n"
  325. " -av inavsrc:str a multiplexed audio and video source named inavsrc\n"
  326. " - If this option is present, non of '-a' or '-v' can be present.\n"
  327. " -vf invfmt:str invfmt is the input video format\n"
  328. #ifdef WIN32
  329. " - To capture from a VfW webcam invfmt will be vfwcap."
  330. " - To capture from a directshow device invfmt will be dshow."
  331. #else
  332. " - To capture from a webcam invfmt will be video4linux2.\n"
  333. " - To capture the screen invfmt will be x11grab.\n"
  334. " -v4l2f inv4l2f:str inv4l2f is the input format for webcam acquisition\n"
  335. " - It can be mjpeg, yuyv422, etc.\n"
  336. #endif
  337. " -pixf FMT spcifies the input pixel format to use\n"
  338. " -vfr invfr:int invfr is the input video framerate\n"
  339. " -vres invres:intxint input video resolution\n"
  340. " -af inafmt:str inafmt is the input audio format\n"
  341. " -conf confname:str confname is the configuration file\n"
  342. " - The default value is dashcast.conf\n\n"
  343. " -seg-dur dur:int dur is the segment duration in millisecond\n"
  344. " - The default value is 1000.\n"
  345. " -frag-dur dur:int dur is the fragment duration in millisecond\n"
  346. " - The default value is 1000.\n"
  347. " -live system is live and input is a camera\n"
  348. " -npts uses frame counting for timestamps (not error-free) instead of source timing (default)\n"
  349. " -live-media system is live and input is a media file\n"
  350. " -no-loop system does not loop on the input media file\n"
  351. " -seg-marker marker:str add a marker box named marker at the end of DASH segment\n"
  352. " -gdr use Gradual Decoder Refresh feature for video encoding\n\n"
  353. " -out outdir:str outdir is the output data directory\n"
  354. " - The default value is output.\n"
  355. " -mpd mpdname:str mpdname is the MPD file name\n"
  356. " - The default value is dashcast.mpd.\n"
  357. " -ast-offset dur:int dur is the MPD availabilityStartTime shift in milliseconds\n"
  358. " - The default value is 1000.\n"
  359. " -time-shift dur:int dur is the MPD TimeShiftBufferDepth in seconds\n"
  360. " - The default value is 10. Specify -1 to keep all files.\n"
  361. " -min-buffer dur:float dur is the MPD minBufferTime in seconds\n"
  362. " - The default value is 1.0.\n\n"
  363. " -switch-source confname:str confname is the name of configuration file for source switching.\n\n"
  364. "Examples:\n"
  365. "\n"
  366. " DashCast -av test.avi -live-media\n"
  367. " DashCast -a test_audio.mp3 -v test_audio.mp4 -live-media\n"
  368. #ifdef WIN32
  369. " DashCast -vf vfwcap -vres 1280x720 -vfr 24 -v 0 -live\n"
  370. " DashCast -vf dshow -vres 1280x720 -vfr 24 -v video=\"screen-capture-recorder\" -live (please install http://screencapturer.sf.net/)\n"
  371. " DashCast -vf dshow -vres 1280x720 -vfr 24 -v video=\"YOUR-WEBCAM\" -pixf yuv420p -live\n"
  372. #else
  373. " DashCast -vf video4linux2 -vres 1280x720 -vfr 24 -v4l2f mjpeg -v /dev/video0 -af alsa -a plughw:1,0 -live\n"
  374. " DashCast -vf x11grab -vres 800x600 -vfr 25 -v :0.0 -live\n"
  375. #endif
  376. "\n";
  377. char *command_error = "\33[31mUnknown option or missing mandatory argument.\33[0m\n";
  378. if (argc == 1) {
  379. fprintf(stdout, "%s", command_usage);
  380. return -2;
  381. }
  382. #ifdef GPAC_MEMORY_TRACKING
  383. i = 1;
  384. while (i < argc) {
  385. if (strcmp(argv[i], "-mem-track") == 0) {
  386. use_mem_track = GF_TRUE;
  387. break;
  388. }
  389. i++;
  390. }
  391. #endif
  392. gf_sys_init(use_mem_track);
  393. if (use_mem_track) {
  394. gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_INFO);
  395. }
  396. /* Initialize command data */
  397. dc_cmd_data_init(cmd_data);
  398. i = 1;
  399. while (i < argc) {
  400. if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-av") == 0) {
  401. i++;
  402. if (i >= argc) {
  403. fprintf(stdout, "%s", command_error);
  404. fprintf(stdout, "%s", command_usage);
  405. return -1;
  406. }
  407. if (strcmp(argv[i - 1], "-a") == 0 || strcmp(argv[i - 1], "-av") == 0) {
  408. if (strcmp(cmd_data->audio_data_conf.filename, "") != 0) {
  409. fprintf(stdout, "Audio source has been already specified.\n");
  410. fprintf(stdout, "%s", command_usage);
  411. return -1;
  412. }
  413. strcpy(cmd_data->audio_data_conf.filename, argv[i]);
  414. }
  415. if (strcmp(argv[i - 1], "-v") == 0 || strcmp(argv[i - 1], "-av") == 0) {
  416. if (strcmp(cmd_data->video_data_conf.filename, "") != 0) {
  417. fprintf(stdout, "Video source has been already specified.\n");
  418. fprintf(stdout, "%s", command_usage);
  419. return -1;
  420. }
  421. strcpy(cmd_data->video_data_conf.filename, argv[i]);
  422. }
  423. i++;
  424. } else if (strcmp(argv[i], "-af") == 0 || strcmp(argv[i], "-vf") == 0) {
  425. i++;
  426. if (i >= argc) {
  427. fprintf(stdout, "%s", command_error);
  428. fprintf(stdout, "%s", command_usage);
  429. return -1;
  430. }
  431. if (strcmp(argv[i - 1], "-af") == 0) {
  432. if (strcmp(cmd_data->audio_data_conf.format, "") != 0) {
  433. fprintf(stdout, "Audio format has been already specified.\n");
  434. fprintf(stdout, "%s", command_usage);
  435. return -1;
  436. }
  437. strcpy(cmd_data->audio_data_conf.format, argv[i]);
  438. }
  439. if (strcmp(argv[i - 1], "-vf") == 0) {
  440. if (strcmp(cmd_data->video_data_conf.format, "") != 0) {
  441. fprintf(stdout, "Video format has been already specified.\n");
  442. fprintf(stdout, "%s", command_usage);
  443. return -1;
  444. }
  445. strcpy(cmd_data->video_data_conf.format, argv[i]);
  446. }
  447. i++;
  448. } else if (strcmp(argv[i], "-pixf") == 0) {
  449. i++;
  450. if (i >= argc) {
  451. fprintf(stdout, "%s", command_error);
  452. fprintf(stdout, "%s", command_usage);
  453. return -1;
  454. }
  455. if (strcmp(cmd_data->video_data_conf.pixel_format, "") != 0) {
  456. fprintf(stdout, "Input pixel format has been already specified.\n");
  457. fprintf(stdout, "%s", command_usage);
  458. return -1;
  459. }
  460. strcpy(cmd_data->video_data_conf.pixel_format, argv[i]);
  461. i++;
  462. } else if (strcmp(argv[i], "-vfr") == 0) {
  463. i++;
  464. if (i >= argc) {
  465. fprintf(stdout, "%s", command_error);
  466. fprintf(stdout, "%s", command_usage);
  467. return -1;
  468. }
  469. if (cmd_data->video_data_conf.framerate != -1) {
  470. fprintf(stdout, "Video framerate has been already specified.\n");
  471. fprintf(stdout, "%s", command_usage);
  472. return -1;
  473. }
  474. cmd_data->video_data_conf.framerate = atoi(argv[i]);
  475. i++;
  476. } else if (strcmp(argv[i], "-vres") == 0) {
  477. i++;
  478. if (i >= argc) {
  479. fprintf(stdout, "%s", command_error);
  480. fprintf(stdout, "%s", command_usage);
  481. return -1;
  482. }
  483. if (cmd_data->video_data_conf.height != -1 && cmd_data->video_data_conf.width != -1) {
  484. fprintf(stdout, "Video resolution has been already specified.\n");
  485. fprintf(stdout, "%s", command_usage);
  486. return -1;
  487. }
  488. dc_str_to_resolution(argv[i], &cmd_data->video_data_conf.width, &cmd_data->video_data_conf.height);
  489. i++;
  490. } else if (strcmp(argv[i], "-conf") == 0) {
  491. i++;
  492. if (i >= argc) {
  493. fprintf(stdout, "%s", command_error);
  494. fprintf(stdout, "%s", command_usage);
  495. return -1;
  496. }
  497. cmd_data->conf = gf_cfg_force_new(NULL, argv[i]);
  498. i++;
  499. } else if (strcmp(argv[i], "-switch-source") == 0) {
  500. i++;
  501. if (i >= argc) {
  502. fprintf(stdout, "%s", command_error);
  503. fprintf(stdout, "%s", command_usage);
  504. return -1;
  505. }
  506. cmd_data->switch_conf = gf_cfg_force_new(NULL, argv[i]);
  507. i++;
  508. } else if (strcmp(argv[i], "-out") == 0) {
  509. i++;
  510. if (i >= argc) {
  511. fprintf(stdout, "%s", command_error);
  512. fprintf(stdout, "%s", command_usage);
  513. return -1;
  514. }
  515. strcpy(cmd_data->out_dir, argv[i]);
  516. i++;
  517. #ifndef WIN32
  518. } else if (strcmp(argv[i], "-v4l2f") == 0) {
  519. i++;
  520. if (i >= argc) {
  521. fprintf(stdout, "%s", command_error);
  522. fprintf(stdout, "%s", command_usage);
  523. return -1;
  524. }
  525. strcpy(cmd_data->video_data_conf.v4l2f, argv[i]);
  526. i++;
  527. #endif
  528. } else if (strcmp(argv[i], "-seg-marker") == 0) {
  529. char *m;
  530. i++;
  531. if (i >= argc) {
  532. fprintf(stdout, "%s", command_error);
  533. fprintf(stdout, "%s", command_usage);
  534. return -1;
  535. }
  536. m = argv[i];
  537. if (strlen(m) == 4) {
  538. cmd_data->seg_marker = GF_4CC(m[0], m[1], m[2], m[3]);
  539. } else {
  540. fprintf(stdout, "Invalid marker box name specified: %s\n", m);
  541. return -1;
  542. }
  543. i++;
  544. } else if (strcmp(argv[i], "-mpd") == 0) {
  545. i++;
  546. if (i >= argc) {
  547. fprintf(stdout, "%s", command_error);
  548. fprintf(stdout, "%s", command_usage);
  549. return -1;
  550. }
  551. if (strcmp(cmd_data->mpd_filename, "") != 0) {
  552. fprintf(stdout, "MPD file has been already specified.\n");
  553. fprintf(stdout, "%s", command_usage);
  554. return -1;
  555. }
  556. strncpy(cmd_data->mpd_filename, argv[i], GF_MAX_PATH);
  557. i++;
  558. } else if (strcmp(argv[i], "-seg-dur") == 0) {
  559. i++;
  560. if (i >= argc) {
  561. fprintf(stdout, "%s", command_error);
  562. fprintf(stdout, "%s", command_usage);
  563. return -1;
  564. }
  565. if (cmd_data->seg_dur != 0) {
  566. fprintf(stdout, "Segment duration has been already specified.\n");
  567. fprintf(stdout, "%s", command_usage);
  568. return -1;
  569. }
  570. cmd_data->seg_dur = atoi(argv[i]);
  571. i++;
  572. } else if (strcmp(argv[i], "-frag-dur") == 0) {
  573. i++;
  574. if (i >= argc) {
  575. fprintf(stdout, "%s", command_error);
  576. fprintf(stdout, "%s", command_usage);
  577. return -1;
  578. }
  579. if (cmd_data->frag_dur != 0) {
  580. fprintf(stdout, "Fragment duration has been already specified.\n");
  581. fprintf(stdout, "%s", command_usage);
  582. return -1;
  583. }
  584. cmd_data->frag_dur = atoi(argv[i]);
  585. i++;
  586. } else if (strcmp(argv[i], "-ast-offset") == 0) {
  587. i++;
  588. if (i >= argc) {
  589. fprintf(stdout, "%s", command_error);
  590. fprintf(stdout, "%s", command_usage);
  591. return -1;
  592. }
  593. if (cmd_data->ast_offset != -1) {
  594. fprintf(stdout, "AvailabilityStartTime offset has been already specified.\n");
  595. fprintf(stdout, "%s", command_usage);
  596. return -1;
  597. }
  598. cmd_data->ast_offset = atoi(argv[i]);
  599. i++;
  600. } else if (strcmp(argv[i], "-time-shift") == 0) {
  601. i++;
  602. if (i >= argc) {
  603. fprintf(stdout, "%s", command_error);
  604. fprintf(stdout, "%s", command_usage);
  605. return -1;
  606. }
  607. if (cmd_data->time_shift != 0) {
  608. fprintf(stdout, "TimeShiftBufferDepth has been already specified.\n");
  609. fprintf(stdout, "%s", command_usage);
  610. return -1;
  611. }
  612. cmd_data->time_shift = atoi(argv[i]);
  613. i++;
  614. } else if (strcmp(argv[i], "-min-buffer") == 0) {
  615. i++;
  616. if (i >= argc) {
  617. fprintf(stdout, "%s", command_error);
  618. fprintf(stdout, "%s", command_usage);
  619. return -1;
  620. }
  621. if (cmd_data->min_buffer_time != -1) {
  622. fprintf(stdout, "Min Buffer Time has been already specified.\n");
  623. fprintf(stdout, "%s", command_usage);
  624. return -1;
  625. }
  626. cmd_data->min_buffer_time = (float)atof(argv[i]);
  627. i++;
  628. } else if (strcmp(argv[i], "-live") == 0) {
  629. cmd_data->mode = LIVE_CAMERA;
  630. i++;
  631. } else if (strcmp(argv[i], "-npts") == 0) {
  632. cmd_data->use_source_timing = 0;
  633. i++;
  634. } else if (strcmp(argv[i], "-live-media") == 0) {
  635. cmd_data->mode = LIVE_MEDIA;
  636. i++;
  637. } else if (strcmp(argv[i], "-no-loop") == 0) {
  638. cmd_data->no_loop = 1;
  639. i++;
  640. } else if (strcmp(argv[i], "-send-message") == 0) {
  641. cmd_data->send_message = 1;
  642. i++;
  643. } else if (strcmp(argv[i], "-logs") == 0) {
  644. i++;
  645. if (i >= argc) {
  646. fprintf(stdout, "%s", command_error);
  647. fprintf(stdout, "%s", command_usage);
  648. return -1;
  649. }
  650. if (gf_log_set_tools_levels(argv[i]) != GF_OK) {
  651. fprintf(stdout, "Invalid log format %s", argv[i]);
  652. return 1;
  653. }
  654. i++;
  655. } else if (strcmp(argv[i], "-mem-track") == 0) {
  656. i++;
  657. #ifndef GPAC_MEMORY_TRACKING
  658. fprintf(stderr, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n");
  659. #endif
  660. } else if (!strcmp(argv[i], "-lf") || !strcmp(argv[i], "-log-file")) {
  661. i++;
  662. if (i >= argc) {
  663. fprintf(stdout, "%s", command_error);
  664. fprintf(stdout, "%s", command_usage);
  665. return -1;
  666. }
  667. cmd_data->logfile = gf_f64_open(argv[i], "wt");
  668. gf_log_set_callback(cmd_data->logfile, on_dc_log);
  669. i++;
  670. } else if (strcmp(argv[i], "-gdr") == 0) {
  671. cmd_data->gdr = 1;
  672. i++;
  673. } else {
  674. fprintf(stdout, "%s", command_error);
  675. fprintf(stdout, "%s", command_usage);
  676. return -1;
  677. }
  678. }
  679. if (strcmp(cmd_data->mpd_filename, "") == 0) {
  680. strcpy(cmd_data->mpd_filename, "dashcast.mpd");
  681. }
  682. if (strcmp(cmd_data->out_dir, "") == 0) {
  683. struct stat status;
  684. strcpy(cmd_data->out_dir, "output");
  685. if (stat(cmd_data->out_dir, &status) != 0) {
  686. gf_mkdir(cmd_data->out_dir);
  687. }
  688. }
  689. if (strcmp(cmd_data->video_data_conf.filename, "") == 0 && strcmp(cmd_data->audio_data_conf.filename, "") == 0) {
  690. fprintf(stdout, "Audio/Video source must be specified.\n");
  691. fprintf(stdout, "%s", command_usage);
  692. return -1;
  693. }
  694. if (cmd_data->seg_dur == 0) {
  695. cmd_data->seg_dur = 1000;
  696. }
  697. if (cmd_data->frag_dur == 0) {
  698. cmd_data->frag_dur = cmd_data->seg_dur;
  699. }
  700. if (cmd_data->ast_offset == -1) {
  701. //generate MPD as soon as possible (no offset)
  702. cmd_data->ast_offset = 0;
  703. }
  704. if (cmd_data->mode == ON_DEMAND)
  705. cmd_data->time_shift = -1;
  706. else {
  707. if (cmd_data->time_shift == 0) {
  708. cmd_data->time_shift = 10;
  709. }
  710. }
  711. if (cmd_data->min_buffer_time == -1) {
  712. cmd_data->min_buffer_time = 1.0;
  713. }
  714. fprintf(stdout, "\33[34m\33[1m");
  715. fprintf(stdout, "Options:\n");
  716. fprintf(stdout, " video source: %s\n", cmd_data->video_data_conf.filename);
  717. if (strcmp(cmd_data->video_data_conf.format, "") != 0) {
  718. fprintf(stdout, " video format: %s\n", cmd_data->video_data_conf.format);
  719. }
  720. #ifndef WIN32
  721. if (strcmp(cmd_data->video_data_conf.v4l2f, "") != 0) {
  722. fprintf(stdout, " v4l2 format: %s\n", cmd_data->video_data_conf.v4l2f);
  723. }
  724. #endif
  725. if (cmd_data->video_data_conf.framerate != -1) {
  726. fprintf(stdout, " video framerate: %d\n", cmd_data->video_data_conf.framerate);
  727. }
  728. if (cmd_data->video_data_conf.height != -1 && cmd_data->video_data_conf.width != -1) {
  729. fprintf(stdout, " video resolution: %dx%d\n", cmd_data->video_data_conf.width, cmd_data->video_data_conf.height);
  730. }
  731. fprintf(stdout, " audio source: %s\n", cmd_data->audio_data_conf.filename);
  732. if (strcmp(cmd_data->audio_data_conf.format, "") != 0) {
  733. fprintf(stdout, " audio format: %s\n", cmd_data->audio_data_conf.format);
  734. }
  735. fprintf(stdout, "\33[0m");
  736. // fflush(stdout);
  737. if (!cmd_data->conf) {
  738. cmd_data->conf = gf_cfg_force_new(NULL, "dashcast.conf");
  739. dc_create_configuration(cmd_data);
  740. }
  741. dc_read_configuration(cmd_data);
  742. if (!cmd_data->switch_conf) {
  743. cmd_data->switch_conf = gf_cfg_force_new(NULL, "switch.conf");
  744. }
  745. dc_read_switch_config(cmd_data);
  746. return 0;
  747. }