1
0
Fork 0

matroskadec_haali: optimize fuzzy CueAware seeking

This allows finding Cues that would match the same frame as the requested timecode,
and allow for more accurate seeking on ordered chapter boundaries.
This commit is contained in:
Hendrik Leppkes 2013-05-04 21:47:23 +02:00
parent 64047e9b53
commit 0710962a3a
Signed by: hendrik
GPG Key ID: 846079A4B0A7C1B5
3 changed files with 25 additions and 7 deletions

View File

@ -3059,20 +3059,38 @@ static inline ulonglong mkv_time_diff(ulonglong one, ulonglong two)
return two-one;
}
void mkv_Seek_CueAware(MatroskaFile *mf, ulonglong timecode, unsigned flags)
void mkv_Seek_CueAware(MatroskaFile *mf, ulonglong timecode, unsigned flags, unsigned fuzzy)
{
if (timecode > 0 && (flags & (MKVF_SEEK_TO_PREV_KEYFRAME|MKVF_SEEK_TO_PREV_KEYFRAME_STRICT))) {
unsigned int count, i;
unsigned char track = 0;
ulonglong default_duration = 10000000;
Cue *cue;
for (i=0;i<mf->nTracks;++i) {
if (mf->Tracks[i]->Type == TT_VIDEO && !(mf->trackMask & (ULL(1)<<i))) {
track = mf->Tracks[i]->Number;
if (mf->Tracks[i]->DefaultDuration)
default_duration = mf->Tracks[i]->DefaultDuration;
break;
}
}
mkv_GetCues(mf, &cue, &count);
if (count > 0) {
ulonglong prevDiff = ULLONG_MAX;
ulonglong newTimecode = timecode;
for (i = 0; i < count; i++) {
ulonglong tcDiff = mkv_time_diff(cue[i].Time, timecode);
if (tcDiff == 0 || (cue[i].Track && cue[i].Track <= mf->nTracks && tcDiff <= mf->Tracks[cue[i].Track-1]->DefaultDuration)) {
if ((!track || !cue[i].Track || cue[i].Track == track) && (tcDiff == 0 || (fuzzy && tcDiff <= default_duration))) {
flags &= ~(MKVF_SEEK_TO_PREV_KEYFRAME|MKVF_SEEK_TO_PREV_KEYFRAME_STRICT);
timecode = cue[i].Time;
if (tcDiff < prevDiff) {
newTimecode = cue[i].Time;
prevDiff = tcDiff;
}
}
}
timecode = newTimecode;
}
}
mkv_Seek(mf, timecode, flags);

View File

@ -341,7 +341,7 @@ X void mkv_Seek(/* in */ MatroskaFile *mf,
/* in */ ulonglong timecode /* in ns */,
/* in */ unsigned flags);
X void mkv_Seek_CueAware(MatroskaFile *mf, ulonglong timecode, unsigned flags);
X void mkv_Seek_CueAware(MatroskaFile *mf, ulonglong timecode, unsigned flags, unsigned fuzzy);
X void mkv_SkipToKeyframe(MatroskaFile *mf);

View File

@ -1023,7 +1023,7 @@ static int mkv_read_header(AVFormatContext *s)
if (ctx->virtual_timeline && ctx->timeline[0].need_seek) {
ctx->matroska = ctx->timeline[ctx->timeline_position].segment->matroska;
mkv_Seek_CueAware(ctx->matroska, ctx->timeline[0].chapter->Start, MKVF_SEEK_TO_PREV_KEYFRAME);
mkv_Seek_CueAware(ctx->matroska, ctx->timeline[0].chapter->Start, MKVF_SEEK_TO_PREV_KEYFRAME, 1);
}
/* Tracks */
@ -1288,7 +1288,7 @@ static int mkv_packet_timeline_update(AVFormatContext *s, ulonglong *start_time,
if (ctx->timeline[ctx->timeline_position].need_seek) {
av_log(s, AV_LOG_INFO, "Seeking to timeline %d (position %I64d)\n", ctx->timeline_position, ctx->timeline[ctx->timeline_position].chapter->Start);
mkv_switch_segment(s, ctx->timeline[ctx->timeline_position].segment->matroska, 0);
mkv_Seek_CueAware(ctx->matroska, ctx->timeline[ctx->timeline_position].chapter->Start, MKVF_SEEK_TO_PREV_KEYFRAME);
mkv_Seek_CueAware(ctx->matroska, ctx->timeline[ctx->timeline_position].chapter->Start, MKVF_SEEK_TO_PREV_KEYFRAME, 1);
// Need to discard the current frame, and re-read after the seek
return AVERROR(EAGAIN);
}
@ -1512,7 +1512,7 @@ static int mkv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
mkv_SetTrackMask(ctx->matroska, mkv_get_track_mask(ctx));
/* perform seek */
mkv_Seek_CueAware(ctx->matroska, timestamp, mkvflags);
mkv_Seek_CueAware(ctx->matroska, timestamp, mkvflags, 0);
/* Update current timestamp */
cur_dts = mkv_GetLowestQTimecode(ctx->matroska);