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

Unified Diff: content/common/gpu/media/video_decode_accelerator_unittest.cc

Issue 1816203003: Add an additional VDA::Flush() mode to return all allocated buffers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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: content/common/gpu/media/video_decode_accelerator_unittest.cc
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc
index 94c0b3664a5f693730c56aafa15500881644ba68..942d7709ae91261de13c91d4bf982100771701bf 100644
--- a/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -325,6 +325,8 @@ class GLRenderingVDAClient
// will start delaying the call to ReusePictureBuffer() for kReuseDelay.
// |decode_calls_per_second| is the number of VDA::Decode calls per second.
// If |decode_calls_per_second| > 0, |num_in_flight_decodes| must be 1.
+ // When |test_full_flush| is true, request the VDA to return all buffers it
+ // owns on Flush(), and verify that.
GLRenderingVDAClient(size_t window_id,
RenderingHelper* rendering_helper,
ClientStateNotification<ClientState>* note,
@@ -340,7 +342,8 @@ class GLRenderingVDAClient
bool suppress_rendering,
int delay_reuse_after_frame_num,
int decode_calls_per_second,
- bool render_as_thumbnails);
+ bool render_as_thumbnails,
+ bool test_full_flush);
~GLRenderingVDAClient() override;
void CreateAndStartDecoder();
@@ -375,7 +378,10 @@ class GLRenderingVDAClient
void SetState(ClientState new_state);
void FinishInitialization();
+ void ReturnTexture(int32_t picture_buffer_id);
void ReturnPicture(int32_t picture_buffer_id);
+ void CallReusePicture(int32_t picture_buffer_id);
+ void FinishFlush();
// Delete the associated decoder helper.
void DeleteDecoder();
@@ -417,6 +423,7 @@ class GLRenderingVDAClient
int num_queued_fragments_;
int num_decoded_frames_;
int num_done_bitstream_buffers_;
+ int num_pictures_at_decoder_;
base::TimeTicks initialize_done_ticks_;
media::VideoCodecProfile profile_;
int fake_decoder_;
@@ -431,6 +438,7 @@ class GLRenderingVDAClient
// The number of VDA::Decode calls per second. This is to simulate webrtc.
int decode_calls_per_second_;
bool render_as_thumbnails_;
+ bool test_full_flush_;
// A map of the textures that are currently active for the decoder, i.e.,
// have been created via AssignPictureBuffers() and not dismissed via
@@ -479,7 +487,8 @@ GLRenderingVDAClient::GLRenderingVDAClient(
bool suppress_rendering,
int delay_reuse_after_frame_num,
int decode_calls_per_second,
- bool render_as_thumbnails)
+ bool render_as_thumbnails,
+ bool test_full_flush)
: window_id_(window_id),
rendering_helper_(rendering_helper),
frame_size_(frame_width, frame_height),
@@ -497,12 +506,14 @@ GLRenderingVDAClient::GLRenderingVDAClient(
num_queued_fragments_(0),
num_decoded_frames_(0),
num_done_bitstream_buffers_(0),
+ num_pictures_at_decoder_(0),
fake_decoder_(fake_decoder),
texture_target_(0),
suppress_rendering_(suppress_rendering),
delay_reuse_after_frame_num_(delay_reuse_after_frame_num),
decode_calls_per_second_(decode_calls_per_second),
render_as_thumbnails_(render_as_thumbnails),
+ test_full_flush_(test_full_flush),
next_picture_buffer_id_(1),
weak_this_factory_(this) {
LOG_ASSERT(num_in_flight_decodes > 0);
@@ -529,10 +540,20 @@ void GLRenderingVDAClient::CreateAndStartDecoder() {
LOG_ASSERT(decoder_deleted());
LOG_ASSERT(!decoder_.get());
+ VideoDecodeAccelerator::Config config(profile_);
+ config.output_mode =
+ (g_test_import
+ ? media::VideoDecodeAccelerator::Config::OutputMode::IMPORT
+ : media::VideoDecodeAccelerator::Config::OutputMode::ALLOCATE);
+ config.flush_mode =
+ (test_full_flush_ ? media::VideoDecodeAccelerator::Config::FlushMode::
+ RETURN_OUTPUT_BUFFERS
+ : media::VideoDecodeAccelerator::Config::FlushMode::
+ KEEP_OUTPUT_BUFFERS);
if (fake_decoder_) {
decoder_.reset(new FakeVideoDecodeAccelerator(
frame_size_, base::Bind(&DoNothingReturnTrue)));
- LOG_ASSERT(decoder_->Initialize(profile_, this));
+ LOG_ASSERT(decoder_->Initialize(config, this));
} else {
if (!vda_factory_) {
vda_factory_ = GpuVideoDecodeAcceleratorFactoryImpl::Create(
@@ -542,16 +563,14 @@ void GLRenderingVDAClient::CreateAndStartDecoder() {
LOG_ASSERT(vda_factory_);
}
- VideoDecodeAccelerator::Config config(profile_);
- if (g_test_import) {
- config.output_mode =
- media::VideoDecodeAccelerator::Config::OutputMode::IMPORT;
- }
gpu::GpuPreferences gpu_preferences;
decoder_ = vda_factory_->CreateVDA(this, config, gpu_preferences);
}
LOG_ASSERT(decoder_) << "Failed creating a VDA";
+ weak_vda_ptr_factory_.reset(
+ new base::WeakPtrFactory<VideoDecodeAccelerator>(decoder_.get()));
+ weak_vda_ = weak_vda_ptr_factory_->GetWeakPtr();
decoder_->TryToSetupDecodeOnSeparateThread(
weak_this_, base::ThreadTaskRunnerHandle::Get());
@@ -645,10 +664,14 @@ void GLRenderingVDAClient::ProvidePictureBuffers(
decoder_->ImportBufferForPicture(buffer.id(), handles);
}
}
+
+ num_pictures_at_decoder_ = buffers.size();
}
void GLRenderingVDAClient::DismissPictureBuffer(int32_t picture_buffer_id) {
LOG_ASSERT(1U == active_textures_.erase(picture_buffer_id));
+ EXPECT_GT(num_pictures_at_decoder_, 0);
+ --num_pictures_at_decoder_;
}
void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
@@ -658,6 +681,15 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
if (decoder_deleted())
return;
+ EXPECT_GT(num_pictures_at_decoder_, 0);
+ --num_pictures_at_decoder_;
+
+ if (picture.bitstream_buffer_id() == -1) {
+ // The picture does not contain any decoded data, reuse it immediately.
+ ReturnPicture(picture.picture_buffer_id());
+ return;
+ }
+
base::TimeTicks now = base::TimeTicks::Now();
frame_delivery_times_.push_back(now);
@@ -689,7 +721,7 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
scoped_refptr<VideoFrameTexture> video_frame = new VideoFrameTexture(
texture_target_, texture_it->second->texture_id(),
- base::Bind(&GLRenderingVDAClient::ReturnPicture, AsWeakPtr(),
+ base::Bind(&GLRenderingVDAClient::ReturnTexture, AsWeakPtr(),
picture.picture_buffer_id()));
ASSERT_TRUE(pending_textures_.insert(*texture_it).second);
@@ -701,9 +733,10 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
}
}
-void GLRenderingVDAClient::ReturnPicture(int32_t picture_buffer_id) {
+void GLRenderingVDAClient::ReturnTexture(int32_t picture_buffer_id) {
if (decoder_deleted())
return;
+
LOG_ASSERT(1U == pending_textures_.erase(picture_buffer_id));
if (pending_textures_.empty() && state_ == CS_RESETTING) {
@@ -712,13 +745,36 @@ void GLRenderingVDAClient::ReturnPicture(int32_t picture_buffer_id) {
return;
}
+ ReturnPicture(picture_buffer_id);
+}
+
+void GLRenderingVDAClient::CallReusePicture(int32_t picture_buffer_id) {
+ if (state_ == CS_FLUSHED && test_full_flush_) {
+ // If we just got a notification from the VDA that it's flushed and are
+ // testing full flush, we want to have a chance to test that VDA really
+ // returned all buffers before NotifyFlushDone(). Delay returning the buffer
+ // so that we have a chance in FinishFlush() to test we got all the buffers.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&GLRenderingVDAClient::CallReusePicture,
+ weak_this_, picture_buffer_id));
+ return;
+ }
+
+ if (weak_vda_)
+ weak_vda_->ReusePictureBuffer(picture_buffer_id);
+ ++num_pictures_at_decoder_;
+}
+
+void GLRenderingVDAClient::ReturnPicture(int32_t picture_buffer_id) {
if (num_decoded_frames_ > delay_reuse_after_frame_num_) {
base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&VideoDecodeAccelerator::ReusePictureBuffer,
- weak_vda_, picture_buffer_id),
+ FROM_HERE, base::Bind(&GLRenderingVDAClient::CallReusePicture,
+ weak_this_, picture_buffer_id),
kReuseDelay);
} else {
- decoder_->ReusePictureBuffer(picture_buffer_id);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&GLRenderingVDAClient::CallReusePicture,
+ weak_this_, picture_buffer_id));
}
}
@@ -745,11 +801,11 @@ void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer(
}
}
-void GLRenderingVDAClient::NotifyFlushDone() {
- if (decoder_deleted())
- return;
+void GLRenderingVDAClient::FinishFlush() {
+ ASSERT_EQ(CS_FLUSHED, state_);
+ if (test_full_flush_)
+ EXPECT_EQ(0, num_pictures_at_decoder_);
- SetState(CS_FLUSHED);
--remaining_play_throughs_;
DCHECK_GE(remaining_play_throughs_, 0);
if (decoder_deleted())
@@ -758,6 +814,27 @@ void GLRenderingVDAClient::NotifyFlushDone() {
SetState(CS_RESETTING);
}
+void GLRenderingVDAClient::NotifyFlushDone() {
+ if (decoder_deleted())
+ return;
+
+ ASSERT_EQ(CS_FLUSHING, state_);
+ SetState(CS_FLUSHED);
+
+ // We may have already posted some ReusePictureBuffer() calls before we got
+ // here. If we are testing RETURN_OUTPUT_BUFFERS flush mode, make sure we
+ // don't execute them returning the buffers to VDA until we have a chance
+ // to verify the VDA really returned all the buffers before finishing flush.
+ // Otherwise, we don't care and can continue without holding off any pending
+ // ReusePictureBuffer() calls
+ if (test_full_flush_) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&GLRenderingVDAClient::FinishFlush, weak_this_));
+ } else {
+ FinishFlush();
+ }
+}
+
void GLRenderingVDAClient::NotifyResetDone() {
if (decoder_deleted())
return;
@@ -1192,10 +1269,12 @@ void VideoDecodeAcceleratorTest::OutputLogFile(
// - delete_decoder_phase: see GLRenderingVDAClient ctor.
// - whether to test slow rendering by delaying ReusePictureBuffer().
// - whether the video frames are rendered as thumbnails.
+// - whether to test VDA::Flush(true)
class VideoDecodeAcceleratorParamTest
: public VideoDecodeAcceleratorTest,
public ::testing::WithParamInterface<
- base::Tuple<int, int, int, ResetPoint, ClientState, bool, bool> > {
+ base::
+ Tuple<int, int, int, ResetPoint, ClientState, bool, bool, bool>> {
};
// Wait for |note| to report a state and if it's not |expected_state| then
@@ -1226,6 +1305,7 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) {
const int delete_decoder_state = base::get<4>(GetParam());
bool test_reuse_delay = base::get<5>(GetParam());
const bool render_as_thumbnails = base::get<6>(GetParam());
+ const bool test_full_flush = base::get<7>(GetParam());
if (test_video_files_.size() > 1)
num_concurrent_decoders = test_video_files_.size();
@@ -1284,7 +1364,8 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) {
suppress_rendering,
delay_after_frame_num,
0,
- render_as_thumbnails);
+ render_as_thumbnails,
+ test_full_flush);
clients[index] = client;
helper_params.window_sizes.push_back(
@@ -1439,59 +1520,74 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) {
INSTANTIATE_TEST_CASE_P(
ReplayAfterEOS, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false)));
+ MakeTuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false,
+ false)));
// Test that Reset() before the first Decode() works fine.
INSTANTIATE_TEST_CASE_P(
ResetBeforeDecode, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false)));
+ MakeTuple(1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false,
+ false)));
// Test Reset() immediately after Decode() containing config info.
INSTANTIATE_TEST_CASE_P(
ResetAfterFirstConfigInfo, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(
- 1, 1, 1, RESET_AFTER_FIRST_CONFIG_INFO, CS_RESET, false, false)));
+ MakeTuple(1, 1, 1, RESET_AFTER_FIRST_CONFIG_INFO, CS_RESET, false,
+ false, false)));
// Test that Reset() mid-stream works fine and doesn't affect decoding even when
// Decode() calls are made during the reset.
INSTANTIATE_TEST_CASE_P(
MidStreamReset, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false)));
+ MakeTuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false, false)));
+
+// Test that the VDA returns all buffers to us on Flush(true).
+INSTANTIATE_TEST_CASE_P(
+ FullFlush, VideoDecodeAcceleratorParamTest,
+ ::testing::Values(
+ MakeTuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false, true)));
+
INSTANTIATE_TEST_CASE_P(
SlowRendering, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false)));
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false, false)));
// Test that Destroy() mid-stream works fine (primarily this is testing that no
// crashes occur).
INSTANTIATE_TEST_CASE_P(
TearDownTiming, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false, false),
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false, false),
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false, false),
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false, false),
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false, false),
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false, false,
+ false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false, false,
+ false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false, false,
+ false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false, false,
+ false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false, false,
+ false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false, false),
MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
- static_cast<ClientState>(-1), false, false),
+ static_cast<ClientState>(-1), false, false, false),
MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
- static_cast<ClientState>(-10), false, false),
+ static_cast<ClientState>(-10), false, false, false),
MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
- static_cast<ClientState>(-100), false, false)));
+ static_cast<ClientState>(-100), false, false, false)));
// Test that decoding various variation works with multiple in-flight decodes.
INSTANTIATE_TEST_CASE_P(
DecodeVariations, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false, false),
+ MakeTuple(1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false, false),
// Tests queuing.
- MakeTuple(1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false)));
+ MakeTuple(1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false,
+ false)));
// Find out how many concurrent decoders can go before we exhaust system
// resources.
@@ -1500,15 +1596,15 @@ INSTANTIATE_TEST_CASE_P(
::testing::Values(
// +0 hack below to promote enum to int.
MakeTuple(kMinSupportedNumConcurrentDecoders + 0, 1, 1,
- END_OF_STREAM_RESET, CS_RESET, false, false),
+ END_OF_STREAM_RESET, CS_RESET, false, false, false),
MakeTuple(kMinSupportedNumConcurrentDecoders + 1, 1, 1,
- END_OF_STREAM_RESET, CS_RESET, false, false)));
+ END_OF_STREAM_RESET, CS_RESET, false, false, false)));
// Thumbnailing test
INSTANTIATE_TEST_CASE_P(
Thumbnail, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true)));
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true, false)));
// Measure the median of the decode time when VDA::Decode is called 30 times per
// second.
@@ -1538,7 +1634,8 @@ TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) {
true,
std::numeric_limits<int>::max(),
kWebRtcDecodeCallsPerSecond,
- false /* render_as_thumbnail */);
+ false /* render_as_thumbnail */,
+ false /* test_full_flush */);
helper_params.window_sizes.push_back(
gfx::Size(test_video_files_[0]->width, test_video_files_[0]->height));
InitializeRenderingHelper(helper_params);

Powered by Google App Engine
This is Rietveld 408576698