Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Unified Diff: media/filters/ffmpeg_demuxer_unittest.cc

Issue 2855373002: Use ffmpeg packet.pos for restarting reading after reenabling video
Patch Set: reset pending_seek_position_ after calling the pending_seek_cb_ Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« media/filters/ffmpeg_demuxer.cc ('K') | « media/filters/ffmpeg_demuxer.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/ffmpeg_demuxer_unittest.cc
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 7ef340b668fe986e2b59eb606dd0f1d2c96a3274..ae43b504034896ee3708655ef8977c8ef6eb73ae 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -278,6 +278,10 @@ class FFmpegDemuxerTest : public testing::Test {
demuxer_->duration_ = kInfiniteDuration;
}
+ void SetStreamCapacity(FFmpegDemuxerStream* s, base::TimeDelta capacity) {
+ s->stream_capacity_ = capacity;
+ }
+
// Fixture members.
base::test::ScopedTaskScheduler task_scheduler_;
@@ -1660,4 +1664,112 @@ TEST_F(FFmpegDemuxerTest, StreamStatusNotifications) {
CheckStreamStatusNotifications(demuxer_.get(), video_stream);
}
+// This test verifies that when a video stream is restarted, we do an internal
+// seek in the ffmpeg demuxer (because we need to read video frames starting
+// with the previous video key frame before the current playback position, so
+// that the video renderer is able to resume playback from the current media
+// time), but then we'd drop all audio packets up to the last_audio_packet_pos_,
+// because those have already been processed and are sitting in the audio stream
+// buffer queue, we don't want to duplicate those.
+TEST_F(FFmpegDemuxerTest, SeekAndDropSeenAudioPacketsAfterVideoRestart) {
+ CreateDemuxer("bear-320x240.webm");
+ InitializeDemuxer();
+ FFmpegDemuxerStream* audio =
+ static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
+ FFmpegDemuxerStream* video =
+ static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
+ EXPECT_NE(nullptr, audio);
+ EXPECT_NE(nullptr, video);
+
+ // The audio stream in the test file has audio frames with timestamps about 3
+ // milliseconds apart (0, 3, 6, 9, 12, 15, 17, 20, 23etc). So setting stream
+ // capacity to 5 millisec allows the demuxer to buffer 3 frames. We'll read
+ // two of them immediately, so the demuxer will have read 5 frames from FFmpeg
+ // by the time the video track is re-enabled.
+ SetStreamCapacity(audio, base::TimeDelta::FromMilliseconds(5));
+
+ // Disable the video stream and read a few frames from the audio stream.
+ demuxer_->OnSelectedVideoTrackChanged(base::nullopt, base::TimeDelta());
+
+ audio->Read(NewReadCB(FROM_HERE, 29, 0, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+ audio->Read(NewReadCB(FROM_HERE, 27, 3000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+
+ // At this point the demuxer have read frames with timestamps 0-15 millisec.
+ // Now re-enable the video stream, which will cause an FFmpeg read position to
+ // be seeked back to 0 (since the previous video key frame is at 0).
+ demuxer_->OnSelectedVideoTrackChanged(MediaTrack::Id("1"), base::TimeDelta());
+
+ // Now verify that frames read from the audio stream are continuous, as
+ // expected. There should be no duplicates or missing frames.
+
+ // The first three frames were read and buffered before the video track was
+ // re-enabled.
+ audio->Read(NewReadCB(FROM_HERE, 31, 6000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+ audio->Read(NewReadCB(FROM_HERE, 30, 9000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+ audio->Read(NewReadCB(FROM_HERE, 32, 12000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+
+ // And the following three frames were read when we freed up capacity by
+ // reading the previous 3 frames above (i.e. after the video track was
+ // restarted). These should continue the audio stream reading sequence.
+ audio->Read(NewReadCB(FROM_HERE, 29, 15000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+ audio->Read(NewReadCB(FROM_HERE, 31, 17000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+ audio->Read(NewReadCB(FROM_HERE, 36, 20000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+}
+
+TEST_F(FFmpegDemuxerTest, SeekDuringVideoStreamRestart) {
+ CreateDemuxer("bear-320x240.webm");
+ InitializeDemuxer();
+ FFmpegDemuxerStream* video =
+ static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
+ EXPECT_NE(nullptr, video);
+
+ // Disable and then re-enable the video stream, this will initiate an
+ // internal seek for the video stream.
+ demuxer_->OnSelectedVideoTrackChanged(base::nullopt, base::TimeDelta());
+ demuxer_->OnSelectedVideoTrackChanged(MediaTrack::Id("1"), base::TimeDelta());
+
+ // Now immediately request a seek to a different position. This should cancel
+ // the previous seek and kick off a new seek.
+ Seek(base::TimeDelta::FromMilliseconds(500));
+
+ // Verify that the next read returns the video buffer from the expected
+ // position, matching the latest seek.
+ video->Read(NewReadCB(FROM_HERE, 5636, 400000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+}
+
+TEST_F(FFmpegDemuxerTest, VideoStreamRestartDuringSeek) {
+ CreateDemuxer("bear-320x240.webm");
+ InitializeDemuxer();
+ FFmpegDemuxerStream* video =
+ static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
+ EXPECT_NE(nullptr, video);
+
+ demuxer_->OnSelectedVideoTrackChanged(base::nullopt, base::TimeDelta());
+
+ // Initiate a seek and re-enable the video track without waiting for the seek
+ // to be completed.
+ base::TimeDelta seek_target = base::TimeDelta::FromMilliseconds(500);
+ WaitableMessageLoopEvent seek_event;
+ demuxer_->Seek(seek_target, seek_event.GetPipelineStatusCB());
+
+ demuxer_->OnSelectedVideoTrackChanged(MediaTrack::Id("1"), base::TimeDelta());
+
+ // Wait for the seek to finish.
+ seek_event.RunAndWaitForStatus(PIPELINE_OK);
+
+ // Verify that the next read returns the video buffer from the expected
+ // position, matching the latest seek.
+ video->Read(NewReadCB(FROM_HERE, 5636, 400000, true, DemuxerStream::kOk));
+ base::RunLoop().Run();
+}
+
} // namespace media
« media/filters/ffmpeg_demuxer.cc ('K') | « media/filters/ffmpeg_demuxer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698