|
- #include "mov-internal.h"
- #include <errno.h>
- #include <stdlib.h>
- #include <assert.h>
-
- // 8.6.1.2 Decoding Time to Sample Box (p47)
- int mov_read_stts(struct mov_t* mov, const struct mov_box_t* box)
- {
- uint32_t i, entry_count;
- struct mov_stbl_t* stbl = &mov->track->stbl;
-
- mov_buffer_r8(&mov->io); /* version */
- mov_buffer_r24(&mov->io); /* flags */
- entry_count = mov_buffer_r32(&mov->io);
-
- assert(0 == stbl->stts_count && NULL == stbl->stts); // duplicated STTS atom
- if (stbl->stts_count < entry_count)
- {
- void* p = realloc(stbl->stts, sizeof(struct mov_stts_t) * entry_count);
- if (NULL == p) return -ENOMEM;
- stbl->stts = (struct mov_stts_t*)p;
- }
- stbl->stts_count = entry_count;
-
- for (i = 0; i < entry_count; i++)
- {
- stbl->stts[i].sample_count = mov_buffer_r32(&mov->io);
- stbl->stts[i].sample_delta = mov_buffer_r32(&mov->io);
- }
-
- (void)box;
- return mov_buffer_error(&mov->io);
- }
-
- // 8.6.1.3 Composition Time to Sample Box (p47)
- int mov_read_ctts(struct mov_t* mov, const struct mov_box_t* box)
- {
- uint32_t i, entry_count;
- struct mov_stbl_t* stbl = &mov->track->stbl;
-
- mov_buffer_r8(&mov->io); /* version */
- mov_buffer_r24(&mov->io); /* flags */
- entry_count = mov_buffer_r32(&mov->io);
-
- assert(0 == stbl->ctts_count && NULL == stbl->ctts); // duplicated CTTS atom
- if (stbl->ctts_count < entry_count)
- {
- void* p = realloc(stbl->ctts, sizeof(struct mov_stts_t) * entry_count);
- if (NULL == p) return -ENOMEM;
- stbl->ctts = (struct mov_stts_t*)p;
- }
- stbl->ctts_count = entry_count;
-
- for (i = 0; i < entry_count; i++)
- {
- stbl->ctts[i].sample_count = mov_buffer_r32(&mov->io);
- stbl->ctts[i].sample_delta = mov_buffer_r32(&mov->io); // parse at int32_t
- }
-
- (void)box;
- return mov_buffer_error(&mov->io);
- }
-
- // 8.6.1.4 Composition to Decode Box (p53)
- int mov_read_cslg(struct mov_t* mov, const struct mov_box_t* box)
- {
- uint8_t version;
- // struct mov_stbl_t* stbl = &mov->track->stbl;
-
- version = (uint8_t)mov_buffer_r8(&mov->io); /* version */
- mov_buffer_r24(&mov->io); /* flags */
-
- if (0 == version)
- {
- mov_buffer_r32(&mov->io); /* compositionToDTSShift */
- mov_buffer_r32(&mov->io); /* leastDecodeToDisplayDelta */
- mov_buffer_r32(&mov->io); /* greatestDecodeToDisplayDelta */
- mov_buffer_r32(&mov->io); /* compositionStartTime */
- mov_buffer_r32(&mov->io); /* compositionEndTime */
- }
- else
- {
- mov_buffer_r64(&mov->io);
- mov_buffer_r64(&mov->io);
- mov_buffer_r64(&mov->io);
- mov_buffer_r64(&mov->io);
- mov_buffer_r64(&mov->io);
- }
-
- (void)box;
- return mov_buffer_error(&mov->io);
- }
-
- size_t mov_write_stts(const struct mov_t* mov, uint32_t count)
- {
- uint32_t size, i;
- const struct mov_sample_t* sample;
- const struct mov_track_t* track = mov->track;
-
- size = 12/* full box */ + 4/* entry count */ + count * 8/* entry */;
-
- mov_buffer_w32(&mov->io, size); /* size */
- mov_buffer_write(&mov->io, "stts", 4);
- mov_buffer_w32(&mov->io, 0); /* version & flags */
- mov_buffer_w32(&mov->io, count); /* entry count */
-
- for (i = 0; i < track->sample_count; i++)
- {
- sample = &track->samples[i];
- if(0 == sample->first_chunk)
- continue;
- mov_buffer_w32(&mov->io, sample->first_chunk); // count
- mov_buffer_w32(&mov->io, sample->samples_per_chunk); // delta * timescale / 1000
- }
-
- return size;
- }
-
- size_t mov_write_ctts(const struct mov_t* mov, uint32_t count)
- {
- uint32_t size, i;
- const struct mov_sample_t* sample;
- const struct mov_track_t* track = mov->track;
-
- size = 12/* full box */ + 4/* entry count */ + count * 8/* entry */;
-
- mov_buffer_w32(&mov->io, size); /* size */
- mov_buffer_write(&mov->io, "ctts", 4);
- mov_buffer_w8(&mov->io, (track->flags & MOV_TRACK_FLAG_CTTS_V1) ? 1 : 0); /* version */
- mov_buffer_w24(&mov->io, 0); /* flags */
- mov_buffer_w32(&mov->io, count); /* entry count */
-
- for (i = 0; i < track->sample_count; i++)
- {
- sample = &track->samples[i];
- if(0 == sample->first_chunk)
- continue;
- mov_buffer_w32(&mov->io, sample->first_chunk); // count
- mov_buffer_w32(&mov->io, sample->samples_per_chunk); // offset * timescale / 1000
- }
-
- return size;
- }
-
- uint32_t mov_build_stts(struct mov_track_t* track)
- {
- size_t i;
- uint32_t delta, count = 0;
- struct mov_sample_t* sample = NULL;
-
- for (i = 0; i < track->sample_count; i++)
- {
- assert(track->samples[i + 1].dts >= track->samples[i].dts || i + 1 == track->sample_count);
- delta = (uint32_t)(i + 1 < track->sample_count && track->samples[i + 1].dts > track->samples[i].dts ? track->samples[i + 1].dts - track->samples[i].dts : 1);
- if (NULL != sample && delta == sample->samples_per_chunk)
- {
- track->samples[i].first_chunk = 0;
- assert(sample->first_chunk > 0);
- ++sample->first_chunk; // compress
- }
- else
- {
- sample = &track->samples[i];
- sample->first_chunk = 1;
- sample->samples_per_chunk = delta;
- ++count;
- }
- }
- return count;
- }
-
- uint32_t mov_build_ctts(struct mov_track_t* track)
- {
- size_t i;
- uint32_t delta;
- uint32_t count = 0;
- struct mov_sample_t* sample = NULL;
-
- for (i = 0; i < track->sample_count; i++)
- {
- delta = (uint32_t)(track->samples[i].pts - track->samples[i].dts);
- if (i > 0 && delta == sample->samples_per_chunk)
- {
- track->samples[i].first_chunk = 0;
- assert(sample->first_chunk > 0);
- ++sample->first_chunk; // compress
- }
- else
- {
- sample = &track->samples[i];
- sample->first_chunk = 1;
- sample->samples_per_chunk = delta;
- ++count;
-
- // fixed: firefox version 51 don't support version 1
- if (track->samples[i].pts < track->samples[i].dts)
- track->flags |= MOV_TRACK_FLAG_CTTS_V1;
- }
- }
-
- return count;
- }
-
- void mov_apply_stts(struct mov_track_t* track)
- {
- size_t i, j, n;
- struct mov_stbl_t* stbl = &track->stbl;
-
- for (i = 0, n = 1; i < stbl->stts_count; i++)
- {
- for (j = 0; j < stbl->stts[i].sample_count; j++, n++)
- {
- track->samples[n].dts = track->samples[n - 1].dts + stbl->stts[i].sample_delta;
- track->samples[n].pts = track->samples[n].dts;
- }
- }
- assert(n - 1 == track->sample_count); // see more mov_read_stsz
- }
-
- void mov_apply_ctts(struct mov_track_t* track)
- {
- size_t i, j, n;
- int32_t delta, dts_shift;
- struct mov_stbl_t* stbl = &track->stbl;
-
- // make sure pts >= dts
- dts_shift = 0;
- for (i = 0; i < stbl->ctts_count; i++)
- {
- delta = (int32_t)stbl->ctts[i].sample_delta;
- if (delta < 0 && dts_shift > delta && delta != -1 /* see more cslg box*/)
- dts_shift = delta;
- }
- assert(dts_shift <= 0);
-
- // sample cts/pts
- for (i = 0, n = 0; i < stbl->ctts_count; i++)
- {
- for (j = 0; j < stbl->ctts[i].sample_count; j++, n++)
- track->samples[n].pts += (int64_t)((int32_t)stbl->ctts[i].sample_delta - dts_shift); // always as int, fixed mp4box delta version error
- }
- assert(0 == stbl->ctts_count || n == track->sample_count);
- }
|