diff options
author | qinmin <qinmin@chromium.org> | 2014-10-24 16:47:51 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-24 23:48:17 +0000 |
commit | 4aa66df2e01c9284c82d85ab1926005f379d91e3 (patch) | |
tree | 00fc64c572ba6e9a6435eda6de2724924903c52b /media | |
parent | 15fedbd0994ffb9a515d18336490a09e572fa038 (diff) | |
download | chromium_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.cc | 48 | ||||
-rw-r--r-- | media/base/android/media_source_player_unittest.cc | 126 |
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 |