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

Unified Diff: media/base/android/media_codec_player_unittest.cc

Issue 1287423004: MediaCodecPlayer implementation (stage 5 - reconfiguration) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-cleanuptest
Patch Set: Fixed AdvanceAccessUnitQueue() Created 5 years, 4 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
« no previous file with comments | « media/base/android/media_codec_player.cc ('k') | media/base/android/media_codec_video_decoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/android/media_codec_player_unittest.cc
diff --git a/media/base/android/media_codec_player_unittest.cc b/media/base/android/media_codec_player_unittest.cc
index e57f7898d38c99436ea251c45287366b397c0205..37e00f58c68125f6c5d6f6400b6f73d4b2478e46 100644
--- a/media/base/android/media_codec_player_unittest.cc
+++ b/media/base/android/media_codec_player_unittest.cc
@@ -62,6 +62,8 @@ class MockMediaPlayerManager : public MediaPlayerManager {
MockMediaPlayerManager()
: playback_completed_(false),
num_seeks_completed_(0),
+ num_audio_codecs_created_(0),
+ num_video_codecs_created_(0),
weak_ptr_factory_(this) {}
~MockMediaPlayerManager() override {}
@@ -112,17 +114,25 @@ class MockMediaPlayerManager : public MediaPlayerManager {
void OnDecodersTimeUpdate(DemuxerStream::Type stream_type,
base::TimeDelta now_playing,
base::TimeDelta last_buffered) {
- PTSTime& hit = first_frame_hit_[stream_type];
- if (hit.is_null())
- hit = PTSTime(now_playing, base::TimeTicks::Now());
+ render_stat_[stream_type].AddValue(
+ PTSTime(now_playing, base::TimeTicks::Now()));
+ }
+
+ // Notification called on MediaCodec creation.
+ // Implementation dependent, used for testing only.
+ void OnMediaCodecCreated(DemuxerStream::Type stream_type) {
+ if (stream_type == DemuxerStream::AUDIO)
+ ++num_audio_codecs_created_;
+ else if (stream_type == DemuxerStream::VIDEO)
+ ++num_video_codecs_created_;
}
// First frame information
base::TimeDelta FirstFramePTS(DemuxerStream::Type stream_type) const {
- return first_frame_hit_[stream_type].pts;
+ return render_stat_[stream_type].min().pts;
}
base::TimeTicks FirstFrameTime(DemuxerStream::Type stream_type) const {
- return first_frame_hit_[stream_type].time;
+ return render_stat_[stream_type].min().time;
}
base::WeakPtr<MockMediaPlayerManager> GetWeakPtr() {
@@ -138,9 +148,12 @@ class MockMediaPlayerManager : public MediaPlayerManager {
}
bool IsSeekCompleted() const { return num_seeks_completed_ > 0; }
bool HasFirstFrame(DemuxerStream::Type stream_type) const {
- return !first_frame_hit_[stream_type].is_null();
+ return render_stat_[stream_type].num_values() != 0;
}
+ int num_audio_codecs_created() const { return num_audio_codecs_created_; }
+ int num_video_codecs_created() const { return num_video_codecs_created_; }
+
struct MediaMetadata {
base::TimeDelta duration;
int width;
@@ -150,20 +163,24 @@ class MockMediaPlayerManager : public MediaPlayerManager {
};
MediaMetadata media_metadata_;
- Minimax<base::TimeDelta> pts_stat_;
-
- private:
- bool playback_completed_;
- int num_seeks_completed_;
-
struct PTSTime {
base::TimeDelta pts;
base::TimeTicks time;
+
PTSTime() : pts(), time() {}
PTSTime(base::TimeDelta p, base::TimeTicks t) : pts(p), time(t) {}
bool is_null() const { return time.is_null(); }
+ bool operator<(const PTSTime& rhs) const { return time < rhs.time; }
};
- PTSTime first_frame_hit_[DemuxerStream::NUM_TYPES];
+ Minimax<PTSTime> render_stat_[DemuxerStream::NUM_TYPES];
+
+ Minimax<base::TimeDelta> pts_stat_;
+
+ private:
+ bool playback_completed_;
+ int num_seeks_completed_;
+ int num_audio_codecs_created_;
+ int num_video_codecs_created_;
base::WeakPtrFactory<MockMediaPlayerManager> weak_ptr_factory_;
@@ -382,6 +399,10 @@ void MockDemuxerAndroid::RequestDemuxerData(DemuxerStream::Type type) {
if (!created)
return;
+ // Request key frame after |kConfigChanged|
+ if (type == DemuxerStream::VIDEO && !chunk.demuxer_configs.empty())
+ video_factory_->RequestKeyFrame();
+
chunk.type = type;
// Post to the Media thread. Use the weak pointer to prevent the data arrival
@@ -1564,7 +1585,7 @@ TEST_F(MediaCodecPlayerTest, AVPrerollVideoEndsWhilePrerolling) {
// Start the playback.
player_->Start();
- // The video decoder should start prerolling
+ // The video decoder should start prerolling.
// Wait till preroll starts.
EXPECT_TRUE(WaitForCondition(
base::Bind(&MediaCodecPlayer::IsPrerollingForTests,
@@ -1588,4 +1609,238 @@ TEST_F(MediaCodecPlayerTest, AVPrerollVideoEndsWhilePrerolling) {
EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO));
}
+TEST_F(MediaCodecPlayerTest, VideoConfigChangeWhilePlaying) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that video only playback continues after video config change.
+
+ // Initialize video playback
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta config_change_position =
+ base::TimeDelta::FromMilliseconds(1000);
+
+ base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
+ base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ demuxer_->SetVideoFactory(
+ scoped_ptr<VideoFactory>(new VideoFactory(duration)));
+
+ demuxer_->video_factory()->RequestConfigChange(config_change_position);
+
+ CreatePlayer();
+ SetVideoSurface();
+
+ // Wait till the player is initialized on media thread.
+ EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
+ base::Unretained(demuxer_))));
+
+ if (!demuxer_->IsInitialized()) {
+ DVLOG(0) << "AVConfigChangeWhilePlaying: demuxer is not initialized";
+ return;
+ }
+
+ // Ask decoders to always reconfigure after the player has been initialized.
+ player_->SetAlwaysReconfigureForTests(DemuxerStream::VIDEO);
+
+ // Set a testing callback to receive PTS from decoders.
+ player_->SetDecodersTimeCallbackForTests(
+ base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
+ base::Unretained(&manager_)));
+
+ // Set a testing callback to receive MediaCodec creation events from decoders.
+ player_->SetCodecCreatedCallbackForTests(
+ base::Bind(&MockMediaPlayerManager::OnMediaCodecCreated,
+ base::Unretained(&manager_)));
+
+ // Post configuration after the player has been initialized.
+ demuxer_->PostInternalConfigs();
+
+ // Start and wait for playback.
+ player_->Start();
+
+ // Wait till we start to play.
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
+ base::Unretained(&manager_)),
+ start_timeout));
+
+ // Wait till completion
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
+ base::Unretained(&manager_)),
+ completion_timeout));
+
+ // The video codec should be recreated upon config changes.
+ EXPECT_EQ(2, manager_.num_video_codecs_created());
+
+ // Check that we did not miss video frames
+ int expected_video_frames = duration / kVideoFramePeriod + 1;
+ EXPECT_EQ(expected_video_frames,
+ manager_.render_stat_[DemuxerStream::VIDEO].num_values());
+}
+
+TEST_F(MediaCodecPlayerTest, AVVideoConfigChangeWhilePlaying) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that A/V playback continues after video config change.
+
+ // Initialize A/V playback
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta config_change_position =
+ base::TimeDelta::FromMilliseconds(1000);
+
+ base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
+ base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ demuxer_->SetAudioFactory(
+ scoped_ptr<AudioFactory>(new AudioFactory(duration)));
+ demuxer_->SetVideoFactory(
+ scoped_ptr<VideoFactory>(new VideoFactory(duration)));
+
+ demuxer_->video_factory()->RequestConfigChange(config_change_position);
+
+ CreatePlayer();
+ SetVideoSurface();
+
+ // Wait till the player is initialized on media thread.
+ EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
+ base::Unretained(demuxer_))));
+
+ if (!demuxer_->IsInitialized()) {
+ DVLOG(0) << "AVConfigChangeWhilePlaying: demuxer is not initialized";
+ return;
+ }
+
+ // Ask decoders to always reconfigure after the player has been initialized.
+ player_->SetAlwaysReconfigureForTests(DemuxerStream::VIDEO);
+
+ // Set a testing callback to receive PTS from decoders.
+ player_->SetDecodersTimeCallbackForTests(
+ base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
+ base::Unretained(&manager_)));
+
+ // Set a testing callback to receive MediaCodec creation events from decoders.
+ player_->SetCodecCreatedCallbackForTests(
+ base::Bind(&MockMediaPlayerManager::OnMediaCodecCreated,
+ base::Unretained(&manager_)));
+
+ // Post configuration after the player has been initialized.
+ demuxer_->PostInternalConfigs();
+
+ // Start and wait for playback.
+ player_->Start();
+
+ // Wait till we start to play.
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
+ base::Unretained(&manager_)),
+ start_timeout));
+
+ // Wait till completion
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
+ base::Unretained(&manager_)),
+ completion_timeout));
+
+ // The audio codec should be kept.
+ EXPECT_EQ(1, manager_.num_audio_codecs_created());
+
+ // The video codec should be recreated upon config changes.
+ EXPECT_EQ(2, manager_.num_video_codecs_created());
+
+ // Check that we did not miss video frames
+ int expected_video_frames = duration / kVideoFramePeriod + 1;
+ EXPECT_EQ(expected_video_frames,
+ manager_.render_stat_[DemuxerStream::VIDEO].num_values());
+
+ // Check that we did not miss audio frames. We expect two postponed frames
+ // that are not reported.
+ // For Nexus 4 KitKat the AAC decoder seems to swallow the first frame
+ // but reports the last pts twice, maybe it just shifts the reported PTS.
+ int expected_audio_frames = duration / kAudioFramePeriod + 1 - 2;
+ EXPECT_EQ(expected_audio_frames,
+ manager_.render_stat_[DemuxerStream::AUDIO].num_values());
+}
+
+TEST_F(MediaCodecPlayerTest, AVAudioConfigChangeWhilePlaying) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that A/V playback continues after audio config change.
+
+ // Initialize A/V playback
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta config_change_position =
+ base::TimeDelta::FromMilliseconds(1000);
+
+ base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
+ base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ demuxer_->SetAudioFactory(
+ scoped_ptr<AudioFactory>(new AudioFactory(duration)));
+ demuxer_->SetVideoFactory(
+ scoped_ptr<VideoFactory>(new VideoFactory(duration)));
+
+ demuxer_->audio_factory()->RequestConfigChange(config_change_position);
+
+ CreatePlayer();
+ SetVideoSurface();
+
+ // Wait till the player is initialized on media thread.
+ EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
+ base::Unretained(demuxer_))));
+
+ if (!demuxer_->IsInitialized()) {
+ DVLOG(0) << "AVConfigChangeWhilePlaying: demuxer is not initialized";
+ return;
+ }
+
+ // Ask decoders to always reconfigure after the player has been initialized.
+ player_->SetAlwaysReconfigureForTests(DemuxerStream::AUDIO);
+
+ // Set a testing callback to receive PTS from decoders.
+ player_->SetDecodersTimeCallbackForTests(
+ base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
+ base::Unretained(&manager_)));
+
+ // Set a testing callback to receive MediaCodec creation events from decoders.
+ player_->SetCodecCreatedCallbackForTests(
+ base::Bind(&MockMediaPlayerManager::OnMediaCodecCreated,
+ base::Unretained(&manager_)));
+
+ // Post configuration after the player has been initialized.
+ demuxer_->PostInternalConfigs();
+
+ // Start and wait for playback.
+ player_->Start();
+
+ // Wait till we start to play.
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
+ base::Unretained(&manager_)),
+ start_timeout));
+
+ // Wait till completion
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
+ base::Unretained(&manager_)),
+ completion_timeout));
+
+ // The audio codec should be recreated upon config changes.
+ EXPECT_EQ(2, manager_.num_audio_codecs_created());
+
+ // The video codec should be kept.
+ EXPECT_EQ(1, manager_.num_video_codecs_created());
+
+ // Check that we did not miss video frames.
+ int expected_video_frames = duration / kVideoFramePeriod + 1;
+ EXPECT_EQ(expected_video_frames,
+ manager_.render_stat_[DemuxerStream::VIDEO].num_values());
+
+ // Check that we did not miss audio frames. We expect two postponed frames
+ // that are not reported.
+ int expected_audio_frames = duration / kAudioFramePeriod + 1 - 2;
+ EXPECT_EQ(expected_audio_frames,
+ manager_.render_stat_[DemuxerStream::AUDIO].num_values());
+}
+
} // namespace media
« no previous file with comments | « media/base/android/media_codec_player.cc ('k') | media/base/android/media_codec_video_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698