From 41af979eb87860eac2488315000dc188be6f4c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 1 Sep 2010 21:55:11 +0000 Subject: [PATCH] Simplified the code a bit, removed debugging output and added a work-around for the problem that FindKeyFrameForFrame() may return another frame for a previously found keyframe (due to rounding issues in the extrator). At the moment, files which used to play horribly play pretty well now for me. One remaining problem is that audio may be mute when seeking far ahead in file, and the audio decoding has to catch up. It will eventually be all ok. Once a section of the file has played, it becomes seekable. This seems to be weird behavior of some FFmpeg demuxers, and only with some files. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38507 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../supplier/MediaTrackVideoSupplier.cpp | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp index 72da223598..5322e8b827 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp +++ b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp @@ -117,9 +117,8 @@ MediaTrackVideoSupplier::ReadFrame(void* buffer, bigtime_t* performanceTime, fprintf(stderr, "MediaTrackVideoSupplier::ReadFrame() - " "error while reading frame of track: %s\n", strerror(ret)); } - } else { + } else fPerformanceTime = mediaHeader.start_time; - } fCurrentFrame = fVideoTrack->CurrentFrame(); if (performanceTime) @@ -148,8 +147,11 @@ MediaTrackVideoSupplier::FindKeyFrameForFrame(int64* frame) if (!fVideoTrack) return B_NO_INIT; - return fVideoTrack->FindKeyFrameForFrame(frame, +//int64 wantedFrame = *frame; + status_t ret = fVideoTrack->FindKeyFrameForFrame(frame, B_MEDIA_SEEK_CLOSEST_BACKWARD); +//printf("found keyframe for frame %lld -> %lld\n", wantedFrame, *frame); + return ret; } @@ -184,31 +186,47 @@ MediaTrackVideoSupplier::SeekToFrame(int64* frame) return B_NO_INIT; int64 wantFrame = *frame; - int64 currentFrame = fVideoTrack->CurrentFrame(); - if (wantFrame == currentFrame) + if (wantFrame == fCurrentFrame) return B_OK; status_t ret = fVideoTrack->FindKeyFrameForFrame(frame, B_MEDIA_SEEK_CLOSEST_BACKWARD); - if (ret < B_OK) + if (ret != B_OK) return ret; + if (wantFrame > *frame) { + // Work around a rounding problem with some extractors and + // converting frames <-> time <-> internal time. + int64 nextWantFrame = wantFrame + 1; + if (fVideoTrack->FindKeyFrameForFrame(&nextWantFrame, + B_MEDIA_SEEK_CLOSEST_BACKWARD) == B_OK) { + if (nextWantFrame == wantFrame) + *frame = wantFrame + 1; + } + } - if (*frame < currentFrame && wantFrame > currentFrame) { - *frame = currentFrame; +//if (wantFrame != *frame) { +// printf("keyframe for frame: %lld -> %lld\n", wantFrame, *frame); +//} + + if (*frame <= fCurrentFrame && wantFrame > fCurrentFrame) { + // The current frame is already closer to the wanted frame + // than the next keyframe before it. + *frame = fCurrentFrame; return B_OK; } -if (wantFrame != *frame) { - printf("seeked by frame: %lld -> %lld, was %lld\n", wantFrame, *frame, - currentFrame); -} - ret = fVideoTrack->SeekToFrame(frame); - if (ret == B_OK) { - fCurrentFrame = *frame; - fPerformanceTime = fVideoTrack->CurrentTime(); - } + if (ret != B_OK) + return ret; + +//if (wantFrame != *frame) { +// printf("seeked by frame: %lld -> %lld, was %lld\n", wantFrame, *frame, +// fCurrentFrame); +//} + + fCurrentFrame = *frame; + fPerformanceTime = fVideoTrack->CurrentTime(); return ret; }