diff options
author | yuli@chromium.org <yuli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-29 22:17:59 +0000 |
---|---|---|
committer | yuli@chromium.org <yuli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-29 22:17:59 +0000 |
commit | aa72609f2bcec9f314939a4dd987db9b8926539f (patch) | |
tree | 73960aea735cdca9e3783096e120c3ec98c73bf9 | |
parent | 1455be7dc5b61cca5dff7a510725fe72c2daec0a (diff) | |
download | chromium_src-aa72609f2bcec9f314939a4dd987db9b8926539f.zip chromium_src-aa72609f2bcec9f314939a4dd987db9b8926539f.tar.gz chromium_src-aa72609f2bcec9f314939a4dd987db9b8926539f.tar.bz2 |
Narrow VDA Decode() API and remove multi-frame tests.
BUG=chrome-os-partner:20275
TEST=build and run the test on daisy
Review URL: https://codereview.chromium.org/48413004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231652 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/common/gpu/media/video_decode_accelerator_unittest.cc | 162 | ||||
-rw-r--r-- | media/video/video_decode_accelerator.h | 6 | ||||
-rw-r--r-- | ppapi/api/dev/ppb_video_decoder_dev.idl | 3 | ||||
-rw-r--r-- | ppapi/c/dev/ppb_video_decoder_dev.h | 5 |
4 files changed, 71 insertions, 105 deletions
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc index 4a67162..4c2ce95 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. diff --git a/media/video/video_decode_accelerator.h b/media/video/video_decode_accelerator.h index 1aa0954..5212db2 100644 --- a/media/video/video_decode_accelerator.h +++ b/media/video/video_decode_accelerator.h @@ -90,9 +90,9 @@ class MEDIA_EXPORT VideoDecodeAccelerator // Returns true when command successfully accepted. Otherwise false. virtual bool Initialize(VideoCodecProfile profile) = 0; - // Decodes given bitstream buffer. Once decoder is done with processing - // |bitstream_buffer| it will call NotifyEndOfBitstreamBuffer() with the - // bitstream buffer id. + // Decodes given bitstream buffer that contains at most one frame. Once + // decoder is done with processing |bitstream_buffer| it will call + // NotifyEndOfBitstreamBuffer() with the bitstream buffer id. // Parameters: // |bitstream_buffer| is the input bitstream that is sent for decoding. virtual void Decode(const BitstreamBuffer& bitstream_buffer) = 0; diff --git a/ppapi/api/dev/ppb_video_decoder_dev.idl b/ppapi/api/dev/ppb_video_decoder_dev.idl index 5b1a94e..da408c9 100644 --- a/ppapi/api/dev/ppb_video_decoder_dev.idl +++ b/ppapi/api/dev/ppb_video_decoder_dev.idl @@ -62,7 +62,8 @@ interface PPB_VideoDecoder_Dev { * * Parameters: * |video_decoder| is the previously created handle to the decoder resource. - * |bitstream_buffer| is the bitstream buffer that contains the input data. + * |bitstream_buffer| is the bitstream buffer that contains at most one + * input frame. * |callback| will be called when |bitstream_buffer| has been processed by * the decoder. * diff --git a/ppapi/c/dev/ppb_video_decoder_dev.h b/ppapi/c/dev/ppb_video_decoder_dev.h index fa57fd4..8b15fb0 100644 --- a/ppapi/c/dev/ppb_video_decoder_dev.h +++ b/ppapi/c/dev/ppb_video_decoder_dev.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From dev/ppb_video_decoder_dev.idl modified Wed Dec 14 18:08:00 2011. */ +/* From dev/ppb_video_decoder_dev.idl modified Tue Oct 29 00:32:59 2013. */ #ifndef PPAPI_C_DEV_PPB_VIDEO_DECODER_DEV_H_ #define PPAPI_C_DEV_PPB_VIDEO_DECODER_DEV_H_ @@ -78,7 +78,8 @@ struct PPB_VideoDecoder_Dev_0_16 { * * Parameters: * |video_decoder| is the previously created handle to the decoder resource. - * |bitstream_buffer| is the bitstream buffer that contains the input data. + * |bitstream_buffer| is the bitstream buffer that contains at most one + * input frame. * |callback| will be called when |bitstream_buffer| has been processed by * the decoder. * |