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

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

Issue 1312103006: MediaCodecPlayer - preroll and reconfiguration fixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-reconfig
Patch Set: Rebased Created 5 years, 3 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') | no next file » | 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 c20cf7daa7b7fdfa758cc6f1a5467dd5d48d6b54..0742bf78bb468d6c5db4097040f57a8fb32809cb 100644
--- a/media/base/android/media_codec_player_unittest.cc
+++ b/media/base/android/media_codec_player_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <stdint.h>
+
#include "base/bind.h"
#include "base/logging.h"
#include "base/timer/timer.h"
@@ -43,6 +45,11 @@ const base::TimeDelta kAudioFramePeriod =
base::TimeDelta::FromSecondsD(1024.0 / 44100); // 1024 samples @ 44100 Hz
const base::TimeDelta kVideoFramePeriod = base::TimeDelta::FromMilliseconds(20);
+enum Flags {
+ kAlwaysReconfigAudio = 0x1,
+ kAlwaysReconfigVideo = 0x2,
+};
+
// The predicate that always returns false, used for WaitForDelay implementation
bool AlwaysFalse() {
return false;
@@ -217,6 +224,7 @@ DemuxerConfigs CreateAudioVideoConfigs(const TestDataFactory* audio,
result.video_codec = vconf.video_codec;
result.video_size = vconf.video_size;
result.is_video_encrypted = vconf.is_video_encrypted;
+ result.duration = std::max(result.duration, vconf.duration);
return result;
}
@@ -530,13 +538,20 @@ class MediaCodecPlayerTest : public testing::Test {
// started.
bool StartVideoPlayback(base::TimeDelta duration, const char* test_name);
+ // Helper method that starts audio and video streams.
+ bool StartAVPlayback(scoped_ptr<AudioFactory> audio_factory,
+ scoped_ptr<VideoFactory> video_factory,
+ uint32_t flags,
+ const char* test_name);
+
// Helper method that starts audio and video streams with preroll.
// The preroll is achieved by setting significant video preroll interval
// so video will have to catch up with audio. To make room for this interval
// the Start() command is preceded by SeekTo().
- bool StartAVSeekAndPreroll(base::TimeDelta duration,
+ bool StartAVSeekAndPreroll(scoped_ptr<AudioFactory> audio_factory,
+ scoped_ptr<VideoFactory> video_factory,
base::TimeDelta seek_position,
- base::TimeDelta video_preroll,
+ uint32_t flags,
const char* test_name);
// Callback sent when demuxer is being deleted.
@@ -702,26 +717,78 @@ bool MediaCodecPlayerTest::StartVideoPlayback(base::TimeDelta duration,
return true;
}
-bool MediaCodecPlayerTest::StartAVSeekAndPreroll(base::TimeDelta duration,
- base::TimeDelta seek_position,
- base::TimeDelta video_preroll,
- const char* test_name) {
- const base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
+bool MediaCodecPlayerTest::StartAVPlayback(
+ scoped_ptr<AudioFactory> audio_factory,
+ scoped_ptr<VideoFactory> video_factory,
+ uint32_t flags,
+ const char* test_name) {
+ demuxer_->SetAudioFactory(audio_factory.Pass());
+ demuxer_->SetVideoFactory(video_factory.Pass());
- demuxer_->SetVideoPrerollInterval(video_preroll);
+ CreatePlayer();
+ SetVideoSurface();
- demuxer_->SetAudioFactory(
- scoped_ptr<AudioFactory>(new AudioFactory(duration)));
- demuxer_->SetVideoFactory(
- scoped_ptr<VideoFactory>(new VideoFactory(duration)));
+ // Wait till the player is initialized on media thread.
+ EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
+ base::Unretained(demuxer_))));
- CreatePlayer();
+ if (!demuxer_->IsInitialized()) {
+ DVLOG(0) << test_name << ": demuxer is not initialized";
+ return false;
+ }
- // Set special testing callback to receive PTS from decoders.
+ // Ask decoders to always reconfigure after the player has been initialized.
+ if (flags & kAlwaysReconfigAudio)
+ player_->SetAlwaysReconfigureForTests(DemuxerStream::AUDIO);
+ if (flags & kAlwaysReconfigVideo)
+ 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.
+ base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
+
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
+ base::Unretained(&manager_)),
+ start_timeout));
+
+ if (!manager_.IsPlaybackStarted()) {
+ DVLOG(0) << test_name << ": playback did not start";
+ return false;
+ }
+
+ return true;
+}
+
+bool MediaCodecPlayerTest::StartAVSeekAndPreroll(
+ scoped_ptr<AudioFactory> audio_factory,
+ scoped_ptr<VideoFactory> video_factory,
+ base::TimeDelta seek_position,
+ uint32_t flags,
+ const char* test_name) {
+ // Initialize A/V playback
+
+ demuxer_->SetAudioFactory(audio_factory.Pass());
+ demuxer_->SetVideoFactory(video_factory.Pass());
+
+ CreatePlayer();
+ SetVideoSurface();
+
// Wait till the player is initialized on media thread.
EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
base::Unretained(demuxer_))));
@@ -731,7 +798,21 @@ bool MediaCodecPlayerTest::StartAVSeekAndPreroll(base::TimeDelta duration,
return false;
}
- SetVideoSurface();
+ // Ask decoders to always reconfigure after the player has been initialized.
+ if (flags & kAlwaysReconfigAudio)
+ player_->SetAlwaysReconfigureForTests(DemuxerStream::AUDIO);
+ if (flags & kAlwaysReconfigVideo)
+ 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();
@@ -743,6 +824,7 @@ bool MediaCodecPlayerTest::StartAVSeekAndPreroll(base::TimeDelta duration,
player_->Start();
// Wait till preroll starts.
+ base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
EXPECT_TRUE(WaitForCondition(
base::Bind(&MediaCodecPlayer::IsPrerollingForTests,
base::Unretained(player_), DemuxerStream::VIDEO),
@@ -1367,7 +1449,13 @@ TEST_F(MediaCodecPlayerTest, AVPrerollAudioWaitsForVideo) {
base::TimeDelta preroll_intvl = base::TimeDelta::FromMilliseconds(500);
base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000);
- ASSERT_TRUE(StartAVSeekAndPreroll(duration, seek_position, preroll_intvl,
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
+
+ demuxer_->SetVideoPrerollInterval(preroll_intvl);
+
+ ASSERT_TRUE(StartAVSeekAndPreroll(audio_factory.Pass(), video_factory.Pass(),
+ seek_position, 0,
"AVPrerollAudioWaitsForVideo"));
// Wait till preroll finishes and the real playback starts.
@@ -1410,7 +1498,13 @@ TEST_F(MediaCodecPlayerTest, AVPrerollReleaseAndRestart) {
base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000);
- ASSERT_TRUE(StartAVSeekAndPreroll(duration, seek_position, preroll_intvl,
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
+
+ demuxer_->SetVideoPrerollInterval(preroll_intvl);
+
+ ASSERT_TRUE(StartAVSeekAndPreroll(audio_factory.Pass(), video_factory.Pass(),
+ seek_position, 0,
"AVPrerollReleaseAndRestart"));
// Issue Release().
@@ -1478,7 +1572,13 @@ TEST_F(MediaCodecPlayerTest, AVPrerollStopAndRestart) {
base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000);
- ASSERT_TRUE(StartAVSeekAndPreroll(duration, seek_position, preroll_intvl,
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
+
+ demuxer_->SetVideoPrerollInterval(preroll_intvl);
+
+ ASSERT_TRUE(StartAVSeekAndPreroll(audio_factory.Pass(), video_factory.Pass(),
+ seek_position, 0,
"AVPrerollStopAndRestart"));
// Video stream should be prerolling. Request to stop.
@@ -1681,7 +1781,7 @@ TEST_F(MediaCodecPlayerTest, VideoConfigChangeWhilePlaying) {
base::Unretained(demuxer_))));
if (!demuxer_->IsInitialized()) {
- DVLOG(0) << "AVConfigChangeWhilePlaying: demuxer is not initialized";
+ DVLOG(0) << "VideoConfigChangeWhilePlaying: demuxer is not initialized";
return;
}
@@ -1735,52 +1835,16 @@ TEST_F(MediaCodecPlayerTest, AVVideoConfigChangeWhilePlaying) {
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();
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
- // Start and wait for playback.
- player_->Start();
+ video_factory->RequestConfigChange(config_change_position);
- // Wait till we start to play.
- EXPECT_TRUE(
- WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
- base::Unretained(&manager_)),
- start_timeout));
+ ASSERT_TRUE(StartAVPlayback(audio_factory.Pass(), video_factory.Pass(),
+ kAlwaysReconfigVideo,
+ "AVVideoConfigChangeWhilePlaying"));
// Wait till completion
EXPECT_TRUE(
@@ -1799,11 +1863,11 @@ TEST_F(MediaCodecPlayerTest, AVVideoConfigChangeWhilePlaying) {
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
+ // Check that we did not miss audio frames. We expect one 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;
+ int expected_audio_frames = duration / kAudioFramePeriod + 1 - 1;
EXPECT_EQ(expected_audio_frames,
manager_.render_stat_[DemuxerStream::AUDIO].num_values());
}
@@ -1813,57 +1877,113 @@ TEST_F(MediaCodecPlayerTest, AVAudioConfigChangeWhilePlaying) {
// 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)));
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
- demuxer_->audio_factory()->RequestConfigChange(config_change_position);
+ audio_factory->RequestConfigChange(config_change_position);
- CreatePlayer();
- SetVideoSurface();
+ ASSERT_TRUE(StartAVPlayback(audio_factory.Pass(), video_factory.Pass(),
+ kAlwaysReconfigAudio,
+ "AVAudioConfigChangeWhilePlaying"));
- // Wait till the player is initialized on media thread.
- EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
- base::Unretained(demuxer_))));
+ // Wait till completion
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
+ base::Unretained(&manager_)),
+ completion_timeout));
- if (!demuxer_->IsInitialized()) {
- DVLOG(0) << "AVConfigChangeWhilePlaying: demuxer is not initialized";
- return;
- }
+ // The audio codec should be recreated upon config changes.
+ EXPECT_EQ(2, manager_.num_audio_codecs_created());
- // Ask decoders to always reconfigure after the player has been initialized.
- player_->SetAlwaysReconfigureForTests(DemuxerStream::AUDIO);
+ // The video codec should be kept.
+ EXPECT_EQ(1, manager_.num_video_codecs_created());
- // Set a testing callback to receive PTS from decoders.
- player_->SetDecodersTimeCallbackForTests(
- base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
- base::Unretained(&manager_)));
+ // 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());
- // Set a testing callback to receive MediaCodec creation events from decoders.
- player_->SetCodecCreatedCallbackForTests(
- base::Bind(&MockMediaPlayerManager::OnMediaCodecCreated,
- base::Unretained(&manager_)));
+ // 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());
+}
- // Post configuration after the player has been initialized.
- demuxer_->PostInternalConfigs();
+TEST_F(MediaCodecPlayerTest, AVSimultaneousConfigChange_1) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
- // Start and wait for playback.
- player_->Start();
+ // Test that the playback continues if audio and video config changes happen
+ // at the same time.
- // Wait till we start to play.
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta config_change_audio = base::TimeDelta::FromMilliseconds(1000);
+ base::TimeDelta config_change_video = base::TimeDelta::FromMilliseconds(1000);
+
+ base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
+
+ audio_factory->RequestConfigChange(config_change_audio);
+ video_factory->RequestConfigChange(config_change_video);
+
+ ASSERT_TRUE(StartAVPlayback(audio_factory.Pass(), video_factory.Pass(),
+ kAlwaysReconfigAudio | kAlwaysReconfigVideo,
+ "AVSimultaneousConfigChange_1"));
+
+ // Wait till completion
EXPECT_TRUE(
- WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
base::Unretained(&manager_)),
- start_timeout));
+ completion_timeout));
+
+ // The audio codec should be recreated upon config changes.
+ EXPECT_EQ(2, 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.
+ int expected_audio_frames = duration / kAudioFramePeriod + 1 - 2;
+ EXPECT_EQ(expected_audio_frames,
+ manager_.render_stat_[DemuxerStream::AUDIO].num_values());
+}
+
+TEST_F(MediaCodecPlayerTest, AVSimultaneousConfigChange_2) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that the playback continues if audio and video config changes happen
+ // at the same time. Move audio change moment slightly to make it drained
+ // after video.
+
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta config_change_audio = base::TimeDelta::FromMilliseconds(1020);
+ base::TimeDelta config_change_video = base::TimeDelta::FromMilliseconds(1000);
+
+ base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
+
+ audio_factory->RequestConfigChange(config_change_audio);
+ video_factory->RequestConfigChange(config_change_video);
+
+ ASSERT_TRUE(StartAVPlayback(audio_factory.Pass(), video_factory.Pass(),
+ kAlwaysReconfigAudio | kAlwaysReconfigVideo,
+ "AVSimultaneousConfigChange_2"));
// Wait till completion
EXPECT_TRUE(
@@ -1874,8 +1994,8 @@ TEST_F(MediaCodecPlayerTest, AVAudioConfigChangeWhilePlaying) {
// 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());
+ // 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;
@@ -1889,4 +2009,197 @@ TEST_F(MediaCodecPlayerTest, AVAudioConfigChangeWhilePlaying) {
manager_.render_stat_[DemuxerStream::AUDIO].num_values());
}
+TEST_F(MediaCodecPlayerTest, AVAudioEndsAcrossVideoConfigChange) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that audio can end while video config change processing.
+
+ base::TimeDelta audio_duration = base::TimeDelta::FromMilliseconds(1000);
+ base::TimeDelta video_duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta config_change_video = base::TimeDelta::FromMilliseconds(1000);
+
+ base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(audio_duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(video_duration));
+
+ video_factory->RequestConfigChange(config_change_video);
+
+ ASSERT_TRUE(StartAVPlayback(audio_factory.Pass(), video_factory.Pass(),
+ kAlwaysReconfigVideo,
+ "AVAudioEndsAcrossVideoConfigChange"));
+
+ // Wait till completion
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
+ base::Unretained(&manager_)),
+ completion_timeout));
+
+ // The audio codec should not be recreated.
+ 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 = video_duration / kVideoFramePeriod + 1;
+ EXPECT_EQ(expected_video_frames,
+ manager_.render_stat_[DemuxerStream::VIDEO].num_values());
+
+ // Check the last video frame timestamp. The maximum render pts may differ
+ // from |video_duration| because of the testing artefact: if the last video
+ // chunk is incomplete if will have different last pts due to B-frames
+ // rearrangements.
+ EXPECT_LE(video_duration,
+ manager_.render_stat_[DemuxerStream::VIDEO].max().pts);
+
+ // Check that the playback time reported by the player goes past
+ // the audio time and corresponds to video after the audio ended.
+ EXPECT_EQ(video_duration, manager_.pts_stat_.max());
+}
+
+TEST_F(MediaCodecPlayerTest, AVVideoEndsAcrossAudioConfigChange) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that video can end while audio config change processing.
+ base::TimeDelta audio_duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta video_duration = base::TimeDelta::FromMilliseconds(1000);
+ base::TimeDelta config_change_audio = base::TimeDelta::FromMilliseconds(1000);
+
+ base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(audio_duration));
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(video_duration));
+
+ audio_factory->RequestConfigChange(config_change_audio);
+
+ ASSERT_TRUE(StartAVPlayback(audio_factory.Pass(), video_factory.Pass(),
+ kAlwaysReconfigAudio,
+ "AVVideoEndsAcrossAudioConfigChange"));
+
+ // 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 not be recreated.
+ EXPECT_EQ(1, manager_.num_video_codecs_created());
+
+ // Check that we did not miss audio frames. We expect two postponed frames
+ // that are not reported.
+ int expected_audio_frames = audio_duration / kAudioFramePeriod + 1 - 2;
+ EXPECT_EQ(expected_audio_frames,
+ manager_.render_stat_[DemuxerStream::AUDIO].num_values());
+}
+
+TEST_F(MediaCodecPlayerTest, AVPrerollAcrossVideoConfigChange) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that preroll continues if interrupted by video config change.
+
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
+ base::TimeDelta config_change_position =
+ base::TimeDelta::FromMilliseconds(800);
+ base::TimeDelta video_preroll_intvl = base::TimeDelta::FromMilliseconds(500);
+ base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ demuxer_->SetVideoPrerollInterval(video_preroll_intvl);
+
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
+ video_factory->RequestConfigChange(config_change_position);
+
+ ASSERT_TRUE(StartAVSeekAndPreroll(audio_factory.Pass(), video_factory.Pass(),
+ seek_position, kAlwaysReconfigVideo,
+ "AVPrerollAcrossVideoConfigChange"));
+
+ // Wait till preroll finishes and the real playback starts.
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
+ base::Unretained(&manager_)),
+ preroll_timeout));
+
+ // The presense of config change should not affect preroll behavior:
+
+ // Ensure that the first audio and video pts are close to each other and are
+ // reported at the close moments in time.
+
+ EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
+ EXPECT_TRUE(WaitForCondition(
+ base::Bind(&MockMediaPlayerManager::HasFirstFrame,
+ base::Unretained(&manager_), DemuxerStream::VIDEO)));
+
+ EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO),
+ manager_.FirstFramePTS(DemuxerStream::VIDEO), 25));
+
+ EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO),
+ manager_.FirstFrameTime(DemuxerStream::VIDEO), 50));
+
+ // The playback should start at |seek_position|
+ EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
+}
+
+TEST_F(MediaCodecPlayerTest, AVPrerollAcrossAudioConfigChange) {
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+ // Test that preroll continues if interrupted by video config change.
+
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
+ base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
+ base::TimeDelta config_change_position =
+ base::TimeDelta::FromMilliseconds(800);
+ base::TimeDelta audio_preroll_intvl = base::TimeDelta::FromMilliseconds(400);
+ base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(3000);
+
+ demuxer_->SetAudioPrerollInterval(audio_preroll_intvl);
+
+ scoped_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
+ audio_factory->RequestConfigChange(config_change_position);
+
+ scoped_ptr<VideoFactory> video_factory(new VideoFactory(duration));
+
+ ASSERT_TRUE(StartAVSeekAndPreroll(audio_factory.Pass(), video_factory.Pass(),
+ seek_position, kAlwaysReconfigAudio,
+ "AVPrerollAcrossAudioConfigChange"));
+
+ // Wait till preroll finishes and the real playback starts.
+ EXPECT_TRUE(
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
+ base::Unretained(&manager_)),
+ preroll_timeout));
+
+ // The presense of config change should not affect preroll behavior:
+
+ // Ensure that the first audio and video pts are close to each other and are
+ // reported at the close moments in time.
+
+ EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
+ EXPECT_TRUE(WaitForCondition(
+ base::Bind(&MockMediaPlayerManager::HasFirstFrame,
+ base::Unretained(&manager_), DemuxerStream::VIDEO)));
+
+ // Wait for some more video
+ WaitForDelay(base::TimeDelta::FromMilliseconds(100));
+
+ EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO),
+ manager_.FirstFramePTS(DemuxerStream::VIDEO), 25));
+
+ // Because for video preroll the first frame after preroll renders during the
+ // preroll stage (and not after the preroll is done) we cannot guarantee the
+ // proper video timimg in this test.
+ // TODO(timav): maybe we should not call the testing callback for
+ // kRenderAfterPreroll for video (for audio we already do not call).
+ // EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO),
+ // manager_.FirstFrameTime(DemuxerStream::VIDEO), 50));
+
+ // The playback should start at |seek_position|
+ EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
+}
+
} // namespace media
« no previous file with comments | « media/base/android/media_codec_player.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698