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

Unified Diff: media/renderers/renderer_impl_unittest.cc

Issue 2684103005: Allow media track switching. (Closed)
Patch Set: Updated log message Created 3 years, 9 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
Index: media/renderers/renderer_impl_unittest.cc
diff --git a/media/renderers/renderer_impl_unittest.cc b/media/renderers/renderer_impl_unittest.cc
index 77480f96ac2c945bf0ed02cbcc10d511c10eb559..7216d7a69e5fabba14d5a57c2226a46ce2e9d0ac 100644
--- a/media/renderers/renderer_impl_unittest.cc
+++ b/media/renderers/renderer_impl_unittest.cc
@@ -5,6 +5,7 @@
#include <stdint.h>
#include <memory>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -32,6 +33,10 @@ namespace media {
const int64_t kStartPlayingTimeInMs = 100;
+ACTION_P2(SetBool, var, value) {
+ *var = value;
+}
+
ACTION_P2(SetBufferingState, renderer_client, buffering_state) {
(*renderer_client)->OnBufferingStateChange(buffering_state);
}
@@ -226,10 +231,7 @@ class RendererImplTest : public ::testing::Test {
base::RunLoop().RunUntilIdle();
}
- void Flush(bool underflowed) {
- if (!underflowed)
- EXPECT_CALL(time_source_, StopTicking());
-
+ void SetFlushExpectationsForAVRenderers() {
if (audio_stream_) {
EXPECT_CALL(*audio_renderer_, Flush(_))
.WillOnce(DoAll(SetBufferingState(&audio_renderer_client_,
@@ -243,7 +245,13 @@ class RendererImplTest : public ::testing::Test {
BUFFERING_HAVE_NOTHING),
RunClosure<0>()));
}
+ }
+ void Flush(bool underflowed) {
+ if (!underflowed)
+ EXPECT_CALL(time_source_, StopTicking());
+
+ SetFlushExpectationsForAVRenderers();
EXPECT_CALL(callbacks_, OnFlushed());
renderer_impl_->Flush(
@@ -848,4 +856,217 @@ TEST_F(RendererImplTest, PostponedStreamStatusNotificationHandling) {
base::RunLoop().Run();
}
-} // namespace media
+// Verify that a RendererImpl::Flush gets postponed until after stream status
+// change handling is completed.
+TEST_F(RendererImplTest, FlushDuringAudioReinit) {
+ CreateAudioAndVideoStream();
+
+ StreamStatusChangeCB stream_status_change_cb;
+ EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_))
+ .WillOnce(SaveArg<0>(&stream_status_change_cb));
+ SetAudioRendererInitializeExpectations(PIPELINE_OK);
+ SetVideoRendererInitializeExpectations(PIPELINE_OK);
+ InitializeAndExpect(PIPELINE_OK);
+ Play();
+
+ EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber());
+ base::Closure audio_renderer_flush_cb;
+ EXPECT_CALL(*audio_renderer_, Flush(_))
+ .WillOnce(SaveArg<0>(&audio_renderer_flush_cb));
+ EXPECT_CALL(*audio_renderer_, StartPlaying())
+ .Times(1)
+ .WillOnce(
+ SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH));
+
+ // This should start flushing the audio renderer (due to audio stream status
+ // change) and should populate the |audio_renderer_flush_cb|.
+ stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta());
+ EXPECT_TRUE(audio_renderer_flush_cb);
+ base::RunLoop().RunUntilIdle();
+
+ bool flush_done = false;
+
+ // Now that audio stream change is being handled the RendererImpl::Flush
+ // should be postponed, instead of being executed immediately.
+ EXPECT_CALL(callbacks_, OnFlushed()).WillOnce(SetBool(&flush_done, true));
+ renderer_impl_->Flush(
+ base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(flush_done);
+
+ // The renderer_impl_->Flush invoked above should proceed after the first
+ // audio renderer flush (initiated by the stream status change) completes.
+ SetFlushExpectationsForAVRenderers();
+ audio_renderer_flush_cb.Run();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(flush_done);
+}
+
+TEST_F(RendererImplTest, FlushDuringVideoReinit) {
+ CreateAudioAndVideoStream();
+
+ StreamStatusChangeCB stream_status_change_cb;
+ EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_))
+ .WillOnce(SaveArg<0>(&stream_status_change_cb));
+ SetAudioRendererInitializeExpectations(PIPELINE_OK);
+ SetVideoRendererInitializeExpectations(PIPELINE_OK);
+ InitializeAndExpect(PIPELINE_OK);
+ Play();
+
+ EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber());
+ base::Closure video_renderer_flush_cb;
+ EXPECT_CALL(*video_renderer_, Flush(_))
+ .WillOnce(SaveArg<0>(&video_renderer_flush_cb));
+ EXPECT_CALL(*video_renderer_, StartPlayingFrom(_))
+ .Times(1)
+ .WillOnce(
+ SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH));
+
+ // This should start flushing the video renderer (due to video stream status
+ // change) and should populate the |video_renderer_flush_cb|.
+ stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta());
+ EXPECT_TRUE(video_renderer_flush_cb);
+ base::RunLoop().RunUntilIdle();
+
+ bool flush_done = false;
+
+ // Now that video stream change is being handled the RendererImpl::Flush
+ // should be postponed, instead of being executed immediately.
+ EXPECT_CALL(callbacks_, OnFlushed()).WillOnce(SetBool(&flush_done, true));
+ renderer_impl_->Flush(
+ base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(flush_done);
+
+ // The renderer_impl_->Flush invoked above should proceed after the first
+ // video renderer flush (initiated by the stream status change) completes.
+ SetFlushExpectationsForAVRenderers();
+ video_renderer_flush_cb.Run();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(flush_done);
+}
+
+TEST_F(RendererImplTest, AudioTrackSwitchDuringFlush) {
+ CreateAudioAndVideoStream();
+ std::unique_ptr<StrictMock<MockDemuxerStream>> primary_audio_stream =
+ std::move(audio_stream_);
+ CreateAudioStream();
+ std::unique_ptr<StrictMock<MockDemuxerStream>> secondary_audio_stream =
+ std::move(audio_stream_);
+ audio_stream_ = std::move(primary_audio_stream);
+
+ StreamStatusChangeCB stream_status_change_cb;
+ EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_))
+ .WillOnce(SaveArg<0>(&stream_status_change_cb));
+ SetAudioRendererInitializeExpectations(PIPELINE_OK);
+ SetVideoRendererInitializeExpectations(PIPELINE_OK);
+ InitializeAndExpect(PIPELINE_OK);
+ Play();
+
+ EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber());
+ EXPECT_CALL(*video_renderer_, Flush(_))
+ .WillRepeatedly(DoAll(
+ SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING),
+ RunClosure<0>()));
+
+ // Initiate RendererImpl::Flush, but postpone its completion by not calling
+ // audio renderer flush callback right away, i.e. pretending audio renderer
+ // flush takes a while.
+ base::Closure audio_renderer_flush_cb;
+ EXPECT_CALL(*audio_renderer_, Flush(_))
+ .WillOnce(SaveArg<0>(&audio_renderer_flush_cb));
+ EXPECT_CALL(callbacks_, OnFlushed());
+ renderer_impl_->Flush(
+ base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(audio_renderer_flush_cb);
+
+ // Now, while the RendererImpl::Flush is pending, perform an audio track
+ // switch. The handling of the track switch will be postponed until after
+ // RendererImpl::Flush completes.
+ stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta());
+ stream_status_change_cb.Run(secondary_audio_stream.get(), true,
+ base::TimeDelta());
+
+ // After RendererImpl::Flush we expect audio renderer flush to happen again,
+ // due to audio track switch handling. And we expect the audio renderer to be
+ // reinitialized for the secondary_audio_stream.
+ EXPECT_CALL(*audio_renderer_, Flush(_))
+ .WillRepeatedly(DoAll(
+ SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING),
+ RunClosure<0>()));
+ EXPECT_CALL(*audio_renderer_, StartPlaying())
+ .WillRepeatedly(
+ SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH));
+ EXPECT_CALL(*audio_renderer_,
+ Initialize(secondary_audio_stream.get(), _, _, _));
+
+ audio_renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING);
+ audio_renderer_flush_cb.Run();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(RendererImplTest, VideoTrackSwitchDuringFlush) {
+ CreateAudioAndVideoStream();
+ std::unique_ptr<StrictMock<MockDemuxerStream>> primary_video_stream =
+ std::move(video_stream_);
+ CreateVideoStream();
+ std::unique_ptr<StrictMock<MockDemuxerStream>> secondary_video_stream =
+ std::move(video_stream_);
+ video_stream_ = std::move(primary_video_stream);
+
+ StreamStatusChangeCB stream_status_change_cb;
+ EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_))
+ .WillOnce(SaveArg<0>(&stream_status_change_cb));
+ SetAudioRendererInitializeExpectations(PIPELINE_OK);
+ SetVideoRendererInitializeExpectations(PIPELINE_OK);
+ InitializeAndExpect(PIPELINE_OK);
+ Play();
+
+ EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber());
+ EXPECT_CALL(*audio_renderer_, Flush(_))
+ .WillRepeatedly(DoAll(
+ SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING),
+ RunClosure<0>()));
+
+ // Initiate RendererImpl::Flush, but postpone its completion by not calling
+ // video renderer flush callback right away, i.e. pretending video renderer
+ // flush takes a while.
+ base::Closure video_renderer_flush_cb;
+ EXPECT_CALL(*video_renderer_, Flush(_))
+ .WillOnce(SaveArg<0>(&video_renderer_flush_cb));
+ EXPECT_CALL(callbacks_, OnFlushed());
+ renderer_impl_->Flush(
+ base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(video_renderer_flush_cb);
+
+ // Now, while the RendererImpl::Flush is pending, perform a video track
+ // switch. The handling of the track switch will be postponed until after
+ // RendererImpl::Flush completes.
+ stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta());
+ stream_status_change_cb.Run(secondary_video_stream.get(), true,
+ base::TimeDelta());
+
+ // After RendererImpl::Flush we expect video renderer flush to happen again,
+ // due to video track switch handling. And we expect the video renderer to be
+ // reinitialized for the video.
+ EXPECT_CALL(*video_renderer_, Flush(_))
+ .WillRepeatedly(DoAll(
+ SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING),
+ RunClosure<0>()));
+ EXPECT_CALL(*video_renderer_, StartPlayingFrom(_))
+ .WillRepeatedly(
+ SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH));
+ EXPECT_CALL(*video_renderer_, OnTimeProgressing())
+ .Times(testing::AnyNumber());
+ EXPECT_CALL(*video_renderer_, OnTimeStopped()).Times(testing::AnyNumber());
+ EXPECT_CALL(*video_renderer_,
+ Initialize(secondary_video_stream.get(), _, _, _, _));
+
+ video_renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING);
+ video_renderer_flush_cb.Run();
+ base::RunLoop().RunUntilIdle();
+}
+
+} // namespace medi
DaleCurtis 2017/04/03 19:17:59 media
servolk 2017/04/03 20:31:12 Done.

Powered by Google App Engine
This is Rietveld 408576698