diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-27 22:15:21 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-27 22:15:21 +0000 |
commit | 97708ca70ee8cb5a316a0a14030efa5e9e963c7d (patch) | |
tree | bb77c3d5d15dd7c57ca6d8cdbb24490c12e4c8d6 | |
parent | 9cddd470b53f54df561ac630c182dfd393cce7fd (diff) | |
download | chromium_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.cc | 13 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer.h | 4 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer_unittest.cc | 13 |
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()); |