Older/MediaServer/libmov/source/mov-elst.c

137 lines
3.5 KiB
C
Raw Normal View History

2024-10-01 00:12:57 +08:00
#include "mov-internal.h"
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
// 8.6.6 Edit List Box (p53)
int mov_read_elst(struct mov_t* mov, const struct mov_box_t* box)
{
uint32_t i, entry_count;
uint32_t version;
struct mov_track_t* track = mov->track;
version = mov_buffer_r8(&mov->io); /* version */
mov_buffer_r24(&mov->io); /* flags */
entry_count = mov_buffer_r32(&mov->io);
assert(0 == track->elst_count && NULL == track->elst);
if (track->elst_count < entry_count)
{
void* p = realloc(track->elst, sizeof(struct mov_elst_t) * entry_count);
if (NULL == p) return -ENOMEM;
track->elst = (struct mov_elst_t*)p;
}
track->elst_count = entry_count;
for (i = 0; i < entry_count; i++)
{
if (1 == version)
{
track->elst[i].segment_duration = mov_buffer_r64(&mov->io);
track->elst[i].media_time = (int64_t)mov_buffer_r64(&mov->io);
}
else
{
assert(0 == version);
track->elst[i].segment_duration = mov_buffer_r32(&mov->io);
track->elst[i].media_time = (int32_t)mov_buffer_r32(&mov->io);
}
track->elst[i].media_rate_integer = (int16_t)mov_buffer_r16(&mov->io);
track->elst[i].media_rate_fraction = (int16_t)mov_buffer_r16(&mov->io);
}
(void)box;
return mov_buffer_error(&mov->io);
}
size_t mov_write_elst(const struct mov_t* mov)
{
uint32_t size;
int64_t time;
int64_t delay;
uint8_t version;
const struct mov_track_t* track = mov->track;
assert(track->start_dts == track->samples[0].dts);
version = track->tkhd.duration > UINT32_MAX ? 1 : 0;
// in media time scale units, in composition time
time = track->samples[0].pts - track->samples[0].dts;
// in units of the timescale in the Movie Header Box
delay = track->samples[0].pts * mov->mvhd.timescale / track->mdhd.timescale;
if (delay > UINT32_MAX)
version = 1;
time = time < 0 ? 0 : time;
size = 12/* full box */ + 4/* entry count */ + (delay > 0 ? 2 : 1) * (version ? 20 : 12);
mov_buffer_w32(&mov->io, size); /* size */
mov_buffer_write(&mov->io, "elst", 4);
mov_buffer_w8(&mov->io, version); /* version */
mov_buffer_w24(&mov->io, 0); /* flags */
mov_buffer_w32(&mov->io, delay > 0 ? 2 : 1); /* entry count */
if (delay > 0)
{
if (1 == version)
{
mov_buffer_w64(&mov->io, (uint64_t)delay); /* segment_duration */
mov_buffer_w64(&mov->io, (uint64_t)-1); /* media_time */
}
else
{
mov_buffer_w32(&mov->io, (uint32_t)delay);
mov_buffer_w32(&mov->io, (uint32_t)-1);
}
mov_buffer_w16(&mov->io, 1); /* media_rate_integer */
mov_buffer_w16(&mov->io, 0); /* media_rate_fraction */
}
/* duration */
if (version == 1)
{
mov_buffer_w64(&mov->io, track->tkhd.duration);
mov_buffer_w64(&mov->io, time);
}
else
{
mov_buffer_w32(&mov->io, (uint32_t)track->tkhd.duration);
mov_buffer_w32(&mov->io, (uint32_t)time);
}
mov_buffer_w16(&mov->io, 1); /* media_rate_integer */
mov_buffer_w16(&mov->io, 0); /* media_rate_fraction */
return size;
}
void mov_apply_elst(struct mov_track_t *track)
{
size_t i;
// edit list
track->samples[0].dts = 0;
track->samples[0].pts = 0;
for (i = 0; i < track->elst_count; i++)
{
if (-1 == track->elst[i].media_time)
{
track->samples[0].dts = track->elst[i].segment_duration;
track->samples[0].pts = track->samples[0].dts;
}
}
}
void mov_apply_elst_tfdt(struct mov_track_t *track)
{
size_t i;
for (i = 0; i < track->elst_count; i++)
{
if (-1 == track->elst[i].media_time)
{
track->tfdt_dts += track->elst[i].segment_duration;
}
}
}