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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <algorithm> 8 #include <algorithm>
9 #include <deque> 9 #include <deque>
10 #include <string> 10 #include <string>
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 media_tracks_ = std::move(tracks); 271 media_tracks_ = std::move(tracks);
272 } 272 }
273 273
274 // Accessor to demuxer internals. 274 // Accessor to demuxer internals.
275 void SetDurationKnown(bool duration_known) { 275 void SetDurationKnown(bool duration_known) {
276 demuxer_->duration_known_ = duration_known; 276 demuxer_->duration_known_ = duration_known;
277 if (!duration_known) 277 if (!duration_known)
278 demuxer_->duration_ = kInfiniteDuration; 278 demuxer_->duration_ = kInfiniteDuration;
279 } 279 }
280 280
281 void SetStreamCapacity(FFmpegDemuxerStream* s, base::TimeDelta capacity) {
282 s->stream_capacity_ = capacity;
283 }
284
281 // Fixture members. 285 // Fixture members.
282 286
283 base::test::ScopedTaskScheduler task_scheduler_; 287 base::test::ScopedTaskScheduler task_scheduler_;
284 MediaLog media_log_; 288 MediaLog media_log_;
285 std::unique_ptr<FileDataSource> data_source_; 289 std::unique_ptr<FileDataSource> data_source_;
286 std::unique_ptr<FFmpegDemuxer> demuxer_; 290 std::unique_ptr<FFmpegDemuxer> demuxer_;
287 StrictMock<MockDemuxerHost> host_; 291 StrictMock<MockDemuxerHost> host_;
288 std::unique_ptr<MediaTracks> media_tracks_; 292 std::unique_ptr<MediaTracks> media_tracks_;
289 293
290 AVFormatContext* format_context() { 294 AVFormatContext* format_context() {
(...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1653 // there is no buffers ready to be returned by the Read right away, thus 1657 // there is no buffers ready to be returned by the Read right away, thus
1654 // ensuring that status changes occur while an async read is pending. 1658 // ensuring that status changes occur while an async read is pending.
1655 audio_stream->FlushBuffers(); 1659 audio_stream->FlushBuffers();
1656 audio_stream->Read(base::Bind(&media::OnReadDone_ExpectEos)); 1660 audio_stream->Read(base::Bind(&media::OnReadDone_ExpectEos));
1657 CheckStreamStatusNotifications(demuxer_.get(), audio_stream); 1661 CheckStreamStatusNotifications(demuxer_.get(), audio_stream);
1658 video_stream->FlushBuffers(); 1662 video_stream->FlushBuffers();
1659 video_stream->Read(base::Bind(&media::OnReadDone_ExpectEos)); 1663 video_stream->Read(base::Bind(&media::OnReadDone_ExpectEos));
1660 CheckStreamStatusNotifications(demuxer_.get(), video_stream); 1664 CheckStreamStatusNotifications(demuxer_.get(), video_stream);
1661 } 1665 }
1662 1666
1667 // This test verifies that when a video stream is restarted, we do an internal
1668 // seek in the ffmpeg demuxer (because we need to read video frames starting
1669 // with the previous video key frame before the current playback position, so
1670 // that the video renderer is able to resume playback from the current media
1671 // time), but then we'd drop all audio packets up to the last_audio_packet_pos_,
1672 // because those have already been processed and are sitting in the audio stream
1673 // buffer queue, we don't want to duplicate those.
1674 TEST_F(FFmpegDemuxerTest, SeekAndDropSeenAudioPacketsAfterVideoRestart) {
1675 CreateDemuxer("bear-320x240.webm");
1676 InitializeDemuxer();
1677 FFmpegDemuxerStream* audio =
1678 static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
1679 FFmpegDemuxerStream* video =
1680 static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
1681 EXPECT_NE(nullptr, audio);
1682 EXPECT_NE(nullptr, video);
1683
1684 // The audio stream in the test file has audio frames with timestamps about 3
1685 // milliseconds apart (0, 3, 6, 9, 12, 15, 17, 20, 23etc). So setting stream
1686 // capacity to 5 millisec allows the demuxer to buffer 3 frames. We'll read
1687 // two of them immediately, so the demuxer will have read 5 frames from FFmpeg
1688 // by the time the video track is re-enabled.
1689 SetStreamCapacity(audio, base::TimeDelta::FromMilliseconds(5));
1690
1691 // Disable the video stream and read a few frames from the audio stream.
1692 demuxer_->OnSelectedVideoTrackChanged(base::nullopt, base::TimeDelta());
1693
1694 audio->Read(NewReadCB(FROM_HERE, 29, 0, true, DemuxerStream::kOk));
1695 base::RunLoop().Run();
1696 audio->Read(NewReadCB(FROM_HERE, 27, 3000, true, DemuxerStream::kOk));
1697 base::RunLoop().Run();
1698
1699 // At this point the demuxer have read frames with timestamps 0-15 millisec.
1700 // Now re-enable the video stream, which will cause an FFmpeg read position to
1701 // be seeked back to 0 (since the previous video key frame is at 0).
1702 demuxer_->OnSelectedVideoTrackChanged(MediaTrack::Id("1"), base::TimeDelta());
1703
1704 // Now verify that frames read from the audio stream are continuous, as
1705 // expected. There should be no duplicates or missing frames.
1706
1707 // The first three frames were read and buffered before the video track was
1708 // re-enabled.
1709 audio->Read(NewReadCB(FROM_HERE, 31, 6000, true, DemuxerStream::kOk));
1710 base::RunLoop().Run();
1711 audio->Read(NewReadCB(FROM_HERE, 30, 9000, true, DemuxerStream::kOk));
1712 base::RunLoop().Run();
1713 audio->Read(NewReadCB(FROM_HERE, 32, 12000, true, DemuxerStream::kOk));
1714 base::RunLoop().Run();
1715
1716 // And the following three frames were read when we freed up capacity by
1717 // reading the previous 3 frames above (i.e. after the video track was
1718 // restarted). These should continue the audio stream reading sequence.
1719 audio->Read(NewReadCB(FROM_HERE, 29, 15000, true, DemuxerStream::kOk));
1720 base::RunLoop().Run();
1721 audio->Read(NewReadCB(FROM_HERE, 31, 17000, true, DemuxerStream::kOk));
1722 base::RunLoop().Run();
1723 audio->Read(NewReadCB(FROM_HERE, 36, 20000, true, DemuxerStream::kOk));
1724 base::RunLoop().Run();
1725 }
1726
1727 TEST_F(FFmpegDemuxerTest, SeekDuringVideoStreamRestart) {
1728 CreateDemuxer("bear-320x240.webm");
1729 InitializeDemuxer();
1730 FFmpegDemuxerStream* video =
1731 static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
1732 EXPECT_NE(nullptr, video);
1733
1734 // Disable and then re-enable the video stream, this will initiate an
1735 // internal seek for the video stream.
1736 demuxer_->OnSelectedVideoTrackChanged(base::nullopt, base::TimeDelta());
1737 demuxer_->OnSelectedVideoTrackChanged(MediaTrack::Id("1"), base::TimeDelta());
1738
1739 // Now immediately request a seek to a different position. This should cancel
1740 // the previous seek and kick off a new seek.
1741 Seek(base::TimeDelta::FromMilliseconds(500));
1742
1743 // Verify that the next read returns the video buffer from the expected
1744 // position, matching the latest seek.
1745 video->Read(NewReadCB(FROM_HERE, 5636, 400000, true, DemuxerStream::kOk));
1746 base::RunLoop().Run();
1747 }
1748
1749 TEST_F(FFmpegDemuxerTest, VideoStreamRestartDuringSeek) {
1750 CreateDemuxer("bear-320x240.webm");
1751 InitializeDemuxer();
1752 FFmpegDemuxerStream* video =
1753 static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
1754 EXPECT_NE(nullptr, video);
1755
1756 demuxer_->OnSelectedVideoTrackChanged(base::nullopt, base::TimeDelta());
1757
1758 // Initiate a seek and re-enable the video track without waiting for the seek
1759 // to be completed.
1760 base::TimeDelta seek_target = base::TimeDelta::FromMilliseconds(500);
1761 WaitableMessageLoopEvent seek_event;
1762 demuxer_->Seek(seek_target, seek_event.GetPipelineStatusCB());
1763
1764 demuxer_->OnSelectedVideoTrackChanged(MediaTrack::Id("1"), base::TimeDelta());
1765
1766 // Wait for the seek to finish.
1767 seek_event.RunAndWaitForStatus(PIPELINE_OK);
1768
1769 // Verify that the next read returns the video buffer from the expected
1770 // position, matching the latest seek.
1771 video->Read(NewReadCB(FROM_HERE, 5636, 400000, true, DemuxerStream::kOk));
1772 base::RunLoop().Run();
1773 }
1774
1663 } // namespace media 1775 } // namespace media
OLDNEW
« 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