You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
2.9KB

  1. #include "mov-internal.h"
  2. #include <assert.h>
  3. #include <errno.h>
  4. #define DIFF(a, b) ((a) > (b) ? ((a) - (b)) : ((b) - (a)))
  5. static int mov_fragment_seek_get_duration(struct mov_t* mov)
  6. {
  7. int i;
  8. struct mov_track_t* track;
  9. track = mov->track_count > 0 ? &mov->tracks[0] : NULL;
  10. if (track && track->frag_capacity < track->frag_count && track->mdhd.timescale)
  11. {
  12. mov_buffer_seek(&mov->io, track->frags[track->frag_count - 1].offset);
  13. mov_reader_root(mov); // moof
  14. track->mdhd.duration = track->samples[track->sample_count - 1].dts - track->samples[0].dts;
  15. mov->mvhd.duration = track->mdhd.duration * mov->mvhd.timescale / track->mdhd.timescale;
  16. // clear samples and seek to the first moof
  17. for (i = 0; i < mov->track_count; i++)
  18. {
  19. mov->tracks[i].sample_count = 0;
  20. mov->tracks[i].sample_offset = 0;
  21. }
  22. track->frag_capacity = 0;
  23. }
  24. return 0;
  25. }
  26. int mov_fragment_seek_read_mfra(struct mov_t* mov)
  27. {
  28. uint64_t pos;
  29. pos = mov_buffer_tell(&mov->io); // for fallback
  30. mov_buffer_seek(&mov->io, -16);
  31. mov_reader_root(mov); // mfro
  32. if (mov->mfro > 0)
  33. {
  34. mov_buffer_seek(&mov->io, -((int64_t)mov->mfro));
  35. mov_reader_root(mov); // mfra
  36. mov_fragment_seek_get_duration(mov); // for get fmp4 duration
  37. }
  38. mov_buffer_seek(&mov->io, pos);
  39. return mov_buffer_error(&mov->io);
  40. }
  41. int mov_fragment_seek(struct mov_t* mov, int64_t* timestamp)
  42. {
  43. int i;
  44. uint64_t clock;
  45. size_t idx, start, end;
  46. struct mov_track_t* track;
  47. struct mov_fragment_t* frag, *prev, *next;
  48. track = mov->track_count > 0 ? &mov->tracks[0] : NULL;
  49. if (!track || track->frag_count < 1)
  50. return -1;
  51. idx = start = 0;
  52. end = track->frag_count;
  53. assert(track->frag_count > 0);
  54. clock = (uint64_t)(*timestamp) * track->mdhd.timescale / 1000; // mvhd timescale
  55. while (start < end)
  56. {
  57. idx = (start + end) / 2;
  58. frag = &track->frags[idx];
  59. if (frag->time > clock)
  60. end = idx;
  61. else if (frag->time < clock)
  62. start = idx + 1;
  63. else
  64. break;
  65. }
  66. frag = &track->frags[idx];
  67. prev = &track->frags[idx > 0 ? idx - 1 : idx];
  68. next = &track->frags[idx + 1 < track->frag_count ? idx + 1 : idx];
  69. if (DIFF(prev->time, clock) < DIFF(frag->time, clock))
  70. frag = prev;
  71. if (DIFF(next->time, clock) < DIFF(frag->time, clock))
  72. frag = next;
  73. *timestamp = frag->time * 1000 / track->mdhd.timescale;
  74. // clear samples and seek
  75. for (i = 0; i < mov->track_count; i++)
  76. {
  77. mov->tracks[i].sample_count = 0;
  78. mov->tracks[i].sample_offset = 0;
  79. }
  80. track->frag_capacity = (uint32_t)idx;
  81. return 0;
  82. }
  83. int mov_fragment_read_next_moof(struct mov_t* mov)
  84. {
  85. int i;
  86. struct mov_track_t* track;
  87. // clear moof samples
  88. for (i = 0; i < mov->track_count; i++)
  89. {
  90. mov->tracks[i].sample_count = 0;
  91. mov->tracks[i].sample_offset = 0;
  92. }
  93. track = mov->track_count > 0 ? &mov->tracks[0] : NULL;
  94. if (track && track->frag_capacity < track->frag_count)
  95. {
  96. mov_buffer_seek(&mov->io, track->frags[track->frag_capacity++].offset);
  97. mov_reader_root(mov); // moof
  98. return 0;
  99. }
  100. return 1; // eof
  101. }