summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-12-07 02:17:34 +0100
committerCarl Hetherington <cth@carlh.net>2025-12-08 20:50:53 +0100
commit9bd8b3304f35f0b27bf18f2167302f1fd5d3f92b (patch)
treea500ed5d7a7247d10a25fdc26f130f3382756183
parentdeacb9bae6893f4d40c7b68a098b72549176df7b (diff)
Try AVSEEK_FLAG_ANY if _BACKWARD fails.
We usually want to do _BACKWARD as this should seek to the keyframe before the seek position. On some files this fails, and then it seems that _ANY is a good next thing to try.
-rwxr-xr-xrun/tests2
-rw-r--r--src/lib/ffmpeg_decoder.cc19
-rw-r--r--test/ffmpeg_decoder_seek_test.cc19
3 files changed, 33 insertions, 7 deletions
diff --git a/run/tests b/run/tests
index b5f45d5e7..8f6b2d3e2 100755
--- a/run/tests
+++ b/run/tests
@@ -3,7 +3,7 @@
# e.g. --run_tests=foo
set -e
-PRIVATE_GIT="81e32cb5962320333839b7020d14d9f291b8ff2d"
+PRIVATE_GIT="e92043f43b024812f2b5f8c8faed159a15a87aaf"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source $DIR/environment
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index ebbc242e3..c70733c4c 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -431,12 +431,19 @@ FFmpegDecoder::seek (ContentTime time, bool accurate)
if (u < ContentTime ()) {
u = ContentTime ();
}
- av_seek_frame (
- _format_context,
- stream.get(),
- u.seconds() / av_q2d (_format_context->streams[stream.get()]->time_base),
- AVSEEK_FLAG_BACKWARD
- );
+
+ auto seek = [&](int flag) {
+ return av_seek_frame(
+ _format_context,
+ stream.get(),
+ u.seconds() / av_q2d (_format_context->streams[stream.get()]->time_base),
+ flag
+ );
+ };
+
+ if (seek(AVSEEK_FLAG_BACKWARD) < 0) {
+ DCPOMATIC_ASSERT(seek(AVSEEK_FLAG_ANY) >= 0);
+ };
/* Force re-creation of filter graphs to reset them, to make sure
they don't have any pre-seek frames.
diff --git a/test/ffmpeg_decoder_seek_test.cc b/test/ffmpeg_decoder_seek_test.cc
index 43967e458..ee0da99da 100644
--- a/test/ffmpeg_decoder_seek_test.cc
+++ b/test/ffmpeg_decoder_seek_test.cc
@@ -133,3 +133,22 @@ BOOST_AUTO_TEST_CASE(ffmpeg_decoder_seek_test)
}
);
}
+
+
+BOOST_AUTO_TEST_CASE(seek_when_backward_fails)
+{
+ auto content = make_shared<FFmpegContent>(TestPaths::private_data() / "strange_keyframes.mp4");
+ auto film = new_test_film("seek_when_backward_fails", { content });
+ auto decoder = make_shared<FFmpegDecoder>(film, content, false);
+ decoder->video->Data.connect(bind(&store, _1));
+
+ /* Due to a bug this seek would fail silently, giving us different frame each time */
+ for (auto i = 0; i < 3; ++i) {
+ decoder->seek(dcpomatic::ContentTime(), true);
+ stored = {};
+ while (!decoder->pass() && !stored) {}
+ BOOST_REQUIRE(static_cast<bool>(stored));
+ BOOST_CHECK(stored->time == dcpomatic::ContentTime());
+ }
+}
+