PageRenderTime 104ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/applications/mp4box/main.c

https://github.com/svettom/gpac-1
C | 3480 lines | 3146 code | 213 blank | 121 comment | 1100 complexity | 0a46f563d3a9eabb437eb04a8c00a626 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. /*
  2. * GPAC - Multimedia Framework C SDK
  3. *
  4. * Copyright (c) Jean Le Feuvre 2000-2005
  5. * All rights reserved
  6. *
  7. * This file is part of GPAC / mp4box application
  8. *
  9. * GPAC is gf_free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as published by
  11. * the Free Software Foundation; either version 2, or (at your option)
  12. * any later version.
  13. *
  14. * GPAC is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; see the file COPYING. If not, write to
  21. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22. *
  23. */
  24. #include <gpac/scene_manager.h>
  25. #include <gpac/download.h>
  26. #ifdef GPAC_DISABLE_ISOM
  27. #error "Cannot compile MP4Box if GPAC is not built with ISO File Format support"
  28. #else
  29. #include <gpac/media_tools.h>
  30. /*RTP packetizer flags*/
  31. #include <gpac/ietf.h>
  32. #include <gpac/ismacryp.h>
  33. #include <gpac/constants.h>
  34. #include <gpac/internal/mpd.h>
  35. #include <time.h>
  36. #define BUFFSIZE 8192
  37. /*in fileimport.c*/
  38. #ifndef GPAC_DISABLE_ISOM_WRITE
  39. GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double force_fps, u32 frames_per_sample);
  40. GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start, Bool adjust_split_end, char *outName, const char *tmpdir);
  41. GF_Err cat_isomedia_file(GF_ISOFile *mp4, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat);
  42. #if !defined(GPAC_DISABLE_MEDIA_IMPORT) && !defined(GPAC_DISABLE_SCENE_ENCODER)
  43. void convert_file_info(char *inName, u32 trackID);
  44. GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *logs);
  45. GF_Err EncodeFileChunk(char *chunkFile, char *bifs, char *inputContext, char *outputContext, const char *tmpdir);
  46. #endif
  47. GF_ISOFile *package_file(char *file_name, char *fcc, const char *tmpdir, Bool make_wgt);
  48. #endif
  49. GF_Err dump_cover_art(GF_ISOFile *file, char *inName);
  50. GF_Err dump_chapters(GF_ISOFile *file, char *inName);
  51. u32 id3_get_genre_tag(const char *name);
  52. /*in filedump.c*/
  53. #ifndef GPAC_DISABLE_SCENE_DUMP
  54. GF_Err dump_file_text(char *file, char *inName, u32 dump_mode, Bool do_log);
  55. #endif
  56. #ifndef GPAC_DISABLE_SCENE_STATS
  57. void dump_scene_stats(char *file, char *inName, u32 stat_level);
  58. #endif
  59. void PrintNode(const char *name, u32 graph_type);
  60. void PrintBuiltInNodes(u32 graph_type);
  61. #ifndef GPAC_DISABLE_ISOM_DUMP
  62. void dump_isom_xml(GF_ISOFile *file, char *inName);
  63. #endif
  64. #ifndef GPAC_DISABLE_ISOM_HINTING
  65. #ifndef GPAC_DISABLE_ISOM_DUMP
  66. void dump_file_rtp(GF_ISOFile *file, char *inName);
  67. #endif
  68. void DumpSDP(GF_ISOFile *file, char *inName);
  69. #endif
  70. void dump_file_ts(GF_ISOFile *file, char *inName);
  71. #ifndef GPAC_DISABLE_ISOM_DUMP
  72. void dump_file_ismacryp(GF_ISOFile *file, char *inName);
  73. void dump_timed_text_track(GF_ISOFile *file, u32 trackID, char *inName, Bool is_convert, u32 dump_type);
  74. #endif /*GPAC_DISABLE_ISOM_DUMP*/
  75. void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump);
  76. void DumpMovieInfo(GF_ISOFile *file);
  77. void PrintLanguages();
  78. const char *GetLanguageCode(char *lang);
  79. #ifndef GPAC_DISABLE_MPEG2TS
  80. void dump_mpeg2_ts(char *mpeg2ts_file, char *pes_out_name, Bool prog_num,
  81. Double dash_duration, Bool seg_at_rap, u32 subseg_per_seg,
  82. char *seg_name, char *seg_ext, Bool use_url_template, Bool single_segment, u32 representation_idx, Bool last_rep);
  83. #endif
  84. #if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_SENG)
  85. void PrintStreamerUsage();
  86. int stream_file_rtp(int argc, char **argv);
  87. int live_session(int argc, char **argv);
  88. void PrintLiveUsage();
  89. #endif
  90. int mp4boxTerminal(int argc, char **argv);
  91. u32 quiet = 0;
  92. Bool dvbhdemux =0;
  93. Bool keep_sys_tracks = 0;
  94. /*some global vars for swf import :(*/
  95. u32 swf_flags = 0;
  96. Float swf_flatten_angle = 0;
  97. s32 laser_resolution = 0;
  98. typedef struct { u32 code; const char *name; const char *comment; } itunes_tag;
  99. static const itunes_tag itags[] = {
  100. {GF_ISOM_ITUNE_ALBUM_ARTIST, "album_artist", "usage: album_artist=album artist"},
  101. {GF_ISOM_ITUNE_ALBUM, "album", "usage: album=name" },
  102. {GF_ISOM_ITUNE_TRACKNUMBER, "tracknum", "usage: track=x/N"},
  103. {GF_ISOM_ITUNE_TRACK, "track", "usage: track=name"},
  104. {GF_ISOM_ITUNE_ARTIST, "artist", "usage: artist=name"},
  105. {GF_ISOM_ITUNE_COMMENT, "comment", "usage: comment=any comment"},
  106. {GF_ISOM_ITUNE_COMPILATION, "compilation", "usage: compilation=yes,no"},
  107. {GF_ISOM_ITUNE_COMPOSER, "composer", "usage: composer=name"},
  108. {GF_ISOM_ITUNE_CREATED, "created", "usage: created=time"},
  109. {GF_ISOM_ITUNE_DISK, "disk", "usage: disk=x/N"},
  110. {GF_ISOM_ITUNE_TOOL, "tool", "usage: tool=name"},
  111. {GF_ISOM_ITUNE_GENRE, "genre", "usage: genre=name"},
  112. {GF_ISOM_ITUNE_NAME, "name", "usage: name=name"},
  113. {GF_ISOM_ITUNE_TEMPO, "tempo", "usage: tempo=integer"},
  114. {GF_ISOM_ITUNE_WRITER, "writer", "usage: writer=name"},
  115. {GF_ISOM_ITUNE_GROUP, "group", "usage: group=name"},
  116. {GF_ISOM_ITUNE_COVER_ART, "cover", "usage: cover=file.jpg,file.png"},
  117. {GF_ISOM_ITUNE_ENCODER, "encoder", "usage: encoder=name"},
  118. {GF_ISOM_ITUNE_GAPLESS, "gapless", "usage: gapless=yes,no"},
  119. };
  120. u32 nb_itunes_tags = sizeof(itags) / sizeof(itunes_tag);
  121. void PrintVersion()
  122. {
  123. fprintf(stdout, "MP4Box - GPAC version " GPAC_FULL_VERSION "\n"
  124. "GPAC Copyright: (c) Jean Le Feuvre 2000-2005\n\t\t(c) ENST 2005-200X\n"
  125. "GPAC Configuration: " GPAC_CONFIGURATION "\n"
  126. "Features: %s\n", gpac_features());
  127. }
  128. void PrintGeneralUsage()
  129. {
  130. fprintf(stdout, "General Options:\n"
  131. #ifdef GPAC_MEMORY_TRACKING
  132. " -mem-track: enables memory tracker\n"
  133. #endif
  134. " -strict-error exits after the first error is reported\n"
  135. " -inter time_in_ms interleaves file data (track chunks of time_in_ms)\n"
  136. " * Note 1: Interleaving is 0.5s by default\n"
  137. " * Note 2: Performs drift checking accross tracks\n"
  138. " * Note 3: a value of 0 disables interleaving\n"
  139. " -old-inter time same as -inter but doesn't perform drift checking\n"
  140. " -tight performs tight interleaving (sample based) of the file\n"
  141. " * Note: reduces disk seek but increases file size\n"
  142. " -flat stores file with all media data first, non-interleaved\n"
  143. " -frag time_in_ms fragments file (track fragments of time_in_ms)\n"
  144. " * Note: Always disables interleaving\n"
  145. " -ffspace size inserts free space before moof in fragmented files\n"
  146. " -out filename specifies output file name\n"
  147. " * Note: By default input (MP4,3GP) file is overwritten\n"
  148. " -tmp dirname specifies directory for temporary file creation\n"
  149. " * Note: Default temp dir is OS-dependent\n"
  150. " -no-sys removes all MPEG-4 Systems info except IOD (profiles)\n"
  151. " * Note: Set by default whith '-add' and '-cat'\n"
  152. " -no-iod removes InitialObjectDescriptor from file\n"
  153. " -isma rewrites the file as an ISMA 1.0 AV file\n"
  154. " -ismax same as \'-isma\' and removes all clock references\n"
  155. " -3gp rewrites as 3GPP(2) file (no more MPEG-4 Systems Info)\n"
  156. " * Note 1: some tracks may be removed in the process\n"
  157. " * Note 2: always on for *.3gp *.3g2 *.3gpp\n"
  158. " -ipod rewrites the file for iPod\n"
  159. " -brand ABCD[:v] sets major brand of file, with optional version\n"
  160. " -ab ABCD adds given brand to file's alternate brand list\n"
  161. " -rb ABCD removes given brand from file's alternate brand list\n"
  162. " -cprt string adds copyright string to movie\n"
  163. " -chap file adds chapter information contained in file\n"
  164. " -rem trackID removes track from file\n"
  165. " -enable trackID enables track\n"
  166. " -disable trackID disables track\n"
  167. " -new forces creation of a new destination file\n"
  168. " -lang [tkID=]LAN sets track language. LAN is the ISO 639-2 code (eng, und)\n"
  169. " -delay tkID=TIME sets track start delay in ms.\n"
  170. " -par tkID=PAR sets visual track pixel aspect ratio (PAR=N:D or \"none\")\n"
  171. " -name tkID=NAME sets track handler name\n"
  172. " * NAME can indicate a UTF-8 file (\"file://file name\"\n"
  173. " -itags tag1[:tag2] sets iTunes tags to file - more info: MP4Box -tag-list.\n"
  174. " -split time_sec splits in files of time_sec max duration\n"
  175. " * Note: this removes all MPEG-4 Systems media\n"
  176. " -split-size size splits in files of max filesize kB. same as -splits.\n"
  177. " * Note: this removes all MPEG-4 Systems media\n"
  178. " -split-rap splits in files begining at each RAP. same as -splitr.\n"
  179. " * Note: this removes all MPEG-4 Systems media\n"
  180. " -split-chunk S:E extracts a new file from Start to End (in seconds). same as -splitx\n"
  181. " * Note: this removes all MPEG-4 Systems media\n"
  182. " -splitz S:E same as -split-chunk, but adjust the end time to be before the last RAP sample\n"
  183. " * Note: this removes all MPEG-4 Systems media\n"
  184. " -group-add fmt creates a new grouping information in the file. Format is\n"
  185. " a colon-separated list of following options:\n"
  186. " refTrack=ID: ID of the track used as a group reference.\n"
  187. " If not set, the track will belong to the same group as the previous trackID specified.\n"
  188. " If 0 or no previous track specified, a new alternate group will be created\n"
  189. " switchID=ID: ID of the switch group to create.\n"
  190. " If 0, a new ID will be computed for you\n"
  191. " If <0, disables SwitchGroup\n"
  192. " criteria=string: list of space-separated 4CCs.\n"
  193. " trackID=ID: ID of the track to add to this group.\n"
  194. "\n"
  195. " *WARNING* Options modify state as they are parsed:\n"
  196. " trackID=1:criteria=lang:trackID=2\n"
  197. " is different from:\n"
  198. " criteria=lang:trackID=1:trackID=2\n"
  199. "\n"
  200. " -group-rem-track ID removes track from its group\n"
  201. " -group-rem ID removes the track's group\n"
  202. " -group-clean removes all group information from all tracks\n"
  203. " -group-single puts all tracks in a single group\n"
  204. " -ref id:XXXX:refID adds a reference of type 4CC from track ID to track refID\n"
  205. "\n"
  206. " -dash dur enables DASH-ing of the file with a segment duration of DUR\n"
  207. " Note: the duration of a fragment (subsegment) is set\n"
  208. " using the interleaver (-inter) switch.\n"
  209. " Note: You can specify -rap switch to split segments at RAP boundaries\n"
  210. " Note: when single-segment is used, this specifies the duration of a subsegment\n"
  211. " -subsegs-per-sidx N sets the number of subsegments to be written in each SIDX box\n"
  212. " If 0, a single SIDX box is used per segment\n"
  213. " If -1, no SIDX box is used\n"
  214. " -rap segments begin with random access points\n"
  215. " Note: segment duration may not be exactly what asked by\n"
  216. " \"-dash\" since raw video data is not modified\n"
  217. " -segment-name name sets the segment name for generated segments\n"
  218. " If not set (default), segments are concatenated in output file\n"
  219. " -segment-ext name sets the segment extension. Default is m4s\n"
  220. " -url-template uses SegmentTemplate instead of explicit sources in segments.\n"
  221. " Ignored if segments are stored in the output file.\n"
  222. " -daisy-chain Uses daisy-chain SIDX instead of hierarchical. Ignored if frags/sidx is 0.\n"
  223. " -single-segment Uses a single segment for the whole file (OnDemand profile). \n"
  224. " -dash-ctx FILE Stores/restore DASH timing from FILE.\n"
  225. " -dash-ts-prog N program_number to be considered in case of an MPTS input file.\n"
  226. "\n");
  227. }
  228. void PrintFormats()
  229. {
  230. fprintf(stdout, "Suppported raw formats and file extensions:\n"
  231. " NHNT .media .nhnt .info\n"
  232. " NHML .nhml (opt: .media .info)\n"
  233. " MPEG-1-2 Video .m1v .m2v\n"
  234. " MPEG-4 Video .cmp .m4v\n"
  235. " H263 Video .263 .h263\n"
  236. " AVC/H264 Video .h264 .h26L .264 .26L\n"
  237. " JPEG Images .jpg .jpeg\n"
  238. " PNG Images .png\n"
  239. " MPEG 1-2 Audio .mp3, .m1a, .m2a\n"
  240. " ADTS-AAC Audio .aac\n"
  241. " AMR(WB) Audio .amr .awb\n"
  242. " EVRC Audio .evc\n"
  243. " SMV Audio .smv\n"
  244. "\n"
  245. "Supported containers and file extensions:\n"
  246. " AVI .avi\n"
  247. " MPEG-2 PS .mpg .mpeg .vob .vcd .svcd\n"
  248. " MPEG-2 TS .ts .m2t\n"
  249. " QCP .qcp\n"
  250. " OGG .ogg\n"
  251. " ISO-Media files no extension checking\n"
  252. "\n"
  253. "Supported text formats:\n"
  254. " SRT Subtitles .srt\n"
  255. " SUB Subtitles .sub\n"
  256. " GPAC Timed Text .ttxt\n"
  257. " QuickTime TeXML Text .xml (cf QT documentation)\n"
  258. "\n"
  259. "Supported Scene formats:\n"
  260. " MPEG-4 XMT-A .xmt .xmta .xmt.gz .xmta.gz\n"
  261. " MPEG-4 BT .bt .bt.gz\n"
  262. " VRML .wrl .wrl.gz\n"
  263. " X3D-XML .x3d .x3d.gz\n"
  264. " X3D-VRML .x3dv .x3dv.gz\n"
  265. " MacroMedia Flash .swf (very limitted import support only)\n"
  266. "\n"
  267. );
  268. }
  269. void PrintImportUsage()
  270. {
  271. fprintf(stdout, "Importing Options\n"
  272. "\nFile importing syntax:\n"
  273. " \"#video\" \"#audio\" base import for most AV files\n"
  274. " \"#trackID=ID\" track import for IsoMedia and other files\n"
  275. " \"#pid=ID\" stream import from MPEG-2 TS\n"
  276. " \":dur=D\" imports only the first D seconds\n"
  277. " \":lang=LAN\" sets imported media language code\n"
  278. " \":delay=delay_ms\" sets imported media initial delay in ms\n"
  279. " \":par=PAR\" sets visual pixel aspect ratio (PAR=Num:Den)\n"
  280. " \":name=NAME\" sets track handler name\n"
  281. " \":ext=EXT\" overrides file extension when importing\n"
  282. " \":hdlr=code\" sets track handler type to the given code point (4CC)\n"
  283. " \":disable\" imported track(s) will be disabled\n"
  284. " \":group=G\" adds the track as part of the G alternate group.\n"
  285. " If G is 0, the first available GroupID will be picked.\n"
  286. " \":fps=VAL\" same as -fps option\n"
  287. " \":agg=VAL\" same as -agg option\n"
  288. " \":par=VAL\" same as -par option\n"
  289. " \":dref\" same as -dref option\n"
  290. " \":nodrop\" same as -nodrop option\n"
  291. " \":packed\" same as -packed option\n"
  292. " \":sbr\" same as -sbr option\n"
  293. " \":sbrx\" same as -sbrx option\n"
  294. " \":ps\": same as -ps option\n"
  295. " \":psx\": same as -psx option\n"
  296. " \":ovsbr\": same as -ovsbr option\n"
  297. " \":mpeg4\" same as -mpeg4 option\n"
  298. " \":svc\" import SVC with explicit signaling (no AVC base compatibility)\n"
  299. " \":nosvc\" discard SVC data when importing\n"
  300. " \":subsamples\" adds SubSample information for AVC+SVC\n"
  301. " \":forcesync\" forces non IDR samples with I slices to be marked as sync points (AVC GDR)\n"
  302. " !! RESULTING FILE IS NOT COMPLIANT WITH THE SPEC but will fix seeking in most players\n"
  303. " \":font=name\" specifies font name for text import (default \"Serif\")\n"
  304. " \":size=s\" specifies font size for text import (default 18)\n"
  305. " \":stype=4CC\" forces the sample description type to a different value\n"
  306. " !! THIS MAY BREAK THE FILE WRITING !!\n"
  307. " \":chap\" specifies the track is a chapter track\n"
  308. " \":layout=WxHxXxY\" specifies the track layout\n"
  309. " - if W (resp H) = 0, the max width (resp height) of\n"
  310. " the tracks in the file are used.\n"
  311. " - if Y=-1, the layout is moved to the bottom of the\n"
  312. " track area\n"
  313. " - X and Y can be omitted (:layout=WxH)\n"
  314. "\n"
  315. " -add file add file tracks to (new) output file\n"
  316. " -cat file concatenates file samples to (new) output file\n"
  317. " * Note: creates tracks if needed\n"
  318. " -force-cat skips media configuration check when concatenating file\n"
  319. " !!! THIS MAY BREAK THE CONCATENATED TRACK(S) !!!\n"
  320. " -keep-sys keeps all MPEG-4 Systems info when using '-add' / 'cat'\n"
  321. " -keep-all keeps all existing tracks when using '-add'\n"
  322. " * Note: only used when adding IsoMedia files\n"
  323. "\n"
  324. "All the following options can be specified as default or for each track.\n"
  325. "When specified by track the syntax is \":opt\" or \":opt=val\".\n\n"
  326. " -dref keeps media data in original file\n"
  327. " -no-drop forces constant FPS when importing AVI video\n"
  328. " -packed forces packed bitstream when importing raw ASP\n"
  329. " -sbr backward compatible signaling of AAC-SBR\n"
  330. " -sbrx non-backward compatible signaling of AAC-SBR\n"
  331. " -ps: backward compatible signaling of AAC-PS\n"
  332. " -psx: non-backward compatible signaling of AAC-PS\n"
  333. " -ovsbr: oversample SBR\n"
  334. " * Note: SBR AAC, PS AAC and oversampled SBR cannot be detected at import time\n"
  335. " -fps FPS forces frame rate for video and SUB subtitles import\n"
  336. " FPS is either a number or expressed as timescale-increment\n"
  337. " * For raw H263 import, default FPS is 15\n"
  338. " * For all other imports, default FPS is 25\n"
  339. " !! THIS IS IGNORED FOR IsoMedia IMPORT !!\n"
  340. " -mpeg4 forces MPEG-4 sample descriptions when possible (3GPP2)\n"
  341. " For AAC, forces MPEG-4 AAC signaling even if MPEG-2\n"
  342. " -agg N aggregates N audio frames in 1 sample (3GP media only)\n"
  343. " * Note: Maximum value is 15 - Disabled by default\n"
  344. "\n"
  345. );
  346. }
  347. void PrintEncodeUsage()
  348. {
  349. fprintf(stdout, "MPEG-4 Scene Encoding Options\n"
  350. " -mp4 specify input file is for encoding.\n"
  351. " -def encode DEF names\n"
  352. " -sync time_in_ms forces BIFS sync sample generation every time_in_ms\n"
  353. " * Note: cannot be used with -shadow\n"
  354. " -shadow time_ms forces BIFS sync shadow sample generation every time_ms.\n"
  355. " * Note: cannot be used with -sync\n"
  356. " -log generates scene codec log file if available\n"
  357. " -ms file specifies file for track importing\n"
  358. "\nChunk Processing\n"
  359. " -ctx-in file specifies initial context (MP4/BT/XMT)\n"
  360. " * Note: input file must be a commands-only file\n"
  361. " -ctx-out file specifies storage of updated context (MP4/BT/XMT)\n"
  362. "\n"
  363. "LASeR Encoding options\n"
  364. " -resolution res resolution factor (-8 to 7, default 0)\n"
  365. " all coords are multiplied by 2^res before truncation\n"
  366. " -coord-bits bits bits used for encoding truncated coordinates\n"
  367. " (0 to 31, default 12)\n"
  368. " -scale-bits bits extra bits used for encoding truncated scales\n"
  369. " (0 to 4, default 0)\n"
  370. " -auto-quant res resolution is given as if using -resolution\n"
  371. " but coord-bits and scale-bits are infered\n"
  372. );
  373. }
  374. void PrintEncryptUsage()
  375. {
  376. fprintf(stdout, "ISMA Encryption/Decryption Options\n"
  377. " -crypt drm_file crypts a specific track using ISMA AES CTR 128\n"
  378. " -decrypt [drm_file] decrypts a specific track using ISMA AES CTR 128\n"
  379. " * Note: drm_file can be omitted if keys are in file\n"
  380. " -set-kms kms_uri changes KMS location for all tracks or a given one.\n"
  381. " * to adress a track, use \'tkID=kms_uri\'\n"
  382. "\n"
  383. "DRM file syntax for GPAC ISMACryp:\n"
  384. " File is XML and shall start with xml header\n"
  385. " File root is an \"ISMACryp\" element\n"
  386. " File is a list of \"ISMACrypTrack\" elements\n"
  387. "\n"
  388. "ISMACrypTrack attributes are\n"
  389. " TrackID ID of track to en/decrypt\n"
  390. " key AES-128 key formatted (hex string \'0x\'+32 chars)\n"
  391. " salt CTR IV salt key (64 bits) (hex string \'0x\'+16 chars)\n"
  392. "\nEncryption only attributes:\n"
  393. " Scheme_URI URI of scheme used\n"
  394. " KMS_URI URI of key management system\n"
  395. " * Note: \'self\' writes key and salt in the file\n"
  396. " selectiveType selective encryption type - understood values are:\n"
  397. " \"None\" all samples encrypted (default)\n"
  398. " \"RAP\" only encrypts random access units\n"
  399. " \"Non-RAP\" only encrypts non-random access units\n"
  400. " \"Rand\" random selection is performed\n"
  401. " \"X\" Encrypts every first sample out of X (uint)\n"
  402. " \"RandX\" Encrypts one random sample out of X (uint)\n"
  403. "\n"
  404. " ipmpType IPMP Signaling Type: None, IPMP, IPMPX\n"
  405. " ipmpDescriptorID IPMP_Descriptor ID to use if IPMP(X) is used\n"
  406. " * If not set MP4Box will generate one for you\n"
  407. "\n"
  408. );
  409. }
  410. void PrintHintUsage()
  411. {
  412. fprintf(stdout, "Hinting Options\n"
  413. " -hint hints the file for RTP/RTSP\n"
  414. " -mtu size specifies RTP MTU (max size) in bytes. Default size is 1450\n"
  415. " * Note: this includes the RTP header (12 bytes)\n"
  416. " -copy copies media data to hint track rather than reference\n"
  417. " * Note: speeds up server but takes much more space\n"
  418. " -multi [maxptime] enables frame concatenation in RTP packets if possible\n"
  419. " maxptime max packet duration in ms (optional, default 100ms)\n"
  420. " -rate ck_rate specifies rtp rate in Hz when no default for payload\n"
  421. " * Note: default value is 90000 (MPEG rtp rates)\n"
  422. " -mpeg4 forces MPEG-4 generic payload whenever possible\n"
  423. " -latm forces MPG4-LATM transport for AAC streams\n"
  424. " -static enables static RTP payload IDs whenever possible\n"
  425. " * By default, dynamic payloads are always used\n"
  426. "\n"
  427. "MPEG-4 Generic Payload Options\n"
  428. " -ocr forces all streams to be synchronized\n"
  429. " * Most RTSP servers only support synchronized streams\n"
  430. " -rap signals random access points in RTP packets\n"
  431. " -ts signals AU Time Stamps in RTP packets\n"
  432. " -size signals AU size in RTP packets\n"
  433. " -idx signals AU sequence numbers in RTP packets\n"
  434. " -iod prevents systems tracks embedding in IOD\n"
  435. " * Note: shouldn't be used with -isma option\n"
  436. "\n"
  437. " -add-sdp string adds sdp string to (hint) track (\"-add-sdp tkID:string\")\n"
  438. " or movie. This will take care of SDP lines ordering\n"
  439. " -unhint removes all hinting information.\n"
  440. "\n");
  441. }
  442. void PrintExtractUsage()
  443. {
  444. fprintf(stdout, "Extracting Options\n"
  445. " -raw TrackID extracts track in raw format when supported\n"
  446. " -raws TrackID extract each track sample to a file\n"
  447. " * Note: \"TrackID:N\" extracts Nth sample\n"
  448. " -nhnt TrackID extracts track in nhnt format\n"
  449. " -nhml TrackID extracts track in nhml format (XML nhnt).\n"
  450. " * Note: \"-nhml +TrackID\" for full dump\n"
  451. " -single TrackID extracts track to a new mp4 file\n"
  452. " -avi TrackID extracts visual track to an avi file\n"
  453. " -qcp TrackID same as \'-raw\' but defaults to QCP file for EVRC/SMV\n"
  454. " -aviraw TK extracts AVI track in raw format\n"
  455. " $TK can be one of \"video\" \"audio\" \"audioN\"\n"
  456. " -saf remux file to SAF multiplex\n"
  457. " -dvbhdemux demux DVB-H file into IP Datagrams\n"
  458. " * Note: can be used when encoding scene descriptions\n"
  459. " -diod extracts file IOD in raw format when supported\n"
  460. "\n");
  461. }
  462. void PrintDumpUsage()
  463. {
  464. fprintf(stdout, "Dumping Options\n"
  465. " -std dumps to stdout instead of file\n"
  466. " -info [trackID] prints movie info / track info if trackID specified\n"
  467. " * Note: for non IsoMedia files, gets import options\n"
  468. " -bt scene to bt format - removes unknown MPEG4 nodes\n"
  469. " -xmt scene to XMT-A format - removes unknown MPEG4 nodes\n"
  470. " -wrl scene VRML format - removes unknown VRML nodes\n"
  471. " -x3d scene to X3D/XML format - removes unknown X3D nodes\n"
  472. " -x3dv scene to X3D/VRML format - removes unknown X3D nodes\n"
  473. " -lsr scene to LASeR format\n"
  474. " -diso scene IsoMedia file boxes in XML output\n"
  475. " -drtp rtp hint samples structure to XML output\n"
  476. " -dts prints sample timing to text output\n"
  477. " -sdp dumps SDP description of hinted file\n"
  478. " -dcr ISMACryp samples structure to XML output\n"
  479. " -dump-cover Extracts cover art\n"
  480. " -dump-chap Extracts chapter file\n"
  481. "\n"
  482. #ifndef GPAC_DISABLE_ISOM_WRITE
  483. " -ttxt Converts input subtitle to GPAC TTXT format\n"
  484. #endif
  485. " -ttxt TrackID Dumps Text track to GPAC TTXT format\n"
  486. #ifndef GPAC_DISABLE_ISOM_WRITE
  487. " -srt Converts input subtitle to SRT format\n"
  488. #endif
  489. " -srt TrackID Dumps Text track to SRT format\n"
  490. "\n"
  491. " -stat generates node/field statistics for scene\n"
  492. " -stats generates node/field statistics per MPEG-4 Access Unit\n"
  493. " -statx generates node/field statistics for scene after each AU\n"
  494. "\n"
  495. " -hash generates SHA-1 Hash of the input file\n"
  496. "\n");
  497. }
  498. void PrintMetaUsage()
  499. {
  500. fprintf(stdout, "Meta handling Options\n"
  501. " -set-meta args sets given meta type - syntax: \"ABCD[:tk=ID]\"\n"
  502. " * ABCD: four char meta type (NULL or 0 to remove meta)\n"
  503. " * [:tk=ID]: if not set use root (file) meta\n"
  504. " if ID is 0 use moov meta\n"
  505. " if ID is not 0 use track meta\n"
  506. " -add-item args adds resource to meta\n"
  507. " * syntax: file_path + options (\':\' separated):\n"
  508. " tk=ID: meta adressing (file, moov, track)\n"
  509. " name=str: item name\n"
  510. " mime=mtype: item mime type\n"
  511. " encoding=enctype: item content-encoding type\n"
  512. " * file_path \"this\" or \"self\": item is the file itself\n"
  513. " -rem-item args removes resource from meta - syntax: item_ID[:tk=ID]\n"
  514. " -set-primary args sets item as primary for meta - syntax: item_ID[:tk=ID]\n"
  515. " -set-xml args sets meta XML data\n"
  516. " * syntax: xml_file_path[:tk=ID][:binary]\n"
  517. " -rem-xml [tk=ID] removes meta XML data\n"
  518. " -dump-xml args dumps meta XML to file - syntax file_path[:tk=ID]\n"
  519. " -dump-item args dumps item to file - syntax item_ID[:tk=ID][:path=fileName]\n"
  520. " -package packages input XML file into an ISO container\n"
  521. " * all media referenced except hyperlinks are added to file\n"
  522. " -mgt packages input XML file into an MPEG-U widget with ISO container.\n"
  523. " * all files contained in the current folder are added to the widget package\n"
  524. "\n");
  525. }
  526. void PrintSWFUsage()
  527. {
  528. fprintf(stdout,
  529. "SWF Importer Options\n"
  530. "\n"
  531. "MP4Box can import simple Macromedia Flash files (\".SWF\")\n"
  532. "You can specify a SWF input file with \'-bt\', \'-xmt\' and \'-mp4\' options\n"
  533. "\n"
  534. " -global all SWF defines are placed in first scene replace\n"
  535. " * Note: By default SWF defines are sent when needed\n"
  536. " -no-ctrl uses a single stream for movie control and dictionary\n"
  537. " * Note: this will disable ActionScript\n"
  538. " -no-text removes all SWF text\n"
  539. " -no-font removes all embedded SWF Fonts (terminal fonts used)\n"
  540. " -no-line removes all lines from SWF shapes\n"
  541. " -no-grad removes all gradients from swf shapes\n"
  542. " -quad uses quadratic bezier curves instead of cubic ones\n"
  543. " -xlp support for lines transparency and scalability\n"
  544. " -flatten ang complementary angle below which 2 lines are merged\n"
  545. " * Note: angle \'0\' means no flattening\n"
  546. "\n"
  547. );
  548. }
  549. void PrintUsage()
  550. {
  551. fprintf (stdout, "MP4Box [option] input [option]\n"
  552. " -h general general options help\n"
  553. " -h hint hinting options help\n"
  554. " -h import import options help\n"
  555. " -h encode encode options help\n"
  556. " -h meta meta handling options help\n"
  557. " -h extract extraction options help\n"
  558. " -h dump dump options help\n"
  559. " -h swf Flash (SWF) options help\n"
  560. " -h crypt ISMA E&A options help\n"
  561. " -h format supported formats help\n"
  562. " -h rtp file streamer help\n"
  563. " -h live BIFS streamer help\n"
  564. "\n"
  565. " -nodes lists supported MPEG4 nodes\n"
  566. " -node NodeName gets MPEG4 node syntax and QP info\n"
  567. " -xnodes lists supported X3D nodes\n"
  568. " -xnode NodeName gets X3D node syntax\n"
  569. " -snodes lists supported SVG nodes\n"
  570. " -snode NodeName gets SVG node syntax\n"
  571. " -languages lists supported ISO 639 languages\n"
  572. "\n"
  573. " -quiet quiet mode\n"
  574. " -noprog disables progress\n"
  575. " -v verbose mode\n"
  576. " -logs set log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@levelX\n"
  577. " -version gets build version\n"
  578. );
  579. }
  580. void scene_coding_log(void *cbk, u32 log_level, u32 log_tool, const char *fmt, va_list vlist)
  581. {
  582. FILE *logs = cbk;
  583. if (log_tool != GF_LOG_CODING) return;
  584. vfprintf(logs, fmt, vlist);
  585. fflush(logs);
  586. }
  587. #ifndef GPAC_DISABLE_ISOM_HINTING
  588. /*
  589. MP4 File Hinting
  590. */
  591. void SetupClockReferences(GF_ISOFile *file)
  592. {
  593. u32 i, count, ocr_id;
  594. count = gf_isom_get_track_count(file);
  595. if (count==1) return;
  596. ocr_id = 0;
  597. for (i=0; i<count; i++) {
  598. if (!gf_isom_is_track_in_root_od(file, i+1)) continue;
  599. ocr_id = gf_isom_get_track_id(file, i+1);
  600. break;
  601. }
  602. /*doesn't look like MP4*/
  603. if (!ocr_id) return;
  604. for (i=0; i<count; i++) {
  605. GF_ESD *esd = gf_isom_get_esd(file, i+1, 1);
  606. if (esd) {
  607. esd->OCRESID = ocr_id;
  608. gf_isom_change_mpeg4_description(file, i+1, 1, esd);
  609. gf_odf_desc_del((GF_Descriptor *) esd);
  610. }
  611. }
  612. }
  613. /*base RTP payload type used (you can specify your own types if needed)*/
  614. #define BASE_PAYT 96
  615. GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 base_flags, Bool copy_data, Bool interleave, Bool regular_iod, Bool single_group)
  616. {
  617. GF_ESD *esd;
  618. GF_InitialObjectDescriptor *iod;
  619. u32 i, val, res, streamType;
  620. u32 sl_mode, prev_ocr, single_ocr, nb_done, tot_bw, bw, flags, spec_type;
  621. GF_Err e;
  622. char szPayload[30];
  623. GF_RTPHinter *hinter;
  624. Bool copy, has_iod, single_av;
  625. u8 init_payt = BASE_PAYT;
  626. u32 iod_mode, mtype;
  627. u32 media_group = 0;
  628. u8 media_prio = 0;
  629. tot_bw = 0;
  630. prev_ocr = 0;
  631. single_ocr = 1;
  632. has_iod = 1;
  633. iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(file);
  634. if (!iod) has_iod = 0;
  635. else {
  636. if (!gf_list_count(iod->ESDescriptors)) has_iod = 0;
  637. gf_odf_desc_del((GF_Descriptor *) iod);
  638. }
  639. spec_type = gf_isom_guess_specification(file);
  640. single_av = single_group ? 1 : gf_isom_is_single_av(file);
  641. /*first make sure we use a systems track as base OCR*/
  642. for (i=0; i<gf_isom_get_track_count(file); i++) {
  643. res = gf_isom_get_media_type(file, i+1);
  644. if ((res==GF_ISOM_MEDIA_SCENE) || (res==GF_ISOM_MEDIA_OD)) {
  645. if (gf_isom_is_track_in_root_od(file, i+1)) {
  646. gf_isom_set_default_sync_track(file, i+1);
  647. break;
  648. }
  649. }
  650. }
  651. nb_done = 0;
  652. for (i=0; i<gf_isom_get_track_count(file); i++) {
  653. sl_mode = base_flags;
  654. copy = copy_data;
  655. /*skip emty tracks (mainly MPEG-4 interaction streams...*/
  656. if (!gf_isom_get_sample_count(file, i+1)) continue;
  657. if (!gf_isom_is_track_enabled(file, i+1)) {
  658. fprintf(stdout, "Track ID %d disabled - skipping hint\n", gf_isom_get_track_id(file, i+1) );
  659. continue;
  660. }
  661. mtype = gf_isom_get_media_type(file, i+1);
  662. switch (mtype) {
  663. case GF_ISOM_MEDIA_VISUAL:
  664. if (single_av) {
  665. media_group = 2;
  666. media_prio = 2;
  667. }
  668. break;
  669. case GF_ISOM_MEDIA_AUDIO:
  670. if (single_av) {
  671. media_group = 2;
  672. media_prio = 1;
  673. }
  674. break;
  675. case GF_ISOM_MEDIA_HINT:
  676. continue;
  677. default:
  678. /*no hinting of systems track on isma*/
  679. if (spec_type==GF_4CC('I','S','M','A')) continue;
  680. }
  681. mtype = gf_isom_get_media_subtype(file, i+1, 1);
  682. if ((mtype==GF_ISOM_SUBTYPE_MPEG4) || (mtype==GF_ISOM_SUBTYPE_MPEG4_CRYP) ) mtype = gf_isom_get_mpeg4_subtype(file, i+1, 1);
  683. if (!single_av) {
  684. /*one media per group only (we should prompt user for group selection)*/
  685. media_group ++;
  686. media_prio = 1;
  687. }
  688. streamType = 0;
  689. esd = gf_isom_get_esd(file, i+1, 1);
  690. if (esd) {
  691. streamType = esd->decoderConfig->streamType;
  692. if (!prev_ocr) {
  693. prev_ocr = esd->OCRESID;
  694. if (!esd->OCRESID) prev_ocr = esd->ESID;
  695. } else if (esd->OCRESID && prev_ocr != esd->OCRESID) {
  696. single_ocr = 0;
  697. }
  698. /*OD MUST BE WITHOUT REFERENCES*/
  699. if (streamType==1) copy = 1;
  700. }
  701. gf_odf_desc_del((GF_Descriptor *) esd);
  702. if (!regular_iod && gf_isom_is_track_in_root_od(file, i+1)) {
  703. /*single AU - check if base64 would fit in ESD (consider 33% overhead of base64), otherwise stream*/
  704. if (gf_isom_get_sample_count(file, i+1)==1) {
  705. GF_ISOSample *samp = gf_isom_get_sample(file, i+1, 1, &val);
  706. if (streamType) {
  707. res = gf_hinter_can_embbed_data(samp->data, samp->dataLength, streamType);
  708. } else {
  709. /*not a system track, we shall hint it*/
  710. res = 0;
  711. }
  712. if (samp) gf_isom_sample_del(&samp);
  713. if (res) continue;
  714. }
  715. }
  716. if (interleave) sl_mode |= GP_RTP_PCK_USE_INTERLEAVING;
  717. hinter = gf_hinter_track_new(file, i+1, MTUSize, max_ptime, rtp_rate, sl_mode, init_payt, copy, media_group, media_prio, &e);
  718. if (!hinter) {
  719. if (e) {
  720. fprintf(stdout, "Cannot create hinter (%s)\n", gf_error_to_string(e));
  721. if (!nb_done) return e;
  722. }
  723. continue;
  724. }
  725. bw = gf_hinter_track_get_bandwidth(hinter);
  726. tot_bw += bw;
  727. flags = gf_hinter_track_get_flags(hinter);
  728. gf_hinter_track_get_payload_name(hinter, szPayload);
  729. fprintf(stdout, "Hinting track ID %d - Type \"%s:%s\" (%s) - BW %d kbps\n", gf_isom_get_track_id(file, i+1), gf_4cc_to_str(mtype), gf_4cc_to_str(mtype), szPayload, bw);
  730. if (flags & GP_RTP_PCK_SYSTEMS_CAROUSEL) fprintf(stdout, "\tMPEG-4 Systems stream carousel enabled\n");
  731. /*
  732. if (flags & GP_RTP_PCK_FORCE_MPEG4) fprintf(stdout, "\tMPEG4 transport forced\n");
  733. if (flags & GP_RTP_PCK_USE_MULTI) fprintf(stdout, "\tRTP aggregation enabled\n");
  734. */
  735. e = gf_hinter_track_process(hinter);
  736. if (!e) e = gf_hinter_track_finalize(hinter, has_iod);
  737. gf_hinter_track_del(hinter);
  738. if (e) {
  739. fprintf(stdout, "Error while hinting (%s)\n", gf_error_to_string(e));
  740. if (!nb_done) return e;
  741. }
  742. init_payt++;
  743. nb_done ++;
  744. }
  745. if (has_iod) {
  746. iod_mode = GF_SDP_IOD_ISMA;
  747. if (regular_iod) iod_mode = GF_SDP_IOD_REGULAR;
  748. } else {
  749. iod_mode = GF_SDP_IOD_NONE;
  750. }
  751. gf_hinter_finalize(file, iod_mode, tot_bw);
  752. if (!single_ocr)
  753. fprintf(stdout, "Warning: at least 2 timelines found in the file\nThis may not be supported by servers/players\n\n");
  754. return GF_OK;
  755. }
  756. #endif /*GPAC_DISABLE_ISOM_HINTING*/
  757. #if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_AV_PARSERS)
  758. static void check_media_profile(GF_ISOFile *file, u32 track)
  759. {
  760. u8 PL;
  761. GF_M4ADecSpecInfo dsi;
  762. GF_ESD *esd = gf_isom_get_esd(file, track, 1);
  763. if (!esd) return;
  764. switch (esd->decoderConfig->streamType) {
  765. case 0x04:
  766. PL = gf_isom_get_pl_indication(file, GF_ISOM_PL_VISUAL);
  767. if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_MPEG4_PART2) {
  768. GF_M4VDecSpecInfo dsi;
  769. gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
  770. if (dsi.VideoPL > PL) gf_isom_set_pl_indication(file, GF_ISOM_PL_VISUAL, dsi.VideoPL);
  771. } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_AVC) {
  772. gf_isom_set_pl_indication(file, GF_ISOM_PL_VISUAL, 0x15);
  773. } else if (!PL) {
  774. gf_isom_set_pl_indication(file, GF_ISOM_PL_VISUAL, 0xFE);
  775. }
  776. break;
  777. case 0x05:
  778. PL = gf_isom_get_pl_indication(file, GF_ISOM_PL_AUDIO);
  779. switch (esd->decoderConfig->objectTypeIndication) {
  780. case GPAC_OTI_AUDIO_AAC_MPEG2_MP:
  781. case GPAC_OTI_AUDIO_AAC_MPEG2_LCP:
  782. case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP:
  783. case GPAC_OTI_AUDIO_AAC_MPEG4:
  784. gf_m4a_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
  785. if (dsi.audioPL > PL) gf_isom_set_pl_indication(file, GF_ISOM_PL_AUDIO, dsi.audioPL);
  786. break;
  787. default:
  788. if (!PL) gf_isom_set_pl_indication(file, GF_ISOM_PL_AUDIO, 0xFE);
  789. }
  790. break;
  791. }
  792. gf_odf_desc_del((GF_Descriptor *) esd);
  793. }
  794. void remove_systems_tracks(GF_ISOFile *file)
  795. {
  796. u32 i, count;
  797. count = gf_isom_get_track_count(file);
  798. if (count==1) return;
  799. /*force PL rewrite*/
  800. gf_isom_set_pl_indication(file, GF_ISOM_PL_VISUAL, 0);
  801. gf_isom_set_pl_indication(file, GF_ISOM_PL_AUDIO, 0);
  802. gf_isom_set_pl_indication(file, GF_ISOM_PL_OD, 1); /*the lib always remove IOD when no profiles are specified..*/
  803. for (i=0; i<gf_isom_get_track_count(file); i++) {
  804. switch (gf_isom_get_media_type(file, i+1)) {
  805. case GF_ISOM_MEDIA_VISUAL:
  806. case GF_ISOM_MEDIA_AUDIO:
  807. case GF_ISOM_MEDIA_TEXT:
  808. case GF_ISOM_MEDIA_SUBT:
  809. gf_isom_remove_track_from_root_od(file, i+1);
  810. check_media_profile(file, i+1);
  811. break;
  812. /*only remove real systems tracks (eg, delaing with scene description & presentation)
  813. but keep meta & all unknown tracks*/
  814. case GF_ISOM_MEDIA_SCENE:
  815. switch (gf_isom_get_media_subtype(file, i+1, 1)) {
  816. case GF_ISOM_MEDIA_DIMS:
  817. gf_isom_remove_track_from_root_od(file, i+1);
  818. continue;
  819. default:
  820. break;
  821. }
  822. case GF_ISOM_MEDIA_OD:
  823. case GF_ISOM_MEDIA_OCR:
  824. case GF_ISOM_MEDIA_MPEGJ:
  825. gf_isom_remove_track(file, i+1);
  826. i--;
  827. break;
  828. default:
  829. break;
  830. }
  831. }
  832. /*none required*/
  833. if (!gf_isom_get_pl_indication(file, GF_ISOM_PL_AUDIO)) gf_isom_set_pl_indication(file, GF_ISOM_PL_AUDIO, 0xFF);
  834. if (!gf_isom_get_pl_indication(file, GF_ISOM_PL_VISUAL)) gf_isom_set_pl_indication(file, GF_ISOM_PL_VISUAL, 0xFF);
  835. gf_isom_set_pl_indication(file, GF_ISOM_PL_OD, 0xFF);
  836. gf_isom_set_pl_indication(file, GF_ISOM_PL_SCENE, 0xFF);
  837. gf_isom_set_pl_indication(file, GF_ISOM_PL_GRAPHICS, 0xFF);
  838. gf_isom_set_pl_indication(file, GF_ISOM_PL_INLINE, 0);
  839. }
  840. #endif /*!defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_AV_PARSERS)*/
  841. /*return value:
  842. 0: not supported
  843. 1: ISO media
  844. 2: input bt file (.bt, .wrl)
  845. 3: input XML file (.xmt)
  846. 4: input SVG file (.svg)
  847. 5: input SWF file (.swf)
  848. 6: input LASeR file (.lsr or .saf)
  849. */
  850. u32 get_file_type_by_ext(char *inName)
  851. {
  852. u32 type = 0;
  853. char *ext = strrchr(inName, '.');
  854. if (ext) {
  855. char *sep;
  856. if (!strcmp(ext, ".gz")) ext = strrchr(ext-1, '.');
  857. ext+=1;
  858. sep = strchr(ext, '.');
  859. if (sep) sep[0] = 0;
  860. if (!stricmp(ext, "mp4") || !stricmp(ext, "3gp") || !stricmp(ext, "mov") || !stricmp(ext, "3g2") || !stricmp(ext, "3gs")) type = 1;
  861. else if (!stricmp(ext, "bt") || !stricmp(ext, "wrl") || !stricmp(ext, "x3dv")) type = 2;
  862. else if (!stricmp(ext, "xmt") || !stricmp(ext, "x3d")) type = 3;
  863. else if (!stricmp(ext, "lsr") || !stricmp(ext, "saf")) type = 6;
  864. else if (!stricmp(ext, "svg")) type = 4;
  865. else if (!stricmp(ext, "xsr")) type = 4;
  866. else if (!stricmp(ext, "xml")) type = 4;
  867. else if (!stricmp(ext, "swf")) type = 5;
  868. else if (!stricmp(ext, "jp2")) {
  869. if (sep) sep[0] = '.';
  870. return 0;
  871. }
  872. else type = 0;
  873. if (sep) sep[0] = '.';
  874. }
  875. /*try open file in read mode*/
  876. if (!type && gf_isom_probe_file(inName)) type = 1;
  877. return type;
  878. }
  879. #ifndef GPAC_DISABLE_ISOM_WRITE
  880. static Bool can_convert_to_isma(GF_ISOFile *file)
  881. {
  882. u32 spec = gf_isom_guess_specification(file);
  883. if (spec==GF_4CC('I','S','M','A')) return 1;
  884. return 0;
  885. }
  886. #endif
  887. static void progress_quiet(const void *cbck, const char *title, u64 done, u64 total) { }
  888. typedef struct
  889. {
  890. u32 trackID;
  891. char *line;
  892. } SDPLine;
  893. typedef struct
  894. {
  895. /*actions:
  896. 0: set meta type
  897. 1: add item
  898. 2: rem item
  899. 3: set item primary
  900. 4: set XML
  901. 5: set binary XML
  902. 6: rem XML
  903. 7: dump item
  904. 8: dump XML
  905. */
  906. u32 act_type;
  907. Bool root_meta, use_dref;
  908. u32 trackID;
  909. u32 meta_4cc;
  910. char szPath[GF_MAX_PATH];
  911. char szName[1024], mime_type[1024], enc_type[1024];
  912. u32 item_id;
  913. } MetaAction;
  914. /*for SDP_EX, AddTrack and RemTrack*/
  915. #define MAX_CUMUL_OPS 20
  916. #ifndef GPAC_DISABLE_ISOM_WRITE
  917. static Bool parse_meta_args(MetaAction *meta, char *opts)
  918. {
  919. Bool ret = 0;
  920. char szSlot[1024], *next;
  921. meta->mime_type[0] = 0;
  922. meta->enc_type[0] = 0;
  923. meta->szName[0] = 0;
  924. meta->szPath[0] = 0;
  925. meta->trackID = 0;
  926. meta->root_meta = 1;
  927. if (!opts) return 0;
  928. while (1) {
  929. if (!opts || !opts[0]) return ret;
  930. if (opts[0]==':') opts += 1;
  931. strcpy(szSlot, opts);
  932. next = strchr(szSlot, ':');
  933. /*use ':' as separator, but beware DOS paths...*/
  934. if (next && next[1]=='\\') next = strchr(szSlot+2, ':');
  935. if (next) next[0] = 0;
  936. if (!strnicmp(szSlot, "tk=", 3)) {
  937. sscanf(szSlot, "tk=%u", &meta->trackID);
  938. meta->root_meta = 0;
  939. ret = 1;
  940. }
  941. else if (!strnicmp(szSlot, "name=", 5)) { strcpy(meta->szName, szSlot+5); ret = 1; }
  942. else if (!strnicmp(szSlot, "path=", 5)) { strcpy(meta->szPath, szSlot+5); ret = 1; }
  943. else if (!strnicmp(szSlot, "mime=", 5)) { strcpy(meta->mime_type, szSlot+5); ret = 1; }
  944. else if (!strnicmp(szSlot, "encoding=", 9)) { strcpy(meta->enc_type, szSlot+9); ret = 1; }
  945. else if (!strnicmp(szSlot, "dref", 4)) { meta->use_dref = 1; ret = 1; }
  946. else if (!stricmp(szSlot, "binary")) {
  947. if (meta->act_type==4) meta->act_type=5;
  948. ret = 1;
  949. }
  950. else if (!strchr(szSlot, '=')) {
  951. switch (meta->act_type) {
  952. case 0:
  953. if (!stricmp(szSlot, "null") || !stricmp(szSlot, "0")) meta->meta_4cc = 0;
  954. else meta->meta_4cc = GF_4CC(szSlot[0], szSlot[1], szSlot[2], szSlot[3]);
  955. ret = 1;
  956. break;
  957. case 1:
  958. case 4:
  959. case 7:
  960. strcpy(meta->szPath, szSlot);
  961. ret = 1;
  962. break;
  963. case 2:
  964. case 3:
  965. case 8:
  966. meta->item_id = atoi(szSlot);
  967. ret = 1;
  968. break;
  969. }
  970. }
  971. opts += strlen(szSlot);
  972. }
  973. return ret;
  974. }
  975. #endif
  976. typedef struct
  977. {
  978. /*0: set tsel param - 1 remove tsel - 2 remove all tsel info in alternate group - 3 remove all tsel info in file*/
  979. u32 act_type;
  980. u32 trackID;
  981. u32 refTrackID;
  982. u32 criteria[30];
  983. u32 nb_criteria;
  984. Bool is_switchGroup;
  985. u32 switchGroupID;
  986. } TSELAction;
  987. static Bool parse_tsel_args(TSELAction *tsel_list, char *opts, u32 *nb_tsel_act)
  988. {
  989. u32 act;
  990. u32 refTrackID = 0;
  991. Bool has_switch_id;
  992. u32 switch_id = 0;
  993. u32 criteria[30];
  994. u32 nb_criteria = 0;
  995. TSELAction *tsel_act;
  996. char szSlot[1024], *next;
  997. has_switch_id = 0;
  998. act = tsel_list[*nb_tsel_act].act_type;
  999. if (!opts) return 0;
  1000. while (1) {
  1001. if (!opts || !opts[0]) return 1;
  1002. if (opts[0]==':') opts += 1;
  1003. strcpy(szSlot, opts);
  1004. next = strchr(szSlot, ':');
  1005. /*use ':' as separator, but beware DOS paths...*/
  1006. if (next && next[1]=='\\') next = strchr(szSlot+2, ':');
  1007. if (next) next[0] = 0;
  1008. if (!strnicmp(szSlot, "ref=", 4)) refTrackID = atoi(szSlot+4);
  1009. else if (!strnicmp(szSlot, "switchID=", 9)) {
  1010. if (atoi(szSlot+9)<0) {
  1011. switch_id = 0;
  1012. has_switch_id = 0;
  1013. } else {
  1014. switch_id = atoi(szSlot+9);
  1015. has_switch_id = 1;
  1016. }
  1017. }
  1018. else if (!strnicmp(szSlot, "switchID", 8)) {
  1019. switch_id = 0;
  1020. has_switch_id = 1;
  1021. }
  1022. else if (!strnicmp(szSlot, "criteria=", 9)) {
  1023. u32 j=9;
  1024. nb_criteria = 0;
  1025. while (j+3<strlen(szSlot)) {
  1026. criteria[nb_criteria] = GF_4CC(szSlot[j], szSlot[j+1], szSlot[j+2], szSlot[j+3]);
  1027. j+=5;
  1028. nb_criteria++;
  1029. }
  1030. }
  1031. else if (!strnicmp(szSlot, "trackID=", 8) || !strchr(szSlot, '=') ) {
  1032. if (*nb_tsel_act>=MAX_CUMUL_OPS) {
  1033. fprintf(stdout, "Sorry - no more than %d track selection operations allowed\n", MAX_CUMUL_OPS);
  1034. return 0;
  1035. }
  1036. tsel_act = &tsel_list[*nb_tsel_act];
  1037. memset(tsel_act, 0, sizeof(TSELAction));
  1038. tsel_act->act_type = act;
  1039. tsel_act->trackID = strchr(szSlot, '=') ? atoi(szSlot+8) : atoi(szSlot);
  1040. tsel_act->refTrackID = refTrackID;
  1041. tsel_act->switchGroupID = switch_id;
  1042. tsel_act->is_switchGroup = has_switch_id;
  1043. tsel_act->nb_criteria = nb_criteria;
  1044. memcpy(tsel_act->criteria, criteria, sizeof(u32)*nb_criteria);
  1045. if (!refTrackID)
  1046. refTrackID = tsel_act->trackID;
  1047. (*nb_tsel_act) ++;
  1048. }
  1049. opts += strlen(szSlot);
  1050. }
  1051. return 1;
  1052. }
  1053. #define CHECK_NEXT_ARG if (i+1==(u32)argc) { fprintf(stdout, "Missing arg - please check usage\n"); return 1; }
  1054. #define CHECK_META_OPS CHECK_NEXT_ARG if (nb_meta_act>=MAX_CUMUL_OPS) { fprintf(stdout, "Sorry - no more than %d meta operations allowed\n", MAX_CUMUL_OPS); return 1; }
  1055. typedef struct
  1056. {
  1057. /*
  1058. 0: rem track
  1059. 1: set track language
  1060. 2: set track delay
  1061. 3: set track KMS URI
  1062. 4: set visual track PAR if possible
  1063. 5: set track handler name
  1064. 6: enables track
  1065. 7: disables track
  1066. 8: referenceTrack
  1067. */
  1068. u32 act_type;
  1069. /*track ID*/
  1070. u32 trackID;
  1071. char lang[4];
  1072. s32 delay_ms;
  1073. const char *kms;
  1074. const char *hdl_name;
  1075. s32 par_num, par_den;
  1076. } TrackAction;
  1077. enum
  1078. {
  1079. GF_ISOM_CONV_TYPE_ISMA = 1,
  1080. GF_ISOM_CONV_TYPE_ISMA_EX,
  1081. GF_ISOM_CONV_TYPE_3GPP,
  1082. GF_ISOM_CONV_TYPE_IPOD,
  1083. GF_ISOM_CONV_TYPE_PSP
  1084. };
  1085. /*for dash*/
  1086. #define MAX_DASH_REP 30
  1087. int mp4boxMain(int argc, char **argv)
  1088. {
  1089. char outfile[5000];
  1090. GF_Err e;
  1091. #ifndef GPAC_DISABLE_SCENE_ENCODER
  1092. GF_SMEncodeOptions opts;
  1093. #endif
  1094. #if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_SENG)
  1095. SDPLine sdp_lines[MAX_CUMUL_OPS];
  1096. #endif
  1097. Double InterleavingTime, split_duration, split_start, import_fps, dash_duration;
  1098. MetaAction metas[MAX_CUMUL_OPS];
  1099. TrackAction tracks[MAX_CUMUL_OPS];
  1100. TSELAction tsel_acts[MAX_CUMUL_OPS];
  1101. u64 movie_time;
  1102. s32 subsegs_per_sidx;
  1103. u32 brand_add[MAX_CUMUL_OPS];
  1104. u32 i, MTUSize, stat_level, hint_flags, info_track_id, import_flags, nb_add, nb_cat, ismaCrypt, agg_samples, nb_sdp_ex, max_ptime, raw_sample_num, split_size, nb_meta_act, nb_track_act, rtp_rate, major_brand, nb_alt_brand_add, nb_alt_brand_rem, old_interleave, car_dur, minor_version, conv_type, nb_tsel_acts, program_number;
  1105. Bool HintIt, needSave, FullInter, Frag, HintInter, dump_std, dump_rtp, dump_mode, regular_iod, trackID, HintCopy, remove_sys_tracks, remove_hint, force_new, remove_root_od, import_subtitle, dump_chap;
  1106. Bool print_sdp, print_info, open_edit, track_dump_type, dump_isom, dump_cr, force_ocr, encode, do_log, do_flat, dump_srt, dump_ttxt, chunk_mode, dump_ts, do_saf, do_mpd, dump_m2ts, dump_cart, do_hash, verbose, force_cat, pack_wgt, single_group;
  1107. char *inName, *outName, *arg, *mediaSource, *tmpdir, *input_ctx, *output_ctx, *drm_file, *avi2raw, *cprt, *chap_file, *pes_dump, *itunes_tags, *pack_file, *raw_cat, *seg_name, *dash_ctx;
  1108. GF_ISOFile *file;
  1109. Bool stream_rtp=0;
  1110. Bool live_scene=0;
  1111. Bool enable_mem_tracker = 0;
  1112. Bool dump_iod=0;
  1113. Bool daisy_chain_sidx=0;
  1114. Bool single_segment=0;
  1115. Bool use_url_template=0;
  1116. Bool seg_at_rap =0;
  1117. Bool adjust_split_end = 0;
  1118. char *dash_inputs[MAX_DASH_REP];
  1119. u32 nb_dash_inputs = 0;
  1120. char *gf_logs = NULL;
  1121. char *seg_ext = NULL;
  1122. if (argc < 2) {
  1123. PrintUsage();
  1124. return 1;
  1125. }
  1126. nb_tsel_acts = nb_add = nb_cat = nb_track_act = nb_sdp_ex = max_ptime = raw_sample_num = nb_meta_act = rtp_rate = major_brand = nb_alt_brand_add = nb_alt_brand_rem = car_dur = minor_version = 0;
  1127. e = GF_OK;
  1128. split_duration = 0.0;
  1129. split_start = -1.0;
  1130. InterleavingTime = 0.5;
  1131. dash_duration = 0.0;
  1132. import_fps = 0;
  1133. import_flags = 0;
  1134. split_size = 0;
  1135. movie_time = 0;
  1136. MTUSize = 1450;
  1137. HintCopy = FullInter = HintInter = encode = do_log = old_interleave = do_saf = do_mpd = do_hash = verbose = 0;
  1138. chunk_mode = dump_mode = Frag = force_ocr = remove_sys_tracks = agg_samples = remove_hint = keep_sys_tracks = remove_root_od = single_group = 0;
  1139. conv_type = HintIt = needSave = print_sdp = print_info = regular_iod = dump_std = open_edit = dump_isom = dump_rtp = dump_cr = dump_chap = dump_srt = dump_ttxt = force_new = dump_ts = dump_m2ts = dump_cart = import_subtitle = force_cat = pack_wgt = 0;
  1140. subsegs_per_sidx = 0;
  1141. track_dump_type = 0;
  1142. ismaCrypt = 0;
  1143. file = NULL;
  1144. itunes_tags = pes_dump = NULL;
  1145. seg_name = dash_ctx = NULL;
  1146. #ifndef GPAC_DISABLE_SCENE_ENCODER
  1147. memset(&opts, 0, sizeof(opts));
  1148. #endif
  1149. trackID = stat_level = hint_flags = 0;
  1150. program_number = 0;
  1151. info_track_id = 0;
  1152. do_flat = 0;
  1153. inName = outName = mediaSource = input_ctx = output_ctx = drm_file = avi2raw = cprt = chap_file = pack_file = raw_cat = NULL;
  1154. swf_flags = GF_SM_SWF_SPLIT_TIMELINE;
  1155. swf_flatten_angle = 0.0f;
  1156. tmpdir = NULL;
  1157. /*parse our args*/
  1158. for (i = 1; i < (u32) argc ; i++) {
  1159. arg = argv[i];
  1160. /*main file*/
  1161. // if (isalnum(arg[0]) || (arg[0]=='/') || (arg[0]=='.') || (arg[0]=='\\') ) {
  1162. if (arg[0] != '-') {
  1163. if (argc < 3) {
  1164. fprintf(stdout, "Error - only one input file found as argument, please check usage\n");
  1165. return 1;
  1166. } else if (inName) {
  1167. if (dash_duration) {
  1168. if (!nb_dash_inputs) {
  1169. dash_inputs[nb_dash_inputs] = inName;
  1170. nb_dash_inputs++;
  1171. }
  1172. if (MAX_DASH_REP<=nb_dash_inputs) {
  1173. fprintf(stdout, "Error - Max %d representations can be DASH'ed\n", MAX_DASH_REP);
  1174. return 1;
  1175. }
  1176. dash_inputs[nb_dash_inputs] = arg;
  1177. nb_dash_inputs++;
  1178. } else {
  1179. fprintf(stdout, "Error - 2 input names specified, please check usage\n");
  1180. return 1;
  1181. }
  1182. } else {
  1183. inName = arg;
  1184. }
  1185. }
  1186. else if (!stricmp(arg, "-?")) { PrintUsage(); return 0; }
  1187. else if (!stricmp(arg, "-version")) { PrintVersion(); return 0; }
  1188. else if (!stricmp(arg, "-sdp")) print_sdp = 1;
  1189. else if (!stricmp(arg, "-quiet")) quiet = 2;
  1190. else if (!stricmp(arg, "-logs")) {
  1191. CHECK_NEXT_ARG
  1192. gf_logs = argv[i+1];
  1193. i++;
  1194. }
  1195. else if (!stricmp(arg, "-noprog")) quiet = 1;
  1196. else if (!stricmp(arg, "-info")) {
  1197. print_info = 1;
  1198. if ((i+1<(u32) argc) && (sscanf(argv[i+1], "%u", &info_track_id)==1)) {
  1199. char szTk[20];
  1200. sprintf(szTk, "%u", info_track_id);
  1201. if (!strcmp(szTk, argv[i+1])) i++;
  1202. else info_track_id=0;
  1203. } else {
  1204. info_track_id=0;
  1205. }
  1206. }
  1207. /*******************************************************************************/
  1208. else if (!stricmp(arg, "-dvbhdemux")) {
  1209. dvbhdemux = 1;
  1210. }
  1211. /********************************************************************************/
  1212. #ifndef GPAC_DISABLE_MEDIA_EXPORT
  1213. else if (!stricmp(arg, "-raw")) {
  1214. CHECK_NEXT_ARG
  1215. track_dump_type = GF_EXPORT_NATIVE;
  1216. trackID = atoi(argv[i+1]);
  1217. i++;
  1218. }
  1219. else if (!stricmp(arg, "-qcp")) {
  1220. CHECK_NEXT_ARG
  1221. track_dump_type = GF_EXPORT_NATIVE | GF_EXPORT_USE_QCP;
  1222. trackID = atoi(argv[i+1]);
  1223. i++;
  1224. }
  1225. else if (!stricmp(arg, "-aviraw")) {
  1226. CHECK_NEXT_ARG
  1227. if (argv[i+1] && !stricmp(argv[i+1], "video")) trackID = 1;
  1228. else if (argv[i+1] && !stricmp(argv[i+1], "audio")) {
  1229. if (strlen(argv[i+1])==5) trackID = 2;
  1230. else trackID = 1 + atoi(argv[i+1] + 5);
  1231. }
  1232. else { fprintf(stdout, "Usage: \"-aviraw video\" or \"-aviraw audio\"\n"); return 1; }
  1233. track_dump_type = GF_EXPORT_AVI_NATIVE;
  1234. i++;
  1235. }
  1236. else if (!stricmp(arg, "-raws")) {
  1237. CHECK_NEXT_ARG
  1238. track_dump_type = GF_EXPORT_RAW_SAMPLES;
  1239. if (strchr(argv[i+1], ':')) {
  1240. sscanf(argv[i+1], "%u:%u", &trackID, &raw_sample_num);
  1241. } else {
  1242. trackID = atoi(argv[i+1]);
  1243. }
  1244. i++;
  1245. }
  1246. else if (!stricmp(arg, "-nhnt")) {
  1247. CHECK_NEXT_ARG
  1248. track_dump_type = GF_EXPORT_NHNT;
  1249. trackID = atoi(argv[i+1]);
  1250. i++;
  1251. }
  1252. else if (!stricmp(arg, "-nhml")) {
  1253. CHECK_NEXT_ARG
  1254. track_dump_type = GF_EXPORT_NHML;
  1255. if (argv[i+1][0]=='+') {
  1256. track_dump_type |= GF_EXPORT_NHML_FULL;
  1257. trackID = atoi(argv[i+1] + 1);
  1258. } else {
  1259. trackID = atoi(argv[i+1]);
  1260. }
  1261. i++;
  1262. }
  1263. else if (!stricmp(arg, "-avi")) {
  1264. CHECK_NEXT_ARG
  1265. track_dump_type = GF_EXPORT_AVI;
  1266. trackID = atoi(argv[i+1]);
  1267. i++;
  1268. }
  1269. #endif /*GPAC_DISABLE_MEDIA_EXPORT*/
  1270. #if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_SENG)
  1271. else if (!stricmp(arg, "-rtp")) {
  1272. stream_rtp = 1;
  1273. }
  1274. else if (!stricmp(arg, "-live")) {
  1275. live_scene = 1;
  1276. }
  1277. #endif
  1278. else if (!stricmp(arg, "-diod")) {
  1279. dump_iod = 1;
  1280. }
  1281. #ifndef GPAC_DISABLE_VRML
  1282. else if (!stricmp(arg, "-node")) { CHECK_NEXT_ARG PrintNode(argv[i+1], 0); return (0); }
  1283. else if (!stricmp(arg, "-xnode")) { CHECK_NEXT_ARG PrintNode(argv[i+1], 1); return (0); }
  1284. else if (!stricmp(arg, "-nodes")) { PrintBuiltInNodes(0); return (0); }
  1285. else if (!stricmp(arg, "-xnodes")) { PrintBuiltInNodes(1); return (0); }
  1286. #endif
  1287. #ifndef GPAC_DISABLE_SVG
  1288. else if (!stricmp(arg, "-snode")) { CHECK_NEXT_ARG PrintNode(argv[i+1], 2); return (0); }
  1289. else if (!stricmp(arg, "-snodes")) { PrintBuiltInNodes(2); return (0); }
  1290. else if (!stricmp(arg, "-std")) dump_std = 1;
  1291. #endif
  1292. #if !defined(GPAC_DISABLE_MEDIA_EXPORT) && !defined(GPAC_DISABLE_SCENE_DUMP)
  1293. else if (!stricmp(arg, "-bt")) dump_mode = 1 + GF_SM_DUMP_BT;
  1294. else if (!stricmp(arg, "-xmt")) dump_mode = 1 + GF_SM_DUMP_XMTA;
  1295. else if (!stricmp(arg, "-wrl")) dump_mode = 1 + GF_SM_DUMP_VRML;
  1296. else if (!stricmp(arg, "-x3dv")) dump_mode = 1 + GF_SM_DUMP_X3D_VRML;
  1297. else if (!stricmp(arg, "-x3d")) dump_mode = 1 + GF_SM_DUMP_X3D_XML;
  1298. else if (!stricmp(arg, "-lsr")) dump_mode = 1 + GF_SM_DUMP_LASER;
  1299. else if (!stricmp(arg, "-svg")) dump_mode = 1 + GF_SM_DUMP_SVG;
  1300. #endif /*defined(GPAC_DISABLE_MEDIA_EXPORT) && !defined(GPAC_DISABLE_SCENE_DUMP)*/
  1301. else if (!stricmp(arg, "-stat")) stat_level = 1;
  1302. else if (!stricmp(arg, "-stats")) stat_level = 2;
  1303. else if (!stricmp(arg, "-statx")) stat_level = 3;
  1304. else if (!stricmp(arg, "-diso")) dump_isom = 1;
  1305. else if (!stricmp(arg, "-dump-cover")) dump_cart = 1;
  1306. else if (!stricmp(arg, "-dump-chap")) dump_chap = 1;
  1307. else if (!stricmp(arg, "-hash")) do_hash = 1;
  1308. else if (!stricmp(arg, "-dmp4")) {
  1309. dump_isom = 1;
  1310. fprintf(stdout, "WARNING: \"-dmp4\" is deprecated - use \"-diso\" option\n");
  1311. }
  1312. else if (!stricmp(arg, "-drtp")) dump_rtp = 1;
  1313. else if (!stricmp(arg, "-dts")) {
  1314. dump_ts = 1;
  1315. if ( ((i+1<(u32) argc) && inName) || (i+2<(u32) argc) ) {
  1316. if (argv[i+1][0] != '-') program_number = atoi(argv[i+1]);
  1317. i++;
  1318. }
  1319. } else if (!stricmp(arg, "-dcr")) dump_cr = 1;
  1320. else if (!stricmp(arg, "-ttxt") || !stricmp(arg, "-srt")) {
  1321. if ((i+1<(u32) argc) && (sscanf(argv[i+1], "%u", &trackID)==1)) {
  1322. char szTk[20];
  1323. sprintf(szTk, "%d", trackID);
  1324. if (!strcmp(szTk, argv[i+1])) i++;
  1325. else trackID=0;
  1326. } else {
  1327. trackID = 0;
  1328. }
  1329. #ifdef GPAC_DISABLE_ISOM_WRITE
  1330. if (trackID) { fprintf(stdout, "Error: Read-Only version - subtitle conversion not available\n"); return 1; }
  1331. #endif
  1332. if (!stricmp(arg, "-ttxt")) dump_ttxt = 1;
  1333. else dump_srt = 1;
  1334. import_subtitle = 1;
  1335. } else if (!stricmp(arg, "-dm2ts")) {
  1336. dump_m2ts = 1;
  1337. if ( ((i+1<(u32) argc) && inName) || (i+2<(u32) argc) ) {
  1338. if (argv[i+1][0] != '-') pes_dump = argv[i+1];
  1339. i++;
  1340. }
  1341. }
  1342. #ifndef GPAC_DISABLE_ISOM_WRITE
  1343. /*SWF importer options*/
  1344. else if (!stricmp(arg, "-global")) swf_flags |= GF_SM_SWF_STATIC_DICT;
  1345. else if (!stricmp(arg, "-no-ctrl")) swf_flags &= ~GF_SM_SWF_SPLIT_TIMELINE;
  1346. else if (!stricmp(arg, "-no-text")) swf_flags |= GF_SM_SWF_NO_TEXT;
  1347. else if (!stricmp(arg, "-no-font")) swf_flags |= GF_SM_SWF_NO_FONT;
  1348. else if (!stricmp(arg, "-no-line")) swf_flags |= GF_SM_SWF_NO_LINE;
  1349. else if (!stricmp(arg, "-no-grad")) swf_flags |= GF_SM_SWF_NO_GRADIENT;
  1350. else if (!stricmp(arg, "-quad")) swf_flags |= GF_SM_SWF_QUAD_CURVE;
  1351. else if (!stricmp(arg, "-xlp")) swf_flags |= GF_SM_SWF_SCALABLE_LINE;
  1352. else if (!stricmp(arg, "-ic2d")) swf_flags |= GF_SM_SWF_USE_IC2D;
  1353. else if (!stricmp(arg, "-same-app")) swf_flags |= GF_SM_SWF_REUSE_APPEARANCE;
  1354. else if (!stricmp(arg, "-flatten")) {
  1355. CHECK_NEXT_ARG
  1356. swf_flatten_angle = (Float) atof(argv[i+1]);
  1357. i++;
  1358. }
  1359. else if (!stricmp(arg, "-isma")) { conv_type = GF_ISOM_CONV_TYPE_ISMA; open_edit = 1; }
  1360. else if (!stricmp(arg, "-3gp")) { conv_type = GF_ISOM_CONV_TYPE_3GPP; open_edit = 1; }
  1361. else if (!stricmp(arg, "-ipod")) { conv_type = GF_ISOM_CONV_TYPE_IPOD; open_edit = 1; }
  1362. else if (!stricmp(arg, "-ismax")) { conv_type = GF_ISOM_CONV_TYPE_ISMA_EX; open_edit = 1; }
  1363. else if (!stricmp(arg, "-no-sys") || !stricmp(arg, "-nosys")) { remove_sys_tracks = 1; open_edit = 1; }
  1364. else if (!stricmp(arg, "-no-iod")) { remove_root_od = 1; open_edit = 1; }
  1365. else if (!stricmp(arg, "-out")) { CHECK_NEXT_ARG outName = argv[i+1]; i++; }
  1366. else if (!stricmp(arg, "-tmp")) {
  1367. CHECK_NEXT_ARG tmpdir = argv[i+1]; i++;
  1368. }
  1369. else if (!stricmp(arg, "-cprt")) { CHECK_NEXT_ARG cprt = argv[i+1]; i++; open_edit = 1; }
  1370. else if (!stricmp(arg, "-chap")) { CHECK_NEXT_ARG chap_file = argv[i+1]; i++; open_edit = 1; }
  1371. else if (!strcmp(arg, "-mem-track")) {
  1372. #ifdef GPAC_MEMORY_TRACKING
  1373. enable_mem_tracker = 1;
  1374. #else
  1375. fprintf(stdout, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n");
  1376. #endif
  1377. } else if (!strcmp(arg, "-strict-error")) {
  1378. gf_log_set_strict_error(1);
  1379. } else if (!stricmp(arg, "-inter") || !stricmp(arg, "-old-inter")) {
  1380. CHECK_NEXT_ARG
  1381. InterleavingTime = atof(argv[i+1]) / 1000;
  1382. open_edit = 1;
  1383. needSave = 1;
  1384. if (!stricmp(arg, "-old-inter")) old_interleave = 1;
  1385. i++;
  1386. } else if (!stricmp(arg, "-frag")) {
  1387. CHECK_NEXT_ARG
  1388. InterleavingTime = atof(argv[i+1]) / 1000;
  1389. needSave = 1;
  1390. i++;
  1391. Frag = 1;
  1392. } else if (!stricmp(arg, "-dash")) {
  1393. CHECK_NEXT_ARG
  1394. dash_duration = atof(argv[i+1]) / 1000;
  1395. needSave = 1;
  1396. i++;
  1397. } else if (!stricmp(arg, "-dash-ts-prog")) {
  1398. CHECK_NEXT_ARG
  1399. program_number = atoi(argv[i+1]);
  1400. i++;
  1401. } else if (!stricmp(arg, "-subsegs-per-sidx") || !stricmp(arg, "-frags-per-sidx")) {
  1402. CHECK_NEXT_ARG
  1403. subsegs_per_sidx = atoi(argv[i+1]);
  1404. i++;
  1405. } else if (!stricmp(arg, "-segment-name")) {
  1406. CHECK_NEXT_ARG
  1407. seg_name = argv[i+1];
  1408. i++;
  1409. } else if (!stricmp(arg, "-segment-ext")) {
  1410. CHECK_NEXT_ARG
  1411. seg_ext = argv[i+1];
  1412. i++;
  1413. } else if (!stricmp(arg, "-dash-ctx")) {
  1414. CHECK_NEXT_ARG
  1415. dash_ctx = argv[i+1];
  1416. i++;
  1417. } else if (!stricmp(arg, "-daisy-chain")) {
  1418. daisy_chain_sidx = 1;
  1419. } else if (!stricmp(arg, "-single-segment")) {
  1420. single_segment = 1;
  1421. } else if (!strnicmp(arg, "-url-template", 13)) {
  1422. use_url_template = 1;
  1423. if ((arg[13]=='=') && arg[14]) {
  1424. if (!strcmp( &arg[14], "simulate")) use_url_template = 2;
  1425. }
  1426. }
  1427. else if (!stricmp(arg, "-itags")) { CHECK_NEXT_ARG itunes_tags = argv[i+1]; i++; open_edit = 1; }
  1428. #ifndef GPAC_DISABLE_ISOM_HINTING
  1429. else if (!stricmp(arg, "-hint")) { open_edit = 1; HintIt = 1; }
  1430. else if (!stricmp(arg, "-unhint")) { open_edit = 1; remove_hint = 1; }
  1431. else if (!stricmp(arg, "-copy")) HintCopy = 1;
  1432. else if (!stricmp(arg, "-tight")) {
  1433. FullInter = 1;
  1434. open_edit = 1;
  1435. needSave = 1;
  1436. } else if (!stricmp(arg, "-ocr")) force_ocr = 1;
  1437. else if (!stricmp(arg, "-latm")) hint_flags |= GP_RTP_PCK_USE_LATM_AAC;
  1438. else if (!stricmp(arg, "-rap")) {
  1439. hint_flags |= GP_RTP_PCK_SIGNAL_RAP;
  1440. seg_at_rap=1;
  1441. }
  1442. else if (!stricmp(arg, "-ts")) hint_flags |= GP_RTP_PCK_SIGNAL_TS;
  1443. else if (!stricmp(arg, "-size")) hint_flags |= GP_RTP_PCK_SIGNAL_SIZE;
  1444. else if (!stricmp(arg, "-idx")) hint_flags |= GP_RTP_PCK_SIGNAL_AU_IDX;
  1445. else if (!stricmp(arg, "-static")) hint_flags |= GP_RTP_PCK_USE_STATIC_ID;
  1446. else if (!stricmp(arg, "-multi")) {
  1447. hint_flags |= GP_RTP_PCK_USE_MULTI;
  1448. if ((i+1<(u32) argc) && (sscanf(argv[i+1], "%u", &max_ptime)==1)) {
  1449. char szPt[20];
  1450. sprintf(szPt, "%u", max_ptime);
  1451. if (!strcmp(szPt, argv[i+1])) i++;
  1452. else max_ptime=0;
  1453. }
  1454. }
  1455. #endif
  1456. else if (!stricmp(arg, "-mpeg4")) {
  1457. #ifndef GPAC_DISABLE_ISOM_HINTING
  1458. hint_flags |= GP_RTP_PCK_FORCE_MPEG4;
  1459. #endif
  1460. #ifndef GPAC_DISABLE_MEDIA_IMPORT
  1461. import_flags |= GF_IMPORT_FORCE_MPEG4;
  1462. #endif
  1463. }
  1464. #ifndef GPAC_DISABLE_ISOM_HINTING
  1465. else if (!stricmp(arg, "-mtu")) { CHECK_NEXT_ARG MTUSize = atoi(argv[i+1]); i++; }
  1466. else if (!stricmp(arg, "-cardur")) { CHECK_NEXT_ARG car_dur = atoi(argv[i+1]); i++; }
  1467. else if (!stricmp(arg, "-rate")) { CHECK_NEXT_ARG rtp_rate = atoi(argv[i+1]); i++; }
  1468. #ifndef GPAC_DISABLE_SENG
  1469. else if (!stricmp(arg, "-add-sdp") || !stricmp(arg, "-sdp_ex")) {
  1470. char *id;
  1471. CHECK_NEXT_ARG
  1472. if (nb_sdp_ex>=MAX_CUMUL_OPS) {
  1473. fprintf(stdout, "Sorry - no more than %d extra SDP lines allowed\n", MAX_CUMUL_OPS);
  1474. return 1;
  1475. }
  1476. id = strchr(argv[i+1], ':');
  1477. if (id) {
  1478. id[0] = 0;
  1479. if (sscanf(argv[i+1], "%u", &sdp_lines[0].trackID)==1) {
  1480. id[0] = ':';
  1481. sdp_lines[nb_sdp_ex].line = id+1;
  1482. } else {
  1483. id[0] = ':';
  1484. sdp_lines[nb_sdp_ex].line = argv[i+1];
  1485. sdp_lines[nb_sdp_ex].trackID = 0;
  1486. }
  1487. } else {
  1488. sdp_lines[nb_sdp_ex].line = argv[i+1];
  1489. sdp_lines[nb_sdp_ex].trackID = 0;
  1490. }
  1491. open_edit = 1;
  1492. nb_sdp_ex++;
  1493. i++;
  1494. }
  1495. #endif /*GPAC_DISABLE_SENG*/
  1496. #endif /*GPAC_DISABLE_ISOM_HINTING*/
  1497. else if (!stricmp(arg, "-single")) {
  1498. #ifndef GPAC_DISABLE_MEDIA_EXPORT
  1499. CHECK_NEXT_ARG
  1500. track_dump_type = GF_EXPORT_MP4;
  1501. trackID = atoi(argv[i+1]);
  1502. i++;
  1503. #endif
  1504. }
  1505. else if (!stricmp(arg, "-iod")) regular_iod = 1;
  1506. else if (!stricmp(arg, "-flat")) do_flat = 1;
  1507. else if (!stricmp(arg, "-new")) force_new = 1;
  1508. else if (!stricmp(arg, "-add") || !stricmp(arg, "-import") || !stricmp(arg, "-convert")) {
  1509. CHECK_NEXT_ARG
  1510. if (!stricmp(arg, "-import")) fprintf(stdout, "\tWARNING: \"-import\" is deprecated - use \"-add\"\n");
  1511. else if (!stricmp(arg, "-convert")) fprintf(stdout, "\tWARNING: \"-convert\" is deprecated - use \"-add\"\n");
  1512. nb_add++;
  1513. i++;
  1514. }
  1515. else if (!stricmp(arg, "-cat")) {
  1516. CHECK_NEXT_ARG
  1517. nb_cat++;
  1518. i++;
  1519. }
  1520. else if (!stricmp(arg, "-time")) {
  1521. struct tm time;
  1522. CHECK_NEXT_ARG
  1523. memset(&time, 0, sizeof(struct tm));
  1524. sscanf(argv[i+1], "%d/%d/%d-%d:%d:%d", &time.tm_mday, &time.tm_mon, &time.tm_year, &time.tm_hour, &time.tm_min, &time.tm_sec);
  1525. time.tm_isdst=0;
  1526. time.tm_year -= 1900;
  1527. time.tm_mon -= 1;
  1528. open_edit = 1;
  1529. movie_time = 2082758400;
  1530. movie_time += mktime(&time);
  1531. i++;
  1532. }
  1533. else if (!stricmp(arg, "-force-cat")) force_cat = 1;
  1534. else if (!stricmp(arg, "-raw-cat")) {
  1535. CHECK_NEXT_ARG
  1536. raw_cat = argv[i+1];
  1537. i++;
  1538. }
  1539. else if (!stricmp(arg, "-rem") || !stricmp(arg, "-disable") || !stricmp(arg, "-enable")) {
  1540. CHECK_NEXT_ARG
  1541. if (nb_track_act>=MAX_CUMUL_OPS) {
  1542. fprintf(stdout, "Sorry - no more than %d track operations allowed\n", MAX_CUMUL_OPS);
  1543. return 1;
  1544. }
  1545. if (!stricmp(arg, "-enable")) tracks[nb_track_act].act_type = 6;
  1546. else if (!stricmp(arg, "-disable")) tracks[nb_track_act].act_type = 7;
  1547. else tracks[nb_track_act].act_type = 0;
  1548. tracks[nb_track_act].trackID = atoi(argv[i+1]);
  1549. open_edit = 1;
  1550. nb_track_act++;
  1551. i++;
  1552. }
  1553. else if (!stricmp(arg, "-par")) {
  1554. char szTK[20], *ext;
  1555. CHECK_NEXT_ARG
  1556. if (nb_track_act>=MAX_CUMUL_OPS) {
  1557. fprintf(stdout, "Sorry - no more than %d track operations allowed\n", MAX_CUMUL_OPS);
  1558. return 1;
  1559. }
  1560. tracks[nb_track_act].act_type = 4;
  1561. strcpy(szTK, argv[i+1]);
  1562. ext = strchr(szTK, '=');
  1563. if (!ext) {
  1564. fprintf(stdout, "Bad format for track par - expecting ID=PAR_NUM:PAR_DEN got %s\n", argv[i+1]);
  1565. return 1;
  1566. }
  1567. if (!stricmp(ext+1, "none")) {
  1568. tracks[nb_track_act].par_num = tracks[nb_track_act].par_den = -1;
  1569. } else {
  1570. sscanf(ext+1, "%d:%d", &tracks[nb_track_act].par_num, &tracks[nb_track_act].par_den);
  1571. }
  1572. ext[0] = 0;
  1573. tracks[nb_track_act].trackID = atoi(szTK);
  1574. open_edit = 1;
  1575. nb_track_act++;
  1576. i++;
  1577. }
  1578. else if (!stricmp(arg, "-lang")) {
  1579. char szTK[20], *ext;
  1580. CHECK_NEXT_ARG
  1581. if (nb_track_act>=MAX_CUMUL_OPS) {
  1582. fprintf(stdout, "Sorry - no more than %d track operations allowed\n", MAX_CUMUL_OPS);
  1583. return 1;
  1584. }
  1585. tracks[nb_track_act].act_type = 1;
  1586. tracks[nb_track_act].lang[3] = 0;
  1587. tracks[nb_track_act].trackID = 0;
  1588. strcpy(szTK, argv[i+1]);
  1589. ext = strchr(szTK, '=');
  1590. if (!strnicmp(argv[i+1], "all=", 4)) {
  1591. strncpy(tracks[nb_track_act].lang, argv[i+1]+1, 3);
  1592. } else if (!ext) {
  1593. strncpy(tracks[nb_track_act].lang, argv[i+1], 3);
  1594. } else {
  1595. strncpy(tracks[nb_track_act].lang, ext+1, 3);
  1596. ext[0] = 0;
  1597. tracks[nb_track_act].trackID = atoi(szTK);
  1598. ext[0] = '=';
  1599. }
  1600. open_edit = 1;
  1601. nb_track_act++;
  1602. i++;
  1603. }
  1604. else if (!stricmp(arg, "-delay")) {
  1605. char szTK[20], *ext;
  1606. CHECK_NEXT_ARG
  1607. if (nb_track_act>=MAX_CUMUL_OPS) {
  1608. fprintf(stdout, "Sorry - no more than %d track operations allowed\n", MAX_CUMUL_OPS);
  1609. return 1;
  1610. }
  1611. strcpy(szTK, argv[i+1]);
  1612. ext = strchr(szTK, '=');
  1613. if (!ext) {
  1614. fprintf(stdout, "Bad format for track delay - expecting ID=DLAY got %s\n", argv[i+1]);
  1615. return 1;
  1616. }
  1617. tracks[nb_track_act].act_type = 2;
  1618. tracks[nb_track_act].delay_ms = atoi(ext+1);
  1619. ext[0] = 0;
  1620. tracks[nb_track_act].trackID = atoi(szTK);
  1621. open_edit = 1;
  1622. nb_track_act++;
  1623. i++;
  1624. }
  1625. else if (!stricmp(arg, "-ref")) {
  1626. char *szTK, *ext;
  1627. CHECK_NEXT_ARG
  1628. if (nb_track_act>=MAX_CUMUL_OPS) {
  1629. fprintf(stdout, "Sorry - no more than %d track operations allowed\n", MAX_CUMUL_OPS);
  1630. return 1;
  1631. }
  1632. szTK = argv[i+1];
  1633. ext = strchr(szTK, ':');
  1634. if (!ext) {
  1635. fprintf(stdout, "Bad format for track reference - expecting ID:XXXX:refID got %s\n", argv[i+1]);
  1636. return 1;
  1637. }
  1638. tracks[nb_track_act].act_type = 8;
  1639. ext[0] = 0; tracks[nb_track_act].trackID = atoi(szTK); ext[0] = ':'; szTK = ext+1;
  1640. ext = strchr(szTK, ':');
  1641. if (!ext) {
  1642. fprintf(stdout, "Bad format for track reference - expecting ID:XXXX:refID got %s\n", argv[i+1]);
  1643. return 1;
  1644. }
  1645. ext[0] = 0;
  1646. strncpy(tracks[nb_track_act].lang, szTK, 4);
  1647. ext[0] = ':';
  1648. tracks[nb_track_act].delay_ms = (s32) atoi(ext+1);
  1649. open_edit = 1;
  1650. nb_track_act++;
  1651. i++;
  1652. }
  1653. else if (!stricmp(arg, "-name")) {
  1654. char szTK[GF_MAX_PATH], *ext;
  1655. CHECK_NEXT_ARG
  1656. if (nb_track_act>=MAX_CUMUL_OPS) {
  1657. fprintf(stdout, "Sorry - no more than %d track operations allowed\n", MAX_CUMUL_OPS);
  1658. return 1;
  1659. }
  1660. strcpy(szTK, argv[i+1]);
  1661. ext = strchr(szTK, '=');
  1662. if (!ext) {
  1663. fprintf(stdout, "Bad format for track name - expecting ID=name got %s\n", argv[i+1]);
  1664. return 1;
  1665. }
  1666. tracks[nb_track_act].act_type = 5;
  1667. tracks[nb_track_act].hdl_name = strchr(argv[i+1], '=') + 1;
  1668. ext[0] = 0;
  1669. tracks[nb_track_act].trackID = atoi(szTK);
  1670. ext[0] = '=';
  1671. open_edit = 1;
  1672. nb_track_act++;
  1673. i++;
  1674. }
  1675. #if !defined(GPAC_DISABLE_MEDIA_EXPORT) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
  1676. else if (!stricmp(arg, "-dref")) import_flags |= GF_IMPORT_USE_DATAREF;
  1677. else if (!stricmp(arg, "-no-drop") || !stricmp(arg, "-nodrop")) import_flags |= GF_IMPORT_NO_FRAME_DROP;
  1678. else if (!stricmp(arg, "-packed")) import_flags |= GF_IMPORT_FORCE_PACKED;
  1679. else if (!stricmp(arg, "-sbr")) import_flags |= GF_IMPORT_SBR_IMPLICIT;
  1680. else if (!stricmp(arg, "-sbrx")) import_flags |= GF_IMPORT_SBR_EXPLICIT;
  1681. else if (!stricmp(arg, "-ps")) import_flags |= GF_IMPORT_PS_IMPLICIT;
  1682. else if (!stricmp(arg, "-psx")) import_flags |= GF_IMPORT_PS_EXPLICIT;
  1683. else if (!stricmp(arg, "-ovsbr")) import_flags |= GF_IMPORT_OVSBR;
  1684. else if (!stricmp(arg, "-fps")) {
  1685. CHECK_NEXT_ARG
  1686. if (!strcmp(argv[i+1], "auto")) import_fps = GF_IMPORT_AUTO_FPS;
  1687. else if (strchr(argv[i+1], '-')) {
  1688. u32 ticks, dts_inc;
  1689. sscanf(argv[i+1], "%u-%u", &ticks, &dts_inc);
  1690. if (!dts_inc) dts_inc=1;
  1691. import_fps = ticks;
  1692. import_fps /= dts_inc;
  1693. } else import_fps = atof(argv[i+1]);
  1694. i++;
  1695. }
  1696. else if (!stricmp(arg, "-agg")) { CHECK_NEXT_ARG agg_samples = atoi(argv[i+1]); i++; }
  1697. else if (!stricmp(arg, "-keep-all") || !stricmp(arg, "-keepall")) import_flags |= GF_IMPORT_KEEP_ALL_TRACKS;
  1698. #endif /*!defined(GPAC_DISABLE_MEDIA_EXPORT) && !defined(GPAC_DISABLE_MEDIA_IMPORT*/
  1699. else if (!stricmp(arg, "-keep-sys") || !stricmp(arg, "-keepsys")) keep_sys_tracks = 1;
  1700. else if (!stricmp(arg, "-ms")) { CHECK_NEXT_ARG mediaSource = argv[i+1]; i++; }
  1701. else if (!stricmp(arg, "-mp4")) { encode = 1; open_edit = 1; }
  1702. else if (!stricmp(arg, "-saf")) { do_saf = 1; }
  1703. else if (!stricmp(arg, "-log")) { do_log = 1; }
  1704. else if (!stricmp(arg, "-mpd")) {
  1705. do_mpd = 1;
  1706. CHECK_NEXT_ARG
  1707. outName = argv[i+1];
  1708. i++;
  1709. }
  1710. #ifndef GPAC_DISABLE_SCENE_ENCODER
  1711. else if (!stricmp(arg, "-def")) opts.flags |= GF_SM_ENCODE_USE_NAMES;
  1712. else if (!stricmp(arg, "-sync")) {
  1713. CHECK_NEXT_ARG
  1714. opts.flags |= GF_SM_ENCODE_RAP_INBAND;
  1715. opts.rap_freq = atoi(argv[i+1]);
  1716. i++;
  1717. } else if (!stricmp(arg, "-shadow")) {
  1718. CHECK_NEXT_ARG
  1719. opts.flags &= ~GF_SM_ENCODE_RAP_INBAND;
  1720. opts.flags |= GF_SM_ENCODE_RAP_SHADOW;
  1721. opts.rap_freq = atoi(argv[i+1]);
  1722. i++;
  1723. } else if (!stricmp(arg, "-carousel")) {
  1724. CHECK_NEXT_ARG
  1725. opts.flags &= ~(GF_SM_ENCODE_RAP_INBAND | GF_SM_ENCODE_RAP_SHADOW);
  1726. opts.rap_freq = atoi(argv[i+1]);
  1727. i++;
  1728. }
  1729. /*LASeR options*/
  1730. else if (!stricmp(arg, "-resolution")) {
  1731. CHECK_NEXT_ARG
  1732. opts.resolution = atoi(argv[i+1]);
  1733. i++;
  1734. }
  1735. #ifndef GPAC_DISABLE_SCENE_STATS
  1736. else if (!stricmp(arg, "-auto-quant")) {
  1737. CHECK_NEXT_ARG
  1738. opts.resolution = atoi(argv[i+1]);
  1739. opts.auto_quant = 1;
  1740. i++;
  1741. }
  1742. #endif
  1743. else if (!stricmp(arg, "-coord-bits")) {
  1744. CHECK_NEXT_ARG
  1745. opts.coord_bits = atoi(argv[i+1]);
  1746. i++;
  1747. }
  1748. else if (!stricmp(arg, "-scale-bits")) {
  1749. CHECK_NEXT_ARG
  1750. opts.scale_bits = atoi(argv[i+1]);
  1751. i++;
  1752. }
  1753. else if (!stricmp(arg, "-global-quant")) {
  1754. CHECK_NEXT_ARG
  1755. opts.resolution = atoi(argv[i+1]);
  1756. opts.auto_quant = 2;
  1757. i++;
  1758. }
  1759. /*chunk encoding*/
  1760. else if (!stricmp(arg, "-ctx-out") || !stricmp(arg, "-outctx")) { CHECK_NEXT_ARG output_ctx = argv[i+1]; i++; }
  1761. else if (!stricmp(arg, "-ctx-in") || !stricmp(arg, "-inctx")) {
  1762. CHECK_NEXT_ARG
  1763. chunk_mode = 1;
  1764. input_ctx = argv[i+1];
  1765. i++;
  1766. }
  1767. #endif /*GPAC_DISABLE_SCENE_ENCODER*/
  1768. else if (!strcmp(arg, "-crypt")) {
  1769. CHECK_NEXT_ARG
  1770. ismaCrypt = 1;
  1771. drm_file = argv[i+1];
  1772. open_edit = 1;
  1773. i += 1;
  1774. }
  1775. else if (!strcmp(arg, "-decrypt")) {
  1776. CHECK_NEXT_ARG
  1777. ismaCrypt = 2;
  1778. if (get_file_type_by_ext(argv[i+1])!=1) {
  1779. drm_file = argv[i+1];
  1780. i += 1;
  1781. }
  1782. open_edit = 1;
  1783. }
  1784. else if (!stricmp(arg, "-set-kms")) {
  1785. char szTK[20], *ext;
  1786. CHECK_NEXT_ARG
  1787. if (nb_track_act>=MAX_CUMUL_OPS) {
  1788. fprintf(stdout, "Sorry - no more than %d track operations allowed\n", MAX_CUMUL_OPS);
  1789. return 1;
  1790. }
  1791. strncpy(szTK, argv[i+1], 19);
  1792. ext = strchr(szTK, '=');
  1793. tracks[nb_track_act].act_type = 3;
  1794. tracks[nb_track_act].trackID = 0;
  1795. if (!strnicmp(argv[i+1], "all=", 4)) {
  1796. tracks[nb_track_act].kms = argv[i+1] + 4;
  1797. } else if (!ext) {
  1798. tracks[nb_track_act].kms = argv[i+1];
  1799. } else {
  1800. tracks[nb_track_act].kms = ext+1;
  1801. ext[0] = 0;
  1802. tracks[nb_track_act].trackID = atoi(szTK);
  1803. ext[0] = '=';
  1804. }
  1805. open_edit = 1;
  1806. nb_track_act++;
  1807. i++;
  1808. }
  1809. else if (!stricmp(arg, "-split")) {
  1810. CHECK_NEXT_ARG
  1811. split_duration = atof(argv[i+1]);
  1812. if (split_duration<0) split_duration=0;;
  1813. i++;
  1814. split_size = 0;
  1815. }
  1816. else if (!stricmp(arg, "-split-rap") || !stricmp(arg, "-splitr")) {
  1817. CHECK_NEXT_ARG
  1818. split_duration = -1;
  1819. split_size = -1;
  1820. }
  1821. else if (!stricmp(arg, "-split-size") || !stricmp(arg, "-splits")) {
  1822. CHECK_NEXT_ARG
  1823. split_size = atoi(argv[i+1]);
  1824. if (split_size<0) split_size = 0;
  1825. i++;
  1826. split_duration = 0;
  1827. }
  1828. else if (!stricmp(arg, "-split-chunk") || !stricmp(arg, "-splitx") || !stricmp(arg, "-splitz")) {
  1829. CHECK_NEXT_ARG
  1830. if (!strstr(argv[i+1], ":")) {
  1831. fprintf(stdout, "Chunk extraction usage: \"-splitx start:end\" expressed in seconds\n");
  1832. return 1;
  1833. }
  1834. sscanf(argv[i+1], "%lf:%lf", &split_start, &split_duration);
  1835. split_duration -= split_start;
  1836. split_size = 0;
  1837. if (!stricmp(arg, "-splitz")) adjust_split_end = 1;
  1838. i++;
  1839. }
  1840. /*meta*/
  1841. else if (!stricmp(arg, "-set-meta")) {
  1842. CHECK_META_OPS
  1843. metas[nb_meta_act].act_type = 0;
  1844. parse_meta_args(&metas[nb_meta_act], argv[i+1]);
  1845. nb_meta_act++;
  1846. open_edit = 1;
  1847. i++;
  1848. }
  1849. else if (!stricmp(arg, "-add-item")) {
  1850. CHECK_META_OPS
  1851. metas[nb_meta_act].act_type = 1;
  1852. parse_meta_args(&metas[nb_meta_act], argv[i+1]);
  1853. nb_meta_act++;
  1854. open_edit = 1;
  1855. i++;
  1856. }
  1857. else if (!stricmp(arg, "-rem-item")) {
  1858. CHECK_META_OPS
  1859. metas[nb_meta_act].act_type = 2;
  1860. parse_meta_args(&metas[nb_meta_act], argv[i+1]);
  1861. nb_meta_act++;
  1862. open_edit = 1;
  1863. i++;
  1864. }
  1865. else if (!stricmp(arg, "-set-primary")) {
  1866. CHECK_META_OPS
  1867. metas[nb_meta_act].act_type = 3;
  1868. parse_meta_args(&metas[nb_meta_act], argv[i+1]);
  1869. nb_meta_act++;
  1870. open_edit = 1;
  1871. i++;
  1872. }
  1873. else if (!stricmp(arg, "-set-xml")) {
  1874. CHECK_META_OPS
  1875. metas[nb_meta_act].act_type = 4;
  1876. parse_meta_args(&metas[nb_meta_act], argv[i+1]);
  1877. nb_meta_act++;
  1878. open_edit = 1;
  1879. i++;
  1880. }
  1881. else if (!stricmp(arg, "-rem-xml")) {
  1882. CHECK_META_OPS
  1883. metas[nb_meta_act].act_type = 6;
  1884. if (parse_meta_args(&metas[nb_meta_act], argv[i+1])) i++;
  1885. nb_meta_act++;
  1886. open_edit = 1;
  1887. }
  1888. else if (!stricmp(arg, "-dump-xml")) {
  1889. CHECK_META_OPS
  1890. metas[nb_meta_act].act_type = 7;
  1891. parse_meta_args(&metas[nb_meta_act], argv[i+1]);
  1892. nb_meta_act++;
  1893. i++;
  1894. }
  1895. else if (!stricmp(arg, "-dump-item")) {
  1896. CHECK_META_OPS
  1897. metas[nb_meta_act].act_type = 8;
  1898. parse_meta_args(&metas[nb_meta_act], argv[i+1]);
  1899. nb_meta_act++;
  1900. i++;
  1901. }
  1902. else if (!stricmp(arg, "-group-add") || !stricmp(arg, "-group-rem-track") || !stricmp(arg, "-group-rem")) {
  1903. tsel_acts[nb_tsel_acts].act_type = !stricmp(arg, "-group-rem") ? 2 : ( !stricmp(arg, "-group-rem-track") ? 1 : 0 );
  1904. if (parse_tsel_args(tsel_acts, argv[i+1], &nb_tsel_acts)==0) {
  1905. fprintf(stdout, "Invalid group syntax - check usage\n");
  1906. return 1;
  1907. }
  1908. open_edit=1;
  1909. i++;
  1910. }
  1911. else if (!stricmp(arg, "-group-clean")) {
  1912. tsel_acts[nb_tsel_acts].act_type = 3;
  1913. nb_tsel_acts++;
  1914. open_edit=1;
  1915. }
  1916. else if (!stricmp(arg, "-group-single")) {
  1917. single_group = 1;
  1918. }
  1919. else if (!stricmp(arg, "-package")) {
  1920. CHECK_NEXT_ARG
  1921. pack_file = argv[i+1];
  1922. i++;
  1923. }
  1924. else if (!stricmp(arg, "-mgt")) {
  1925. CHECK_NEXT_ARG
  1926. pack_file = argv[i+1];
  1927. pack_wgt = 1;
  1928. i++;
  1929. }
  1930. else if (!stricmp(arg, "-brand")) {
  1931. char *b = argv[i+1];
  1932. CHECK_NEXT_ARG
  1933. major_brand = GF_4CC(b[0], b[1], b[2], b[3]);
  1934. open_edit = 1;
  1935. if (b[4]==':') minor_version = atoi(b+5);
  1936. i++;
  1937. }
  1938. else if (!stricmp(arg, "-ab")) {
  1939. char *b = argv[i+1];
  1940. CHECK_NEXT_ARG
  1941. if (nb_alt_brand_add>=MAX_CUMUL_OPS) {
  1942. fprintf(stdout, "Sorry - no more than %d brand remove operations allowed\n", MAX_CUMUL_OPS);
  1943. return 1;
  1944. }
  1945. brand_add[nb_alt_brand_add] = GF_4CC(b[0], b[1], b[2], b[3]);
  1946. nb_alt_brand_add++;
  1947. open_edit = 1;
  1948. i++;
  1949. }
  1950. else if (!stricmp(arg, "-rb")) {
  1951. CHECK_NEXT_ARG
  1952. if (nb_alt_brand_rem>=MAX_CUMUL_OPS) {
  1953. fprintf(stdout, "Sorry - no more than %d brand remove operations allowed\n", MAX_CUMUL_OPS);
  1954. return 1;
  1955. }
  1956. nb_alt_brand_rem++;
  1957. open_edit = 1;
  1958. i++;
  1959. }
  1960. #endif
  1961. else if (!stricmp(arg, "-languages")) {
  1962. PrintLanguages();
  1963. return 0;
  1964. }
  1965. else if (!stricmp(arg, "-h")) {
  1966. if (i+1== (u32) argc) PrintUsage();
  1967. else if (!strcmp(argv[i+1], "general")) PrintGeneralUsage();
  1968. else if (!strcmp(argv[i+1], "extract")) PrintExtractUsage();
  1969. else if (!strcmp(argv[i+1], "dump")) PrintDumpUsage();
  1970. else if (!strcmp(argv[i+1], "import")) PrintImportUsage();
  1971. else if (!strcmp(argv[i+1], "format")) PrintFormats();
  1972. else if (!strcmp(argv[i+1], "hint")) PrintHintUsage();
  1973. else if (!strcmp(argv[i+1], "encode")) PrintEncodeUsage();
  1974. else if (!strcmp(argv[i+1], "crypt")) PrintEncryptUsage();
  1975. else if (!strcmp(argv[i+1], "meta")) PrintMetaUsage();
  1976. else if (!strcmp(argv[i+1], "swf")) PrintSWFUsage();
  1977. #if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_SENG)
  1978. else if (!strcmp(argv[i+1], "rtp")) PrintStreamerUsage();
  1979. else if (!strcmp(argv[i+1], "live")) PrintLiveUsage ();
  1980. #endif
  1981. else if (!strcmp(argv[i+1], "all")) {
  1982. PrintGeneralUsage();
  1983. PrintExtractUsage();
  1984. PrintDumpUsage();
  1985. PrintImportUsage();
  1986. PrintFormats();
  1987. PrintHintUsage();
  1988. PrintEncodeUsage();
  1989. PrintEncryptUsage();
  1990. PrintMetaUsage();
  1991. PrintSWFUsage();
  1992. #if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_SENG)
  1993. PrintStreamerUsage();
  1994. PrintLiveUsage ();
  1995. #endif
  1996. }
  1997. else PrintUsage();
  1998. return 0;
  1999. }
  2000. else if (!stricmp(arg, "-v")) verbose++;
  2001. else if (!stricmp(arg, "-tag-list")) {
  2002. fprintf(stdout, "Supported iTunes tag modifiers:\n");
  2003. for (i=0; i<nb_itunes_tags; i++) {
  2004. fprintf(stdout, "\t%s\t%s\n", itags[i].name, itags[i].comment);
  2005. }
  2006. return 0;
  2007. } else if (!live_scene && !stream_rtp) {
  2008. fprintf(stdout, "Option %s unknown. Please check usage\n", arg);
  2009. return 1;
  2010. }
  2011. }
  2012. if (!inName) {
  2013. PrintUsage();
  2014. return 1;
  2015. }
  2016. #if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_SENG)
  2017. if (live_scene) {
  2018. return live_session(argc, argv);
  2019. }
  2020. if (stream_rtp) {
  2021. return stream_file_rtp(argc, argv);
  2022. }
  2023. #endif
  2024. if (raw_cat) {
  2025. char chunk[4096];
  2026. FILE *fin, *fout;
  2027. s64 to_copy, done;
  2028. fin = gf_f64_open(raw_cat, "rb");
  2029. if (!fin) return 1;
  2030. fout = gf_f64_open(inName, "a+b");
  2031. if (!fout) {
  2032. fclose(fin);
  2033. return 1;
  2034. }
  2035. gf_f64_seek(fin, 0, SEEK_END);
  2036. to_copy = gf_f64_tell(fin);
  2037. gf_f64_seek(fin, 0, SEEK_SET);
  2038. done = 0;
  2039. while (1) {
  2040. u32 nb_bytes = fread(chunk, 1, 4096, fin);
  2041. gf_fwrite(chunk, 1, nb_bytes, fout);
  2042. done += nb_bytes;
  2043. fprintf(stdout, "Appending file %s - %02.2f done\r", raw_cat, 100.0*done/to_copy);
  2044. if (done >= to_copy) break;
  2045. }
  2046. fclose(fin);
  2047. fclose(fout);
  2048. return 0;
  2049. }
  2050. /*init libgpac*/
  2051. gf_sys_init(enable_mem_tracker);
  2052. if (gf_logs) {
  2053. gf_log_set_tools_levels(gf_logs);
  2054. } else {
  2055. u32 level = verbose ? GF_LOG_DEBUG : GF_LOG_INFO;
  2056. gf_log_set_tool_level(GF_LOG_CONTAINER, level);
  2057. gf_log_set_tool_level(GF_LOG_SCENE, level);
  2058. gf_log_set_tool_level(GF_LOG_PARSER, level);
  2059. gf_log_set_tool_level(GF_LOG_AUTHOR, level);
  2060. gf_log_set_tool_level(GF_LOG_CODING, level);
  2061. #ifdef GPAC_MEMORY_TRACKING
  2062. if (enable_mem_tracker)
  2063. gf_log_set_tool_level(GF_LOG_MEMORY, level);
  2064. #endif
  2065. if (quiet) {
  2066. if (quiet==2) gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_QUIET);
  2067. gf_set_progress_callback(NULL, progress_quiet);
  2068. }
  2069. }
  2070. if (do_mpd) {
  2071. Bool remote = 0;
  2072. char *mpd_base_url = gf_strdup(inName);
  2073. if (!strnicmp(inName, "http://", 7)) {
  2074. e = gf_dm_wget(inName, "tmp_main.m3u8");
  2075. if (e != GF_OK) {
  2076. fprintf(stdout, "Cannot retrieve M3U8 (%s): %s\n", inName, gf_error_to_string(e));
  2077. gf_free(mpd_base_url);
  2078. return 1;
  2079. }
  2080. inName = "tmp_main.m3u8";
  2081. remote = 1;
  2082. }
  2083. e = gf_m3u8_to_mpd(inName, mpd_base_url, (outName ? outName : inName), 0, "video/mp2t", 1, use_url_template, NULL);
  2084. gf_free(mpd_base_url);
  2085. if (remote) {
  2086. //gf_delete_file("tmp_main.m3u8");
  2087. }
  2088. if (e != GF_OK) {
  2089. fprintf(stdout, "Error converting M3U8 (%s) to MPD (%s): %s\n", inName, outName, gf_error_to_string(e));
  2090. return 1;
  2091. } else {
  2092. fprintf(stdout, "Done converting M3U8 (%s) to MPD (%s)\n", inName, outName);
  2093. return 0;
  2094. }
  2095. }
  2096. if (dash_duration && !nb_dash_inputs) {
  2097. dash_inputs[nb_dash_inputs] = inName;
  2098. nb_dash_inputs++;
  2099. }
  2100. if (do_saf && !encode) {
  2101. switch (get_file_type_by_ext(inName)) {
  2102. case 2: case 3: case 4:
  2103. encode = 1;
  2104. break;
  2105. }
  2106. }
  2107. #ifndef GPAC_DISABLE_SCENE_DUMP
  2108. if (dump_mode == 1 + GF_SM_DUMP_SVG) {
  2109. if (strstr(inName, ".srt") || strstr(inName, ".ttxt")) import_subtitle = 2;
  2110. }
  2111. #endif
  2112. if (import_subtitle && !trackID) {
  2113. #ifndef GPAC_DISABLE_MEDIA_IMPORT
  2114. GF_MediaImporter import;
  2115. file = gf_isom_open("ttxt_convert", GF_ISOM_OPEN_WRITE, NULL);
  2116. memset(&import, 0, sizeof(GF_MediaImporter));
  2117. import.dest = file;
  2118. import.in_name = inName;
  2119. e = gf_media_import(&import);
  2120. if (e) {
  2121. fprintf(stdout, "Error importing %s: %s\n", inName, gf_error_to_string(e));
  2122. gf_isom_delete(file);
  2123. gf_delete_file("ttxt_convert");
  2124. return 1;
  2125. }
  2126. strcpy(outfile, outName ? outName : inName);
  2127. if (strchr(outfile, '.')) {
  2128. while (outfile[strlen(outfile)-1] != '.') outfile[strlen(outfile)-1] = 0;
  2129. outfile[strlen(outfile)-1] = 0;
  2130. }
  2131. #ifndef GPAC_DISABLE_ISOM_DUMP
  2132. dump_timed_text_track(file, gf_isom_get_track_id(file, 1), dump_std ? NULL : outfile, 1, (import_subtitle==2) ? 2 : dump_srt);
  2133. #endif
  2134. gf_isom_delete(file);
  2135. gf_delete_file("ttxt_convert");
  2136. if (e) {
  2137. fprintf(stdout, "Error converting %s: %s\n", inName, gf_error_to_string(e));
  2138. return 1;
  2139. }
  2140. return 0;
  2141. #else
  2142. fprintf(stdout, "Feature not supported\n");
  2143. return 1;
  2144. #endif
  2145. }
  2146. #if !defined(GPAC_DISABLE_MEDIA_IMPORT) && !defined(GPAC_DISABLE_ISOM_WRITE)
  2147. if (nb_add) {
  2148. u8 open_mode = GF_ISOM_OPEN_EDIT;
  2149. if (force_new) {
  2150. open_mode = (do_flat) ? GF_ISOM_OPEN_WRITE : GF_ISOM_WRITE_EDIT;
  2151. } else {
  2152. FILE *test = gf_f64_open(inName, "rb");
  2153. if (!test) {
  2154. open_mode = (do_flat) ? GF_ISOM_OPEN_WRITE : GF_ISOM_WRITE_EDIT;
  2155. if (!outName) outName = inName;
  2156. } else {
  2157. fclose(test);
  2158. if (! gf_isom_probe_file(inName) ) {
  2159. open_mode = (do_flat) ? GF_ISOM_OPEN_WRITE : GF_ISOM_WRITE_EDIT;
  2160. if (!outName) outName = inName;
  2161. }
  2162. }
  2163. }
  2164. open_edit = 1;
  2165. file = gf_isom_open(inName, open_mode, tmpdir);
  2166. if (!file) {
  2167. fprintf(stdout, "Cannot open destination file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL)) );
  2168. return 1;
  2169. }
  2170. for (i=0; i<(u32) argc; i++) {
  2171. if (!strcmp(argv[i], "-add")) {
  2172. e = import_file(file, argv[i+1], import_flags, import_fps, agg_samples);
  2173. if (e) {
  2174. fprintf(stdout, "Error importing %s: %s\n", argv[i+1], gf_error_to_string(e));
  2175. gf_isom_delete(file);
  2176. return 1;
  2177. }
  2178. i++;
  2179. }
  2180. }
  2181. /*unless explicitly asked, remove all systems tracks*/
  2182. if (!keep_sys_tracks) remove_systems_tracks(file);
  2183. needSave = 1;
  2184. /*JLF commented: if you want ISMA, just ask for it, no more auto-detect*/
  2185. // if (!conv_type && can_convert_to_isma(file)) conv_type = GF_ISOM_CONV_TYPE_ISMA;
  2186. }
  2187. if (nb_cat) {
  2188. if (!file) {
  2189. u8 open_mode = GF_ISOM_OPEN_EDIT;
  2190. if (force_new) {
  2191. open_mode = (do_flat) ? GF_ISOM_OPEN_WRITE : GF_ISOM_WRITE_EDIT;
  2192. } else {
  2193. FILE *test = gf_f64_open(inName, "rb");
  2194. if (!test) {
  2195. open_mode = (do_flat) ? GF_ISOM_OPEN_WRITE : GF_ISOM_WRITE_EDIT;
  2196. if (!outName) outName = inName;
  2197. }
  2198. else fclose(test);
  2199. }
  2200. open_edit = 1;
  2201. file = gf_isom_open(inName, open_mode, tmpdir);
  2202. if (!file) {
  2203. fprintf(stdout, "Cannot open destination file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL)) );
  2204. return 1;
  2205. }
  2206. }
  2207. for (i=0; i<(u32)argc; i++) {
  2208. if (!strcmp(argv[i], "-cat")) {
  2209. e = cat_isomedia_file(file, argv[i+1], import_flags, import_fps, agg_samples, tmpdir, force_cat);
  2210. if (e) {
  2211. fprintf(stdout, "Error appending %s: %s\n", argv[i+1], gf_error_to_string(e));
  2212. gf_isom_delete(file);
  2213. return 1;
  2214. }
  2215. i++;
  2216. }
  2217. }
  2218. /*unless explicitly asked, remove all systems tracks*/
  2219. if (!keep_sys_tracks) remove_systems_tracks(file);
  2220. needSave = 1;
  2221. if (conv_type && can_convert_to_isma(file)) conv_type = GF_ISOM_CONV_TYPE_ISMA;
  2222. }
  2223. #endif
  2224. #if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
  2225. else if (chunk_mode) {
  2226. if (!inName) {
  2227. fprintf(stdout, "chunk encoding syntax: [-outctx outDump] -inctx inScene auFile\n");
  2228. return 1;
  2229. }
  2230. e = EncodeFileChunk(inName, outName ? outName : inName, input_ctx, output_ctx, tmpdir);
  2231. if (e) fprintf(stdout, "Error encoding chunk file %s\n", gf_error_to_string(e));
  2232. return e ? 1 : 0;
  2233. }
  2234. #endif
  2235. else if (encode) {
  2236. #if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
  2237. FILE *logs = NULL;
  2238. if (do_log) {
  2239. char logfile[5000];
  2240. strcpy(logfile, inName);
  2241. if (strchr(logfile, '.')) {
  2242. while (logfile[strlen(logfile)-1] != '.') logfile[strlen(logfile)-1] = 0;
  2243. logfile[strlen(logfile)-1] = 0;
  2244. }
  2245. strcat(logfile, "_enc.logs");
  2246. logs = gf_f64_open(logfile, "wt");
  2247. }
  2248. strcpy(outfile, outName ? outName : inName);
  2249. if (strchr(outfile, '.')) {
  2250. while (outfile[strlen(outfile)-1] != '.') outfile[strlen(outfile)-1] = 0;
  2251. outfile[strlen(outfile)-1] = 0;
  2252. }
  2253. strcat(outfile, ".mp4");
  2254. file = gf_isom_open(outfile, GF_ISOM_WRITE_EDIT, tmpdir);
  2255. opts.mediaSource = mediaSource ? mediaSource : outfile;
  2256. e = EncodeFile(inName, file, &opts, logs);
  2257. if (logs) fclose(logs);
  2258. if (e) goto err_exit;
  2259. needSave = 1;
  2260. if (do_saf) {
  2261. needSave = 0;
  2262. open_edit = 0;
  2263. }
  2264. #endif
  2265. }
  2266. #ifndef GPAC_DISABLE_ISOM_WRITE
  2267. else if (pack_file) {
  2268. char *fileName = strchr(pack_file, ':');
  2269. if (fileName && ((fileName - pack_file)==4)) {
  2270. fileName[0] = 0;
  2271. file = package_file(fileName + 1, pack_file, tmpdir, pack_wgt);
  2272. fileName[0] = ':';
  2273. } else {
  2274. file = package_file(pack_file, NULL, tmpdir, pack_wgt);
  2275. }
  2276. if (!outName) outName = inName;
  2277. needSave = 1;
  2278. open_edit = 1;
  2279. }
  2280. #endif
  2281. else if (!file
  2282. #ifndef GPAC_DISABLE_MEDIA_EXPORT
  2283. && !(track_dump_type & GF_EXPORT_AVI_NATIVE)
  2284. #endif
  2285. ) {
  2286. FILE *st = gf_f64_open(inName, "rb");
  2287. Bool file_exists = 0;
  2288. if (st) {
  2289. file_exists = 1;
  2290. fclose(st);
  2291. }
  2292. switch (get_file_type_by_ext(inName)) {
  2293. case 1:
  2294. file = gf_isom_open(inName, (u8) (open_edit ? GF_ISOM_OPEN_EDIT : ( (dump_isom>0) ? GF_ISOM_OPEN_READ_DUMP : GF_ISOM_OPEN_READ) ), tmpdir);
  2295. if (!file && (gf_isom_last_error(NULL) == GF_ISOM_INCOMPLETE_FILE) && !open_edit) {
  2296. u64 missing_bytes;
  2297. e = gf_isom_open_progressive(inName, 0, 0, &file, &missing_bytes);
  2298. fprintf(stdout, "Truncated file - missing "LLD" bytes\n", missing_bytes);
  2299. }
  2300. if (!file) {
  2301. if (open_edit && nb_meta_act) {
  2302. file = gf_isom_open(inName, GF_ISOM_WRITE_EDIT, tmpdir);
  2303. if (!outName && file) outName = inName;
  2304. }
  2305. if (!file) {
  2306. fprintf(stdout, "Error opening file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL)));
  2307. return 1;
  2308. }
  2309. }
  2310. break;
  2311. /*allowed for bt<->xmt*/
  2312. case 2:
  2313. case 3:
  2314. /*allowed for svg->lsr**/
  2315. case 4:
  2316. /*allowed for swf->bt, swf->xmt*/
  2317. case 5:
  2318. break;
  2319. /*used for .saf / .lsr dump*/
  2320. case 6:
  2321. #ifndef GPAC_DISABLE_SCENE_DUMP
  2322. if ((dump_mode==1+GF_SM_DUMP_LASER) || (dump_mode==1+GF_SM_DUMP_SVG)) {
  2323. break;
  2324. }
  2325. #endif
  2326. default:
  2327. if (!open_edit && file_exists && !gf_isom_probe_file(inName) && track_dump_type) {
  2328. }
  2329. #ifndef GPAC_DISABLE_ISOM_WRITE
  2330. else if (!open_edit && file_exists /* && !gf_isom_probe_file(inName) */ && !dump_mode) {
  2331. /*************************************************************************************************/
  2332. #ifndef GPAC_DISABLE_MEDIA_IMPORT
  2333. if(dvbhdemux)
  2334. {
  2335. GF_MediaImporter import;
  2336. file = gf_isom_open("ttxt_convert", GF_ISOM_OPEN_WRITE, NULL);
  2337. memset(&import, 0, sizeof(GF_MediaImporter));
  2338. import.dest = file;
  2339. import.in_name = inName;
  2340. import.flags = GF_IMPORT_MPE_DEMUX;
  2341. e = gf_media_import(&import);
  2342. if (e) {
  2343. fprintf(stdout, "Error importing %s: %s\n", inName, gf_error_to_string(e));
  2344. gf_isom_delete(file);
  2345. gf_delete_file("ttxt_convert");
  2346. return 1;
  2347. }
  2348. }
  2349. #endif /*GPAC_DISABLE_MEDIA_IMPORT*/
  2350. if (dash_duration) {
  2351. if (subsegs_per_sidx<0) subsegs_per_sidx = 0;
  2352. #ifndef GPAC_DISABLE_MPEG2TS
  2353. for (i=0; i<nb_dash_inputs; i++) {
  2354. dump_mpeg2_ts(dash_inputs[i], outName, program_number, dash_duration, seg_at_rap, subsegs_per_sidx,
  2355. seg_name, seg_ext, use_url_template, single_segment, i, (i+1 == nb_dash_inputs) ? 1 : 0);
  2356. }
  2357. #endif
  2358. } else if (dump_m2ts) {
  2359. #ifndef GPAC_DISABLE_MPEG2TS
  2360. dump_mpeg2_ts(inName, pes_dump, program_number, 0, 0, 0, NULL, NULL, 0, 0, 0, 0);
  2361. #endif
  2362. } else if (dump_ts) { /* dump_ts means dump time stamp information */
  2363. #ifndef GPAC_DISABLE_MPEG2TS
  2364. dump_mpeg2_ts(inName, pes_dump, program_number, 0, 0, 0, NULL, NULL, 0, 0, 0, 0);
  2365. #endif
  2366. #ifndef GPAC_DISABLE_MEDIA_IMPORT
  2367. } else {
  2368. convert_file_info(inName, info_track_id);
  2369. #endif
  2370. }
  2371. return 0;
  2372. }
  2373. #endif /*GPAC_DISABLE_ISOM_WRITE*/
  2374. else if (open_edit) {
  2375. file = gf_isom_open(inName, GF_ISOM_WRITE_EDIT, tmpdir);
  2376. if (!outName && file) outName = inName;
  2377. } else if (!file_exists) {
  2378. fprintf(stdout, "Error creating file %s: %s\n", inName, gf_error_to_string(GF_URL_ERROR));
  2379. return 1;
  2380. } else {
  2381. fprintf(stdout, "Cannot open %s - extension not supported\n", inName);
  2382. return 1;
  2383. }
  2384. }
  2385. }
  2386. strcpy(outfile, outName ? outName : inName);
  2387. if (strrchr(outfile, '.')) {
  2388. char *szExt = strrchr(outfile, '.');
  2389. /*turn on 3GP saving*/
  2390. if (!stricmp(szExt, ".3gp") || !stricmp(szExt, ".3gpp") || !stricmp(szExt, ".3g2"))
  2391. conv_type = GF_ISOM_CONV_TYPE_3GPP;
  2392. else if (!stricmp(szExt, ".m4a") || !stricmp(szExt, ".m4v"))
  2393. conv_type = GF_ISOM_CONV_TYPE_IPOD;
  2394. else if (!stricmp(szExt, ".psp"))
  2395. conv_type = GF_ISOM_CONV_TYPE_PSP;
  2396. while (outfile[strlen(outfile)-1] != '.') outfile[strlen(outfile)-1] = 0;
  2397. outfile[strlen(outfile)-1] = 0;
  2398. }
  2399. #ifndef GPAC_DISABLE_MEDIA_EXPORT
  2400. if (track_dump_type & GF_EXPORT_AVI_NATIVE) {
  2401. char szFile[1024];
  2402. GF_MediaExporter mdump;
  2403. memset(&mdump, 0, sizeof(mdump));
  2404. mdump.in_name = inName;
  2405. mdump.flags = GF_EXPORT_AVI_NATIVE;
  2406. mdump.trackID = trackID;
  2407. if (trackID>2) {
  2408. sprintf(szFile, "%s_audio%d", outfile, trackID-1);
  2409. } else {
  2410. sprintf(szFile, "%s_%s", outfile, (trackID==1) ? "video" : "audio");
  2411. }
  2412. mdump.out_name = szFile;
  2413. e = gf_media_export(&mdump);
  2414. if (e) goto err_exit;
  2415. return 0;
  2416. }
  2417. if (!open_edit && !gf_isom_probe_file(inName) && track_dump_type) {
  2418. GF_MediaExporter mdump;
  2419. memset(&mdump, 0, sizeof(mdump));
  2420. mdump.in_name = inName;
  2421. mdump.flags = track_dump_type;
  2422. mdump.trackID = trackID;
  2423. mdump.out_name = outfile;
  2424. e = gf_media_export(&mdump);
  2425. if (e) goto err_exit;
  2426. return 0;
  2427. }
  2428. #endif /*GPAC_DISABLE_MEDIA_EXPORT*/
  2429. #ifndef GPAC_DISABLE_SCENE_DUMP
  2430. if (dump_mode) {
  2431. e = dump_file_text(inName, dump_std ? NULL : outfile, dump_mode-1, do_log);
  2432. if (e) goto err_exit;
  2433. }
  2434. #endif
  2435. #ifndef GPAC_DISABLE_SCENE_STATS
  2436. if (stat_level) dump_scene_stats(inName, dump_std ? NULL : outfile, stat_level);
  2437. #endif
  2438. #ifndef GPAC_DISABLE_ISOM_HINTING
  2439. if (!HintIt && print_sdp) DumpSDP(file, dump_std ? NULL : outfile);
  2440. #endif
  2441. if (print_info) {
  2442. if (info_track_id) DumpTrackInfo(file, info_track_id, 1);
  2443. else DumpMovieInfo(file);
  2444. }
  2445. #ifndef GPAC_DISABLE_ISOM_DUMP
  2446. if (dump_isom) dump_isom_xml(file, dump_std ? NULL : outfile);
  2447. if (dump_cr) dump_file_ismacryp(file, dump_std ? NULL : outfile);
  2448. if ((dump_ttxt || dump_srt) && trackID) dump_timed_text_track(file, trackID, dump_std ? NULL : outfile, 0, dump_srt);
  2449. #ifndef GPAC_DISABLE_ISOM_HINTING
  2450. if (dump_rtp) dump_file_rtp(file, dump_std ? NULL : outfile);
  2451. #endif
  2452. #endif
  2453. if (dump_ts) dump_file_ts(file, dump_std ? NULL : outfile);
  2454. if (do_hash) {
  2455. u8 hash[20];
  2456. e = gf_media_get_file_hash(inName, hash);
  2457. if (e) goto err_exit;
  2458. fprintf(stdout, "File %s hash (SHA-1): ", inName);
  2459. for (i=0; i<20; i++) fprintf(stdout, "%02X", hash[i]);
  2460. fprintf(stdout, "\n");
  2461. }
  2462. if (dump_cart) dump_cover_art(file, outfile);
  2463. if (dump_chap) dump_chapters(file, outfile);
  2464. if (dump_iod) {
  2465. GF_InitialObjectDescriptor *iod = (GF_InitialObjectDescriptor *)gf_isom_get_root_od(file);
  2466. if (!iod) {
  2467. fprintf(stdout, "File %s has no IOD", inName);
  2468. } else {
  2469. char szName[GF_MAX_PATH];
  2470. FILE *iodf;
  2471. GF_BitStream *bs = NULL;
  2472. sprintf(szName, "%s.iod", outfile);
  2473. iodf = gf_f64_open(szName, "wb");
  2474. if (!iodf) {
  2475. fprintf(stdout, "Cannot open destination %s\n", szName);
  2476. } else {
  2477. char *desc;
  2478. u32 size;
  2479. bs = gf_bs_from_file(iodf, GF_BITSTREAM_WRITE);
  2480. if (gf_odf_desc_write((GF_Descriptor *)iod, &desc, &size)==GF_OK) {
  2481. gf_fwrite(desc, 1, size, iodf);
  2482. gf_free(desc);
  2483. } else {
  2484. fprintf(stdout, "Error writing IOD %s\n", szName);
  2485. }
  2486. fclose(iodf);
  2487. }
  2488. gf_free(bs);
  2489. }
  2490. }
  2491. #if !(definedGPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
  2492. if (split_duration || split_size) {
  2493. split_isomedia_file(file, split_duration, split_size, inName, InterleavingTime, split_start, adjust_split_end, outName, tmpdir);
  2494. /*never save file when splitting is desired*/
  2495. open_edit = 0;
  2496. needSave = 0;
  2497. }
  2498. #endif
  2499. #ifndef GPAC_DISABLE_MEDIA_EXPORT
  2500. if (do_saf || track_dump_type) {
  2501. char szFile[1024];
  2502. GF_MediaExporter mdump;
  2503. memset(&mdump, 0, sizeof(mdump));
  2504. mdump.file = file;
  2505. mdump.flags = do_saf ? GF_EXPORT_SAF : track_dump_type;
  2506. if (!do_saf) {
  2507. mdump.trackID = trackID;
  2508. mdump.sample_num = raw_sample_num;
  2509. if (outName) {
  2510. mdump.out_name = outName;
  2511. mdump.flags |= GF_EXPORT_MERGE;
  2512. } else {
  2513. sprintf(szFile, "%s_track%d", outfile, trackID);
  2514. mdump.out_name = szFile;
  2515. }
  2516. } else {
  2517. mdump.out_name = outfile;
  2518. }
  2519. e = gf_media_export(&mdump);
  2520. if (e) goto err_exit;
  2521. }
  2522. #endif
  2523. for (i=0; i<nb_meta_act; i++) {
  2524. u32 tk = 0;
  2525. Bool self_ref;
  2526. MetaAction *meta = &metas[i];
  2527. if (meta->trackID) tk = gf_isom_get_track_by_id(file, meta->trackID);
  2528. switch (meta->act_type) {
  2529. #ifndef GPAC_DISABLE_ISOM_WRITE
  2530. case 0:
  2531. /*note: we don't handle file brand modification, this is an author stuff and cannot be guessed from meta type*/
  2532. e = gf_isom_set_meta_type(file, meta->root_meta, tk, meta->meta_4cc);
  2533. gf_isom_modify_alternate_brand(file, GF_ISOM_BRAND_ISO2, 1);
  2534. needSave = 1;
  2535. break;
  2536. case 1:
  2537. self_ref = !stricmp(meta->szPath, "NULL") || !stricmp(meta->szPath, "this") || !stricmp(meta->szPath, "self");
  2538. e = gf_isom_add_meta_item(file, meta->root_meta, tk, self_ref, self_ref ? NULL : meta->szPath,
  2539. strlen(meta->szName) ? meta->szName : NULL,
  2540. strlen(meta->mime_type) ? meta->mime_type : NULL,
  2541. strlen(meta->enc_type) ? meta->enc_type : NULL,
  2542. meta->use_dref ? meta->szPath : NULL, NULL);
  2543. needSave = 1;
  2544. break;
  2545. case 2:
  2546. e = gf_isom_remove_meta_item(file, meta->root_meta, tk, meta->item_id);
  2547. needSave = 1;
  2548. break;
  2549. case 3:
  2550. e = gf_isom_set_meta_primary_item(file, meta->root_meta, tk, meta->item_id);
  2551. needSave = 1;
  2552. break;
  2553. case 4:
  2554. case 5:
  2555. e = gf_isom_set_meta_xml(file, meta->root_meta, tk, meta->szPath, (meta->act_type==5) ? 1 : 0);
  2556. needSave = 1;
  2557. break;
  2558. case 6:
  2559. if (gf_isom_get_meta_item_count(file, meta->root_meta, tk)) {
  2560. e = gf_isom_remove_meta_xml(file, meta->root_meta, tk);
  2561. needSave = 1;
  2562. } else {
  2563. fprintf(stdout, "No meta box in input file\n");
  2564. }
  2565. break;
  2566. case 8:
  2567. if (gf_isom_get_meta_item_count(file, meta->root_meta, tk)) {
  2568. e = gf_isom_extract_meta_item(file, meta->root_meta, tk, meta->item_id, strlen(meta->szPath) ? meta->szPath : NULL);
  2569. } else {
  2570. fprintf(stdout, "No meta box in input file\n");
  2571. }
  2572. break;
  2573. #endif
  2574. case 7:
  2575. if (gf_isom_has_meta_xml(file, meta->root_meta, tk)) {
  2576. e = gf_isom_extract_meta_xml(file, meta->root_meta, tk, meta->szPath, NULL);
  2577. } else {
  2578. fprintf(stdout, "No meta box in input file\n");
  2579. }
  2580. break;
  2581. }
  2582. if (e) goto err_exit;
  2583. }
  2584. if (!open_edit && !needSave) {
  2585. if (file) gf_isom_delete(file);
  2586. gf_sys_close();
  2587. return 0;
  2588. }
  2589. #ifndef GPAC_DISABLE_ISOM_WRITE
  2590. for (i=0; i<nb_tsel_acts; i++) {
  2591. switch (tsel_acts[i].act_type) {
  2592. case 0:
  2593. e = gf_isom_set_track_switch_parameter(file,
  2594. gf_isom_get_track_by_id(file, tsel_acts[i].trackID),
  2595. tsel_acts[i].refTrackID ? gf_isom_get_track_by_id(file, tsel_acts[i].refTrackID) : 0,
  2596. tsel_acts[i].is_switchGroup ? 1 : 0,
  2597. &tsel_acts[i].switchGroupID,
  2598. tsel_acts[i].criteria, tsel_acts[i].nb_criteria);
  2599. if (e) goto err_exit;
  2600. needSave = 1;
  2601. break;
  2602. case 1:
  2603. e = gf_isom_reset_track_switch_parameter(file, gf_isom_get_track_by_id(file, tsel_acts[i].trackID), 0);
  2604. if (e) goto err_exit;
  2605. needSave = 1;
  2606. break;
  2607. case 2:
  2608. e = gf_isom_reset_track_switch_parameter(file, gf_isom_get_track_by_id(file, tsel_acts[i].trackID), 1);
  2609. if (e) goto err_exit;
  2610. needSave = 1;
  2611. break;
  2612. case 3:
  2613. e = gf_isom_reset_switch_parameters(file);
  2614. if (e) goto err_exit;
  2615. needSave = 1;
  2616. break;
  2617. }
  2618. }
  2619. if (remove_sys_tracks) {
  2620. #ifndef GPAC_DISABLE_AV_PARSERS
  2621. remove_systems_tracks(file);
  2622. #endif
  2623. needSave = 1;
  2624. if (conv_type < GF_ISOM_CONV_TYPE_ISMA_EX) conv_type = 0;
  2625. }
  2626. if (remove_root_od) {
  2627. gf_isom_remove_root_od(file);
  2628. needSave = 1;
  2629. }
  2630. #ifndef GPAC_DISABLE_ISOM_HINTING
  2631. if (remove_hint) {
  2632. for (i=0; i<gf_isom_get_track_count(file); i++) {
  2633. if (gf_isom_get_media_type(file, i+1) == GF_ISOM_MEDIA_HINT) {
  2634. fprintf(stdout, "Removing hint track ID %d\n", gf_isom_get_track_id(file, i+1));
  2635. gf_isom_remove_track(file, i+1);
  2636. i--;
  2637. }
  2638. }
  2639. gf_isom_sdp_clean(file);
  2640. needSave = 1;
  2641. }
  2642. #endif
  2643. if (!encode) {
  2644. if (!file) {
  2645. fprintf(stdout, "Nothing to do - exiting\n");
  2646. gf_sys_close();
  2647. return 0;
  2648. }
  2649. if (outName) {
  2650. strcpy(outfile, outName);
  2651. } else {
  2652. char *rel_name = strrchr(inName, GF_PATH_SEPARATOR);
  2653. if (!rel_name) rel_name = strrchr(inName, '/');
  2654. strcpy(outfile, "");
  2655. if (tmpdir) {
  2656. strcpy(outfile, tmpdir);
  2657. if (!strchr("\\/", tmpdir[strlen(tmpdir)-1])) strcat(outfile, "/");
  2658. }
  2659. if (!pack_file) strcat(outfile, "out_");
  2660. strcat(outfile, rel_name ? rel_name + 1 : inName);
  2661. if (pack_file) {
  2662. strcpy(outfile, rel_name ? rel_name + 1 : inName);
  2663. rel_name = strrchr(outfile, '.');
  2664. if (rel_name) rel_name[0] = 0;
  2665. strcat(outfile, ".m21");
  2666. }
  2667. }
  2668. #ifndef GPAC_DISABLE_MEDIA_IMPORT
  2669. if ((conv_type == GF_ISOM_CONV_TYPE_ISMA) || (conv_type == GF_ISOM_CONV_TYPE_ISMA_EX)) {
  2670. fprintf(stdout, "Converting to ISMA Audio-Video MP4 file...\n");
  2671. /*keep ESIDs when doing ISMACryp*/
  2672. e = gf_media_make_isma(file, ismaCrypt ? 1 : 0, 0, (conv_type==GF_ISOM_CONV_TYPE_ISMA_EX) ? 1 : 0);
  2673. if (e) goto err_exit;
  2674. needSave = 1;
  2675. }
  2676. if (conv_type == GF_ISOM_CONV_TYPE_3GPP) {
  2677. fprintf(stdout, "Converting to 3GP file...\n");
  2678. e = gf_media_make_3gpp(file);
  2679. if (e) goto err_exit;
  2680. needSave = 1;
  2681. }
  2682. if (conv_type == GF_ISOM_CONV_TYPE_PSP) {
  2683. fprintf(stdout, "Converting to PSP file...\n");
  2684. e = gf_media_make_psp(file);
  2685. if (e) goto err_exit;
  2686. needSave = 1;
  2687. }
  2688. #endif /*GPAC_DISABLE_MEDIA_IMPORT*/
  2689. if (conv_type == GF_ISOM_CONV_TYPE_IPOD) {
  2690. u32 major_brand = 0;
  2691. fprintf(stdout, "Setting up iTunes/iPod file...\n");
  2692. for (i=0; i<gf_isom_get_track_count(file); i++) {
  2693. u32 mType = gf_isom_get_media_type(file, i+1);
  2694. switch (mType) {
  2695. case GF_ISOM_MEDIA_VISUAL:
  2696. major_brand = GF_4CC('M','4','V',' ');
  2697. gf_isom_set_ipod_compatible(file, i+1);
  2698. #if 0
  2699. switch (gf_isom_get_media_subtype(file, i+1, 1)) {
  2700. case GF_ISOM_SUBTYPE_AVC_H264:
  2701. case GF_ISOM_SUBTYPE_AVC2_H264:
  2702. fprintf(stdout, "Forcing AVC/H264 SAR to 1:1...\n");
  2703. gf_media_change_par(file, i+1, 1, 1);
  2704. break;
  2705. }
  2706. #endif
  2707. break;
  2708. case GF_ISOM_MEDIA_AUDIO:
  2709. if (!major_brand) major_brand = GF_4CC('M','4','A',' ');
  2710. else gf_isom_modify_alternate_brand(file, GF_4CC('M','4','A',' '), 1);
  2711. break;
  2712. case GF_ISOM_MEDIA_TEXT:
  2713. /*this is a text track track*/
  2714. if (gf_isom_get_media_subtype(file, i+1, 1) == GF_4CC('t','x','3','g')) {
  2715. u32 j;
  2716. Bool is_chap = 0;
  2717. for (j=0; j<gf_isom_get_track_count(file); j++) {
  2718. s32 count = gf_isom_get_reference_count(file, j+1, GF_4CC('c','h','a','p'));
  2719. if (count>0) {
  2720. u32 tk, k;
  2721. for (k=0; k<(u32) count; k++) {
  2722. gf_isom_get_reference(file, j+1, GF_4CC('c','h','a','p'), k+1, &tk);
  2723. if (tk==i+1) {
  2724. is_chap = 1;
  2725. break;
  2726. }
  2727. }
  2728. if (is_chap) break;
  2729. }
  2730. if (is_chap) break;
  2731. }
  2732. /*this is a subtitle track*/
  2733. if (!is_chap)
  2734. gf_isom_set_media_type(file, i+1, GF_ISOM_MEDIA_SUBT);
  2735. }
  2736. break;
  2737. }
  2738. }
  2739. gf_isom_set_brand_info(file, major_brand, 1);
  2740. gf_isom_modify_alternate_brand(file, GF_ISOM_BRAND_MP42, 1);
  2741. needSave = 1;
  2742. }
  2743. #ifndef GPAC_DISABLE_MCRYPT
  2744. if (ismaCrypt) {
  2745. if (ismaCrypt == 1) {
  2746. if (!drm_file) {
  2747. fprintf(stdout, "Missing DRM file location - usage '-%s drm_file input_file\n", (ismaCrypt==1) ? "crypt" : "decrypt");
  2748. e = GF_BAD_PARAM;
  2749. goto err_exit;
  2750. }
  2751. e = gf_ismacryp_crypt_file(file, drm_file);
  2752. } else if (ismaCrypt ==2) {
  2753. e = gf_ismacryp_decrypt_file(file, drm_file);
  2754. }
  2755. if (e) goto err_exit;
  2756. needSave = 1;
  2757. }
  2758. #endif /*GPAC_DISABLE_MCRYPT*/
  2759. } else if (outName) {
  2760. strcpy(outfile, outName);
  2761. }
  2762. for (i=0; i<nb_track_act; i++) {
  2763. TrackAction *tka = &tracks[i];
  2764. u32 track = tka->trackID ? gf_isom_get_track_by_id(file, tka->trackID) : 0;
  2765. u32 timescale = gf_isom_get_timescale(file);
  2766. switch (tka->act_type) {
  2767. case 0:
  2768. e = gf_isom_remove_track(file, track);
  2769. if (e) {
  2770. fprintf(stdout, "Error Removing track ID %d: %s\n", tka->trackID, gf_error_to_string(e));
  2771. } else {
  2772. fprintf(stdout, "Removing track ID %d\n", tka->trackID);
  2773. }
  2774. needSave = 1;
  2775. break;
  2776. case 1:
  2777. for (i=0; i<gf_isom_get_track_count(file); i++) {
  2778. if (track && (track != i+1)) continue;
  2779. e = gf_isom_set_media_language(file, i+1, (char *) GetLanguageCode(tka->lang));
  2780. if (e) goto err_exit;
  2781. needSave = 1;
  2782. }
  2783. needSave = 1;
  2784. break;
  2785. case 2:
  2786. if (tka->delay_ms) {
  2787. u64 tk_dur;
  2788. gf_isom_remove_edit_segments(file, track);
  2789. tk_dur = gf_isom_get_track_duration(file, track);
  2790. if (gf_isom_get_edit_segment_count(file, track))
  2791. needSave = 1;
  2792. if (tka->delay_ms>0) {
  2793. gf_isom_append_edit_segment(file, track, (timescale*tka->delay_ms)/1000, 0, GF_ISOM_EDIT_EMPTY);
  2794. gf_isom_append_edit_segment(file, track, tk_dur, 0, GF_ISOM_EDIT_NORMAL);
  2795. needSave = 1;
  2796. } else {
  2797. u64 to_skip = (timescale*(-tka->delay_ms))/1000;
  2798. if (to_skip<tk_dur) {
  2799. u64 media_time = (-tka->delay_ms)*gf_isom_get_media_timescale(file, track) / 1000;
  2800. gf_isom_append_edit_segment(file, track, tk_dur-to_skip, media_time, GF_ISOM_EDIT_NORMAL);
  2801. needSave = 1;
  2802. } else {
  2803. fprintf(stdout, "Warning: request negative delay longer than track duration - ignoring\n");
  2804. }
  2805. }
  2806. } else if (gf_isom_get_edit_segment_count(file, track)) {
  2807. gf_isom_remove_edit_segments(file, track);
  2808. needSave = 1;
  2809. }
  2810. break;
  2811. case 3:
  2812. for (i=0; i<gf_isom_get_track_count(file); i++) {
  2813. if (track && (track != i+1)) continue;
  2814. if (!gf_isom_is_media_encrypted(file, i+1, 1)) continue;
  2815. if (!gf_isom_is_ismacryp_media(file, i+1, 1)) continue;
  2816. e = gf_isom_change_ismacryp_protection(file, i+1, 1, NULL, (char *) tka->kms);
  2817. if (e) goto err_exit;
  2818. needSave = 1;
  2819. }
  2820. break;
  2821. case 4:
  2822. e = gf_media_change_par(file, track, tka->par_num, tka->par_den);
  2823. needSave = 1;
  2824. break;
  2825. case 5:
  2826. e = gf_isom_set_handler_name(file, track, tka->hdl_name);
  2827. needSave = 1;
  2828. break;
  2829. case 6:
  2830. if (!gf_isom_is_track_enabled(file, track)) {
  2831. e = gf_isom_set_track_enabled(file, track, 1);
  2832. needSave = 1;
  2833. }
  2834. break;
  2835. case 7:
  2836. if (gf_isom_is_track_enabled(file, track)) {
  2837. e = gf_isom_set_track_enabled(file, track, 0);
  2838. needSave = 1;
  2839. }
  2840. break;
  2841. case 8:
  2842. e = gf_isom_set_track_reference(file, track, GF_4CC(tka->lang[0], tka->lang[1], tka->lang[2], tka->lang[3]), (u32) tka->delay_ms);
  2843. needSave = 1;
  2844. break;
  2845. }
  2846. if (e) goto err_exit;
  2847. }
  2848. if (itunes_tags) {
  2849. char *tags = itunes_tags;
  2850. while (tags) {
  2851. char *val;
  2852. char *sep = strchr(tags, ':');
  2853. u32 tlen, itag = 0;
  2854. if (sep) {
  2855. while (sep) {
  2856. for (itag=0; itag<nb_itunes_tags;itag++) {
  2857. if (!strnicmp(sep+1, itags[itag].name, strlen(itags[itag].name))) break;
  2858. }
  2859. if (itag<nb_itunes_tags) {
  2860. break;
  2861. }
  2862. sep = strchr(sep+1, ':');
  2863. }
  2864. if (sep) sep[0] = 0;
  2865. }
  2866. for (itag=0; itag<nb_itunes_tags;itag++) {
  2867. if (!strnicmp(tags, itags[itag].name, strlen(itags[itag].name))) {
  2868. break;
  2869. }
  2870. }
  2871. if (itag==nb_itunes_tags) {
  2872. fprintf(stdout, "Invalid iTune tag format \"%s\" - ignoring\n", tags);
  2873. tags = NULL;
  2874. continue;
  2875. }
  2876. itag = itags[itag].code;
  2877. val = strchr(tags, '=');
  2878. if (!val) {
  2879. fprintf(stdout, "Invalid iTune tag format \"%s\" (expecting '=') - ignoring\n", tags);
  2880. tags = NULL;
  2881. continue;
  2882. }
  2883. if (val) {
  2884. val ++;
  2885. if ((val[0]==':') || !val[0] || !stricmp(val, "NULL") ) val = NULL;
  2886. }
  2887. tlen = val ? strlen(val) : 0;
  2888. switch (itag) {
  2889. case GF_ISOM_ITUNE_COVER_ART:
  2890. {
  2891. char *d, *ext;
  2892. FILE *t = gf_f64_open(val, "rb");
  2893. gf_f64_seek(t, 0, SEEK_END);
  2894. tlen = (u32) gf_f64_tell(t);
  2895. gf_f64_seek(t, 0, SEEK_SET);
  2896. d = gf_malloc(sizeof(char) * tlen);
  2897. tlen = fread(d, sizeof(char), tlen, t);
  2898. fclose(t);
  2899. ext = strrchr(val, '.');
  2900. if (!stricmp(ext, ".png")) tlen |= 0x80000000;
  2901. e = gf_isom_apple_set_tag(file, GF_ISOM_ITUNE_COVER_ART, d, tlen);
  2902. gf_free(d);
  2903. }
  2904. break;
  2905. case GF_ISOM_ITUNE_TEMPO:
  2906. gf_isom_apple_set_tag(file, itag, NULL, atoi(val) );
  2907. break;
  2908. case GF_ISOM_ITUNE_GENRE:
  2909. {
  2910. u8 _v = id3_get_genre_tag(val);
  2911. if (_v) {
  2912. gf_isom_apple_set_tag(file, itag, NULL, _v);
  2913. } else {
  2914. gf_isom_apple_set_tag(file, itag, val, strlen(val) );
  2915. }
  2916. }
  2917. break;
  2918. case GF_ISOM_ITUNE_DISK:
  2919. case GF_ISOM_ITUNE_TRACKNUMBER:
  2920. {
  2921. u32 n, t;
  2922. char _t[8];
  2923. n = t = 0;
  2924. memset(_t, 0, sizeof(char)*8);
  2925. tlen = (itag==GF_ISOM_ITUNE_DISK) ? 6 : 8;
  2926. if (sscanf(val, "%u/%u", &n, &t) == 2) { _t[3]=n; _t[5]=t;}
  2927. else if (sscanf(val, "%u", &n) == 1) { _t[3]=n;}
  2928. else tlen = 0;
  2929. if (tlen) gf_isom_apple_set_tag(file, itag, _t, tlen);
  2930. }
  2931. break;
  2932. case GF_ISOM_ITUNE_GAPLESS:
  2933. case GF_ISOM_ITUNE_COMPILATION:
  2934. {
  2935. char _t[1];
  2936. if (!stricmp(val, "yes")) _t[0] = 1;
  2937. else _t[0] = 0;
  2938. gf_isom_apple_set_tag(file, itag, _t, 1);
  2939. }
  2940. break;
  2941. default:
  2942. gf_isom_apple_set_tag(file, itag, val, tlen);
  2943. break;
  2944. }
  2945. needSave = 1;
  2946. if (sep) {
  2947. sep[0] = ':';
  2948. tags = sep+1;
  2949. } else {
  2950. tags = NULL;
  2951. }
  2952. }
  2953. }
  2954. if (movie_time) {
  2955. gf_isom_set_creation_time(file, movie_time);
  2956. for (i=0; i<gf_isom_get_track_count(file); i++) {
  2957. gf_isom_set_track_creation_time(file, i+1, movie_time);
  2958. }
  2959. needSave = 1;
  2960. }
  2961. /*split file*/
  2962. if (dash_duration) {
  2963. char szMPD[GF_MAX_PATH];
  2964. char szInit[GF_MAX_PATH];
  2965. GF_ISOFile *init_seg;
  2966. Bool sps_merge_failed = 0;
  2967. Double period_duration = 0;
  2968. if (single_segment) {
  2969. fprintf(stdout, "DASH-ing file%s with single segment\nSubsegment duration %.3f - Fragment duration: %.3f secs\n", (nb_dash_inputs>1) ? "s" : "", dash_duration, InterleavingTime);
  2970. subsegs_per_sidx = 0;
  2971. seg_name = seg_ext = NULL;
  2972. } else {
  2973. if (!seg_ext) seg_ext = "m4s";
  2974. fprintf(stdout, "DASH-ing file with %.3f secs segments - fragments: %.3f secs\n", dash_duration, InterleavingTime);
  2975. if (subsegs_per_sidx<0) fprintf(stdout, "No sidx used");
  2976. else if (subsegs_per_sidx) fprintf(stdout, "%d subsegments per sidx", subsegs_per_sidx);
  2977. else fprintf(stdout, "Single sidx used");
  2978. }
  2979. fprintf(stdout, "\n");
  2980. if (seg_at_rap) fprintf(stdout, "Spliting segments at GOP boundaries\n");
  2981. strcpy(outfile, outName ? outName : inName);
  2982. while (outfile[strlen(outfile)-1] != '.') outfile[strlen(outfile)-1] = 0;
  2983. outfile[strlen(outfile)-1] = 0;
  2984. if (!outName) strcat(outfile, "_dash");
  2985. strcpy(szInit, outfile);
  2986. strcat(szInit, "_init.mp4");
  2987. strcpy(szMPD, outfile);
  2988. strcat(szMPD, ".mpd");
  2989. init_seg = gf_isom_open(szInit, GF_ISOM_OPEN_WRITE, tmpdir);
  2990. for (i=0; i<nb_dash_inputs; i++) {
  2991. u32 j;
  2992. Double dur;
  2993. GF_ISOFile *in = file;
  2994. if (i) {
  2995. in = gf_isom_open(dash_inputs[i], GF_ISOM_OPEN_READ, NULL);
  2996. if (!in) {
  2997. fprintf(stdout, "Error while opening %s: %s\n", dash_inputs[i], gf_error_to_string( gf_isom_last_error(NULL) ));
  2998. gf_isom_delete(file);
  2999. gf_sys_close();
  3000. return 1;
  3001. }
  3002. }
  3003. for (j=0; j<gf_isom_get_track_count(in); j++) {
  3004. u32 track = gf_isom_get_track_by_id(init_seg, gf_isom_get_track_id(in, j+1));
  3005. if (track) {
  3006. u32 outDescIndex;
  3007. assert( gf_isom_get_sample_description_count(in, j+1) == 1);
  3008. /*if not the same sample desc we might need to clone it*/
  3009. if (! gf_isom_is_same_sample_description(in, j+1, 1, init_seg, track, 1)) {
  3010. Bool do_merge = 1;
  3011. u32 stype1, stype2;
  3012. stype1 = gf_isom_get_media_subtype(in, j+1, 1);
  3013. stype2 = gf_isom_get_media_subtype(init_seg, track, 1);
  3014. if (stype1 != stype2) do_merge = 0;
  3015. switch (stype1) {
  3016. case GF_4CC( 'a', 'v', 'c', '1'):
  3017. case GF_4CC( 'a', 'v', 'c', '2'):
  3018. case GF_4CC( 's', 'v', 'c', '1'):
  3019. break;
  3020. default:
  3021. do_merge = 0;
  3022. break;
  3023. }
  3024. if (do_merge) {
  3025. u32 k, l, sps_id1, sps_id2;
  3026. GF_AVCConfig *avccfg1 = gf_isom_avc_config_get(in, j+1, 1);
  3027. GF_AVCConfig *avccfg2 = gf_isom_avc_config_get(init_seg, track, 1);
  3028. #ifndef GPAC_DISABLE_AV_PARSERS
  3029. for (k=0; k<gf_list_count(avccfg2->sequenceParameterSets); k++) {
  3030. GF_AVCConfigSlot *slc = gf_list_get(avccfg2->sequenceParameterSets, k);
  3031. gf_avc_get_sps_info(slc->data, slc->size, &sps_id1, NULL, NULL, NULL, NULL);
  3032. for (l=0; l<gf_list_count(avccfg1->sequenceParameterSets); l++) {
  3033. GF_AVCConfigSlot *slc_orig = gf_list_get(avccfg1->sequenceParameterSets, l);
  3034. gf_avc_get_sps_info(slc_orig->data, slc_orig->size, &sps_id2, NULL, NULL, NULL, NULL);
  3035. if (sps_id2==sps_id1) {
  3036. do_merge = 0;
  3037. break;
  3038. }
  3039. }
  3040. }
  3041. #endif
  3042. /*no conflicts in SPS ids, merge all SPS in a single sample desc*/
  3043. if (do_merge) {
  3044. while (gf_list_count(avccfg1->sequenceParameterSets)) {
  3045. GF_AVCConfigSlot *slc = gf_list_get(avccfg1->sequenceParameterSets, 0);
  3046. gf_list_rem(avccfg1->sequenceParameterSets, 0);
  3047. gf_list_add(avccfg2->sequenceParameterSets, slc);
  3048. }
  3049. while (gf_list_count(avccfg1->pictureParameterSets)) {
  3050. GF_AVCConfigSlot *slc = gf_list_get(avccfg1->pictureParameterSets, 0);
  3051. gf_list_rem(avccfg1->pictureParameterSets, 0);
  3052. gf_list_add(avccfg2->pictureParameterSets, slc);
  3053. }
  3054. gf_isom_avc_config_update(init_seg, track, 1, avccfg2);
  3055. } else {
  3056. sps_merge_failed = 1;
  3057. }
  3058. gf_odf_avc_cfg_del(avccfg1);
  3059. gf_odf_avc_cfg_del(avccfg2);
  3060. }
  3061. /*cannot merge, clone*/
  3062. if (!do_merge)
  3063. gf_isom_clone_sample_description(init_seg, track, in, j+1, 1, NULL, NULL, &outDescIndex);
  3064. }
  3065. } else {
  3066. gf_isom_clone_track(in, j+1, init_seg, 0, &track);
  3067. }
  3068. dur = (Double) gf_isom_get_track_duration(in, j+1);
  3069. dur /= gf_isom_get_timescale(in);
  3070. if (dur>period_duration) period_duration = dur;
  3071. }
  3072. if (i) gf_isom_close(in);
  3073. }
  3074. if (sps_merge_failed) {
  3075. fprintf(stdout, "Couldnt merge AVC|H264 SPS from different files (same SPS ID used) - different sample descriptions will be used\n");
  3076. }
  3077. if (!seg_name) use_url_template = 0;
  3078. gf_media_mpd_start(szMPD, (char *)gf_isom_get_filename(file), use_url_template, single_segment, dash_ctx, init_seg, period_duration);
  3079. for (i=0; i<nb_dash_inputs; i++) {
  3080. char szSegName[GF_MAX_PATH], *segment_name;
  3081. GF_ISOFile *in = file;
  3082. if (i) in = gf_isom_open(dash_inputs[i], GF_ISOM_OPEN_READ, NULL);
  3083. segment_name = seg_name;
  3084. if (nb_dash_inputs>1) {
  3085. char *sep = strrchr(dash_inputs[i], '/');
  3086. if (!sep) sep = strrchr(dash_inputs[i], '\\');
  3087. if (sep) strcpy(outfile, sep+1);
  3088. else strcpy(outfile, dash_inputs[i]);
  3089. sep = strrchr(outfile, '.');
  3090. if (sep) sep[0] = 0;
  3091. if (seg_name) {
  3092. if (strstr(seg_name, "%s")) sprintf(szSegName, seg_name, outfile);
  3093. else strcpy(szSegName, seg_name);
  3094. segment_name = szSegName;
  3095. }
  3096. strcat(outfile, "_dash");
  3097. }
  3098. if (nb_dash_inputs>1) {
  3099. fprintf(stdout, "DASHing file %s\n", dash_inputs[i]);
  3100. }
  3101. #ifndef GPAC_DISABLE_ISOM_FRAGMENTS
  3102. e = gf_media_fragment_file(in, outfile, szMPD, InterleavingTime, seg_at_rap ? 2 : 1, dash_duration, segment_name, seg_ext, subsegs_per_sidx, daisy_chain_sidx, use_url_template, single_segment, dash_ctx, init_seg, i+1);
  3103. #else
  3104. fprintf(stderr, "GPAC was compiled without fragment support\n");
  3105. e = GF_NOT_SUPPORTED;
  3106. #endif
  3107. if (e) {
  3108. fprintf(stdout, "Error while DASH-ing file: %s\n", gf_error_to_string(e));
  3109. break;
  3110. }
  3111. if (i) gf_isom_close(in);
  3112. }
  3113. /*close MPD*/
  3114. gf_media_mpd_end(szMPD);
  3115. /*if init segment shared, write to file*/
  3116. if (nb_dash_inputs>1) {
  3117. gf_isom_close(init_seg);
  3118. } else {
  3119. gf_isom_delete(init_seg);
  3120. gf_delete_file(szInit);
  3121. }
  3122. gf_isom_delete(file);
  3123. gf_sys_close();
  3124. return (e!=GF_OK) ? 1 : 0;
  3125. #ifndef GPAC_DISABLE_ISOM_FRAGMENTS
  3126. } else if (Frag) {
  3127. if (!InterleavingTime) InterleavingTime = 0.5;
  3128. if (HintIt) fprintf(stdout, "Warning: cannot hint and fragment - ignoring hint\n");
  3129. fprintf(stdout, "Fragmenting file (%.3f seconds fragments)\n", InterleavingTime);
  3130. e = gf_media_fragment_file(file, outfile, NULL, InterleavingTime, 0, 0, NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0);
  3131. if (e) fprintf(stdout, "Error while fragmenting file: %s\n", gf_error_to_string(e));
  3132. gf_isom_delete(file);
  3133. if (!e && !outName && !force_new) {
  3134. if (remove(inName)) fprintf(stdout, "Error removing file %s\n", inName);
  3135. else if (rename(outfile, inName)) fprintf(stdout, "Error renaming file %s to %s\n", outfile, inName);
  3136. }
  3137. gf_sys_close();
  3138. return (e!=GF_OK) ? 1 : 0;
  3139. #endif
  3140. }
  3141. #ifndef GPAC_DISABLE_ISOM_HINTING
  3142. if (HintIt) {
  3143. if (force_ocr) SetupClockReferences(file);
  3144. fprintf(stdout, "Hinting file with Path-MTU %d Bytes\n", MTUSize);
  3145. MTUSize -= 12;
  3146. e = HintFile(file, MTUSize, max_ptime, rtp_rate, hint_flags, HintCopy, HintInter, regular_iod, single_group);
  3147. if (e) goto err_exit;
  3148. needSave = 1;
  3149. if (print_sdp) DumpSDP(file, dump_std ? NULL : outfile);
  3150. }
  3151. #endif
  3152. /*full interleave (sample-based) if just hinted*/
  3153. if (FullInter) {
  3154. e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_TIGHT);
  3155. } else if (!InterleavingTime) {
  3156. e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_STREAMABLE);
  3157. needSave = 1;
  3158. } else if (do_flat) {
  3159. e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_FLAT);
  3160. needSave = 1;
  3161. } else {
  3162. e = gf_isom_make_interleave(file, InterleavingTime);
  3163. if (!e && !old_interleave) e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_DRIFT_INTERLEAVED);
  3164. }
  3165. if (e) goto err_exit;
  3166. #if !defined(GPAC_DISABLE_ISOM_HINTING) && !defined(GPAC_DISABLE_SENG)
  3167. for (i=0; i<nb_sdp_ex; i++) {
  3168. if (sdp_lines[i].trackID) {
  3169. u32 track = gf_isom_get_track_by_id(file, sdp_lines[i].trackID);
  3170. if (gf_isom_get_media_type(file, track)!=GF_ISOM_MEDIA_HINT) {
  3171. s32 ref_count;
  3172. u32 j, k, count = gf_isom_get_track_count(file);
  3173. for (j=0; j<count; j++) {
  3174. if (gf_isom_get_media_type(file, j+1)!=GF_ISOM_MEDIA_HINT) continue;
  3175. ref_count = gf_isom_get_reference_count(file, j+1, GF_ISOM_REF_HINT);
  3176. if (ref_count<0) continue;
  3177. for (k=0; k<(u32) ref_count; k++) {
  3178. u32 refTk;
  3179. if (gf_isom_get_reference(file, j+1, GF_ISOM_REF_HINT, k+1, &refTk)) continue;
  3180. if (refTk==track) {
  3181. track = j+1;
  3182. j=count;
  3183. break;
  3184. }
  3185. }
  3186. }
  3187. }
  3188. gf_isom_sdp_add_track_line(file, track, sdp_lines[i].line);
  3189. needSave = 1;
  3190. } else {
  3191. gf_isom_sdp_add_line(file, sdp_lines[i].line);
  3192. needSave = 1;
  3193. }
  3194. }
  3195. #endif /*!defined(GPAC_DISABLE_ISOM_HINTING) && !defined(GPAC_DISABLE_SENG)*/
  3196. if (cprt) {
  3197. e = gf_isom_set_copyright(file, "und", cprt);
  3198. needSave = 1;
  3199. if (e) goto err_exit;
  3200. }
  3201. if (chap_file) {
  3202. #ifndef GPAC_DISABLE_MEDIA_IMPORT
  3203. e = gf_media_import_chapters(file, chap_file, import_fps);
  3204. needSave = 1;
  3205. #else
  3206. fprintf(stdout, "Warning: GPAC compiled without Media Import, chapters can't be imported\n");
  3207. e = GF_NOT_SUPPORTED;
  3208. #endif
  3209. if (e) goto err_exit;
  3210. }
  3211. if (major_brand) {
  3212. gf_isom_set_brand_info(file, major_brand, minor_version);
  3213. needSave = 1;
  3214. }
  3215. for (i=0; i<nb_alt_brand_add; i++) {
  3216. gf_isom_modify_alternate_brand(file, brand_add[i], 1);
  3217. needSave = 1;
  3218. }
  3219. for (i=0; i<nb_alt_brand_rem; i++) {
  3220. gf_isom_modify_alternate_brand(file, brand_add[i], 0);
  3221. needSave = 1;
  3222. }
  3223. if (!encode && !force_new) gf_isom_set_final_name(file, outfile);
  3224. if (needSave) {
  3225. if (outName) {
  3226. fprintf(stdout, "Saving to %s: ", outfile);
  3227. gf_isom_set_final_name(file, outfile);
  3228. } else if (encode || pack_file) {
  3229. fprintf(stdout, "Saving to %s: ", gf_isom_get_filename(file) );
  3230. } else {
  3231. fprintf(stdout, "Saving %s: ", inName);
  3232. }
  3233. if (HintIt && FullInter) fprintf(stdout, "Hinted file - Full Interleaving\n");
  3234. else if (FullInter) fprintf(stdout, "Full Interleaving\n");
  3235. else if (do_flat || !InterleavingTime) fprintf(stdout, "Flat storage\n");
  3236. else fprintf(stdout, "%.3f secs Interleaving%s\n", InterleavingTime, old_interleave ? " - no drift control" : "");
  3237. e = gf_isom_close(file);
  3238. if (!e && !outName && !encode && !force_new && !pack_file) {
  3239. if (remove(inName)) fprintf(stdout, "Error removing file %s\n", inName);
  3240. else if (rename(outfile, inName)) fprintf(stdout, "Error renaming file %s to %s\n", outfile, inName);
  3241. }
  3242. } else {
  3243. gf_isom_delete(file);
  3244. }
  3245. /*close libgpac*/
  3246. gf_sys_close();
  3247. if (e) fprintf(stdout, "Error: %s\n", gf_error_to_string(e));
  3248. return (e!=GF_OK) ? 1 : 0;
  3249. #else
  3250. /*close libgpac*/
  3251. gf_sys_close();
  3252. gf_isom_delete(file);
  3253. fprintf(stdout, "Error: Read-only version of MP4Box.\n");
  3254. return 1;
  3255. #endif
  3256. err_exit:
  3257. /*close libgpac*/
  3258. gf_sys_close();
  3259. if (file) gf_isom_delete(file);
  3260. fprintf(stdout, "\n\tError: %s\n", gf_error_to_string(e));
  3261. return 1;
  3262. }
  3263. int main( int argc, char** argv )
  3264. {
  3265. return mp4boxMain( argc, argv );
  3266. }
  3267. #endif /*GPAC_DISABLE_ISOM*/