diff options
author | sheu@chromium.org <sheu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 01:55:58 +0000 |
---|---|---|
committer | sheu@chromium.org <sheu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 01:55:58 +0000 |
commit | e837081a43a4c758a2bc07e7ae0767d506e7dec0 (patch) | |
tree | b6f2a5c2d515ce49c60c78f5e1a2b04255473719 /content/common | |
parent | 22fdaa65859604b35e1196cfe568e020f71310f3 (diff) | |
download | chromium_src-e837081a43a4c758a2bc07e7ae0767d506e7dec0.zip chromium_src-e837081a43a4c758a2bc07e7ae0767d506e7dec0.tar.gz chromium_src-e837081a43a4c758a2bc07e7ae0767d506e7dec0.tar.bz2 |
vda_unittest: skip H264 NALUs until first SPS
An H264 stream decode cannot start until it encounters the first SPS
(sequence parameter set) NALU, which encodes things like picture width,
height, etc. video_decode_accelerator_unittest should skip initial
NALUs until it encounters the first SPS, and only feed the decode NALUs
starting with that one.
TEST=local build, run on ARM, unittests on ARM
BUG=None
Change-Id: Ib8e47cb8058bd18adc3a85ca01b754736300226c
Review URL: https://chromiumcodereview.appspot.com/11316183
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@170347 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common')
-rw-r--r-- | content/common/gpu/media/video_decode_accelerator_unittest.cc | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc index 265cc4f..f7b3a4a 100644 --- a/content/common/gpu/media/video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc @@ -226,6 +226,8 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { // Simple getters for inspecting the state of the Client. int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } + int num_skipped_fragments() { return num_skipped_fragments_; } + int num_queued_fragments() { return num_queued_fragments_; } int num_decoded_frames() { return num_decoded_frames_; } double frames_per_second(); bool decoder_deleted() { return !decoder_.get(); } @@ -238,11 +240,15 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { // Delete the associated OMX decoder helper. 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. - void GetBytesForNextNALUs(size_t start_pos, size_t* end_pos); // For h.264. + void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264. std::string GetBytesForNextFrames( size_t start_pos, size_t* end_pos); // For VP8. @@ -264,6 +270,8 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { int reset_after_frame_num_; int delete_decoder_state_; ClientState state_; + int num_skipped_fragments_; + int num_queued_fragments_; int num_decoded_frames_; int num_done_bitstream_buffers_; PictureBufferById picture_buffers_by_id_; @@ -296,6 +304,7 @@ GLRenderingVDAClient::GLRenderingVDAClient( reset_after_frame_num_(reset_after_frame_num), delete_decoder_state_(delete_decoder_state), state_(CS_CREATED), + num_skipped_fragments_(0), num_queued_fragments_(0), num_decoded_frames_(0), num_done_bitstream_buffers_(0), profile_(profile) { CHECK_GT(num_fragments_per_decode, 0); @@ -469,8 +478,7 @@ void GLRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) { } static bool LookingAtNAL(const std::string& encoded, size_t pos) { - return pos + 3 < encoded.size() && - encoded[pos] == 0 && encoded[pos + 1] == 0 && + return encoded[pos] == 0 && encoded[pos + 1] == 0 && encoded[pos + 2] == 0 && encoded[pos + 3] == 1; } @@ -498,31 +506,54 @@ void GLRenderingVDAClient::DeleteDecoder() { SetState(static_cast<ClientState>(i)); } +std::string GLRenderingVDAClient::GetBytesForFirstFragments( + 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); + GetBytesForNextNALU(*end_pos, end_pos); + num_skipped_fragments_++; + } + *end_pos = start_pos; + return std::string(); + } + DCHECK_LE(profile_, media::VP8PROFILE_MAX); + return GetBytesForNextFragments(start_pos, end_pos); +} + std::string GLRenderingVDAClient::GetBytesForNextFragments( size_t start_pos, size_t* end_pos) { if (profile_ < media::H264PROFILE_MAX) { - GetBytesForNextNALUs(start_pos, end_pos); + 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; + 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); } -void GLRenderingVDAClient::GetBytesForNextNALUs( +void GLRenderingVDAClient::GetBytesForNextNALU( size_t start_pos, size_t* end_pos) { *end_pos = start_pos; + if (*end_pos + 4 > encoded_data_.size()) + return; CHECK(LookingAtNAL(encoded_data_, start_pos)); - for (int i = 0; i < num_fragments_per_decode_; ++i) { - *end_pos += 4; - while (*end_pos + 3 < encoded_data_.size() && - !LookingAtNAL(encoded_data_, *end_pos)) { - ++*end_pos; - } - if (*end_pos + 3 >= encoded_data_.size()) { - *end_pos = encoded_data_.size(); - return; - } + *end_pos += 4; + while (*end_pos + 4 <= encoded_data_.size() && + !LookingAtNAL(encoded_data_, *end_pos)) { + ++*end_pos; } + if (*end_pos + 3 >= encoded_data_.size()) + *end_pos = encoded_data_.size(); } std::string GLRenderingVDAClient::GetBytesForNextFrames( @@ -537,6 +568,7 @@ std::string GLRenderingVDAClient::GetBytesForNextFrames( *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; } @@ -554,8 +586,13 @@ void GLRenderingVDAClient::DecodeNextFragments() { return; } size_t end_pos; - std::string next_fragment_bytes = - GetBytesForNextFragments(encoded_data_next_pos_to_decode_, &end_pos); + std::string next_fragment_bytes; + if (encoded_data_next_pos_to_decode_ == 0) { + next_fragment_bytes = GetBytesForFirstFragments(0, &end_pos); + } else { + next_fragment_bytes = + GetBytesForNextFragments(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, @@ -756,9 +793,11 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { GLRenderingVDAClient* client = clients[i]; if (num_frames > 0) EXPECT_EQ(client->num_decoded_frames(), num_frames); - if (num_fragments > 0 && reset_after_frame_num < 0) { + if (reset_after_frame_num < 0) { + EXPECT_EQ(num_fragments, client->num_skipped_fragments() + + client->num_queued_fragments()); EXPECT_EQ(client->num_done_bitstream_buffers(), - ceil(static_cast<double>(num_fragments) / + ceil(static_cast<double>(client->num_queued_fragments()) / num_fragments_per_decode)); } LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second(); |