mp4info.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. * The contents of this file are subject to the Mozilla Public
  3. * License Version 1.1 (the "License"); you may not use this file
  4. * except in compliance with the License. You may obtain a copy of
  5. * the License at http://www.mozilla.org/MPL/
  6. *
  7. * Software distributed under the License is distributed on an "AS
  8. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9. * implied. See the License for the specific language governing
  10. * rights and limitations under the License.
  11. *
  12. * The Original Code is MPEG4IP.
  13. *
  14. * The Initial Developer of the Original Code is Cisco Systems Inc.
  15. * Portions created by Cisco Systems Inc. are
  16. * Copyright (C) Cisco Systems Inc. 2001-2002. All Rights Reserved.
  17. *
  18. * Portions created by Ximpo Group Ltd. are
  19. * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Dave Mackie [email protected]
  23. * Bill May [email protected]
  24. * Alix Marchandise-Franquet [email protected]
  25. * Ximpo Group Ltd. [email protected]
  26. */
  27. #include "mp4common.h"
  28. extern "C" char* MP4PrintAudioInfo(
  29. MP4FileHandle mp4File,
  30. MP4TrackId trackId)
  31. {
  32. static const char* mpeg4AudioNames[] =
  33. {
  34. "MPEG-4 AAC main",
  35. "MPEG-4 AAC LC",
  36. "MPEG-4 AAC SSR",
  37. "MPEG-4 AAC LTP",
  38. "MPEG-4 AAC HE",
  39. "MPEG-4 AAC Scalable",
  40. "MPEG-4 TwinVQ",
  41. "MPEG-4 CELP",
  42. "MPEG-4 HVXC",
  43. NULL, NULL,
  44. "MPEG-4 TTSI",
  45. "MPEG-4 Main Synthetic",
  46. "MPEG-4 Wavetable Syn",
  47. "MPEG-4 General MIDI",
  48. "MPEG-4 Algo Syn and Audio FX",
  49. "MPEG-4 ER AAC LC",
  50. NULL,
  51. "MPEG-4 ER AAC LTP",
  52. "MPEG-4 ER AAC Scalable",
  53. "MPEG-4 ER TwinVQ",
  54. "MPEG-4 ER BSAC",
  55. "MPEG-4 ER ACC LD",
  56. "MPEG-4 ER CELP",
  57. "MPEG-4 ER HVXC",
  58. "MPEG-4 ER HILN",
  59. "MPEG-4 ER Parametric",
  60. "MPEG-4 SSC",
  61. "MPEG-4 PS",
  62. "MPEG-4 MPEG Surround",
  63. NULL,
  64. "MPEG-4 Layer-1",
  65. "MPEG-4 Layer-2",
  66. "MPEG-4 Layer-3",
  67. "MPEG-4 DST",
  68. "MPEG-4 Audio Lossless",
  69. "MPEG-4 SLS",
  70. "MPEG-4 SLS non-core",
  71. };
  72. static const u_int8_t mpegAudioTypes[] =
  73. {
  74. MP4_MPEG2_AAC_MAIN_AUDIO_TYPE, // 0x66
  75. MP4_MPEG2_AAC_LC_AUDIO_TYPE, // 0x67
  76. MP4_MPEG2_AAC_SSR_AUDIO_TYPE, // 0x68
  77. MP4_MPEG2_AUDIO_TYPE, // 0x69
  78. MP4_MPEG1_AUDIO_TYPE, // 0x6B
  79. // private types
  80. MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE,
  81. MP4_VORBIS_AUDIO_TYPE,
  82. MP4_ALAW_AUDIO_TYPE,
  83. MP4_ULAW_AUDIO_TYPE,
  84. MP4_G723_AUDIO_TYPE,
  85. MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE,
  86. };
  87. static const char* mpegAudioNames[] =
  88. {
  89. "MPEG-2 AAC Main",
  90. "MPEG-2 AAC LC",
  91. "MPEG-2 AAC SSR",
  92. "MPEG-2 Audio (13818-3)",
  93. "MPEG-1 Audio (11172-3)",
  94. // private types
  95. "PCM16 (little endian)",
  96. "Vorbis",
  97. "G.711 aLaw",
  98. "G.711 uLaw",
  99. "G.723.1",
  100. "PCM16 (big endian)",
  101. };
  102. u_int8_t numMpegAudioTypes =
  103. sizeof(mpegAudioTypes) / sizeof(u_int8_t);
  104. const char* typeName = "Unknown";
  105. bool foundType = false;
  106. u_int8_t type = 0;
  107. const char *media_data_name;
  108. media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
  109. u_int32_t timeScale = 0;
  110. if (media_data_name == NULL)
  111. {
  112. typeName = "Unknown - no media data name";
  113. }
  114. else if (strcasecmp(media_data_name, "samr") == 0)
  115. {
  116. typeName = "AMR";
  117. foundType = true;
  118. }
  119. else if (strcasecmp(media_data_name, "sawb") == 0)
  120. {
  121. typeName = "AMR-WB";
  122. foundType = true;
  123. }
  124. else if (strcasecmp(media_data_name, "mp4a") == 0)
  125. {
  126. type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
  127. switch (type)
  128. {
  129. case MP4_INVALID_AUDIO_TYPE:
  130. typeName = "AAC from .mov";
  131. foundType = true;
  132. break;
  133. case MP4_MPEG4_AUDIO_TYPE:
  134. {
  135. type = MP4GetTrackAudioMpeg4Type(mp4File, trackId);
  136. if (type == MP4_MPEG4_INVALID_AUDIO_TYPE ||
  137. type > NUM_ELEMENTS_IN_ARRAY(mpeg4AudioNames) ||
  138. mpeg4AudioNames[type - 1] == NULL)
  139. {
  140. typeName = "MPEG-4 Unknown Profile";
  141. }
  142. else
  143. {
  144. if (type == 2)
  145. {
  146. u_int8_t* pAacConfig = NULL;
  147. u_int32_t aacConfigLength;
  148. MP4GetTrackESConfiguration(mp4File,
  149. trackId,
  150. &pAacConfig,
  151. &aacConfigLength);
  152. if (aacConfigLength >= 5 && (pAacConfig[4] >> 7) == 1)
  153. {
  154. int samplingRates[]={96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,-1};
  155. type = 5;
  156. int index = (pAacConfig[4] >> 3) & 0x7;
  157. timeScale = samplingRates[index];
  158. }
  159. MP4Free(pAacConfig);
  160. }
  161. typeName = mpeg4AudioNames[type - 1];
  162. foundType = true;
  163. }
  164. break;
  165. }
  166. // fall through
  167. default:
  168. for (u_int8_t i = 0; i < numMpegAudioTypes; i++)
  169. {
  170. if (type == mpegAudioTypes[i])
  171. {
  172. typeName = mpegAudioNames[i];
  173. foundType = true;
  174. break;
  175. }
  176. }
  177. }
  178. }
  179. else
  180. {
  181. typeName = media_data_name;
  182. foundType = true;
  183. }
  184. if (!timeScale)
  185. timeScale = MP4GetTrackTimeScale(mp4File, trackId);
  186. MP4Duration trackDuration =
  187. MP4GetTrackDuration(mp4File, trackId);
  188. double msDuration =
  189. UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId,
  190. trackDuration, MP4_MSECS_TIME_SCALE));
  191. char *sInfo = (char*)MP4Malloc(256);
  192. // type duration avgBitrate samplingFrequency
  193. if (foundType)
  194. snprintf(sInfo, 256,
  195. "%s",
  196. typeName);
  197. else
  198. snprintf(sInfo, 256,
  199. "%s(%u)",
  200. typeName,
  201. type);
  202. return sInfo;
  203. }
  204. static const struct
  205. {
  206. uint8_t profile;
  207. const char *name;
  208. }
  209. VisualProfileToName[] = {
  210. { MPEG4_SP_L1, "MPEG-4 Simple @ L1"},
  211. { MPEG4_SP_L2, "MPEG-4 Simple @ L2" },
  212. { MPEG4_SP_L3, "MPEG-4 Simple @ L3" },
  213. { MPEG4_SP_L0, "MPEG-4 Simple @ L0" },
  214. { MPEG4_SSP_L1, "MPEG-4 Simple Scalable @ L1"},
  215. { MPEG4_SSP_L2, "MPEG-4 Simple Scalable @ L2" },
  216. { MPEG4_CP_L1, "MPEG-4 Core @ L1"},
  217. { MPEG4_CP_L2, "MPEG-4 Core @ L2"},
  218. { MPEG4_MP_L2, "MPEG-4 Main @ L2"},
  219. { MPEG4_MP_L3, "MPEG-4 Main @ L3"},
  220. { MPEG4_MP_L4, "MPEG-4 Main @ L4"},
  221. { MPEG4_NBP_L2, "MPEG-4 N-bit @ L2"},
  222. { MPEG4_STP_L1, "MPEG-4 Scalable Texture @ L1"},
  223. { MPEG4_SFAP_L1, "MPEG-4 Simple Face Anim @ L1"},
  224. { MPEG4_SFAP_L2, "MPEG-4 Simple Face Anim @ L2"},
  225. { MPEG4_SFBAP_L1, "MPEG-4 Simple FBA @ L1"},
  226. { MPEG4_SFBAP_L2, "MPEG-4 Simple FBA @ L2"},
  227. { MPEG4_BATP_L1, "MPEG-4 Basic Anim Text @ L1"},
  228. { MPEG4_BATP_L2, "MPEG-4 Basic Anim Text @ L2"},
  229. { MPEG4_HP_L1, "MPEG-4 Hybrid @ L1"},
  230. { MPEG4_HP_L2, "MPEG-4 Hybrid @ L2"},
  231. { MPEG4_ARTSP_L1, "MPEG-4 Adv RT Simple @ L1"},
  232. { MPEG4_ARTSP_L2, "MPEG-4 Adv RT Simple @ L2"},
  233. { MPEG4_ARTSP_L3, "MPEG-4 Adv RT Simple @ L3"},
  234. { MPEG4_ARTSP_L4, "MPEG-4 Adv RT Simple @ L4"},
  235. { MPEG4_CSP_L1, "MPEG-4 Core Scalable @ L1"},
  236. { MPEG4_CSP_L2, "MPEG-4 Core Scalable @ L2"},
  237. { MPEG4_CSP_L3, "MPEG-4 Core Scalable @ L3"},
  238. { MPEG4_ACEP_L1, "MPEG-4 Adv Coding Efficieny @ L1"},
  239. { MPEG4_ACEP_L2, "MPEG-4 Adv Coding Efficieny @ L2"},
  240. { MPEG4_ACEP_L3, "MPEG-4 Adv Coding Efficieny @ L3"},
  241. { MPEG4_ACEP_L4, "MPEG-4 Adv Coding Efficieny @ L4"},
  242. { MPEG4_ACP_L1, "MPEG-4 Adv Core Profile @ L1"},
  243. { MPEG4_ACP_L2, "MPEG-4 Adv Core Profile @ L2"},
  244. { MPEG4_AST_L1, "MPEG-4 Adv Scalable Texture @ L1"},
  245. { MPEG4_AST_L2, "MPEG-4 Adv Scalable Texture @ L2"},
  246. { MPEG4_AST_L3, "MPEG-4 Adv Scalable Texture @ L3"},
  247. { MPEG4_S_STUDIO_P_L1, "MPEG-4 Simple Studio @ L1"},
  248. { MPEG4_S_STUDIO_P_L2, "MPEG-4 Simple Studio @ L2"},
  249. { MPEG4_S_STUDIO_P_L3, "MPEG-4 Simple Studio @ L3"},
  250. { MPEG4_S_STUDIO_P_L4, "MPEG-4 Simple Studio @ L4"},
  251. { MPEG4_C_STUDIO_P_L1, "MPEG-4 Core Studio @ L1"},
  252. { MPEG4_C_STUDIO_P_L2, "MPEG-4 Core Studio @ L2"},
  253. { MPEG4_C_STUDIO_P_L3, "MPEG-4 Core Studio @ L3"},
  254. { MPEG4_C_STUDIO_P_L4, "MPEG-4 Core Studio @ L4"},
  255. { MPEG4_ASP_L0, "MPEG-4 Adv Simple@L0"},
  256. { MPEG4_ASP_L1, "MPEG-4 Adv Simple@L1"},
  257. { MPEG4_ASP_L2, "MPEG-4 Adv Simple@L2"},
  258. { MPEG4_ASP_L3, "MPEG-4 Adv Simple@L3"},
  259. { MPEG4_ASP_L4, "MPEG-4 Adv Simple@L4"},
  260. { MPEG4_ASP_L5, "MPEG-4 Adv Simple@L5"},
  261. { MPEG4_ASP_L3B, "MPEG-4 Adv Simple@L3b"},
  262. { MPEG4_FGSP_L0, "MPEG-4 FGS @ L0" },
  263. { MPEG4_FGSP_L1, "MPEG-4 FGS @ L1" },
  264. { MPEG4_FGSP_L2, "MPEG-4 FGS @ L2" },
  265. { MPEG4_FGSP_L3, "MPEG-4 FGS @ L3" },
  266. { MPEG4_FGSP_L4, "MPEG-4 FGS @ L4" },
  267. { MPEG4_FGSP_L5, "MPEG-4 FGS @ L5" }
  268. };
  269. static const char *Mpeg4VisualProfileName(uint8_t visual_profile)
  270. {
  271. size_t size = sizeof(VisualProfileToName) / sizeof(*VisualProfileToName);
  272. for (size_t ix = 0; ix < size; ix++)
  273. {
  274. if (visual_profile == VisualProfileToName[ix].profile)
  275. {
  276. return (VisualProfileToName[ix].name);
  277. }
  278. }
  279. return (NULL);
  280. }
  281. extern "C" char* MP4PrintVideoInfo(
  282. MP4FileHandle mp4File,
  283. MP4TrackId trackId)
  284. {
  285. static const u_int8_t mpegVideoTypes[] =
  286. {
  287. MP4_MPEG2_SIMPLE_VIDEO_TYPE, // 0x60
  288. MP4_MPEG2_MAIN_VIDEO_TYPE, // 0x61
  289. MP4_MPEG2_SNR_VIDEO_TYPE, // 0x62
  290. MP4_MPEG2_SPATIAL_VIDEO_TYPE, // 0x63
  291. MP4_MPEG2_HIGH_VIDEO_TYPE, // 0x64
  292. MP4_MPEG2_442_VIDEO_TYPE, // 0x65
  293. MP4_MPEG1_VIDEO_TYPE, // 0x6A
  294. MP4_JPEG_VIDEO_TYPE, // 0x6C
  295. MP4_YUV12_VIDEO_TYPE,
  296. MP4_H263_VIDEO_TYPE,
  297. MP4_H261_VIDEO_TYPE,
  298. };
  299. static const char* mpegVideoNames[] =
  300. {
  301. "MPEG-2 Simple",
  302. "MPEG-2 Main",
  303. "MPEG-2 SNR",
  304. "MPEG-2 Spatial",
  305. "MPEG-2 High",
  306. "MPEG-2 4:2:2",
  307. "MPEG-1",
  308. "JPEG",
  309. "YUV12",
  310. "H.263",
  311. "H.261",
  312. };
  313. u_int8_t numMpegVideoTypes =
  314. sizeof(mpegVideoTypes) / sizeof(u_int8_t);
  315. bool foundTypeName = false;
  316. const char* typeName = "Unknown";
  317. const char *media_data_name;
  318. char originalFormat[8];
  319. char oformatbuffer[32];
  320. originalFormat[0] = 0;
  321. *oformatbuffer = 0;
  322. uint8_t type = 0;
  323. media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
  324. // encv 264b
  325. if (media_data_name && strcasecmp(media_data_name, "encv") == 0)
  326. {
  327. if (MP4GetTrackMediaDataOriginalFormat(mp4File,
  328. trackId,
  329. originalFormat,
  330. sizeof(originalFormat)) == false)
  331. media_data_name = NULL;
  332. }
  333. char typebuffer[80];
  334. if (media_data_name == NULL)
  335. {
  336. typeName = "Unknown - no media data name";
  337. foundTypeName = true;
  338. }
  339. else if ((strcasecmp(media_data_name, "avc1") == 0) ||
  340. (strcasecmp(originalFormat, "264b") == 0))
  341. {
  342. // avc
  343. uint8_t profile, level;
  344. char profileb[20], levelb[20];
  345. if (MP4GetTrackH264ProfileLevel(mp4File, trackId,
  346. &profile, &level))
  347. {
  348. if (profile == 44)
  349. {
  350. strcpy(profileb, "CAVLC 4:4:4");
  351. }
  352. else if (profile == 66)
  353. {
  354. strcpy(profileb, "Baseline");
  355. }
  356. else if (profile == 77)
  357. {
  358. strcpy(profileb, "Main");
  359. }
  360. else if (profile == 88)
  361. {
  362. strcpy(profileb, "Extended");
  363. }
  364. else if (profile == 100)
  365. {
  366. strcpy(profileb, "High");
  367. }
  368. else if (profile == 110)
  369. {
  370. strcpy(profileb, "High 10");
  371. }
  372. else if (profile == 122)
  373. {
  374. strcpy(profileb, "High 4:2:2");
  375. }
  376. else if (profile == 144 || profile == 244)
  377. {
  378. strcpy(profileb, "High 4:4:4");
  379. }
  380. else
  381. {
  382. snprintf(profileb, 20, "Unknown Profile %x", profile);
  383. }
  384. switch (level)
  385. {
  386. case 10: case 20: case 30: case 40: case 50:
  387. snprintf(levelb, 20, "%u", level / 10);
  388. break;
  389. case 11: case 12: case 13:
  390. case 21: case 22:
  391. case 31: case 32:
  392. case 41: case 42:
  393. case 51:
  394. snprintf(levelb, 20, "%u.%u", level / 10, level % 10);
  395. break;
  396. default:
  397. snprintf(levelb, 20, "unknown level %x", level);
  398. break;
  399. }
  400. if (originalFormat != NULL && originalFormat[0] != '\0')
  401. snprintf(oformatbuffer, 32, "(%s) ", originalFormat);
  402. snprintf(typebuffer, sizeof(typebuffer), "H.264 %s%s@%s",
  403. oformatbuffer, profileb, levelb);
  404. typeName = typebuffer;
  405. }
  406. else
  407. {
  408. typeName = "H.264 - profile/level error";
  409. }
  410. foundTypeName = true;
  411. }
  412. else if (strcasecmp(media_data_name, "s263") == 0)
  413. {
  414. // 3gp h.263
  415. typeName = "H.263";
  416. foundTypeName = true;
  417. }
  418. else if ((strcasecmp(media_data_name, "mp4v") == 0) ||
  419. (strcasecmp(media_data_name, "encv") == 0))
  420. {
  421. // note encv might needs it's own field eventually.
  422. type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
  423. if (type == MP4_MPEG4_VIDEO_TYPE)
  424. {
  425. type = MP4GetVideoProfileLevel(mp4File, trackId);
  426. typeName = Mpeg4VisualProfileName(type);
  427. if (typeName == NULL)
  428. {
  429. typeName = "MPEG-4 Unknown Profile";
  430. }
  431. else
  432. {
  433. foundTypeName = true;
  434. }
  435. }
  436. else
  437. {
  438. for (u_int8_t i = 0; i < numMpegVideoTypes; i++)
  439. {
  440. if (type == mpegVideoTypes[i])
  441. {
  442. typeName = mpegVideoNames[i];
  443. foundTypeName = true;
  444. break;
  445. }
  446. }
  447. }
  448. }
  449. else
  450. {
  451. typeName = media_data_name;
  452. foundTypeName = true; // we don't have a type value to display
  453. }
  454. MP4Duration trackDuration =
  455. MP4GetTrackDuration(mp4File, trackId);
  456. double msDuration =
  457. UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId,
  458. trackDuration, MP4_MSECS_TIME_SCALE));
  459. // Note not all mp4 implementations set width and height correctly
  460. // The real answer can be buried inside the ES configuration info
  461. u_int16_t width = MP4GetTrackVideoWidth(mp4File, trackId);
  462. u_int16_t height = MP4GetTrackVideoHeight(mp4File, trackId);
  463. double fps = MP4GetTrackVideoFrameRate(mp4File, trackId);
  464. char *sInfo = (char*)MP4Malloc(256);
  465. // type duration avgBitrate frameSize frameRate
  466. if (foundTypeName)
  467. {
  468. sprintf(sInfo,
  469. "%s",
  470. typeName);
  471. }
  472. else
  473. {
  474. sprintf(sInfo,
  475. "%s(%u)",
  476. typeName,
  477. type);
  478. }
  479. return sInfo;
  480. }
  481. static char* PrintCntlInfo(
  482. MP4FileHandle mp4File,
  483. MP4TrackId trackId)
  484. {
  485. const char *media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
  486. const char *typeName = "Unknown";
  487. if (media_data_name == NULL)
  488. {
  489. typeName = "Unknown - no media data name";
  490. }
  491. else if (strcasecmp(media_data_name, "href") == 0)
  492. {
  493. typeName = "ISMA Href";
  494. }
  495. else
  496. {
  497. typeName = media_data_name;
  498. }
  499. MP4Duration trackDuration =
  500. MP4GetTrackDuration(mp4File, trackId);
  501. double msDuration =
  502. UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId,
  503. trackDuration, MP4_MSECS_TIME_SCALE));
  504. char *sInfo = (char *)MP4Malloc(256);
  505. snprintf(sInfo, 256,
  506. "%u\tcontrol\t%s, %.3f secs\r\n",
  507. trackId,
  508. typeName,
  509. msDuration / 1000.0);
  510. return sInfo;
  511. }
  512. static char* PrintHintInfo(
  513. MP4FileHandle mp4File,
  514. MP4TrackId trackId)
  515. {
  516. MP4TrackId referenceTrackId =
  517. MP4GetHintTrackReferenceTrackId(mp4File, trackId);
  518. char* payloadName = NULL;
  519. if (!MP4GetHintTrackRtpPayload(mp4File, trackId, &payloadName))
  520. return NULL;
  521. char *sInfo = (char*)MP4Malloc(256);
  522. snprintf(sInfo, 256,
  523. "%u\thint\tPayload %s for track %u\r\n",
  524. trackId,
  525. payloadName,
  526. referenceTrackId);
  527. free(payloadName);
  528. return sInfo;
  529. }
  530. #if 0
  531. static char* PrintTrackInfo(
  532. MP4FileHandle mp4File,
  533. MP4TrackId trackId)
  534. {
  535. char* trackInfo = NULL;
  536. const char* trackType =
  537. MP4GetTrackType(mp4File, trackId);
  538. if (trackType == NULL) return NULL;
  539. if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE))
  540. {
  541. trackInfo = PrintAudioInfo(mp4File, trackId);
  542. }
  543. else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE))
  544. {
  545. trackInfo = PrintVideoInfo(mp4File, trackId);
  546. }
  547. else if (!strcmp(trackType, MP4_HINT_TRACK_TYPE))
  548. {
  549. trackInfo = PrintHintInfo(mp4File, trackId);
  550. }
  551. else if (strcmp(trackType, MP4_CNTL_TRACK_TYPE) == 0)
  552. {
  553. trackInfo = PrintCntlInfo(mp4File, trackId);
  554. }
  555. else
  556. {
  557. trackInfo = (char*)MP4Malloc(256);
  558. if (!strcmp(trackType, MP4_OD_TRACK_TYPE))
  559. {
  560. snprintf(trackInfo, 256,
  561. "%u\tod\tObject Descriptors\r\n",
  562. trackId);
  563. }
  564. else if (!strcmp(trackType, MP4_SCENE_TRACK_TYPE))
  565. {
  566. snprintf(trackInfo, 256,
  567. "%u\tscene\tBIFS\r\n",
  568. trackId);
  569. }
  570. else
  571. {
  572. snprintf(trackInfo, 256,
  573. "%u\t%s\r\n",
  574. trackId, trackType);
  575. }
  576. }
  577. return trackInfo;
  578. }
  579. extern "C" char* MP4Info(
  580. MP4FileHandle mp4File,
  581. MP4TrackId trackId)
  582. {
  583. char* info = NULL;
  584. if (MP4_IS_VALID_FILE_HANDLE(mp4File))
  585. {
  586. try
  587. {
  588. if (trackId == MP4_INVALID_TRACK_ID)
  589. {
  590. uint buflen = 4 * 1024;
  591. info = (char*)MP4Calloc(buflen);
  592. buflen -= snprintf(info, buflen,
  593. "Track\tType\tInfo\r\n");
  594. u_int32_t numTracks = MP4GetNumberOfTracks(mp4File);
  595. for (u_int32_t i = 0; i < numTracks; i++)
  596. {
  597. trackId = MP4FindTrackId(mp4File, i);
  598. char* trackInfo = PrintTrackInfo(mp4File, trackId);
  599. strncat(info, trackInfo, buflen);
  600. uint newlen = strlen(trackInfo);
  601. if (newlen > buflen) buflen = 0;
  602. else buflen -= newlen;
  603. MP4Free(trackInfo);
  604. }
  605. }
  606. else
  607. {
  608. info = PrintTrackInfo(mp4File, trackId);
  609. }
  610. }
  611. catch (MP4Error* e)
  612. {
  613. delete e;
  614. }
  615. }
  616. return info;
  617. }
  618. extern "C" char* MP4FileInfo(
  619. const MP4_FILENAME_CHAR* fileName,
  620. MP4TrackId trackId)
  621. {
  622. MP4FileHandle mp4File =
  623. MP4Read(fileName);
  624. if (!mp4File)
  625. {
  626. return NULL;
  627. }
  628. char* info = MP4Info(mp4File, trackId);
  629. MP4Close(mp4File);
  630. return info; // caller should free this
  631. }
  632. #endif