summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorqinmin <qinmin@chromium.org>2014-10-24 16:47:51 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-24 23:48:17 +0000
commit4aa66df2e01c9284c82d85ab1926005f379d91e3 (patch)
tree00fc64c572ba6e9a6435eda6de2724924903c52b /media
parent15fedbd0994ffb9a515d18336490a09e572fa038 (diff)
downloadchromium_src-4aa66df2e01c9284c82d85ab1926005f379d91e3.zip
chromium_src-4aa66df2e01c9284c82d85ab1926005f379d91e3.tar.gz
chromium_src-4aa66df2e01c9284c82d85ab1926005f379d91e3.tar.bz2
Don't let input buffer overwhelm output buffer
When dequeueInputBuffer returns a OUTPUT_FORMAT_CHANGED or OUTPUT_BUFFER_CHANGED, the buffer is not actually dequeued. However, we still queue an input buffer in the next decode cycle. As a result, the balance between input and output buffer is broken. This change fixes the issue so that we will skip queueing an input buffer when that happens internal b/17662122 Review URL: https://codereview.chromium.org/650293005 Cr-Commit-Position: refs/heads/master@{#301229}
Diffstat (limited to 'media')
-rw-r--r--media/base/android/media_decoder_job.cc48
-rw-r--r--media/base/android/media_source_player_unittest.cc126
2 files changed, 106 insertions, 68 deletions
diff --git a/media/base/android/media_decoder_job.cc b/media/base/android/media_decoder_job.cc
index 2ab5db0..9eb7fac 100644
--- a/media/base/android/media_decoder_job.cc
+++ b/media/base/android/media_decoder_job.cc
@@ -24,7 +24,8 @@ MediaDecoderJob::MediaDecoderJob(
const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner,
const base::Closure& request_data_cb,
const base::Closure& config_changed_cb)
- : ui_task_runner_(base::MessageLoopProxy::current()),
+ : need_to_reconfig_decoder_job_(false),
+ ui_task_runner_(base::MessageLoopProxy::current()),
decoder_task_runner_(decoder_task_runner),
needs_flush_(false),
input_eos_encountered_(false),
@@ -421,20 +422,31 @@ void MediaDecoderJob::DecodeInternal(
base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(
kMediaCodecTimeoutInMilliseconds);
- MediaCodecStatus status =
- media_codec_bridge_->DequeueOutputBuffer(timeout,
- &buffer_index,
- &offset,
- &size,
- &presentation_timestamp,
- &output_eos_encountered_,
- NULL);
-
- if (status != MEDIA_CODEC_OK) {
+ MediaCodecStatus status = MEDIA_CODEC_OK;
+ bool has_format_change = false;
+ // Dequeue the output buffer until a MEDIA_CODEC_OK, MEDIA_CODEC_ERROR or
+ // MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER is received.
+ do {
+ status = media_codec_bridge_->DequeueOutputBuffer(
+ timeout,
+ &buffer_index,
+ &offset,
+ &size,
+ &presentation_timestamp,
+ &output_eos_encountered_,
+ NULL);
if (status == MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED &&
!media_codec_bridge_->GetOutputBuffers()) {
status = MEDIA_CODEC_ERROR;
+ } else if (status == MEDIA_CODEC_OUTPUT_FORMAT_CHANGED) {
+ // TODO(qinmin): instead of waiting for the next output buffer to be
+ // dequeued, post a task on the UI thread to signal the format change.
+ has_format_change = true;
}
+ } while (status != MEDIA_CODEC_OK && status != MEDIA_CODEC_ERROR &&
+ status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER);
+
+ if (status != MEDIA_CODEC_OK) {
callback.Run(status, kNoTimestamp(), kNoTimestamp());
return;
}
@@ -442,6 +454,8 @@ void MediaDecoderJob::DecodeInternal(
// TODO(xhwang/qinmin): This logic is correct but strange. Clean it up.
if (output_eos_encountered_)
status = MEDIA_CODEC_OUTPUT_END_OF_STREAM;
+ else if (has_format_change)
+ status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED;
bool render_output = presentation_timestamp >= preroll_timestamp_ &&
(status != MEDIA_CODEC_OUTPUT_END_OF_STREAM || size != 0u);
@@ -510,7 +524,6 @@ void MediaDecoderJob::OnDecodeCompleted(
switch (status) {
case MEDIA_CODEC_OK:
case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
- case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
case MEDIA_CODEC_OUTPUT_END_OF_STREAM:
if (!input_eos_encountered_) {
@@ -527,6 +540,10 @@ void MediaDecoderJob::OnDecodeCompleted(
case MEDIA_CODEC_ERROR:
// Do nothing.
break;
+
+ case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
+ DCHECK(false) << "Invalid output status";
+ break;
};
if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM && drain_decoder_) {
@@ -534,8 +551,11 @@ void MediaDecoderJob::OnDecodeCompleted(
status = MEDIA_CODEC_OK;
}
- if (status == MEDIA_CODEC_OUTPUT_FORMAT_CHANGED && UpdateOutputFormat())
- config_changed_cb_.Run();
+ if (status == MEDIA_CODEC_OUTPUT_FORMAT_CHANGED) {
+ if (UpdateOutputFormat())
+ config_changed_cb_.Run();
+ status = MEDIA_CODEC_OK;
+ }
if (release_resources_pending_) {
ReleaseMediaCodecBridge();
diff --git a/media/base/android/media_source_player_unittest.cc b/media/base/android/media_source_player_unittest.cc
index 1a73f44..376e0b1 100644
--- a/media/base/android/media_source_player_unittest.cc
+++ b/media/base/android/media_source_player_unittest.cc
@@ -375,13 +375,19 @@ class MediaSourcePlayerTest : public testing::Test {
EXPECT_TRUE(false);
}
- AccessUnit CreateAccessUnitWithData(bool is_audio, int audio_packet_id) {
+ AccessUnit CreateAccessUnitWithData(bool is_audio, int audio_packet_id,
+ bool use_large_size_video) {
AccessUnit unit;
unit.status = DemuxerStream::kOk;
- scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(
- is_audio ? base::StringPrintf("vorbis-packet-%d", audio_packet_id)
- : "vp8-I-frame-320x240");
+ scoped_refptr<DecoderBuffer> buffer;
+ if (is_audio) {
+ buffer = ReadTestDataFile(
+ base::StringPrintf("vorbis-packet-%d", audio_packet_id));
+ } else {
+ buffer = ReadTestDataFile(
+ use_large_size_video ? "vp8-I-frame-640x240" : "vp8-I-frame-320x240");
+ }
unit.data = std::vector<uint8>(
buffer->data(), buffer->data() + buffer->data_size());
@@ -399,15 +405,16 @@ class MediaSourcePlayerTest : public testing::Test {
DemuxerData data;
data.type = DemuxerStream::AUDIO;
data.access_units.resize(1);
- data.access_units[0] = CreateAccessUnitWithData(true, packet_id);
+ data.access_units[0] = CreateAccessUnitWithData(true, packet_id, false);
+
return data;
}
- DemuxerData CreateReadFromDemuxerAckForVideo() {
+ DemuxerData CreateReadFromDemuxerAckForVideo(bool use_large_size) {
DemuxerData data;
data.type = DemuxerStream::VIDEO;
data.access_units.resize(1);
- data.access_units[0] = CreateAccessUnitWithData(false, 0);
+ data.access_units[0] = CreateAccessUnitWithData(false, 0, use_large_size);
return data;
}
@@ -507,7 +514,7 @@ class MediaSourcePlayerTest : public testing::Test {
// |start_timestamp| must be smaller than |target_timestamp|.
EXPECT_LE(start_timestamp, target_timestamp);
DemuxerData data = is_audio ? CreateReadFromDemuxerAckForAudio(1) :
- CreateReadFromDemuxerAckForVideo();
+ CreateReadFromDemuxerAckForVideo(false);
int current_timestamp = start_timestamp.InMilliseconds();
// Send some data with access unit timestamps before the |target_timestamp|,
@@ -538,7 +545,7 @@ class MediaSourcePlayerTest : public testing::Test {
data.access_units.resize(config_unit_index + 1);
for (int i = 0; i < config_unit_index; ++i)
- data.access_units[i] = CreateAccessUnitWithData(is_audio, i);
+ data.access_units[i] = CreateAccessUnitWithData(is_audio, i, false);
data.access_units[config_unit_index].status = DemuxerStream::kConfigChanged;
data.demuxer_configs.resize(1);
@@ -564,13 +571,13 @@ class MediaSourcePlayerTest : public testing::Test {
if (trigger_with_release_start) {
// Consume the first frame, so that the next VideoDecoderJob will not
// inherit the I-frame from the previous decoder.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
ReleasePlayer();
WaitForVideoDecodeDone();
// Simulate demuxer's response to the video data request. The data will be
// passed to the next MediaCodecBridge.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_FALSE(GetMediaCodecBridge(false));
EXPECT_FALSE(player_.IsPlaying());
EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests());
@@ -584,7 +591,7 @@ class MediaSourcePlayerTest : public testing::Test {
message_loop_.RunUntilIdle();
} else {
// Simulate demuxer's response to the video data request.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
// While the decoder is decoding, trigger a browser seek by changing
// surface. Demuxer does not know of browser seek in advance, so no
@@ -600,7 +607,7 @@ class MediaSourcePlayerTest : public testing::Test {
// Wait for the media codec bridge to finish decoding and be reset pending
// the browser seek.
WaitForVideoDecodeDone();
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
}
// Only one browser seek should have been initiated, and no further data
@@ -640,7 +647,7 @@ class MediaSourcePlayerTest : public testing::Test {
if (is_audio) {
player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0));
} else {
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EnableAdaptiveVideoPlayback(enable_adaptive_playback);
}
@@ -652,7 +659,7 @@ class MediaSourcePlayerTest : public testing::Test {
}
DemuxerConfigs configs = is_audio ?
- CreateAudioDemuxerConfigs(kCodecAAC, false) :
+ CreateAudioDemuxerConfigs(kCodecVorbis, true) :
CreateVideoDemuxerConfigs(true);
// Feed and decode access units with data for any units prior to
// |config_unit_index|, and a |kConfigChanged| unit at that index.
@@ -666,7 +673,7 @@ class MediaSourcePlayerTest : public testing::Test {
if (is_audio)
player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0));
else
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(true));
// If the adaptive playback setting was not passed to the MediaCodecBridge
// earlier, do it here.
@@ -787,7 +794,7 @@ class MediaSourcePlayerTest : public testing::Test {
player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0));
if (have_video)
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
// Run until more data is requested a number of times equal to the number of
// media types configured. Since prefetching may be in progress, we cannot
@@ -808,7 +815,7 @@ class MediaSourcePlayerTest : public testing::Test {
if (eos_video)
player_.OnDemuxerDataAvailable(CreateEOSAck(false));
else
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
}
player_.SeekTo(base::TimeDelta());
@@ -901,7 +908,7 @@ TEST_F(MediaSourcePlayerTest, StartVideoCodecWithValidSurface) {
EXPECT_EQ(0, demuxer_->num_seek_requests());
// Send the first input chunk and verify that decoder will be created.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_TRUE(GetMediaCodecBridge(false));
WaitForVideoDecodeDone();
}
@@ -923,7 +930,7 @@ TEST_F(MediaSourcePlayerTest, StartVideoCodecWithInvalidSurface) {
EXPECT_EQ(0, demuxer_->num_seek_requests());
EXPECT_EQ(1, demuxer_->num_data_requests());
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_FALSE(GetMediaCodecBridge(false));
}
@@ -956,7 +963,7 @@ TEST_F(MediaSourcePlayerTest, SetSurfaceWhileSeeking) {
player_.OnDemuxerSeekDone(kNoTimestamp());
EXPECT_FALSE(GetMediaCodecBridge(false));
EXPECT_EQ(1, demuxer_->num_data_requests());
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_TRUE(GetMediaCodecBridge(false));
// Reconfirm exactly 1 seek request has been made of demuxer, and that it
@@ -975,7 +982,7 @@ TEST_F(MediaSourcePlayerTest, ChangeMultipleSurfaceWhileDecoding) {
EXPECT_EQ(0, demuxer_->num_seek_requests());
// Send the first input chunk.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
// While the decoder is decoding, change multiple surfaces. Pass an empty
// surface first.
@@ -987,7 +994,7 @@ TEST_F(MediaSourcePlayerTest, ChangeMultipleSurfaceWhileDecoding) {
// Wait for the media codec bridge to finish decoding and be reset pending a
// browser seek.
WaitForVideoDecodeDone();
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
// Only one browser seek should have been initiated. No further data request
// should have been processed on |message_loop_| before surface change event
@@ -1002,7 +1009,7 @@ TEST_F(MediaSourcePlayerTest, ChangeMultipleSurfaceWhileDecoding) {
EXPECT_EQ(3, demuxer_->num_data_requests());
EXPECT_EQ(1, demuxer_->num_seek_requests());
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_TRUE(GetMediaCodecBridge(false));
WaitForVideoDecodeDone();
}
@@ -1016,7 +1023,7 @@ TEST_F(MediaSourcePlayerTest, SetEmptySurfaceAndStarveWhileDecoding) {
EXPECT_EQ(1, demuxer_->num_data_requests());
// Send the first input chunk.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
// While the decoder is decoding, pass an empty surface.
gfx::ScopedJavaSurface empty_surface;
@@ -1032,7 +1039,7 @@ TEST_F(MediaSourcePlayerTest, SetEmptySurfaceAndStarveWhileDecoding) {
// surface is empty.
EXPECT_EQ(0, demuxer_->num_browser_seek_requests());
EXPECT_EQ(2, demuxer_->num_data_requests());
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
// Playback resumes once a non-empty surface is passed.
CreateNextTextureAndSetVideoSurface();
@@ -1050,7 +1057,7 @@ TEST_F(MediaSourcePlayerTest, ReleaseVideoDecoderResourcesWhileDecoding) {
// No resource is requested since there is no data to decode.
EXPECT_EQ(0, manager_.num_resources_requested());
ReleasePlayer();
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
// Recreate the video decoder.
CreateNextTextureAndSetVideoSurface();
@@ -1118,7 +1125,7 @@ TEST_F(MediaSourcePlayerTest, VideoOnlyStartAfterSeekFinish) {
EXPECT_EQ(1, demuxer_->num_seek_requests());
// Decoder is created after data is received.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_TRUE(GetMediaCodecBridge(false));
WaitForVideoDecodeDone();
}
@@ -1169,7 +1176,7 @@ TEST_F(MediaSourcePlayerTest, DecoderJobsCannotStartWithoutAudio) {
EXPECT_FALSE(video_decoder_job->is_decoding());
// Sending video data to player, video decoder should not start.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_FALSE(video_decoder_job->is_decoding());
// Sending audio data to player, both decoders should start now.
@@ -1216,7 +1223,7 @@ TEST_F(MediaSourcePlayerTest, V_SecondAccessUnitIsEOSAndResumePlayAfterSeek) {
StartVideoDecoderJob();
// Send the first input chunk.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
WaitForVideoDecodeDone();
VerifyPlaybackCompletesOnEOSDecode(true, false);
@@ -1352,7 +1359,7 @@ TEST_F(MediaSourcePlayerTest, V_StarvationDuringEOSDecode) {
// starvation occurs during EOS decode.
CreateNextTextureAndSetVideoSurface();
StartVideoDecoderJob();
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
WaitForVideoDecodeDone();
// Simulate decoder underrun to trigger prefetch while decoding EOS.
@@ -1484,7 +1491,7 @@ TEST_F(MediaSourcePlayerTest, BrowserSeek_RegularSeekPendsBrowserSeekDone) {
EXPECT_FALSE(GetMediaCodecBridge(false));
EXPECT_EQ(3, demuxer_->num_data_requests());
EXPECT_EQ(2, demuxer_->num_seek_requests());
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_TRUE(GetMediaCodecBridge(false));
WaitForVideoDecodeDone();
}
@@ -1508,7 +1515,7 @@ TEST_F(MediaSourcePlayerTest, BrowserSeek_InitialReleaseAndStart) {
EXPECT_FALSE(GetMediaCodecBridge(false));
// No browser seek is needed.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_EQ(0, demuxer_->num_browser_seek_requests());
EXPECT_EQ(2, demuxer_->num_data_requests());
WaitForVideoDecodeDone();
@@ -1709,7 +1716,7 @@ TEST_F(MediaSourcePlayerTest, AudioPrerollFinishesBeforeVideo) {
base::TimeDelta seek_ack_position = base::TimeDelta::FromMilliseconds(70);
DemuxerData audio_data = CreateReadFromDemuxerAckForAudio(0);
audio_data.access_units[0].timestamp = seek_ack_position;
- DemuxerData video_data = CreateReadFromDemuxerAckForVideo();
+ DemuxerData video_data = CreateReadFromDemuxerAckForVideo(false);
video_data.access_units[0].timestamp = seek_ack_position;
player_.OnDemuxerDataAvailable(audio_data);
player_.OnDemuxerDataAvailable(video_data);
@@ -1744,16 +1751,17 @@ TEST_F(MediaSourcePlayerTest, SimultaneousAudioVideoConfigChange) {
CreateNextTextureAndSetVideoSurface();
Start(CreateAudioVideoDemuxerConfigs());
player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0));
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_TRUE(GetMediaCodecBridge(true));
EXPECT_TRUE(GetMediaCodecBridge(false));
EnableAdaptiveVideoPlayback(false);
WaitForAudioVideoDecodeDone();
- EXPECT_TRUE(IsPrerolling(true));
- EXPECT_TRUE(IsPrerolling(false));
- PrerollDecoderToTime(true, base::TimeDelta(), base::TimeDelta(), true);
- PrerollDecoderToTime(false, base::TimeDelta(), base::TimeDelta(), false);
+ // If audio or video hasn't finished prerolling, let them finish it.
+ if (IsPrerolling(true))
+ PrerollDecoderToTime(true, base::TimeDelta(), base::TimeDelta(), true);
+ if (IsPrerolling(false))
+ PrerollDecoderToTime(false, base::TimeDelta(), base::TimeDelta(), false);
int expected_num_data_requests = demuxer_->num_data_requests();
// Simulate audio |kConfigChanged| prefetched as standalone access unit.
@@ -1783,12 +1791,20 @@ TEST_F(MediaSourcePlayerTest,
CreateNextTextureAndSetVideoSurface();
Start(CreateAudioVideoDemuxerConfigs());
player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0));
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
+ EXPECT_EQ(4, demuxer_->num_data_requests());
EXPECT_TRUE(GetMediaCodecBridge(true));
EXPECT_TRUE(GetMediaCodecBridge(false));
EnableAdaptiveVideoPlayback(true);
WaitForAudioVideoDecodeDone();
+ // If audio or video hasn't finished prerolling, let them finish it.
+ if (IsPrerolling(true))
+ PrerollDecoderToTime(true, base::TimeDelta(), base::TimeDelta(), true);
+ if (IsPrerolling(false))
+ PrerollDecoderToTime(false, base::TimeDelta(), base::TimeDelta(), false);
+ int expected_num_data_requests = demuxer_->num_data_requests();
+
// Simulate audio |kConfigChanged| prefetched as standalone access unit.
DemuxerConfigs audio_configs = CreateAudioDemuxerConfigs(kCodecVorbis, true);
player_.OnDemuxerDataAvailable(
@@ -1798,7 +1814,7 @@ TEST_F(MediaSourcePlayerTest,
player_.OnDemuxerDataAvailable(
CreateReadFromDemuxerAckWithConfigChanged(
false, 0, CreateVideoDemuxerConfigs(true)));
- EXPECT_EQ(6, demuxer_->num_data_requests());
+ EXPECT_EQ(expected_num_data_requests + 2, demuxer_->num_data_requests());
EXPECT_TRUE(IsDrainingDecoder(true));
EXPECT_FALSE(IsDrainingDecoder(false));
@@ -1815,6 +1831,7 @@ TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInPrefetchUnit0) {
// received in OnDemuxerDataAvailable() ostensibly while
// |PREFETCH_DONE_EVENT_PENDING|.
StartConfigChange(true, true, 0, false);
+ WaitForAudioDecodeDone();
}
TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInPrefetchUnit1) {
@@ -1825,6 +1842,7 @@ TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInPrefetchUnit1) {
// received in OnDemuxerDataAvailable() ostensibly while
// |PREFETCH_DONE_EVENT_PENDING|.
StartConfigChange(true, true, 1, false);
+ WaitForAudioDecodeDone();
}
TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInUnit0AfterPrefetch) {
@@ -1835,6 +1853,7 @@ TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInUnit0AfterPrefetch) {
// received in OnDemuxerDataAvailable() from data requested ostensibly while
// not prefetching.
StartConfigChange(true, false, 0, false);
+ WaitForAudioDecodeDone();
}
TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInUnit1AfterPrefetch) {
@@ -1845,6 +1864,7 @@ TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInUnit1AfterPrefetch) {
// received in OnDemuxerDataAvailable() from data requested ostensibly while
// not prefetching.
StartConfigChange(true, false, 1, false);
+ WaitForAudioDecodeDone();
}
TEST_F(MediaSourcePlayerTest, BrowserSeek_PrerollAfterBrowserSeek) {
@@ -1883,6 +1903,7 @@ TEST_F(MediaSourcePlayerTest, VideoDemuxerConfigChange) {
// 2 codecs should have been created, one before the config change, and one
// after it.
EXPECT_EQ(2, manager_.num_resources_requested());
+ WaitForVideoDecodeDone();
}
TEST_F(MediaSourcePlayerTest, VideoDemuxerConfigChangeWithAdaptivePlayback) {
@@ -1900,6 +1921,7 @@ TEST_F(MediaSourcePlayerTest, VideoDemuxerConfigChangeWithAdaptivePlayback) {
// Only 1 codec should have been created so far.
EXPECT_EQ(1, manager_.num_resources_requested());
+ WaitForVideoDecodeDone();
}
TEST_F(MediaSourcePlayerTest, DecoderDrainInterruptedBySeek) {
@@ -1952,13 +1974,13 @@ TEST_F(MediaSourcePlayerTest, DecoderDrainInterruptedBySurfaceChange) {
WaitForVideoDecodeDone();
EXPECT_FALSE(IsDrainingDecoder(false));
- EXPECT_FALSE(GetMediaCodecBridge(false));
EXPECT_TRUE(player_.IsPlaying());
- EXPECT_EQ(3, demuxer_->num_data_requests());
- // Finish the browser seek introduced by surface change.
- player_.OnDemuxerSeekDone(base::TimeDelta());
+ // The frame after the config change should always be an iframe, so no browser
+ // seek is needed when recreating the video decoder due to surface change.
+ EXPECT_TRUE(GetMediaCodecBridge(false));
EXPECT_EQ(4, demuxer_->num_data_requests());
+ EXPECT_EQ(0, demuxer_->num_seek_requests());
}
TEST_F(MediaSourcePlayerTest,
@@ -1969,7 +1991,7 @@ TEST_F(MediaSourcePlayerTest,
// should not cause any crashes.
CreateNextTextureAndSetVideoSurface();
StartVideoDecoderJob();
- DemuxerData data = CreateReadFromDemuxerAckForVideo();
+ DemuxerData data = CreateReadFromDemuxerAckForVideo(false);
player_.OnDemuxerDataAvailable(data);
// Trigger a surface change and decoder starvation.
@@ -2168,6 +2190,7 @@ TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenStart) {
EXPECT_TRUE(player_.IsPlaying());
EXPECT_EQ(3, demuxer_->num_data_requests());
EXPECT_EQ(0, demuxer_->num_seek_requests());
+ WaitForAudioDecodeDone();
}
TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenDemuxerSeekDone) {
@@ -2226,7 +2249,7 @@ TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenStart) {
EXPECT_EQ(1, demuxer_->num_seek_requests());
// Decoder will be created once data is received.
- player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo());
+ player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false));
EXPECT_TRUE(GetMediaCodecBridge(false));
WaitForVideoDecodeDone();
}
@@ -2294,13 +2317,7 @@ TEST_F(MediaSourcePlayerTest, VideoMetadataChangeAfterConfigChange) {
EXPECT_FALSE(IsDrainingDecoder(false));
// Create video data with new resolutions.
- DemuxerData data = CreateReadFromDemuxerAckForVideo();
- AccessUnit unit;
- unit.status = DemuxerStream::kOk;
- scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vp8-I-frame-640x240");
- unit.data = std::vector<uint8>(
- buffer->data(), buffer->data() + buffer->data_size());
- data.access_units[0] = unit;
+ DemuxerData data = CreateReadFromDemuxerAckForVideo(true);
// Wait for the metadata change.
while(manager_.num_metadata_changes() == 1) {
@@ -2308,6 +2325,7 @@ TEST_F(MediaSourcePlayerTest, VideoMetadataChangeAfterConfigChange) {
WaitForVideoDecodeDone();
}
EXPECT_EQ(2, manager_.num_metadata_changes());
+ WaitForVideoDecodeDone();
}
} // namespace media