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.

175 lines
4.7KB

  1. #include "mov-internal.h"
  2. #include <errno.h>
  3. #include <stdlib.h>
  4. #include <assert.h>
  5. // 8.7.5 Chunk Offset Box (p58)
  6. /*
  7. aligned(8) class ChunkOffsetBox extends FullBox('stco', version = 0, 0) {
  8. unsigned int(32) entry_count;
  9. for (i=1; i <= entry_count; i++) {
  10. unsigned int(32) chunk_offset;
  11. }
  12. }
  13. aligned(8) class ChunkLargeOffsetBox extends FullBox('co64', version = 0, 0) {
  14. unsigned int(32) entry_count;
  15. for (i=1; i <= entry_count; i++) {
  16. unsigned int(64) chunk_offset;
  17. }
  18. }
  19. */
  20. int mov_read_stco(struct mov_t* mov, const struct mov_box_t* box)
  21. {
  22. uint32_t i, entry_count;
  23. struct mov_stbl_t* stbl = &mov->track->stbl;
  24. mov_buffer_r8(&mov->io); /* version */
  25. mov_buffer_r24(&mov->io); /* flags */
  26. entry_count = mov_buffer_r32(&mov->io);
  27. assert(0 == stbl->stco_count && NULL == stbl->stco);
  28. if (stbl->stco_count < entry_count)
  29. {
  30. void* p = realloc(stbl->stco, sizeof(stbl->stco[0]) * entry_count);
  31. if (NULL == p) return -ENOMEM;
  32. stbl->stco = p;
  33. }
  34. stbl->stco_count = entry_count;
  35. if (MOV_TAG('s', 't', 'c', 'o') == box->type)
  36. {
  37. for (i = 0; i < entry_count; i++)
  38. stbl->stco[i] = mov_buffer_r32(&mov->io); // chunk_offset
  39. }
  40. else if (MOV_TAG('c', 'o', '6', '4') == box->type)
  41. {
  42. for (i = 0; i < entry_count; i++)
  43. stbl->stco[i] = mov_buffer_r64(&mov->io); // chunk_offset
  44. }
  45. else
  46. {
  47. i = 0;
  48. assert(0);
  49. }
  50. stbl->stco_count = i;
  51. return mov_buffer_error(&mov->io);
  52. }
  53. size_t mov_write_stco(const struct mov_t* mov, uint32_t count)
  54. {
  55. int co64;
  56. uint32_t size, i;
  57. const struct mov_sample_t* sample;
  58. const struct mov_track_t* track = mov->track;
  59. sample = track->sample_count > 0 ? &track->samples[track->sample_count - 1] : NULL;
  60. co64 = (sample && sample->offset + track->offset > UINT32_MAX) ? 1 : 0;
  61. size = 12/* full box */ + 4/* entry count */ + count * (co64 ? 8 : 4);
  62. mov_buffer_w32(&mov->io, size); /* size */
  63. mov_buffer_write(&mov->io, co64 ? "co64" : "stco", 4);
  64. mov_buffer_w32(&mov->io, 0); /* version & flags */
  65. mov_buffer_w32(&mov->io, count); /* entry count */
  66. for (i = 0; i < track->sample_count; i++)
  67. {
  68. sample = track->samples + i;
  69. if(0 == sample->first_chunk)
  70. continue;
  71. if(0 == co64)
  72. mov_buffer_w32(&mov->io, (uint32_t)(sample->offset + track->offset));
  73. else
  74. mov_buffer_w64(&mov->io, sample->offset + track->offset);
  75. }
  76. return size;
  77. }
  78. size_t mov_stco_size(const struct mov_track_t* track, uint64_t offset)
  79. {
  80. size_t i, j;
  81. uint64_t co64;
  82. const struct mov_sample_t* sample;
  83. if (track->sample_count < 1)
  84. return 0;
  85. sample = &track->samples[track->sample_count - 1];
  86. co64 = sample->offset + track->offset;
  87. if (co64 > UINT32_MAX || co64 + offset <= UINT32_MAX)
  88. return 0;
  89. for (i = 0, j = 0; i < track->sample_count; i++)
  90. {
  91. sample = track->samples + i;
  92. if (0 != sample->first_chunk)
  93. j++;
  94. }
  95. return j * 4;
  96. }
  97. uint32_t mov_build_stco(struct mov_track_t* track)
  98. {
  99. size_t i;
  100. size_t bytes = 0;
  101. uint32_t count = 0;
  102. struct mov_sample_t* sample = NULL;
  103. assert(track->stsd.entry_count > 0);
  104. for (i = 0; i < track->sample_count; i++)
  105. {
  106. if (NULL != sample
  107. && sample->offset + bytes == track->samples[i].offset
  108. && sample->sample_description_index == track->samples[i].sample_description_index)
  109. {
  110. track->samples[i].first_chunk = 0; // mark invalid value
  111. bytes += track->samples[i].bytes;
  112. ++sample->samples_per_chunk;
  113. }
  114. else
  115. {
  116. sample = &track->samples[i];
  117. sample->first_chunk = ++count; // chunk start from 1
  118. sample->samples_per_chunk = 1;
  119. bytes = sample->bytes;
  120. }
  121. }
  122. return count;
  123. }
  124. void mov_apply_stco(struct mov_track_t* track)
  125. {
  126. uint32_t i, j, k;
  127. uint64_t n, chunk_offset;
  128. struct mov_stbl_t* stbl = &track->stbl;
  129. // sample offset
  130. assert(stbl->stsc_count > 0 && stbl->stco_count > 0);
  131. stbl->stsc[stbl->stsc_count].first_chunk = stbl->stco_count + 1; // fill stco count
  132. for (i = 0, n = 0; i < stbl->stsc_count; i++)
  133. {
  134. assert(stbl->stsc[i].first_chunk <= stbl->stco_count);
  135. for (j = stbl->stsc[i].first_chunk; j < stbl->stsc[i + 1].first_chunk; j++)
  136. {
  137. chunk_offset = stbl->stco[j - 1]; // chunk start from 1
  138. for (k = 0; k < stbl->stsc[i].samples_per_chunk; k++, n++)
  139. {
  140. track->samples[n].sample_description_index = stbl->stsc[i].sample_description_index;
  141. track->samples[n].offset = chunk_offset;
  142. track->samples[n].data = NULL;
  143. chunk_offset += track->samples[n].bytes;
  144. assert(track->samples[n].bytes > 0);
  145. assert(0 == n || track->samples[n - 1].offset + track->samples[n - 1].bytes <= track->samples[n].offset);
  146. }
  147. }
  148. }
  149. assert(n == track->sample_count);
  150. }