| 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 4a671627839eeba8bb3197814d0599890ff47fa6..4c2ce9509f722c8a98cf9ea3bf3004347cf97c20 100644
|
| --- a/content/common/gpu/media/video_decode_accelerator_unittest.cc
|
| +++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc
|
| @@ -15,7 +15,6 @@
|
| // infrastructure.
|
|
|
| #include <fcntl.h>
|
| -#include <math.h>
|
| #include <sys/stat.h>
|
| #include <sys/types.h>
|
| #include <deque>
|
| @@ -400,7 +399,6 @@ class GLRenderingVDAClient
|
| public:
|
| // Doesn't take ownership of |rendering_helper| or |note|, which must outlive
|
| // |*this|.
|
| - // |num_fragments_per_decode| counts NALUs for h264 and frames for VP8.
|
| // |num_play_throughs| indicates how many times to play through the video.
|
| // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream
|
| // Reset() should be done after that frame number is delivered, or
|
| @@ -419,7 +417,6 @@ class GLRenderingVDAClient
|
| int rendering_window_id,
|
| ClientStateNotification<ClientState>* note,
|
| const std::string& encoded_data,
|
| - int num_fragments_per_decode,
|
| int num_in_flight_decodes,
|
| int num_play_throughs,
|
| int reset_after_frame_num,
|
| @@ -468,24 +465,23 @@ class GLRenderingVDAClient
|
| void DeleteDecoder();
|
|
|
| // Compute & return the first encoded bytes (including a start frame) to send
|
| - // to the decoder, starting at |start_pos| and returning
|
| - // |num_fragments_per_decode| units. Skips to the first decodable position.
|
| - std::string GetBytesForFirstFragments(size_t start_pos, size_t* end_pos);
|
| - // Compute & return the next encoded bytes to send to the decoder (based on
|
| - // |start_pos| & |num_fragments_per_decode_|).
|
| - std::string GetBytesForNextFragments(size_t start_pos, size_t* end_pos);
|
| - // Helpers for GetRangeForNextFragments above.
|
| + // to the decoder, starting at |start_pos| and returning one fragment. Skips
|
| + // to the first decodable position.
|
| + std::string GetBytesForFirstFragment(size_t start_pos, size_t* end_pos);
|
| + // Compute & return the encoded bytes of next fragment to send to the decoder
|
| + // (based on |start_pos|).
|
| + std::string GetBytesForNextFragment(size_t start_pos, size_t* end_pos);
|
| + // Helpers for GetBytesForNextFragment above.
|
| void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264.
|
| - std::string GetBytesForNextFrames(
|
| + std::string GetBytesForNextFrame(
|
| size_t start_pos, size_t* end_pos); // For VP8.
|
|
|
| - // Request decode of the next batch of fragments in the encoded data.
|
| - void DecodeNextFragments();
|
| + // Request decode of the next fragment in the encoded data.
|
| + void DecodeNextFragment();
|
|
|
| RenderingHelper* rendering_helper_;
|
| int rendering_window_id_;
|
| std::string encoded_data_;
|
| - const int num_fragments_per_decode_;
|
| const int num_in_flight_decodes_;
|
| int outstanding_decodes_;
|
| size_t encoded_data_next_pos_to_decode_;
|
| @@ -517,7 +513,6 @@ GLRenderingVDAClient::GLRenderingVDAClient(
|
| int rendering_window_id,
|
| ClientStateNotification<ClientState>* note,
|
| const std::string& encoded_data,
|
| - int num_fragments_per_decode,
|
| int num_in_flight_decodes,
|
| int num_play_throughs,
|
| int reset_after_frame_num,
|
| @@ -531,7 +526,6 @@ GLRenderingVDAClient::GLRenderingVDAClient(
|
| : rendering_helper_(rendering_helper),
|
| rendering_window_id_(rendering_window_id),
|
| encoded_data_(encoded_data),
|
| - num_fragments_per_decode_(num_fragments_per_decode),
|
| num_in_flight_decodes_(num_in_flight_decodes),
|
| outstanding_decodes_(0),
|
| encoded_data_next_pos_to_decode_(0),
|
| @@ -548,7 +542,6 @@ GLRenderingVDAClient::GLRenderingVDAClient(
|
| profile_(profile),
|
| suppress_rendering_(suppress_rendering),
|
| delay_reuse_after_frame_num_(delay_reuse_after_frame_num) {
|
| - CHECK_GT(num_fragments_per_decode, 0);
|
| CHECK_GT(num_in_flight_decodes, 0);
|
| CHECK_GT(num_play_throughs, 0);
|
| CHECK_GE(rendering_fps, 0);
|
| @@ -697,7 +690,7 @@ void GLRenderingVDAClient::NotifyInitializeDone() {
|
| }
|
|
|
| for (int i = 0; i < num_in_flight_decodes_; ++i)
|
| - DecodeNextFragments();
|
| + DecodeNextFragment();
|
| DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_);
|
| }
|
|
|
| @@ -709,7 +702,7 @@ void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer(
|
| // VaapiVideoDecodeAccelerator::FinishReset()).
|
| ++num_done_bitstream_buffers_;
|
| --outstanding_decodes_;
|
| - DecodeNextFragments();
|
| + DecodeNextFragment();
|
| }
|
|
|
| void GLRenderingVDAClient::NotifyFlushDone() {
|
| @@ -730,12 +723,12 @@ void GLRenderingVDAClient::NotifyResetDone() {
|
|
|
| if (reset_after_frame_num_ == MID_STREAM_RESET) {
|
| reset_after_frame_num_ = END_OF_STREAM_RESET;
|
| - DecodeNextFragments();
|
| + DecodeNextFragment();
|
| return;
|
| } else if (reset_after_frame_num_ == START_OF_STREAM_RESET) {
|
| reset_after_frame_num_ = END_OF_STREAM_RESET;
|
| for (int i = 0; i < num_in_flight_decodes_; ++i)
|
| - DecodeNextFragments();
|
| + DecodeNextFragment();
|
| return;
|
| }
|
|
|
| @@ -801,13 +794,13 @@ void GLRenderingVDAClient::DeleteDecoder() {
|
| SetState(static_cast<ClientState>(i));
|
| }
|
|
|
| -std::string GLRenderingVDAClient::GetBytesForFirstFragments(
|
| +std::string GLRenderingVDAClient::GetBytesForFirstFragment(
|
| size_t start_pos, size_t* end_pos) {
|
| if (profile_ < media::H264PROFILE_MAX) {
|
| *end_pos = start_pos;
|
| while (*end_pos + 4 < encoded_data_.size()) {
|
| if ((encoded_data_[*end_pos + 4] & 0x1f) == 0x7) // SPS start frame
|
| - return GetBytesForNextFragments(*end_pos, end_pos);
|
| + return GetBytesForNextFragment(*end_pos, end_pos);
|
| GetBytesForNextNALU(*end_pos, end_pos);
|
| num_skipped_fragments_++;
|
| }
|
| @@ -815,25 +808,21 @@ std::string GLRenderingVDAClient::GetBytesForFirstFragments(
|
| return std::string();
|
| }
|
| DCHECK_LE(profile_, media::VP8PROFILE_MAX);
|
| - return GetBytesForNextFragments(start_pos, end_pos);
|
| + return GetBytesForNextFragment(start_pos, end_pos);
|
| }
|
|
|
| -std::string GLRenderingVDAClient::GetBytesForNextFragments(
|
| +std::string GLRenderingVDAClient::GetBytesForNextFragment(
|
| size_t start_pos, size_t* end_pos) {
|
| if (profile_ < media::H264PROFILE_MAX) {
|
| - size_t new_end_pos = start_pos;
|
| *end_pos = start_pos;
|
| - for (int i = 0; i < num_fragments_per_decode_; ++i) {
|
| - GetBytesForNextNALU(*end_pos, &new_end_pos);
|
| - if (*end_pos == new_end_pos)
|
| - break;
|
| - *end_pos = new_end_pos;
|
| + GetBytesForNextNALU(*end_pos, end_pos);
|
| + if (start_pos != *end_pos) {
|
| num_queued_fragments_++;
|
| }
|
| return encoded_data_.substr(start_pos, *end_pos - start_pos);
|
| }
|
| DCHECK_LE(profile_, media::VP8PROFILE_MAX);
|
| - return GetBytesForNextFrames(start_pos, end_pos);
|
| + return GetBytesForNextFrame(start_pos, end_pos);
|
| }
|
|
|
| void GLRenderingVDAClient::GetBytesForNextNALU(
|
| @@ -851,26 +840,22 @@ void GLRenderingVDAClient::GetBytesForNextNALU(
|
| *end_pos = encoded_data_.size();
|
| }
|
|
|
| -std::string GLRenderingVDAClient::GetBytesForNextFrames(
|
| +std::string GLRenderingVDAClient::GetBytesForNextFrame(
|
| size_t start_pos, size_t* end_pos) {
|
| // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF
|
| std::string bytes;
|
| if (start_pos == 0)
|
| start_pos = 32; // Skip IVF header.
|
| *end_pos = start_pos;
|
| - for (int i = 0; i < num_fragments_per_decode_; ++i) {
|
| - uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]);
|
| - *end_pos += 12; // Skip frame header.
|
| - bytes.append(encoded_data_.substr(*end_pos, frame_size));
|
| - *end_pos += frame_size;
|
| - num_queued_fragments_++;
|
| - if (*end_pos + 12 >= encoded_data_.size())
|
| - return bytes;
|
| - }
|
| + uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]);
|
| + *end_pos += 12; // Skip frame header.
|
| + bytes.append(encoded_data_.substr(*end_pos, frame_size));
|
| + *end_pos += frame_size;
|
| + num_queued_fragments_++;
|
| return bytes;
|
| }
|
|
|
| -void GLRenderingVDAClient::DecodeNextFragments() {
|
| +void GLRenderingVDAClient::DecodeNextFragment() {
|
| if (decoder_deleted())
|
| return;
|
| if (encoded_data_next_pos_to_decode_ == encoded_data_.size()) {
|
| @@ -883,14 +868,14 @@ void GLRenderingVDAClient::DecodeNextFragments() {
|
| size_t end_pos;
|
| std::string next_fragment_bytes;
|
| if (encoded_data_next_pos_to_decode_ == 0) {
|
| - next_fragment_bytes = GetBytesForFirstFragments(0, &end_pos);
|
| + next_fragment_bytes = GetBytesForFirstFragment(0, &end_pos);
|
| } else {
|
| next_fragment_bytes =
|
| - GetBytesForNextFragments(encoded_data_next_pos_to_decode_, &end_pos);
|
| + GetBytesForNextFragment(encoded_data_next_pos_to_decode_, &end_pos);
|
| }
|
| size_t next_fragment_size = next_fragment_bytes.size();
|
|
|
| - // Populate the shared memory buffer w/ the fragments, duplicate its handle,
|
| + // Populate the shared memory buffer w/ the fragment, duplicate its handle,
|
| // and hand it off to the decoder.
|
| base::SharedMemory shm;
|
| CHECK(shm.CreateAndMapAnonymous(next_fragment_size));
|
| @@ -924,7 +909,6 @@ double GLRenderingVDAClient::frames_per_second() {
|
| }
|
|
|
| // Test parameters:
|
| -// - Number of fragments per Decode() call.
|
| // - Number of concurrent decoders.
|
| // - Number of concurrent in-flight Decode() calls per decoder.
|
| // - Number of play-throughs.
|
| @@ -934,16 +918,16 @@ double GLRenderingVDAClient::frames_per_second() {
|
| // - whether the video frames are rendered as thumbnails.
|
| class VideoDecodeAcceleratorTest
|
| : public ::testing::TestWithParam<
|
| - Tuple8<int, int, int, int, ResetPoint, ClientState, bool, bool> > {
|
| + Tuple7<int, int, int, ResetPoint, ClientState, bool, bool> > {
|
| };
|
|
|
| // Helper so that gtest failures emit a more readable version of the tuple than
|
| // its byte representation.
|
| ::std::ostream& operator<<(
|
| ::std::ostream& os,
|
| - const Tuple8<int, int, int, int, ResetPoint, ClientState, bool, bool>& t) {
|
| + const Tuple7<int, int, int, ResetPoint, ClientState, bool, bool>& t) {
|
| return os << t.a << ", " << t.b << ", " << t.c << ", " << t.d << ", " << t.e
|
| - << ", " << t.f << ", " << t.g << ", " << t.h;
|
| + << ", " << t.f << ", " << t.g;
|
| }
|
|
|
| // Wait for |note| to report a state and if it's not |expected_state| then
|
| @@ -970,14 +954,13 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
|
| // Required for Thread to work. Not used otherwise.
|
| base::ShadowingAtExitManager at_exit_manager;
|
|
|
| - const int num_fragments_per_decode = GetParam().a;
|
| - const size_t num_concurrent_decoders = GetParam().b;
|
| - const size_t num_in_flight_decodes = GetParam().c;
|
| - const int num_play_throughs = GetParam().d;
|
| - const int reset_point = GetParam().e;
|
| - const int delete_decoder_state = GetParam().f;
|
| - bool test_reuse_delay = GetParam().g;
|
| - const bool render_as_thumbnails = GetParam().h;
|
| + const size_t num_concurrent_decoders = GetParam().a;
|
| + const size_t num_in_flight_decodes = GetParam().b;
|
| + const int num_play_throughs = GetParam().c;
|
| + const int reset_point = GetParam().d;
|
| + const int delete_decoder_state = GetParam().e;
|
| + bool test_reuse_delay = GetParam().f;
|
| + const bool render_as_thumbnails = GetParam().g;
|
|
|
| std::vector<TestVideoFile*> test_video_files;
|
| ParseAndReadTestVideoData(g_test_video_data,
|
| @@ -986,10 +969,7 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
|
| &test_video_files);
|
|
|
| // Suppress GL rendering for all tests when the "--disable_rendering" is set.
|
| - // Otherwise, suppress rendering in all but a few tests, to cut down overall
|
| - // test runtime.
|
| - const bool suppress_rendering =
|
| - num_fragments_per_decode > 1 || g_disable_rendering;
|
| + const bool suppress_rendering = g_disable_rendering;
|
|
|
| std::vector<ClientStateNotification<ClientState>*>
|
| notes(num_concurrent_decoders, NULL);
|
| @@ -1056,7 +1036,6 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
|
| index,
|
| note,
|
| video_file->data_str,
|
| - num_fragments_per_decode,
|
| num_in_flight_decodes,
|
| num_play_throughs,
|
| video_file->reset_after_frame_num,
|
| @@ -1136,8 +1115,7 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
|
| EXPECT_EQ(video_file->num_fragments, client->num_skipped_fragments() +
|
| client->num_queued_fragments());
|
| EXPECT_EQ(client->num_done_bitstream_buffers(),
|
| - ceil(static_cast<double>(client->num_queued_fragments()) /
|
| - num_fragments_per_decode));
|
| + client->num_queued_fragments());
|
| }
|
| LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second();
|
| if (!render_as_thumbnails) {
|
| @@ -1230,7 +1208,7 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
|
| INSTANTIATE_TEST_CASE_P(
|
| ReplayAfterEOS, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| - MakeTuple(1, 1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false)));
|
| + MakeTuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false)));
|
|
|
| // This hangs on Exynos, preventing further testing and wasting test machine
|
| // time.
|
| @@ -1240,7 +1218,7 @@ INSTANTIATE_TEST_CASE_P(
|
| INSTANTIATE_TEST_CASE_P(
|
| ResetBeforeDecode, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| - MakeTuple(1, 1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false)));
|
| + MakeTuple(1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false)));
|
| #endif // ARCH_CPU_X86_FAMILY
|
|
|
| // Test that Reset() mid-stream works fine and doesn't affect decoding even when
|
| @@ -1248,53 +1226,39 @@ INSTANTIATE_TEST_CASE_P(
|
| INSTANTIATE_TEST_CASE_P(
|
| MidStreamReset, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| - MakeTuple(1, 1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false)));
|
| + MakeTuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false)));
|
|
|
| INSTANTIATE_TEST_CASE_P(
|
| SlowRendering, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false)));
|
| + MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false)));
|
|
|
| // Test that Destroy() mid-stream works fine (primarily this is testing that no
|
| // crashes occur).
|
| INSTANTIATE_TEST_CASE_P(
|
| TearDownTiming, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false,
|
| - false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false,
|
| - false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false, false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false, false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false, false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET,
|
| + 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,
|
| static_cast<ClientState>(-1), false, false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET,
|
| + MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
|
| static_cast<ClientState>(-10), false, false),
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET,
|
| + MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
|
| static_cast<ClientState>(-100), false, false)));
|
|
|
| -// Test that decoding various variation works: multiple fragments per Decode()
|
| -// call and multiple in-flight decodes.
|
| +// Test that decoding various variation works with multiple in-flight decodes.
|
| INSTANTIATE_TEST_CASE_P(
|
| DecodeVariations, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - MakeTuple(1, 1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| + MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| + MakeTuple(1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| // Tests queuing.
|
| - MakeTuple(1, 1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - MakeTuple(2, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - MakeTuple(3, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - MakeTuple(5, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - MakeTuple(8, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - // TODO(fischman): decoding more than 15 NALUs at once breaks decode -
|
| - // visual artifacts are introduced as well as spurious frames are
|
| - // delivered (more pictures are returned than NALUs are fed to the
|
| - // decoder). Increase the "15" below when
|
| - // http://code.google.com/p/chrome-os-partner/issues/detail?id=4378 is
|
| - // fixed.
|
| - MakeTuple(15, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false)));
|
| + MakeTuple(1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false)));
|
|
|
| // Find out how many concurrent decoders can go before we exhaust system
|
| // resources.
|
| @@ -1302,16 +1266,16 @@ INSTANTIATE_TEST_CASE_P(
|
| ResourceExhaustion, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| // +0 hack below to promote enum to int.
|
| - MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, 1,
|
| + MakeTuple(kMinSupportedNumConcurrentDecoders + 0, 1, 1,
|
| END_OF_STREAM_RESET, CS_RESET, false, false),
|
| - MakeTuple(1, kMinSupportedNumConcurrentDecoders + 1, 1, 1,
|
| + MakeTuple(kMinSupportedNumConcurrentDecoders + 1, 1, 1,
|
| END_OF_STREAM_RESET, CS_RESET, false, false)));
|
|
|
| // Thumbnailing test
|
| INSTANTIATE_TEST_CASE_P(
|
| Thumbnail, VideoDecodeAcceleratorTest,
|
| ::testing::Values(
|
| - MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true)));
|
| + MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true)));
|
|
|
| // TODO(fischman, vrk): add more tests! In particular:
|
| // - Test life-cycle: Seek/Stop/Pause/Play for a single decoder.
|
|
|