選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

686 行
20KB

  1. #include "mov-reader.h"
  2. #include "mov-internal.h"
  3. #include <errno.h>
  4. #include <stdio.h>
  5. #include <stdint.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #define MOV_NULL MOV_TAG(0, 0, 0, 0)
  10. #define AV_TRACK_TIMEBASE 1000
  11. //#define MOV_READER_BOX_TREE 1
  12. //#define MOV_READER_FMP4_FAST 1
  13. #define MOV_READER_FLAG_FMP4_FAST 0x01
  14. struct mov_reader_t
  15. {
  16. int flags;
  17. int have_read_mfra;
  18. struct mov_t mov;
  19. };
  20. #define MOV_READER_FROM_MOV(ptr) ((struct mov_reader_t*)((char*)(ptr)-(ptrdiff_t)(&((struct mov_reader_t*)0)->mov)))
  21. struct mov_parse_t
  22. {
  23. uint32_t type;
  24. uint32_t parent;
  25. int(*parse)(struct mov_t* mov, const struct mov_box_t* box);
  26. };
  27. static int mov_stss_seek(struct mov_track_t* track, int64_t *timestamp);
  28. static int mov_sample_seek(struct mov_track_t* track, int64_t timestamp);
  29. // 8.1.1 Media Data Box (p28)
  30. static int mov_read_mdat(struct mov_t* mov, const struct mov_box_t* box)
  31. {
  32. mov_buffer_skip(&mov->io, box->size);
  33. return mov_buffer_error(&mov->io);
  34. }
  35. // 8.1.2 Free Space Box (p28)
  36. static int mov_read_free(struct mov_t* mov, const struct mov_box_t* box)
  37. {
  38. // Container: File or other box
  39. mov_buffer_skip(&mov->io, box->size);
  40. return mov_buffer_error(&mov->io);
  41. }
  42. //static struct mov_sample_entry_t* mov_track_stsd_find(struct mov_track_t* track, uint32_t sample_description_index)
  43. //{
  44. // if (sample_description_index > 0 && sample_description_index <= track->stsd.entry_count)
  45. // return &track->stsd.entries[sample_description_index-1];
  46. // return NULL;
  47. //}
  48. static int mov_index_build(struct mov_track_t* track)
  49. {
  50. void* p;
  51. uint32_t i, j;
  52. struct mov_stbl_t* stbl = &track->stbl;
  53. if (stbl->stss_count > 0 || MOV_VIDEO != track->handler_type)
  54. return 0;
  55. for (i = 0; i < track->sample_count; i++)
  56. {
  57. if (track->samples[i].flags & MOV_AV_FLAG_KEYFREAME)
  58. ++stbl->stss_count;
  59. }
  60. p = realloc(stbl->stss, sizeof(stbl->stss[0]) * stbl->stss_count);
  61. if (!p) return -ENOMEM;
  62. stbl->stss = p;
  63. for (j = i = 0; i < track->sample_count && j < stbl->stss_count; i++)
  64. {
  65. if (track->samples[i].flags & MOV_AV_FLAG_KEYFREAME)
  66. stbl->stss[j++] = i + 1; // uint32_t sample_number, start from 1
  67. }
  68. assert(j == stbl->stss_count);
  69. return 0;
  70. }
  71. // 8.3.1 Track Box (p31)
  72. // Box Type : 'trak'
  73. // Container : Movie Box('moov')
  74. // Mandatory : Yes
  75. // Quantity : One or more
  76. static int mov_read_trak(struct mov_t* mov, const struct mov_box_t* box)
  77. {
  78. int r;
  79. mov->track = NULL;
  80. r = mov_reader_box(mov, box);
  81. if (0 == r)
  82. {
  83. mov->track->tfdt_dts = 0;
  84. if (mov->track->sample_count > 0)
  85. {
  86. mov_apply_stco(mov->track);
  87. mov_apply_elst(mov->track);
  88. mov_apply_stts(mov->track);
  89. mov_apply_ctts(mov->track);
  90. mov_apply_stss(mov->track);
  91. mov->track->tfdt_dts = mov->track->samples[mov->track->sample_count - 1].dts;
  92. }
  93. }
  94. return r;
  95. }
  96. static int mov_read_dref(struct mov_t* mov, const struct mov_box_t* box)
  97. {
  98. uint32_t i, entry_count;
  99. mov_buffer_r8(&mov->io); /* version */
  100. mov_buffer_r24(&mov->io); /* flags */
  101. entry_count = mov_buffer_r32(&mov->io);
  102. for (i = 0; i < entry_count; i++)
  103. {
  104. uint32_t size = mov_buffer_r32(&mov->io);
  105. /*uint32_t type = */mov_buffer_r32(&mov->io);
  106. /*uint32_t vern = */mov_buffer_r32(&mov->io); /* version + flags */
  107. mov_buffer_skip(&mov->io, size-12);
  108. }
  109. (void)box;
  110. return 0;
  111. }
  112. static int mov_read_btrt(struct mov_t* mov, const struct mov_box_t* box)
  113. {
  114. // ISO/IEC 14496-15:2010(E)
  115. // 5.3.4 AVC Video Stream Definition (p19)
  116. mov_buffer_r32(&mov->io); /* bufferSizeDB */
  117. mov_buffer_r32(&mov->io); /* maxBitrate */
  118. mov_buffer_r32(&mov->io); /* avgBitrate */
  119. (void)box;
  120. return 0;
  121. }
  122. static int mov_read_uuid(struct mov_t* mov, const struct mov_box_t* box)
  123. {
  124. uint8_t usertype[16] = { 0 };
  125. if(box->size > 16)
  126. {
  127. mov_buffer_read(&mov->io, usertype, sizeof(usertype));
  128. mov_buffer_skip(&mov->io, box->size - 16);
  129. }
  130. return mov_buffer_error(&mov->io);
  131. }
  132. static int mov_read_moof(struct mov_t* mov, const struct mov_box_t* box)
  133. {
  134. // 8.8.7 Track Fragment Header Box (p71)
  135. // If base-data-offset-present not provided and if the default-base-is-moof flag is not set,
  136. // the base-data-offset for the first track in the movie fragment is the position of
  137. // the first byte of the enclosing Movie Fragment Box, for second and subsequent track fragments,
  138. // the default is the end of the data defined by the preceding track fragment.
  139. mov->moof_offset = mov->implicit_offset = mov_buffer_tell(&mov->io) - 8 /*box size */;
  140. return mov_reader_box(mov, box);
  141. }
  142. static int mov_read_mfra(struct mov_t* mov, const struct mov_box_t* box)
  143. {
  144. int r;
  145. struct mov_reader_t* reader;
  146. reader = MOV_READER_FROM_MOV(mov);
  147. r = mov_reader_box(mov, box);
  148. reader->have_read_mfra = 1;
  149. return r;
  150. }
  151. // 8.8.11 Movie Fragment Random Access Offset Box (p75)
  152. static int mov_read_mfro(struct mov_t* mov, const struct mov_box_t* box)
  153. {
  154. (void)box;
  155. mov_buffer_r32(&mov->io); /* version & flags */
  156. mov->mfro = mov_buffer_r32(&mov->io); /* size */
  157. return mov_buffer_error(&mov->io);
  158. }
  159. int mov_reader_root(struct mov_t* mov)
  160. {
  161. struct mov_box_t box;
  162. box.type = MOV_ROOT;
  163. box.size = UINT64_MAX;
  164. #if defined(DEBUG) || defined(_DEBUG)
  165. box.level = 0;
  166. #endif
  167. return mov_reader_box(mov, &box);
  168. }
  169. static int mov_read_default(struct mov_t* mov, const struct mov_box_t* box)
  170. {
  171. return mov_reader_box(mov, box);
  172. }
  173. static struct mov_parse_t s_mov_parse_table[] = {
  174. { MOV_TAG('a', 'v', '1', 'C'), MOV_NULL, mov_read_av1c }, // av1-isobmff
  175. { MOV_TAG('a', 'v', 'c', 'C'), MOV_NULL, mov_read_avcc }, // ISO/IEC 14496-15:2010(E) avcC
  176. { MOV_TAG('b', 't', 'r', 't'), MOV_NULL, mov_read_btrt }, // ISO/IEC 14496-15:2010(E) 5.3.4.1.1 Definition
  177. { MOV_TAG('c', 'o', '6', '4'), MOV_STBL, mov_read_stco },
  178. { MOV_TAG('C', 'o', 'L', 'L'), MOV_STBL, mov_read_coll },
  179. { MOV_TAG('c', 't', 't', 's'), MOV_STBL, mov_read_ctts },
  180. { MOV_TAG('c', 's', 'l', 'g'), MOV_STBL, mov_read_cslg },
  181. { MOV_TAG('d', 'i', 'n', 'f'), MOV_MINF, mov_read_default },
  182. { MOV_TAG('d', 'O', 'p', 's'), MOV_NULL, mov_read_dops },
  183. { MOV_TAG('d', 'r', 'e', 'f'), MOV_DINF, mov_read_dref },
  184. { MOV_TAG('e', 'd', 't', 's'), MOV_TRAK, mov_read_default },
  185. { MOV_TAG('e', 'l', 's', 't'), MOV_EDTS, mov_read_elst },
  186. { MOV_TAG('e', 's', 'd', 's'), MOV_NULL, mov_read_esds }, // ISO/IEC 14496-14:2003(E) mp4a/mp4v/mp4s
  187. { MOV_TAG('f', 'r', 'e', 'e'), MOV_NULL, mov_read_free },
  188. { MOV_TAG('f', 't', 'y', 'p'), MOV_ROOT, mov_read_ftyp },
  189. { MOV_TAG('g', 'm', 'i', 'n'), MOV_GMHD, mov_read_gmin }, // Apple QuickTime gmin
  190. { MOV_TAG('g', 'm', 'h', 'd'), MOV_MINF, mov_read_default }, // Apple QuickTime gmhd
  191. { MOV_TAG('h', 'd', 'l', 'r'), MOV_MDIA, mov_read_hdlr }, // Apple QuickTime minf also has hdlr
  192. { MOV_TAG('h', 'v', 'c', 'C'), MOV_NULL, mov_read_hvcc }, // ISO/IEC 14496-15:2014 hvcC
  193. { MOV_TAG('l', 'e', 'v', 'a'), MOV_MVEX, mov_read_leva },
  194. { MOV_TAG('m', 'd', 'a', 't'), MOV_ROOT, mov_read_mdat },
  195. { MOV_TAG('m', 'd', 'h', 'd'), MOV_MDIA, mov_read_mdhd },
  196. { MOV_TAG('m', 'd', 'i', 'a'), MOV_TRAK, mov_read_default },
  197. { MOV_TAG('m', 'e', 'h', 'd'), MOV_MVEX, mov_read_mehd },
  198. { MOV_TAG('m', 'f', 'h', 'd'), MOV_MOOF, mov_read_mfhd },
  199. { MOV_TAG('m', 'f', 'r', 'a'), MOV_ROOT, mov_read_mfra },
  200. { MOV_TAG('m', 'f', 'r', 'o'), MOV_MFRA, mov_read_mfro },
  201. { MOV_TAG('m', 'i', 'n', 'f'), MOV_MDIA, mov_read_default },
  202. { MOV_TAG('m', 'o', 'o', 'v'), MOV_ROOT, mov_read_default },
  203. { MOV_TAG('m', 'o', 'o', 'f'), MOV_ROOT, mov_read_moof },
  204. { MOV_TAG('m', 'v', 'e', 'x'), MOV_MOOV, mov_read_default },
  205. { MOV_TAG('m', 'v', 'h', 'd'), MOV_MOOV, mov_read_mvhd },
  206. { MOV_TAG('n', 'm', 'h', 'd'), MOV_MINF, mov_read_nmhd }, // ISO/IEC 14496-12:2015(E) 8.4.5.2 Null Media Header Box (p45)
  207. { MOV_TAG('p', 'a', 's', 'p'), MOV_NULL, mov_read_pasp },
  208. { MOV_TAG('s', 'i', 'd', 'x'), MOV_ROOT, mov_read_sidx },
  209. { MOV_TAG('s', 'k', 'i', 'p'), MOV_NULL, mov_read_free },
  210. { MOV_TAG('S', 'm', 'D', 'm'), MOV_MINF, mov_read_smdm },
  211. { MOV_TAG('s', 'm', 'h', 'd'), MOV_MINF, mov_read_smhd },
  212. { MOV_TAG('s', 't', 'b', 'l'), MOV_MINF, mov_read_default },
  213. { MOV_TAG('s', 't', 'c', 'o'), MOV_STBL, mov_read_stco },
  214. // { MOV_TAG('s', 't', 'h', 'd'), MOV_MINF, mov_read_default }, // ISO/IEC 14496-12:2015(E) 12.6.2 Subtitle media header (p185)
  215. { MOV_TAG('s', 't', 's', 'c'), MOV_STBL, mov_read_stsc },
  216. { MOV_TAG('s', 't', 's', 'd'), MOV_STBL, mov_read_stsd },
  217. { MOV_TAG('s', 't', 's', 's'), MOV_STBL, mov_read_stss },
  218. { MOV_TAG('s', 't', 's', 'z'), MOV_STBL, mov_read_stsz },
  219. { MOV_TAG('s', 't', 't', 's'), MOV_STBL, mov_read_stts },
  220. { MOV_TAG('s', 't', 'z', '2'), MOV_STBL, mov_read_stz2 },
  221. { MOV_TAG('t', 'e', 'x', 't'), MOV_GMHD, mov_read_text },
  222. { MOV_TAG('t', 'f', 'd', 't'), MOV_TRAF, mov_read_tfdt },
  223. { MOV_TAG('t', 'f', 'h', 'd'), MOV_TRAF, mov_read_tfhd },
  224. { MOV_TAG('t', 'f', 'r', 'a'), MOV_MFRA, mov_read_tfra },
  225. { MOV_TAG('t', 'k', 'h', 'd'), MOV_TRAK, mov_read_tkhd },
  226. { MOV_TAG('t', 'r', 'a', 'k'), MOV_MOOV, mov_read_trak },
  227. { MOV_TAG('t', 'r', 'e', 'x'), MOV_MVEX, mov_read_trex },
  228. { MOV_TAG('t', 'r', 'a', 'f'), MOV_MOOF, mov_read_default },
  229. { MOV_TAG('t', 'r', 'u', 'n'), MOV_TRAF, mov_read_trun },
  230. { MOV_TAG('u', 'd', 't', 'a'), MOV_MOOV, mov_read_udta },
  231. { MOV_TAG('u', 'u', 'i', 'd'), MOV_NULL, mov_read_uuid },
  232. { MOV_TAG('v', 'm', 'h', 'd'), MOV_MINF, mov_read_vmhd },
  233. { MOV_TAG('v', 'p', 'c', 'C'), MOV_NULL, mov_read_vpcc },
  234. { 0, 0, NULL } // last
  235. };
  236. int mov_reader_box(struct mov_t* mov, const struct mov_box_t* parent)
  237. {
  238. int i;
  239. uint64_t bytes = 0;
  240. struct mov_box_t box;
  241. struct mov_reader_t* reader;
  242. int (*parse)(struct mov_t* mov, const struct mov_box_t* box);
  243. reader = MOV_READER_FROM_MOV(mov);
  244. while (bytes + 8 < parent->size && 0 == mov_buffer_error(&mov->io))
  245. {
  246. uint64_t n = 8;
  247. box.size = mov_buffer_r32(&mov->io);
  248. box.type = mov_buffer_r32(&mov->io);
  249. #if defined(MOV_READER_BOX_TREE) && !defined(NDEBUG)
  250. box.level = parent->level + 1;
  251. for (i = 0; i < parent->level; i++)
  252. printf("\t");
  253. printf("%c%c%c%c, size: %d\n", (char)(box.type >> 24), (char)(box.type >> 16), (char)(box.type >> 8), (char)box.type, (int)box.size);
  254. #endif
  255. if (1 == box.size)
  256. {
  257. // unsigned int(64) large size
  258. box.size = mov_buffer_r64(&mov->io);
  259. n += 8;
  260. }
  261. else if (0 == box.size)
  262. {
  263. if (0 == box.type)
  264. return 0; // all done
  265. box.size = UINT64_MAX;
  266. }
  267. if (UINT64_MAX == box.size)
  268. {
  269. bytes = parent->size;
  270. }
  271. else
  272. {
  273. bytes += box.size;
  274. box.size -= n;
  275. }
  276. if (bytes > parent->size)
  277. return -1;
  278. for (i = 0, parse = NULL; s_mov_parse_table[i].type && !parse; i++)
  279. {
  280. if (s_mov_parse_table[i].type == box.type)
  281. {
  282. // Apple QuickTime minf also has hdlr
  283. if(!s_mov_parse_table[i].parent || MOV_ROOT == parent->type || s_mov_parse_table[i].parent == parent->type)
  284. parse = s_mov_parse_table[i].parse;
  285. }
  286. }
  287. if (NULL == parse)
  288. {
  289. mov_buffer_skip(&mov->io, box.size);
  290. }
  291. else
  292. {
  293. int r;
  294. uint64_t pos, pos2;
  295. pos = mov_buffer_tell(&mov->io);
  296. r = parse(mov, &box);
  297. assert(0 == r || mov_buffer_error(&mov->io));
  298. if (0 != r) return r;
  299. pos2 = mov_buffer_tell(&mov->io);
  300. assert(pos2 - pos == box.size);
  301. mov_buffer_skip(&mov->io, box.size - (pos2 - pos));
  302. }
  303. // fmp4: read one-fragment only
  304. if ((reader->flags & MOV_READER_FLAG_FMP4_FAST) && MOV_TAG('m', 'o', 'o', 'f') == box.type)
  305. {
  306. if (!reader->have_read_mfra)
  307. {
  308. mov_fragment_seek_read_mfra(mov);
  309. reader->have_read_mfra = 1; // force, seek once only
  310. }
  311. // skip fast mode, fallback to read all
  312. if(mov->mfro > 0)
  313. break;
  314. }
  315. }
  316. return mov_buffer_error(&mov->io) ? -1 : 0;
  317. }
  318. static int mov_reader_init(struct mov_reader_t* reader)
  319. {
  320. int i, r;
  321. struct mov_t* mov;
  322. struct mov_track_t* track;
  323. mov = &reader->mov;
  324. r = mov_reader_root(mov);
  325. if (0 != r) { /*return r;*/ } // ignore file read error(for streaming file)
  326. for (i = 0; i < mov->track_count; i++)
  327. {
  328. track = mov->tracks + i;
  329. mov_index_build(track);
  330. //track->sample_offset = 0; // reset
  331. // fragment mp4
  332. if (0 == track->mdhd.duration && track->sample_count > 0)
  333. track->mdhd.duration = track->samples[track->sample_count - 1].dts - track->samples[0].dts;
  334. if (0 == track->tkhd.duration)
  335. track->tkhd.duration = track->mdhd.duration * mov->mvhd.timescale / track->mdhd.timescale;
  336. if (track->tkhd.duration > mov->mvhd.duration)
  337. mov->mvhd.duration = track->tkhd.duration; // maximum track duration
  338. }
  339. return 0;
  340. }
  341. struct mov_reader_t* mov_reader_create(const struct mov_buffer_t* buffer, void* param)
  342. {
  343. struct mov_reader_t* reader;
  344. reader = (struct mov_reader_t*)calloc(1, sizeof(*reader));
  345. if (NULL == reader)
  346. return NULL;
  347. #if defined(MOV_READER_FMP4_FAST)
  348. reader->flags |= MOV_READER_FLAG_FMP4_FAST;
  349. #endif
  350. // ISO/IEC 14496-12:2012(E) 4.3.1 Definition (p17)
  351. // Files with no file-type box should be read as if they contained an FTYP box
  352. // with Major_brand='mp41', minor_version=0, and the single compatible brand 'mp41'.
  353. reader->mov.ftyp.major_brand = MOV_BRAND_MP41;
  354. reader->mov.ftyp.minor_version = 0;
  355. reader->mov.ftyp.brands_count = 0;
  356. reader->mov.header = 0;
  357. reader->mov.io.param = param;
  358. memcpy(&reader->mov.io.io, buffer, sizeof(reader->mov.io.io));
  359. if (0 != mov_reader_init(reader))
  360. {
  361. mov_reader_destroy(reader);
  362. return NULL;
  363. }
  364. return reader;
  365. }
  366. void mov_reader_destroy(struct mov_reader_t* reader)
  367. {
  368. int i;
  369. for (i = 0; i < reader->mov.track_count; i++)
  370. mov_free_track(reader->mov.tracks + i);
  371. if (reader->mov.tracks)
  372. free(reader->mov.tracks);
  373. free(reader);
  374. }
  375. static struct mov_track_t* mov_reader_next(struct mov_reader_t* reader)
  376. {
  377. int i;
  378. int64_t dts, best_dts = 0;
  379. struct mov_track_t* track = NULL;
  380. struct mov_track_t* track2;
  381. for (i = 0; i < reader->mov.track_count; i++)
  382. {
  383. track2 = &reader->mov.tracks[i];
  384. assert(track2->sample_offset <= track2->sample_count);
  385. if (track2->sample_offset >= track2->sample_count)
  386. continue;
  387. dts = track2->samples[track2->sample_offset].dts * 1000 / track2->mdhd.timescale;
  388. //if (NULL == track || dts < best_dts)
  389. //if (NULL == track || track->samples[track->sample_offset].offset > track2->samples[track2->sample_offset].offset)
  390. if (NULL == track || (dts < best_dts && best_dts - dts > AV_TRACK_TIMEBASE) || track2->samples[track2->sample_offset].offset < track->samples[track->sample_offset].offset)
  391. {
  392. track = track2;
  393. best_dts = dts;
  394. }
  395. }
  396. return track;
  397. }
  398. int mov_reader_read2(struct mov_reader_t* reader, mov_reader_onread2 onread, void* param)
  399. {
  400. void* ptr;
  401. struct mov_track_t* track;
  402. struct mov_sample_t* sample;
  403. FMP4_NEXT_FRAGMENT:
  404. track = mov_reader_next(reader);
  405. if (NULL == track || 0 == track->mdhd.timescale)
  406. {
  407. if ((MOV_READER_FLAG_FMP4_FAST & reader->flags) && reader->have_read_mfra
  408. && 0 == mov_fragment_read_next_moof(&reader->mov))
  409. {
  410. goto FMP4_NEXT_FRAGMENT;
  411. }
  412. return 0; // EOF
  413. }
  414. assert(track->sample_offset < track->sample_count);
  415. sample = &track->samples[track->sample_offset];
  416. assert(sample->sample_description_index > 0);
  417. ptr = onread(param, track->tkhd.track_ID, /*sample->sample_description_index-1,*/ sample->bytes, sample->pts * 1000 / track->mdhd.timescale, sample->dts * 1000 / track->mdhd.timescale, sample->flags);
  418. if(!ptr)
  419. return -ENOMEM;
  420. mov_buffer_seek(&reader->mov.io, sample->offset);
  421. mov_buffer_read(&reader->mov.io, ptr, sample->bytes);
  422. if (mov_buffer_error(&reader->mov.io))
  423. {
  424. // TODO: user free buffer
  425. return mov_buffer_error(&reader->mov.io);
  426. }
  427. track->sample_offset++; //mark as read
  428. return 1;
  429. }
  430. static void* mov_reader_read_helper(void* param, uint32_t track, size_t bytes, int64_t pts, int64_t dts, int flags)
  431. {
  432. struct mov_sample_t* sample;
  433. sample = (struct mov_sample_t*)param;
  434. if (sample->bytes < bytes)
  435. return NULL;
  436. sample->pts = pts;
  437. sample->dts = dts;
  438. sample->flags = flags;
  439. sample->bytes = (uint32_t)bytes;
  440. sample->sample_description_index = track;
  441. return sample->data;
  442. }
  443. int mov_reader_read(struct mov_reader_t* reader, void* buffer, size_t bytes, mov_reader_onread onread, void* param)
  444. {
  445. int r;
  446. struct mov_sample_t sample; // temp
  447. //memset(&sample, 0, sizeof(sample));
  448. sample.data = buffer;
  449. sample.bytes = (uint32_t)bytes;
  450. r = mov_reader_read2(reader, mov_reader_read_helper, &sample);
  451. if (r <= 0)
  452. return r;
  453. onread(param, sample.sample_description_index, buffer, sample.bytes, sample.pts, sample.dts, sample.flags);
  454. return 1;
  455. }
  456. int mov_reader_seek(struct mov_reader_t* reader, int64_t* timestamp)
  457. {
  458. int i;
  459. struct mov_track_t* track;
  460. if (reader->have_read_mfra && (MOV_READER_FLAG_FMP4_FAST & reader->flags)
  461. && reader->mov.track_count > 0 && reader->mov.tracks[0].frag_count > 0)
  462. return mov_fragment_seek(&reader->mov, timestamp);
  463. // seek video track(s)
  464. for (i = 0; i < reader->mov.track_count; i++)
  465. {
  466. track = &reader->mov.tracks[i];
  467. if (MOV_VIDEO == track->handler_type && track->stbl.stss_count > 0)
  468. {
  469. if (0 != mov_stss_seek(track, timestamp))
  470. return -1;
  471. }
  472. }
  473. // seek other track(s)
  474. for (i = 0; i < reader->mov.track_count; i++)
  475. {
  476. track = &reader->mov.tracks[i];
  477. if (MOV_VIDEO == track->handler_type && track->stbl.stss_count > 0)
  478. continue; // seek done
  479. mov_sample_seek(track, *timestamp);
  480. }
  481. return 0;
  482. }
  483. int mov_reader_getinfo(struct mov_reader_t* reader, struct mov_reader_trackinfo_t *ontrack, void* param)
  484. {
  485. int i;
  486. uint32_t j;
  487. struct mov_track_t* track;
  488. struct mov_sample_entry_t* entry;
  489. for (i = 0; i < reader->mov.track_count; i++)
  490. {
  491. track = &reader->mov.tracks[i];
  492. for (j = 0; j < track->stsd.entry_count && j < 1 /* only the first */; j++)
  493. {
  494. entry = &track->stsd.entries[j];
  495. switch (track->handler_type)
  496. {
  497. case MOV_VIDEO:
  498. if(ontrack->onvideo) ontrack->onvideo(param, track->tkhd.track_ID, entry->object_type_indication, entry->u.visual.width, entry->u.visual.height, entry->extra_data, entry->extra_data_size);
  499. break;
  500. case MOV_AUDIO:
  501. if (ontrack->onaudio) ontrack->onaudio(param, track->tkhd.track_ID, entry->object_type_indication, entry->u.audio.channelcount, entry->u.audio.samplesize, entry->u.audio.samplerate >> 16, entry->extra_data, entry->extra_data_size);
  502. break;
  503. case MOV_SUBT:
  504. case MOV_TEXT:
  505. case MOV_SBTL:
  506. if (ontrack->onsubtitle) ontrack->onsubtitle(param, track->tkhd.track_ID, entry->object_type_indication, entry->extra_data, entry->extra_data_size);
  507. break;
  508. default:
  509. break;
  510. }
  511. }
  512. }
  513. return 0;
  514. }
  515. uint64_t mov_reader_getduration(struct mov_reader_t* reader)
  516. {
  517. return 0 != reader->mov.mvhd.timescale ? reader->mov.mvhd.duration * 1000 / reader->mov.mvhd.timescale : 0;
  518. }
  519. #define DIFF(a, b) ((a) > (b) ? ((a) - (b)) : ((b) - (a)))
  520. static int mov_stss_seek(struct mov_track_t* track, int64_t *timestamp)
  521. {
  522. int64_t clock;
  523. size_t start, end, mid;
  524. size_t idx, prev, next;
  525. struct mov_sample_t* sample;
  526. idx = mid = start = 0;
  527. end = track->stbl.stss_count;
  528. assert(track->stbl.stss_count > 0);
  529. clock = *timestamp * track->mdhd.timescale / 1000; // mvhd timescale
  530. while (start < end)
  531. {
  532. mid = (start + end) / 2;
  533. idx = track->stbl.stss[mid];
  534. if (idx < 1 || idx > track->sample_count)
  535. {
  536. // start from 1
  537. assert(0);
  538. return -1;
  539. }
  540. idx -= 1;
  541. sample = &track->samples[idx];
  542. if (sample->dts > clock)
  543. end = mid;
  544. else if (sample->dts < clock)
  545. start = mid + 1;
  546. else
  547. break;
  548. }
  549. prev = track->stbl.stss[mid > 0 ? mid - 1 : mid] - 1;
  550. next = track->stbl.stss[mid + 1 < track->stbl.stss_count ? mid + 1 : mid] - 1;
  551. if (DIFF(track->samples[prev].dts, clock) < DIFF(track->samples[idx].dts, clock))
  552. idx = prev;
  553. if (DIFF(track->samples[next].dts, clock) < DIFF(track->samples[idx].dts, clock))
  554. idx = next;
  555. *timestamp = track->samples[idx].dts * 1000 / track->mdhd.timescale;
  556. track->sample_offset = idx;
  557. return 0;
  558. }
  559. static int mov_sample_seek(struct mov_track_t* track, int64_t timestamp)
  560. {
  561. size_t prev, next;
  562. size_t start, end, mid;
  563. struct mov_sample_t* sample;
  564. if (track->sample_count < 1)
  565. return -1;
  566. sample = NULL;
  567. mid = start = 0;
  568. end = track->sample_count;
  569. timestamp = timestamp * track->mdhd.timescale / 1000; // mvhd timecale
  570. while (start < end)
  571. {
  572. mid = (start + end) / 2;
  573. sample = track->samples + mid;
  574. if (sample->dts > timestamp)
  575. end = mid;
  576. else if (sample->dts < timestamp)
  577. start = mid + 1;
  578. else
  579. break;
  580. }
  581. prev = mid > 0 ? mid - 1 : mid;
  582. next = mid + 1 < track->sample_count ? mid + 1 : mid;
  583. if (DIFF(track->samples[prev].dts, timestamp) < DIFF(track->samples[mid].dts, timestamp))
  584. mid = prev;
  585. if (DIFF(track->samples[next].dts, timestamp) < DIFF(track->samples[mid].dts, timestamp))
  586. mid = next;
  587. track->sample_offset = mid;
  588. return 0;
  589. }