Older/MediaServer/libmov/source/fmp4-reader.c

120 lines
2.9 KiB
C
Raw Normal View History

2024-10-01 00:12:57 +08:00
#include "mov-internal.h"
#include <assert.h>
#include <errno.h>
#define DIFF(a, b) ((a) > (b) ? ((a) - (b)) : ((b) - (a)))
static int mov_fragment_seek_get_duration(struct mov_t* mov)
{
int i;
struct mov_track_t* track;
track = mov->track_count > 0 ? &mov->tracks[0] : NULL;
if (track && track->frag_capacity < track->frag_count && track->mdhd.timescale)
{
mov_buffer_seek(&mov->io, track->frags[track->frag_count - 1].offset);
mov_reader_root(mov); // moof
track->mdhd.duration = track->samples[track->sample_count - 1].dts - track->samples[0].dts;
mov->mvhd.duration = track->mdhd.duration * mov->mvhd.timescale / track->mdhd.timescale;
// clear samples and seek to the first moof
for (i = 0; i < mov->track_count; i++)
{
mov->tracks[i].sample_count = 0;
mov->tracks[i].sample_offset = 0;
}
track->frag_capacity = 0;
}
return 0;
}
int mov_fragment_seek_read_mfra(struct mov_t* mov)
{
uint64_t pos;
pos = mov_buffer_tell(&mov->io); // for fallback
mov_buffer_seek(&mov->io, -16);
mov_reader_root(mov); // mfro
if (mov->mfro > 0)
{
mov_buffer_seek(&mov->io, -((int64_t)mov->mfro));
mov_reader_root(mov); // mfra
mov_fragment_seek_get_duration(mov); // for get fmp4 duration
}
mov_buffer_seek(&mov->io, pos);
return mov_buffer_error(&mov->io);
}
int mov_fragment_seek(struct mov_t* mov, int64_t* timestamp)
{
int i;
uint64_t clock;
size_t idx, start, end;
struct mov_track_t* track;
struct mov_fragment_t* frag, *prev, *next;
track = mov->track_count > 0 ? &mov->tracks[0] : NULL;
if (!track || track->frag_count < 1)
return -1;
idx = start = 0;
end = track->frag_count;
assert(track->frag_count > 0);
clock = (uint64_t)(*timestamp) * track->mdhd.timescale / 1000; // mvhd timescale
while (start < end)
{
idx = (start + end) / 2;
frag = &track->frags[idx];
if (frag->time > clock)
end = idx;
else if (frag->time < clock)
start = idx + 1;
else
break;
}
frag = &track->frags[idx];
prev = &track->frags[idx > 0 ? idx - 1 : idx];
next = &track->frags[idx + 1 < track->frag_count ? idx + 1 : idx];
if (DIFF(prev->time, clock) < DIFF(frag->time, clock))
frag = prev;
if (DIFF(next->time, clock) < DIFF(frag->time, clock))
frag = next;
*timestamp = frag->time * 1000 / track->mdhd.timescale;
// clear samples and seek
for (i = 0; i < mov->track_count; i++)
{
mov->tracks[i].sample_count = 0;
mov->tracks[i].sample_offset = 0;
}
track->frag_capacity = (uint32_t)idx;
return 0;
}
int mov_fragment_read_next_moof(struct mov_t* mov)
{
int i;
struct mov_track_t* track;
// clear moof samples
for (i = 0; i < mov->track_count; i++)
{
mov->tracks[i].sample_count = 0;
mov->tracks[i].sample_offset = 0;
}
track = mov->track_count > 0 ? &mov->tracks[0] : NULL;
if (track && track->frag_capacity < track->frag_count)
{
mov_buffer_seek(&mov->io, track->frags[track->frag_capacity++].offset);
mov_reader_root(mov); // moof
return 0;
}
return 1; // eof
}