#include "mov-internal.h" #include #include #include #include // 8.8.8 Track Fragment Run Box (p72) int mov_read_trun(struct mov_t* mov, const struct mov_box_t* box) { unsigned int version; uint32_t flags; uint32_t i, sample_count; uint64_t data_offset; uint32_t first_sample_flags; uint32_t sample_duration, sample_size, sample_flags; int64_t sample_composition_time_offset; struct mov_track_t* track; struct mov_sample_t* sample; version = mov_buffer_r8(&mov->io); /* version */ flags = mov_buffer_r24(&mov->io); /* flags */ sample_count = mov_buffer_r32(&mov->io); /* sample_count */ track = mov->track; if (sample_count > 0) { void* p = realloc(track->samples, sizeof(struct mov_sample_t) * (track->sample_count + sample_count + 1)); if (NULL == p) return -ENOMEM; track->samples = (struct mov_sample_t*)p; memset(track->samples + track->sample_count, 0, sizeof(struct mov_sample_t) * (sample_count + 1)); } data_offset = track->tfhd.base_data_offset; if (MOV_TRUN_FLAG_DATA_OFFSET_PRESENT & flags) data_offset += (int32_t)mov_buffer_r32(&mov->io); /* data_offset */ if (MOV_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT & flags) first_sample_flags = mov_buffer_r32(&mov->io); /* first_sample_flags */ else first_sample_flags = track->tfhd.flags; sample = track->samples + track->sample_count; for (i = 0; i < sample_count; i++) { if (MOV_TRUN_FLAG_SAMPLE_DURATION_PRESENT & flags) sample_duration = mov_buffer_r32(&mov->io); /* sample_duration*/ else sample_duration = track->tfhd.default_sample_duration; if (MOV_TRUN_FLAG_SAMPLE_SIZE_PRESENT & flags) sample_size = mov_buffer_r32(&mov->io); /* sample_size*/ else sample_size = track->tfhd.default_sample_size; if (MOV_TRUN_FLAG_SAMPLE_FLAGS_PRESENT & flags) sample_flags = mov_buffer_r32(&mov->io); /* sample_flags*/ else sample_flags = i ? track->tfhd.default_sample_flags : first_sample_flags; if (MOV_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT & flags) { sample_composition_time_offset = mov_buffer_r32(&mov->io); /* sample_composition_time_offset*/ if (1 == version) sample_composition_time_offset = (int32_t)sample_composition_time_offset; } else sample_composition_time_offset = 0; sample[i].offset = data_offset; sample[i].bytes = sample_size; sample[i].dts = track->tfdt_dts; sample[i].pts = sample[i].dts + sample_composition_time_offset; sample[i].flags = (sample_flags & (MOV_TREX_FLAG_SAMPLE_IS_NO_SYNC_SAMPLE | 0x01000000)) ? 0 : MOV_AV_FLAG_KEYFREAME; sample[i].sample_description_index = track->tfhd.sample_description_index; data_offset += sample_size; track->tfdt_dts += sample_duration; } track->sample_count += sample_count; mov->implicit_offset = data_offset; (void)box; return mov_buffer_error(&mov->io); } size_t mov_write_trun(const struct mov_t* mov, uint32_t from, uint32_t count, uint32_t moof) { uint32_t flags; uint32_t delta; uint64_t offset; uint32_t size, i; const struct mov_sample_t* sample; const struct mov_track_t* track = mov->track; if (count < 1) return 0; assert(from + count <= track->sample_count); flags = MOV_TRUN_FLAG_DATA_OFFSET_PRESENT; if (track->samples[from].flags & MOV_AV_FLAG_KEYFREAME) flags |= MOV_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT; for (i = from; i < from + count; i++) { sample = track->samples + i; if (sample->bytes != track->tfhd.default_sample_size) flags |= MOV_TRUN_FLAG_SAMPLE_SIZE_PRESENT; if ((uint32_t)(i + 1 < track->sample_count ? track->samples[i + 1].dts - track->samples[i].dts : track->turn_last_duration) != track->tfhd.default_sample_duration) flags |= MOV_TRUN_FLAG_SAMPLE_DURATION_PRESENT; if (sample->pts != sample->dts) flags |= MOV_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT; } size = 12/* full box */ + 4/* sample count */; offset = mov_buffer_tell(&mov->io); mov_buffer_w32(&mov->io, 0); /* size */ mov_buffer_write(&mov->io, "trun", 4); mov_buffer_w8(&mov->io, 1); /* version */ mov_buffer_w24(&mov->io, flags); /* flags */ mov_buffer_w32(&mov->io, count); /* sample_count */ assert(flags & MOV_TRUN_FLAG_DATA_OFFSET_PRESENT); if (flags & MOV_TRUN_FLAG_DATA_OFFSET_PRESENT) { mov_buffer_w32(&mov->io, moof + (uint32_t)track->samples[from].offset); size += 4; } if (flags & MOV_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) { mov_buffer_w32(&mov->io, MOV_TREX_FLAG_SAMPLE_DEPENDS_ON_I_PICTURE); /* first_sample_flags */ size += 4; } assert(from + count <= track->sample_count); for (i = from; i < from + count; i++) { sample = track->samples + i; if (flags & MOV_TRUN_FLAG_SAMPLE_DURATION_PRESENT) { delta = (uint32_t)(i + 1 < track->sample_count ? track->samples[i + 1].dts - track->samples[i].dts : track->turn_last_duration); mov_buffer_w32(&mov->io, delta); /* sample_duration */ size += 4; } if (flags & MOV_TRUN_FLAG_SAMPLE_SIZE_PRESENT) { mov_buffer_w32(&mov->io, (uint32_t)sample->bytes); /* sample_size */ size += 4; } assert(0 == (flags & MOV_TRUN_FLAG_SAMPLE_FLAGS_PRESENT)); // mov_buffer_w32(&mov->io, 0); /* sample_flags */ if (flags & MOV_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) { mov_buffer_w32(&mov->io, (int32_t)(sample->pts - sample->dts)); /* sample_composition_time_offset */ size += 4; } } mov_write_size(mov, offset, size); return size; }