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:
parent
64047e9b53
commit
0710962a3a
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue