summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-27 22:15:21 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-27 22:15:21 +0000
commit97708ca70ee8cb5a316a0a14030efa5e9e963c7d (patch)
treebb77c3d5d15dd7c57ca6d8cdbb24490c12e4c8d6
parent9cddd470b53f54df561ac630c182dfd393cce7fd (diff)
downloadchromium_src-97708ca70ee8cb5a316a0a14030efa5e9e963c7d.zip
chromium_src-97708ca70ee8cb5a316a0a14030efa5e9e963c7d.tar.gz
chromium_src-97708ca70ee8cb5a316a0a14030efa5e9e963c7d.tar.bz2
Quick work around for av_seek_frame() causing video to go completely out of sync.
If we have a freshly opened AVFormatContext, telling it to seek to the beginning (pts=0) apparently causes the video and/or audio streams to get timestampped incorrectly, causing video sync issues. If the video has been playing a bit, a seek to the beginning causes no issues. Go figure. BUG=17832 TEST=ogg videos should remain in sync Review URL: http://codereview.chromium.org/159438 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21720 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--media/filters/ffmpeg_demuxer.cc13
-rw-r--r--media/filters/ffmpeg_demuxer.h4
-rw-r--r--media/filters/ffmpeg_demuxer_unittest.cc13
3 files changed, 29 insertions, 1 deletions
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index c3b2d62..189aac4 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -220,7 +220,8 @@ FFmpegDemuxer::FFmpegDemuxer()
read_event_(false, false),
read_has_failed_(false),
last_read_bytes_(0),
- read_position_(0) {
+ read_position_(0),
+ first_seek_hack_(true) {
}
FFmpegDemuxer::~FFmpegDemuxer() {
@@ -425,6 +426,16 @@ void FFmpegDemuxer::SeekTask(base::TimeDelta time, FilterCallback* callback) {
(*iter)->FlushBuffers();
}
+ // Do NOT call av_seek_frame() if we were just created. For some reason it
+ // causes Ogg+Theora/Vorbis videos to become heavily out of sync.
+ //
+ // TODO(scherkus): fix the av_seek_frame() hackery!
+ if (first_seek_hack_) {
+ first_seek_hack_ = false;
+ callback->Run();
+ return;
+ }
+
// Seek backwards if requested timestamp is behind FFmpeg's current time.
int flags = 0;
if (time <= current_timestamp_) {
diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h
index ebd1274..0777855 100644
--- a/media/filters/ffmpeg_demuxer.h
+++ b/media/filters/ffmpeg_demuxer.h
@@ -219,6 +219,10 @@ class FFmpegDemuxer : public Demuxer,
size_t last_read_bytes_;
int64 read_position_;
+ // If true, then it's our first seek and we won't call av_read_frame(). It's
+ // a hack to get around some issue with FFmpeg.
+ bool first_seek_hack_;
+
DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxer);
};
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 08580da..e8c9df7 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -456,6 +456,13 @@ TEST_F(FFmpegDemuxerTest, Seek) {
EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
+ // ... then we'll call Seek() to get around the first seek hack...
+ //
+ // TODO(scherkus): fix the av_seek_frame() hackery!
+ StrictMock<MockFilterCallback> hack_callback;
+ EXPECT_CALL(hack_callback, OnFilterCallback());
+ EXPECT_CALL(hack_callback, OnCallbackDestroyed());
+
// ...then we'll expect the actual seek call...
EXPECT_CALL(*MockFFmpeg::get(),
AVSeekFrame(&format_context_, -1, kExpectedTimestamp, kExpectedFlags))
@@ -501,6 +508,12 @@ TEST_F(FFmpegDemuxerTest, Seek) {
message_loop_.RunAllPending();
MockFFmpeg::get()->CheckPoint(1);
+ // Issue a preliminary seek to get around the "first seek" hack.
+ //
+ // TODO(scherkus): fix the av_seek_frame() hackery!
+ demuxer_->Seek(base::TimeDelta(), hack_callback.NewCallback());
+ message_loop_.RunAllPending();
+
// Now issue a simple forward seek, which should discard queued packets.
demuxer_->Seek(base::TimeDelta::FromMicroseconds(kExpectedTimestamp),
seek_callback.NewCallback());