Index: media/gpu/video_decode_accelerator_unittest.cc |
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc |
index 9611b14c1c6feae6f3f445f02cc936c552e94cf4..96e5d0b06e96c07bf1f213bcf18634e3b77fc7d0 100644 |
--- a/media/gpu/video_decode_accelerator_unittest.cc |
+++ b/media/gpu/video_decode_accelerator_unittest.cc |
@@ -217,15 +217,15 @@ void ReadGoldenThumbnailMD5s(const TestVideoFile* video_file, |
if (md5_string.at(0) == '#') |
continue; |
- LOG_ASSERT(static_cast<int>(md5_string.length()) == kMD5StringLength) |
- << md5_string; |
+ LOG_IF(ERROR, static_cast<int>(md5_string.length()) != kMD5StringLength) |
+ << "MD5 length error: " << md5_string; |
bool hex_only = std::count_if(md5_string.begin(), md5_string.end(), |
isxdigit) == kMD5StringLength; |
- LOG_ASSERT(hex_only) << md5_string; |
+ LOG_IF(ERROR, !hex_only) << "MD5 includes non-hex char: " << md5_string; |
} |
- LOG_ASSERT(md5_strings->size() >= 1U) << " MD5 checksum file (" |
- << filepath.MaybeAsASCII() |
- << ") missing or empty."; |
+ LOG_IF(ERROR, md5_strings->empty()) << " MD5 checksum file (" |
+ << filepath.MaybeAsASCII() |
+ << ") missing or empty."; |
} |
// State of the GLRenderingVDAClient below. Order matters here as the test |
@@ -808,6 +808,9 @@ void GLRenderingVDAClient::ReturnPicture(int32_t picture_buffer_id) { |
void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( |
int32_t bitstream_buffer_id) { |
+ if (decoder_deleted()) |
+ return; |
+ |
// TODO(fischman): this test currently relies on this notification to make |
// forward progress during a Reset(). But the VDA::Reset() API doesn't |
// guarantee this, so stop relying on it (and remove the notifications from |
@@ -925,9 +928,8 @@ void GLRenderingVDAClient::DeleteDecoder() { |
base::STLClearObject(&encoded_data_); |
active_textures_.clear(); |
- // Cascade through the rest of the states to simplify test code below. |
- for (int i = state_ + 1; i < CS_MAX; ++i) |
- SetState(static_cast<ClientState>(i)); |
+ // Set state to CS_DESTROYED after decoder is deleted. |
+ SetState(CS_DESTROYED); |
} |
std::string GLRenderingVDAClient::GetBytesForFirstFragment(size_t start_pos, |
@@ -1129,7 +1131,7 @@ class VideoDecodeAcceleratorTest : public ::testing::Test { |
protected: |
// Must be static because this method may run after the destructor. |
template <typename T> |
- static void Delete(std::unique_ptr<T> item) { |
+ static void Delete(T item) { |
// |item| is cleared when the scope of this function is left. |
} |
@@ -1147,12 +1149,9 @@ void VideoDecodeAcceleratorTest::SetUp() { |
} |
void VideoDecodeAcceleratorTest::TearDown() { |
- std::unique_ptr<TestFilesVector> test_video_files(new TestFilesVector); |
- test_video_files->swap(test_video_files_); |
- |
g_env->GetRenderingTaskRunner()->PostTask( |
FROM_HERE, |
- base::Bind(&Delete<TestFilesVector>, base::Passed(&test_video_files))); |
+ base::Bind(&Delete<TestFilesVector>, base::Passed(&test_video_files_))); |
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
base::WaitableEvent::InitialState::NOT_SIGNALED); |
@@ -1291,7 +1290,31 @@ void VideoDecodeAcceleratorTest::OutputLogFile( |
class VideoDecodeAcceleratorParamTest |
: public VideoDecodeAcceleratorTest, |
public ::testing::WithParamInterface< |
- std::tuple<int, int, int, ResetPoint, ClientState, bool, bool>> {}; |
+ std::tuple<int, int, int, ResetPoint, ClientState, bool, bool>> { |
+ protected: |
+ using NotesVector = |
+ std::vector<std::unique_ptr<ClientStateNotification<ClientState>>>; |
+ using ClientsVector = std::vector<std::unique_ptr<GLRenderingVDAClient>>; |
+ |
+ void TearDown() override; |
+ |
+ NotesVector notes_; |
+ ClientsVector clients_; |
+}; |
+ |
+void VideoDecodeAcceleratorParamTest::TearDown() { |
+ // |clients_| must be deleted first because |clients_| use |notes_|. |
+ g_env->GetRenderingTaskRunner()->PostTask( |
+ FROM_HERE, base::Bind(&Delete<ClientsVector>, base::Passed(&clients_))); |
+ |
+ g_env->GetRenderingTaskRunner()->PostTask( |
+ FROM_HERE, base::Bind(&Delete<NotesVector>, base::Passed(¬es_))); |
+ |
+ WaitUntilIdle(); |
+ |
+ // Do VideoDecodeAcceleratorTest clean-up after deleting clients and notes. |
+ VideoDecodeAcceleratorTest::TearDown(); |
+} |
// Wait for |note| to report a state and if it's not |expected_state| then |
// assert |client| has deleted its decoder. |
@@ -1299,6 +1322,9 @@ static void AssertWaitForStateOrDeleted( |
ClientStateNotification<ClientState>* note, |
GLRenderingVDAClient* client, |
ClientState expected_state) { |
+ // Skip waiting state if decoder of |client| is already deleted. |
+ if (client->decoder_deleted()) |
+ return; |
ClientState state = note->Wait(); |
if (state == expected_state) |
return; |
@@ -1335,11 +1361,8 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
// Suppress GL rendering for all tests when the "--rendering_fps" is 0. |
const bool suppress_rendering = g_rendering_fps == 0; |
- using NotesVector = |
- std::vector<std::unique_ptr<ClientStateNotification<ClientState>>>; |
- using ClientsVector = std::vector<std::unique_ptr<GLRenderingVDAClient>>; |
- NotesVector notes(num_concurrent_decoders); |
- ClientsVector clients(num_concurrent_decoders); |
+ notes_.resize(num_concurrent_decoders); |
+ clients_.resize(num_concurrent_decoders); |
RenderingHelperParams helper_params; |
helper_params.rendering_fps = g_rendering_fps; |
@@ -1358,7 +1381,7 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
test_video_files_[index % test_video_files_.size()].get(); |
std::unique_ptr<ClientStateNotification<ClientState>> note = |
base::MakeUnique<ClientStateNotification<ClientState>>(); |
- notes[index] = std::move(note); |
+ notes_[index] = std::move(note); |
int delay_after_frame_num = std::numeric_limits<int>::max(); |
if (test_reuse_delay && |
@@ -1368,14 +1391,14 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
std::unique_ptr<GLRenderingVDAClient> client = |
base::MakeUnique<GLRenderingVDAClient>( |
- index, &rendering_helper_, notes[index].get(), video_file->data_str, |
- num_in_flight_decodes, num_play_throughs, |
+ index, &rendering_helper_, notes_[index].get(), |
+ video_file->data_str, num_in_flight_decodes, num_play_throughs, |
video_file->reset_after_frame_num, delete_decoder_state, |
video_file->width, video_file->height, video_file->profile, |
g_fake_decoder, suppress_rendering, delay_after_frame_num, 0, |
render_as_thumbnails); |
- clients[index] = std::move(client); |
+ clients_[index] = std::move(client); |
helper_params.window_sizes.push_back( |
render_as_thumbnails |
? kThumbnailsPageSize |
@@ -1385,14 +1408,14 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
InitializeRenderingHelper(helper_params); |
for (size_t index = 0; index < num_concurrent_decoders; ++index) { |
- CreateAndStartDecoder(clients[index].get(), notes[index].get()); |
+ CreateAndStartDecoder(clients_[index].get(), notes_[index].get()); |
} |
// Then wait for all the decodes to finish. |
// Only check performance & correctness later if we play through only once. |
bool skip_performance_and_correctness_checks = num_play_throughs > 1; |
for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
- ClientStateNotification<ClientState>* note = notes[i].get(); |
+ ClientStateNotification<ClientState>* note = notes_[i].get(); |
ClientState state = note->Wait(); |
if (state != CS_INITIALIZED) { |
skip_performance_and_correctness_checks = true; |
@@ -1403,29 +1426,28 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
static_cast<size_t>(kMinSupportedNumConcurrentDecoders)); |
continue; |
} |
- ASSERT_EQ(state, CS_INITIALIZED); |
for (int n = 0; n < num_play_throughs; ++n) { |
// For play-throughs other than the first, we expect initialization to |
// succeed unconditionally. |
if (n > 0) { |
ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
- note, clients[i].get(), CS_INITIALIZED)); |
+ note, clients_[i].get(), CS_INITIALIZED)); |
} |
// InitializeDone kicks off decoding inside the client, so we just need to |
// wait for Flush. |
ASSERT_NO_FATAL_FAILURE( |
- AssertWaitForStateOrDeleted(note, clients[i].get(), CS_FLUSHING)); |
+ AssertWaitForStateOrDeleted(note, clients_[i].get(), CS_FLUSHING)); |
ASSERT_NO_FATAL_FAILURE( |
- AssertWaitForStateOrDeleted(note, clients[i].get(), CS_FLUSHED)); |
+ AssertWaitForStateOrDeleted(note, clients_[i].get(), CS_FLUSHED)); |
// FlushDone requests Reset(). |
ASSERT_NO_FATAL_FAILURE( |
- AssertWaitForStateOrDeleted(note, clients[i].get(), CS_RESETTING)); |
+ AssertWaitForStateOrDeleted(note, clients_[i].get(), CS_RESETTING)); |
} |
ASSERT_NO_FATAL_FAILURE( |
- AssertWaitForStateOrDeleted(note, clients[i].get(), CS_RESET)); |
+ AssertWaitForStateOrDeleted(note, clients_[i].get(), CS_RESET)); |
// ResetDone requests Destroy(). |
ASSERT_NO_FATAL_FAILURE( |
- AssertWaitForStateOrDeleted(note, clients[i].get(), CS_DESTROYED)); |
+ AssertWaitForStateOrDeleted(note, clients_[i].get(), CS_DESTROYED)); |
} |
// Finally assert that decoding went as expected. |
for (size_t i = 0; |
@@ -1435,7 +1457,7 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
// allowed to finish. |
if (delete_decoder_state < CS_FLUSHED) |
continue; |
- GLRenderingVDAClient* client = clients[i].get(); |
+ GLRenderingVDAClient* client = clients_[i].get(); |
TestVideoFile* video_file = |
test_video_files_[i % test_video_files_.size()].get(); |
if (video_file->num_frames > 0) { |
@@ -1497,9 +1519,9 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
int num_bytes = |
base::WriteFile(GetTestDataFile(filepath), |
reinterpret_cast<char*>(&png[0]), png.size()); |
- ASSERT_EQ(num_bytes, static_cast<int>(png.size())); |
+ EXPECT_EQ(num_bytes, static_cast<int>(png.size())); |
} |
- ASSERT_NE(match, golden_md5s.end()); |
+ EXPECT_NE(match, golden_md5s.end()); |
EXPECT_EQ(alpha_solid, true) << "RGBA frame had incorrect alpha"; |
} |
@@ -1511,23 +1533,9 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
base::FilePath(g_output_log), |
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); |
for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
- clients[i]->OutputFrameDeliveryTimes(&output_file); |
+ clients_[i]->OutputFrameDeliveryTimes(&output_file); |
} |
} |
- |
- std::unique_ptr<ClientsVector> clients2(new ClientsVector); |
- clients2->swap(clients); |
- std::unique_ptr<NotesVector> notes2(new NotesVector); |
- notes2->swap(notes); |
- |
- // |clients| must be deleted first because |clients| use |notes2|. |
- g_env->GetRenderingTaskRunner()->PostTask( |
- FROM_HERE, base::Bind(&Delete<ClientsVector>, base::Passed(&clients2))); |
- |
- g_env->GetRenderingTaskRunner()->PostTask( |
- FROM_HERE, base::Bind(&Delete<NotesVector>, base::Passed(¬es2))); |
- |
- WaitUntilIdle(); |
}; |
// Test that replay after EOS works fine. |