diff options
author | posciak@chromium.org <posciak@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-10 09:11:28 +0000 |
---|---|---|
committer | posciak@chromium.org <posciak@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-10 09:11:28 +0000 |
commit | ece777aed5f1b000467b9202abd193baf146319b (patch) | |
tree | d051b98038469881175b0abc6493bfeab5ca11c6 /content/common | |
parent | b885a70783f397c78e6da8b11eb58ba10e28af86 (diff) | |
download | chromium_src-ece777aed5f1b000467b9202abd193baf146319b.zip chromium_src-ece777aed5f1b000467b9202abd193baf146319b.tar.gz chromium_src-ece777aed5f1b000467b9202abd193baf146319b.tar.bz2 |
Move H264Parser and H264BitReader to media/filters.
In preparation for wider usage in media code, move the H.264 parser and
reader classes to media/filters from GPU-accelerated media locations, and
into the media namespace. These classes have only been, up to now, used
by hardware decode accelerators.
Also, move their unittests along and make them a part of media_unittests,
demoting H264ParserUnittest from being a standalone executable. While it
was designed to be run on a set of streams from commandline, it should make
more sense to run it more regularly (if only on just one stream), together
with media tests, to prevent basic regressions, if it's to be used more
widely than only in CrOS hardware acceleration classes.
BUG=None
TEST=Build VAVDA and vdaunittest for x86,
build EVDA, vdaunittest and veaunittest for ARM.
Also build and run media_unittests for both.
Review URL: https://codereview.chromium.org/119153002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244132 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common')
-rw-r--r-- | content/common/gpu/media/h264_bit_reader.cc | 112 | ||||
-rw-r--r-- | content/common/gpu/media/h264_bit_reader.h | 79 | ||||
-rw-r--r-- | content/common/gpu/media/h264_bit_reader_unittest.cc | 72 | ||||
-rw-r--r-- | content/common/gpu/media/h264_dpb.h | 5 | ||||
-rw-r--r-- | content/common/gpu/media/h264_parser.cc | 1133 | ||||
-rw-r--r-- | content/common/gpu/media/h264_parser.h | 355 | ||||
-rw-r--r-- | content/common/gpu/media/h264_parser_unittest.cc | 93 | ||||
-rw-r--r-- | content/common/gpu/media/v4l2_video_decode_accelerator.cc | 28 | ||||
-rw-r--r-- | content/common/gpu/media/v4l2_video_decode_accelerator.h | 8 | ||||
-rw-r--r-- | content/common/gpu/media/vaapi_h264_decoder.cc | 77 | ||||
-rw-r--r-- | content/common/gpu/media/vaapi_h264_decoder.h | 24 | ||||
-rw-r--r-- | content/common/gpu/media/video_encode_accelerator_unittest.cc | 20 |
12 files changed, 84 insertions, 1922 deletions
diff --git a/content/common/gpu/media/h264_bit_reader.cc b/content/common/gpu/media/h264_bit_reader.cc deleted file mode 100644 index dbeb4db..0000000 --- a/content/common/gpu/media/h264_bit_reader.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/common/gpu/media/h264_bit_reader.h" -#include "base/logging.h" - -namespace content { - -H264BitReader::H264BitReader() - : data_(NULL), bytes_left_(0), curr_byte_(0), - num_remaining_bits_in_curr_byte_(0), prev_two_bytes_(0), - emulation_prevention_bytes_(0) { -} - -H264BitReader::~H264BitReader() {} - -bool H264BitReader::Initialize(const uint8* data, off_t size) { - DCHECK(data); - - if (size < 1) - return false; - - data_ = data; - bytes_left_ = size; - num_remaining_bits_in_curr_byte_ = 0; - // Initially set to 0xffff to accept all initial two-byte sequences. - prev_two_bytes_ = 0xffff; - emulation_prevention_bytes_ = 0; - - return true; -} - -bool H264BitReader::UpdateCurrByte() { - if (bytes_left_ < 1) - return false; - - // Emulation prevention three-byte detection. - // If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03). - if (*data_ == 0x03 && (prev_two_bytes_ & 0xffff) == 0) { - // Detected 0x000003, skip last byte. - ++data_; - --bytes_left_; - ++emulation_prevention_bytes_; - // Need another full three bytes before we can detect the sequence again. - prev_two_bytes_ = 0xffff; - - if (bytes_left_ < 1) - return false; - } - - // Load a new byte and advance pointers. - curr_byte_ = *data_++ & 0xff; - --bytes_left_; - num_remaining_bits_in_curr_byte_ = 8; - - prev_two_bytes_ = (prev_two_bytes_ << 8) | curr_byte_; - - return true; -} - -// Read |num_bits| (1 to 31 inclusive) from the stream and return them -// in |out|, with first bit in the stream as MSB in |out| at position -// (|num_bits| - 1). -bool H264BitReader::ReadBits(int num_bits, int *out) { - int bits_left = num_bits; - *out = 0; - DCHECK(num_bits <= 31); - - while (num_remaining_bits_in_curr_byte_ < bits_left) { - // Take all that's left in current byte, shift to make space for the rest. - *out |= (curr_byte_ << (bits_left - num_remaining_bits_in_curr_byte_)); - bits_left -= num_remaining_bits_in_curr_byte_; - - if (!UpdateCurrByte()) - return false; - } - - *out |= (curr_byte_ >> (num_remaining_bits_in_curr_byte_ - bits_left)); - *out &= ((1 << num_bits) - 1); - num_remaining_bits_in_curr_byte_ -= bits_left; - - return true; -} - -off_t H264BitReader::NumBitsLeft() { - return (num_remaining_bits_in_curr_byte_ + bytes_left_ * 8); -} - -bool H264BitReader::HasMoreRBSPData() { - // Make sure we have more bits, if we are at 0 bits in current byte - // and updating current byte fails, we don't have more data anyway. - if (num_remaining_bits_in_curr_byte_ == 0 && !UpdateCurrByte()) - return false; - - // On last byte? - if (bytes_left_) - return true; - - // Last byte, look for stop bit; - // We have more RBSP data if the last non-zero bit we find is not the - // first available bit. - return (curr_byte_ & - ((1 << (num_remaining_bits_in_curr_byte_ - 1)) - 1)) != 0; -} - -size_t H264BitReader::NumEmulationPreventionBytesRead() -{ - return emulation_prevention_bytes_; -} - -} // namespace content diff --git a/content/common/gpu/media/h264_bit_reader.h b/content/common/gpu/media/h264_bit_reader.h deleted file mode 100644 index a2d32b5..0000000 --- a/content/common/gpu/media/h264_bit_reader.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This file contains an implementation of an H264 Annex-B video stream parser. - -#ifndef CONTENT_COMMON_GPU_MEDIA_H264_BIT_READER_H_ -#define CONTENT_COMMON_GPU_MEDIA_H264_BIT_READER_H_ - -#include <sys/types.h> - -#include "base/basictypes.h" -#include "content/common/content_export.h" - -namespace content { - -// A class to provide bit-granularity reading of H.264 streams. -// This is not a generic bit reader class, as it takes into account -// H.264 stream-specific constraints, such as skipping emulation-prevention -// bytes and stop bits. See spec for more details. -class CONTENT_EXPORT H264BitReader { - public: - H264BitReader(); - ~H264BitReader(); - - // Initialize the reader to start reading at |data|, |size| being size - // of |data| in bytes. - // Return false on insufficient size of stream.. - // TODO(posciak,fischman): consider replacing Initialize() with - // heap-allocating and creating bit readers on demand instead. - bool Initialize(const uint8* data, off_t size); - - // Read |num_bits| next bits from stream and return in |*out|, first bit - // from the stream starting at |num_bits| position in |*out|. - // |num_bits| may be 1-32, inclusive. - // Return false if the given number of bits cannot be read (not enough - // bits in the stream), true otherwise. - bool ReadBits(int num_bits, int *out); - - // Return the number of bits left in the stream. - off_t NumBitsLeft(); - - // See the definition of more_rbsp_data() in spec. - bool HasMoreRBSPData(); - - // Return the number of emulation prevention bytes already read. - size_t NumEmulationPreventionBytesRead(); - - private: - // Advance to the next byte, loading it into curr_byte_. - // Return false on end of stream. - bool UpdateCurrByte(); - - // Pointer to the next unread (not in curr_byte_) byte in the stream. - const uint8* data_; - - // Bytes left in the stream (without the curr_byte_). - off_t bytes_left_; - - // Contents of the current byte; first unread bit starting at position - // 8 - num_remaining_bits_in_curr_byte_ from MSB. - int curr_byte_; - - // Number of bits remaining in curr_byte_ - int num_remaining_bits_in_curr_byte_; - - // Used in emulation prevention three byte detection (see spec). - // Initially set to 0xffff to accept all initial two-byte sequences. - int prev_two_bytes_; - - // Number of emulation preventation bytes (0x000003) we met. - size_t emulation_prevention_bytes_; - - DISALLOW_COPY_AND_ASSIGN(H264BitReader); -}; - -} // namespace content - -#endif // CONTENT_COMMON_GPU_MEDIA_H264_BIT_READER_H_ diff --git a/content/common/gpu/media/h264_bit_reader_unittest.cc b/content/common/gpu/media/h264_bit_reader_unittest.cc deleted file mode 100644 index a02a21c..0000000 --- a/content/common/gpu/media/h264_bit_reader_unittest.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "testing/gtest/include/gtest/gtest.h" - -#include "content/common/gpu/media/h264_bit_reader.h" - -using content::H264BitReader; - -TEST(H264BitReaderTest, ReadStreamWithoutEscapeAndTrailingZeroBytes) { - H264BitReader reader; - const unsigned char rbsp[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xa0}; - int dummy = 0; - - EXPECT_TRUE(reader.Initialize(rbsp, sizeof(rbsp))); - - EXPECT_TRUE(reader.ReadBits(1, &dummy)); - EXPECT_EQ(dummy, 0x00); - EXPECT_EQ(reader.NumBitsLeft(), 47); - EXPECT_TRUE(reader.HasMoreRBSPData()); - - EXPECT_TRUE(reader.ReadBits(8, &dummy)); - EXPECT_EQ(dummy, 0x02); - EXPECT_EQ(reader.NumBitsLeft(), 39); - EXPECT_TRUE(reader.HasMoreRBSPData()); - - EXPECT_TRUE(reader.ReadBits(31, &dummy)); - EXPECT_EQ(dummy, 0x23456789); - EXPECT_EQ(reader.NumBitsLeft(), 8); - EXPECT_TRUE(reader.HasMoreRBSPData()); - - EXPECT_TRUE(reader.ReadBits(1, &dummy)); - EXPECT_EQ(dummy, 1); - EXPECT_EQ(reader.NumBitsLeft(), 7); - EXPECT_TRUE(reader.HasMoreRBSPData()); - - EXPECT_TRUE(reader.ReadBits(1, &dummy)); - EXPECT_EQ(dummy, 0); - EXPECT_EQ(reader.NumBitsLeft(), 6); - EXPECT_FALSE(reader.HasMoreRBSPData()); -} - -TEST(H264BitReaderTest, SingleByteStream) { - H264BitReader reader; - const unsigned char rbsp[] = {0x18}; - int dummy = 0; - - EXPECT_TRUE(reader.Initialize(rbsp, sizeof(rbsp))); - EXPECT_EQ(reader.NumBitsLeft(), 8); - EXPECT_TRUE(reader.HasMoreRBSPData()); - - EXPECT_TRUE(reader.ReadBits(4, &dummy)); - EXPECT_EQ(dummy, 0x01); - EXPECT_EQ(reader.NumBitsLeft(), 4); - EXPECT_FALSE(reader.HasMoreRBSPData()); -} - -TEST(H264BitReaderTest, StopBitOccupyFullByte) { - H264BitReader reader; - const unsigned char rbsp[] = {0xab, 0x80}; - int dummy = 0; - - EXPECT_TRUE(reader.Initialize(rbsp, sizeof(rbsp))); - EXPECT_EQ(reader.NumBitsLeft(), 16); - EXPECT_TRUE(reader.HasMoreRBSPData()); - - EXPECT_TRUE(reader.ReadBits(8, &dummy)); - EXPECT_EQ(dummy, 0xab); - EXPECT_EQ(reader.NumBitsLeft(), 8); - EXPECT_FALSE(reader.HasMoreRBSPData()); -} diff --git a/content/common/gpu/media/h264_dpb.h b/content/common/gpu/media/h264_dpb.h index fe15c70..29be0bc 100644 --- a/content/common/gpu/media/h264_dpb.h +++ b/content/common/gpu/media/h264_dpb.h @@ -12,7 +12,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_vector.h" -#include "content/common/gpu/media/h264_parser.h" +#include "media/filters/h264_parser.h" namespace content { @@ -55,7 +55,8 @@ struct H264Picture { // memory management after finishing this picture. bool long_term_reference_flag; bool adaptive_ref_pic_marking_mode_flag; - H264DecRefPicMarking ref_pic_marking[H264SliceHeader::kRefListSize]; + media::H264DecRefPicMarking + ref_pic_marking[media::H264SliceHeader::kRefListSize]; typedef std::vector<H264Picture*> PtrVector; }; diff --git a/content/common/gpu/media/h264_parser.cc b/content/common/gpu/media/h264_parser.cc deleted file mode 100644 index 177668b..0000000 --- a/content/common/gpu/media/h264_parser.cc +++ /dev/null @@ -1,1133 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/common/gpu/media/h264_parser.h" - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" - -namespace content { - -bool H264SliceHeader::IsPSlice() const { - return (slice_type % 5 == kPSlice); -} - -bool H264SliceHeader::IsBSlice() const { - return (slice_type % 5 == kBSlice); -} - -bool H264SliceHeader::IsISlice() const { - return (slice_type % 5 == kISlice); -} - -bool H264SliceHeader::IsSPSlice() const { - return (slice_type % 5 == kSPSlice); -} - -bool H264SliceHeader::IsSISlice() const { - return (slice_type % 5 == kSISlice); -} - -H264NALU::H264NALU() { - memset(this, 0, sizeof(*this)); -} - -H264SPS::H264SPS() { - memset(this, 0, sizeof(*this)); -} - -H264PPS::H264PPS() { - memset(this, 0, sizeof(*this)); -} - -H264SliceHeader::H264SliceHeader() { - memset(this, 0, sizeof(*this)); -} - -H264SEIMessage::H264SEIMessage() { - memset(this, 0, sizeof(*this)); -} - -#define READ_BITS_OR_RETURN(num_bits, out) \ -do { \ - int _out; \ - if (!br_.ReadBits(num_bits, &_out)) { \ - DVLOG(1) << "Error in stream: unexpected EOS while trying to read " #out; \ - return kInvalidStream; \ - } \ - *out = _out; \ -} while (0) - -#define READ_BOOL_OR_RETURN(out) \ -do { \ - int _out; \ - if (!br_.ReadBits(1, &_out)) { \ - DVLOG(1) << "Error in stream: unexpected EOS while trying to read " #out; \ - return kInvalidStream; \ - } \ - *out = _out != 0; \ -} while (0) - -#define READ_UE_OR_RETURN(out) \ -do { \ - if (ReadUE(out) != kOk) { \ - DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \ - return kInvalidStream; \ - } \ -} while (0) - -#define READ_SE_OR_RETURN(out) \ -do { \ - if (ReadSE(out) != kOk) { \ - DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \ - return kInvalidStream; \ - } \ -} while (0) - -#define IN_RANGE_OR_RETURN(val, min, max) \ -do { \ - if ((val) < (min) || (val) > (max)) { \ - DVLOG(1) << "Error in stream: invalid value, expected " #val " to be" \ - << " in range [" << (min) << ":" << (max) << "]" \ - << " found " << (val) << " instead"; \ - return kInvalidStream; \ - } \ -} while (0) - -#define TRUE_OR_RETURN(a) \ -do { \ - if (!(a)) { \ - DVLOG(1) << "Error in stream: invalid value, expected " << #a; \ - return kInvalidStream; \ - } \ -} while (0) - -H264Parser::H264Parser() { - Reset(); -} - -H264Parser::~H264Parser() { - STLDeleteValues(&active_SPSes_); - STLDeleteValues(&active_PPSes_); -} - -void H264Parser::Reset() { - stream_ = NULL; - bytes_left_ = 0; -} - -void H264Parser::SetStream(const uint8* stream, off_t stream_size) { - DCHECK(stream); - DCHECK_GT(stream_size, 0); - - stream_ = stream; - bytes_left_ = stream_size; -} - -const H264PPS* H264Parser::GetPPS(int pps_id) { - return active_PPSes_[pps_id]; -} - -const H264SPS* H264Parser::GetSPS(int sps_id) { - return active_SPSes_[sps_id]; -} - -static inline bool IsStartCode(const uint8* data) { - return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01; -} - -// Find offset from start of data to next NALU start code -// and size of found start code (3 or 4 bytes). -static bool FindStartCode(const uint8* data, off_t data_size, - off_t* offset, - off_t* start_code_size) { - off_t bytes_left = data_size; - - while (bytes_left > 3) { - if (IsStartCode(data)) { - // Found three-byte start code, set pointer at its beginning. - *offset = data_size - bytes_left; - *start_code_size = 3; - - // If there is a zero byte before this start code, - // then it's actually a four-byte start code, so backtrack one byte. - if (*offset > 0 && *(data - 1) == 0x00) { - --(*offset); - ++(*start_code_size); - } - - return true; - } - - ++data; - --bytes_left; - } - - // End of data. - return false; -} - -// Find the next NALU in stream, returning its start offset without the start -// code (i.e. at the beginning of NALU data). -// Size will include trailing zero bits, and will be from start offset to -// before the start code of the next NALU (or end of stream). -static bool LocateNALU(const uint8* stream, off_t stream_size, - off_t* nalu_start_off, off_t* nalu_size) { - off_t start_code_size; - - // Find start code of the next NALU. - if (!FindStartCode(stream, stream_size, nalu_start_off, &start_code_size)) { - DVLOG(4) << "Could not find start code, end of stream?"; - return false; - } - - // Discard its start code. - *nalu_start_off += start_code_size; - // Move the stream to the beginning of it (skip the start code). - stream_size -= *nalu_start_off; - stream += *nalu_start_off; - - // Find the start code of next NALU; if successful, NALU size is the number - // of bytes from after previous start code to before this one; - // if next start code is not found, it is still a valid NALU if there - // are still some bytes left after the first start code. - // nalu_size is the offset to the next start code - if (!FindStartCode(stream, stream_size, nalu_size, &start_code_size)) { - // end of stream (no next NALU), but still valid NALU if any bytes left - *nalu_size = stream_size; - if (*nalu_size < 1) { - DVLOG(3) << "End of stream"; - return false; - } - } - - return true; -} - -H264Parser::Result H264Parser::ReadUE(int* val) { - int num_bits = -1; - int bit; - int rest; - - // Count the number of contiguous zero bits. - do { - READ_BITS_OR_RETURN(1, &bit); - num_bits++; - } while (bit == 0); - - if (num_bits > 31) - return kInvalidStream; - - // Calculate exp-Golomb code value of size num_bits. - *val = (1 << num_bits) - 1; - - if (num_bits > 0) { - READ_BITS_OR_RETURN(num_bits, &rest); - *val += rest; - } - - return kOk; -} - -H264Parser::Result H264Parser::ReadSE(int* val) { - int ue; - Result res; - - // See Chapter 9 in the spec. - res = ReadUE(&ue); - if (res != kOk) - return res; - - if (ue % 2 == 0) - *val = -(ue / 2); - else - *val = ue / 2 + 1; - - return kOk; -} - -H264Parser::Result H264Parser::AdvanceToNextNALU(H264NALU *nalu) { - int data; - off_t off_to_nalu_start; - - if (!LocateNALU(stream_, bytes_left_, &off_to_nalu_start, &nalu->size)) { - DVLOG(4) << "Could not find next NALU, bytes left in stream: " - << bytes_left_; - return kEOStream; - } - - nalu->data = stream_ + off_to_nalu_start; - - // Initialize bit reader at the start of found NALU. - if (!br_.Initialize(nalu->data, nalu->size)) - return kEOStream; - - DVLOG(4) << "Looking for NALU, Stream bytes left: " << bytes_left_ - << " off to next nalu: " << off_to_nalu_start; - - // Move parser state to after this NALU, so next time AdvanceToNextNALU - // is called, we will effectively be skipping it; - // other parsing functions will use the position saved - // in bit reader for parsing, so we don't have to remember it here. - stream_ += off_to_nalu_start + nalu->size; - bytes_left_ -= off_to_nalu_start + nalu->size; - - // Read NALU header, skip the forbidden_zero_bit, but check for it. - READ_BITS_OR_RETURN(1, &data); - TRUE_OR_RETURN(data == 0); - - READ_BITS_OR_RETURN(2, &nalu->nal_ref_idc); - READ_BITS_OR_RETURN(5, &nalu->nal_unit_type); - - DVLOG(4) << "NALU type: " << static_cast<int>(nalu->nal_unit_type) - << " at: " << reinterpret_cast<const void*>(nalu->data) - << " size: " << nalu->size - << " ref: " << static_cast<int>(nalu->nal_ref_idc); - - return kOk; -} - -// Default scaling lists (per spec). -static const int kDefault4x4Intra[kH264ScalingList4x4Length] = { - 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, }; - -static const int kDefault4x4Inter[kH264ScalingList4x4Length] = { - 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, }; - -static const int kDefault8x8Intra[kH264ScalingList8x8Length] = { - 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, - 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, - 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, - 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, }; - -static const int kDefault8x8Inter[kH264ScalingList8x8Length] = { - 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, - 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, - 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, - 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, }; - -static inline void DefaultScalingList4x4( - int i, - int scaling_list4x4[][kH264ScalingList4x4Length]) { - DCHECK_LT(i, 6); - - if (i < 3) - memcpy(scaling_list4x4[i], kDefault4x4Intra, sizeof(kDefault4x4Intra)); - else if (i < 6) - memcpy(scaling_list4x4[i], kDefault4x4Inter, sizeof(kDefault4x4Inter)); -} - -static inline void DefaultScalingList8x8( - int i, - int scaling_list8x8[][kH264ScalingList8x8Length]) { - DCHECK_LT(i, 6); - - if (i % 2 == 0) - memcpy(scaling_list8x8[i], kDefault8x8Intra, sizeof(kDefault8x8Intra)); - else - memcpy(scaling_list8x8[i], kDefault8x8Inter, sizeof(kDefault8x8Inter)); -} - -static void FallbackScalingList4x4( - int i, - const int default_scaling_list_intra[], - const int default_scaling_list_inter[], - int scaling_list4x4[][kH264ScalingList4x4Length]) { - static const int kScalingList4x4ByteSize = sizeof(scaling_list4x4[0][0]) * - kH264ScalingList4x4Length; - - switch (i) { - case 0: - memcpy(scaling_list4x4[i], default_scaling_list_intra, - kScalingList4x4ByteSize); - break; - - case 1: - memcpy(scaling_list4x4[i], scaling_list4x4[0], - kScalingList4x4ByteSize); - break; - - case 2: - memcpy(scaling_list4x4[i], scaling_list4x4[1], - kScalingList4x4ByteSize); - break; - - case 3: - memcpy(scaling_list4x4[i], default_scaling_list_inter, - kScalingList4x4ByteSize); - break; - - case 4: - memcpy(scaling_list4x4[i], scaling_list4x4[3], - kScalingList4x4ByteSize); - break; - - case 5: - memcpy(scaling_list4x4[i], scaling_list4x4[4], - kScalingList4x4ByteSize); - break; - - default: - NOTREACHED(); - break; - } -} - -static void FallbackScalingList8x8( - int i, - const int default_scaling_list_intra[], - const int default_scaling_list_inter[], - int scaling_list8x8[][kH264ScalingList8x8Length]) { - static const int kScalingList8x8ByteSize = sizeof(scaling_list8x8[0][0]) * - kH264ScalingList8x8Length; - - switch (i) { - case 0: - memcpy(scaling_list8x8[i], default_scaling_list_intra, - kScalingList8x8ByteSize); - break; - - case 1: - memcpy(scaling_list8x8[i], default_scaling_list_inter, - kScalingList8x8ByteSize); - break; - - case 2: - memcpy(scaling_list8x8[i], scaling_list8x8[0], - kScalingList8x8ByteSize); - break; - - case 3: - memcpy(scaling_list8x8[i], scaling_list8x8[1], - kScalingList8x8ByteSize); - break; - - case 4: - memcpy(scaling_list8x8[i], scaling_list8x8[2], - kScalingList8x8ByteSize); - break; - - case 5: - memcpy(scaling_list8x8[i], scaling_list8x8[3], - kScalingList8x8ByteSize); - break; - - default: - NOTREACHED(); - break; - } -} - -H264Parser::Result H264Parser::ParseScalingList(int size, - int* scaling_list, - bool* use_default) { - // See chapter 7.3.2.1.1.1. - int last_scale = 8; - int next_scale = 8; - int delta_scale; - - *use_default = false; - - for (int j = 0; j < size; ++j) { - if (next_scale != 0) { - READ_SE_OR_RETURN(&delta_scale); - IN_RANGE_OR_RETURN(delta_scale, -128, 127); - next_scale = (last_scale + delta_scale + 256) & 0xff; - - if (j == 0 && next_scale == 0) { - *use_default = true; - return kOk; - } - } - - scaling_list[j] = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list[j]; - } - - return kOk; -} - -H264Parser::Result H264Parser::ParseSPSScalingLists(H264SPS* sps) { - // See 7.4.2.1.1. - bool seq_scaling_list_present_flag; - bool use_default; - Result res; - - // Parse scaling_list4x4. - for (int i = 0; i < 6; ++i) { - READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag); - - if (seq_scaling_list_present_flag) { - res = ParseScalingList(arraysize(sps->scaling_list4x4[i]), - sps->scaling_list4x4[i], &use_default); - if (res != kOk) - return res; - - if (use_default) - DefaultScalingList4x4(i, sps->scaling_list4x4); - - } else { - FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter, - sps->scaling_list4x4); - } - } - - // Parse scaling_list8x8. - for (int i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) { - READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag); - - if (seq_scaling_list_present_flag) { - res = ParseScalingList(arraysize(sps->scaling_list8x8[i]), - sps->scaling_list8x8[i], &use_default); - if (res != kOk) - return res; - - if (use_default) - DefaultScalingList8x8(i, sps->scaling_list8x8); - - } else { - FallbackScalingList8x8(i, kDefault8x8Intra, kDefault8x8Inter, - sps->scaling_list8x8); - } - } - - return kOk; -} - -H264Parser::Result H264Parser::ParsePPSScalingLists(const H264SPS& sps, - H264PPS* pps) { - // See 7.4.2.2. - bool pic_scaling_list_present_flag; - bool use_default; - Result res; - - for (int i = 0; i < 6; ++i) { - READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag); - - if (pic_scaling_list_present_flag) { - res = ParseScalingList(arraysize(pps->scaling_list4x4[i]), - pps->scaling_list4x4[i], &use_default); - if (res != kOk) - return res; - - if (use_default) - DefaultScalingList4x4(i, pps->scaling_list4x4); - - } else { - if (sps.seq_scaling_matrix_present_flag) { - // Table 7-2 fallback rule A in spec. - FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter, - pps->scaling_list4x4); - } else { - // Table 7-2 fallback rule B in spec. - FallbackScalingList4x4(i, sps.scaling_list4x4[0], - sps.scaling_list4x4[3], pps->scaling_list4x4); - } - } - } - - if (pps->transform_8x8_mode_flag) { - for (int i = 0; i < ((sps.chroma_format_idc != 3) ? 2 : 6); ++i) { - READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag); - - if (pic_scaling_list_present_flag) { - res = ParseScalingList(arraysize(pps->scaling_list8x8[i]), - pps->scaling_list8x8[i], &use_default); - if (res != kOk) - return res; - - if (use_default) - DefaultScalingList8x8(i, pps->scaling_list8x8); - - } else { - if (sps.seq_scaling_matrix_present_flag) { - // Table 7-2 fallback rule A in spec. - FallbackScalingList8x8(i, kDefault8x8Intra, - kDefault8x8Inter, pps->scaling_list8x8); - } else { - // Table 7-2 fallback rule B in spec. - FallbackScalingList8x8(i, sps.scaling_list8x8[0], - sps.scaling_list8x8[1], pps->scaling_list8x8); - } - } - } - } - return kOk; -} - -static void FillDefaultSeqScalingLists(H264SPS* sps) { - for (int i = 0; i < 6; ++i) - for (int j = 0; j < kH264ScalingList4x4Length; ++j) - sps->scaling_list4x4[i][j] = 16; - - for (int i = 0; i < 6; ++i) - for (int j = 0; j < kH264ScalingList8x8Length; ++j) - sps->scaling_list8x8[i][j] = 16; -} - -H264Parser::Result H264Parser::ParseSPS(int* sps_id) { - // See 7.4.2.1. - int data; - Result res; - - *sps_id = -1; - - scoped_ptr<H264SPS> sps(new H264SPS()); - - READ_BITS_OR_RETURN(8, &sps->profile_idc); - READ_BITS_OR_RETURN(6, &sps->constraint_setx_flag); - READ_BITS_OR_RETURN(2, &data); - READ_BITS_OR_RETURN(8, &sps->level_idc); - READ_UE_OR_RETURN(&sps->seq_parameter_set_id); - TRUE_OR_RETURN(sps->seq_parameter_set_id < 32); - - if (sps->profile_idc == 100 || sps->profile_idc == 110 || - sps->profile_idc == 122 || sps->profile_idc == 244 || - sps->profile_idc == 44 || sps->profile_idc == 83 || - sps->profile_idc == 86 || sps->profile_idc == 118 || - sps->profile_idc == 128) { - READ_UE_OR_RETURN(&sps->chroma_format_idc); - TRUE_OR_RETURN(sps->chroma_format_idc < 4); - - if (sps->chroma_format_idc == 3) - READ_BOOL_OR_RETURN(&sps->separate_colour_plane_flag); - - READ_UE_OR_RETURN(&sps->bit_depth_luma_minus8); - TRUE_OR_RETURN(sps->bit_depth_luma_minus8 < 7); - - READ_UE_OR_RETURN(&sps->bit_depth_chroma_minus8); - TRUE_OR_RETURN(sps->bit_depth_chroma_minus8 < 7); - - READ_BOOL_OR_RETURN(&sps->qpprime_y_zero_transform_bypass_flag); - READ_BOOL_OR_RETURN(&sps->seq_scaling_matrix_present_flag); - - if (sps->seq_scaling_matrix_present_flag) { - DVLOG(4) << "Scaling matrix present"; - res = ParseSPSScalingLists(sps.get()); - if (res != kOk) - return res; - } else { - FillDefaultSeqScalingLists(sps.get()); - } - } else { - sps->chroma_format_idc = 1; - FillDefaultSeqScalingLists(sps.get()); - } - - if (sps->separate_colour_plane_flag) - sps->chroma_array_type = 0; - else - sps->chroma_array_type = sps->chroma_format_idc; - - READ_UE_OR_RETURN(&sps->log2_max_frame_num_minus4); - TRUE_OR_RETURN(sps->log2_max_frame_num_minus4 < 13); - - READ_UE_OR_RETURN(&sps->pic_order_cnt_type); - TRUE_OR_RETURN(sps->pic_order_cnt_type < 3); - - sps->expected_delta_per_pic_order_cnt_cycle = 0; - if (sps->pic_order_cnt_type == 0) { - READ_UE_OR_RETURN(&sps->log2_max_pic_order_cnt_lsb_minus4); - TRUE_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 < 13); - } else if (sps->pic_order_cnt_type == 1) { - READ_BOOL_OR_RETURN(&sps->delta_pic_order_always_zero_flag); - READ_SE_OR_RETURN(&sps->offset_for_non_ref_pic); - READ_SE_OR_RETURN(&sps->offset_for_top_to_bottom_field); - READ_UE_OR_RETURN(&sps->num_ref_frames_in_pic_order_cnt_cycle); - TRUE_OR_RETURN(sps->num_ref_frames_in_pic_order_cnt_cycle < 255); - - for (int i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) { - READ_SE_OR_RETURN(&sps->offset_for_ref_frame[i]); - sps->expected_delta_per_pic_order_cnt_cycle += - sps->offset_for_ref_frame[i]; - } - } - - READ_UE_OR_RETURN(&sps->max_num_ref_frames); - READ_BOOL_OR_RETURN(&sps->gaps_in_frame_num_value_allowed_flag); - - if (sps->gaps_in_frame_num_value_allowed_flag) - return kUnsupportedStream; - - READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1); - READ_UE_OR_RETURN(&sps->pic_height_in_map_units_minus1); - - READ_BOOL_OR_RETURN(&sps->frame_mbs_only_flag); - if (!sps->frame_mbs_only_flag) - READ_BOOL_OR_RETURN(&sps->mb_adaptive_frame_field_flag); - - READ_BOOL_OR_RETURN(&sps->direct_8x8_inference_flag); - - READ_BOOL_OR_RETURN(&sps->frame_cropping_flag); - if (sps->frame_cropping_flag) { - READ_UE_OR_RETURN(&sps->frame_crop_left_offset); - READ_UE_OR_RETURN(&sps->frame_crop_right_offset); - READ_UE_OR_RETURN(&sps->frame_crop_top_offset); - READ_UE_OR_RETURN(&sps->frame_crop_bottom_offset); - } - - READ_BOOL_OR_RETURN(&sps->vui_parameters_present_flag); - if (sps->vui_parameters_present_flag) { - DVLOG(1) << "VUI parameters present in SPS, ignoring"; - } - - // If an SPS with the same id already exists, replace it. - *sps_id = sps->seq_parameter_set_id; - delete active_SPSes_[*sps_id]; - active_SPSes_[*sps_id] = sps.release(); - - return kOk; -} - -H264Parser::Result H264Parser::ParsePPS(int* pps_id) { - // See 7.4.2.2. - const H264SPS* sps; - Result res; - - *pps_id = -1; - - scoped_ptr<H264PPS> pps(new H264PPS()); - - READ_UE_OR_RETURN(&pps->pic_parameter_set_id); - READ_UE_OR_RETURN(&pps->seq_parameter_set_id); - TRUE_OR_RETURN(pps->seq_parameter_set_id < 32); - - sps = GetSPS(pps->seq_parameter_set_id); - TRUE_OR_RETURN(sps); - - READ_BOOL_OR_RETURN(&pps->entropy_coding_mode_flag); - READ_BOOL_OR_RETURN(&pps->bottom_field_pic_order_in_frame_present_flag); - - READ_UE_OR_RETURN(&pps->num_slice_groups_minus1); - if (pps->num_slice_groups_minus1 > 1) { - DVLOG(1) << "Slice groups not supported"; - return kUnsupportedStream; - } - - READ_UE_OR_RETURN(&pps->num_ref_idx_l0_default_active_minus1); - TRUE_OR_RETURN(pps->num_ref_idx_l0_default_active_minus1 < 32); - - READ_UE_OR_RETURN(&pps->num_ref_idx_l1_default_active_minus1); - TRUE_OR_RETURN(pps->num_ref_idx_l1_default_active_minus1 < 32); - - READ_BOOL_OR_RETURN(&pps->weighted_pred_flag); - READ_BITS_OR_RETURN(2, &pps->weighted_bipred_idc); - TRUE_OR_RETURN(pps->weighted_bipred_idc < 3); - - READ_SE_OR_RETURN(&pps->pic_init_qp_minus26); - IN_RANGE_OR_RETURN(pps->pic_init_qp_minus26, -26, 25); - - READ_SE_OR_RETURN(&pps->pic_init_qs_minus26); - IN_RANGE_OR_RETURN(pps->pic_init_qs_minus26, -26, 25); - - READ_SE_OR_RETURN(&pps->chroma_qp_index_offset); - IN_RANGE_OR_RETURN(pps->chroma_qp_index_offset, -12, 12); - pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset; - - READ_BOOL_OR_RETURN(&pps->deblocking_filter_control_present_flag); - READ_BOOL_OR_RETURN(&pps->constrained_intra_pred_flag); - READ_BOOL_OR_RETURN(&pps->redundant_pic_cnt_present_flag); - - if (br_.HasMoreRBSPData()) { - READ_BOOL_OR_RETURN(&pps->transform_8x8_mode_flag); - READ_BOOL_OR_RETURN(&pps->pic_scaling_matrix_present_flag); - - if (pps->pic_scaling_matrix_present_flag) { - DVLOG(4) << "Picture scaling matrix present"; - res = ParsePPSScalingLists(*sps, pps.get()); - if (res != kOk) - return res; - } - - READ_SE_OR_RETURN(&pps->second_chroma_qp_index_offset); - } - - // If a PPS with the same id already exists, replace it. - *pps_id = pps->pic_parameter_set_id; - delete active_PPSes_[*pps_id]; - active_PPSes_[*pps_id] = pps.release(); - - return kOk; -} - -H264Parser::Result H264Parser::ParseRefPicListModification( - int num_ref_idx_active_minus1, - H264ModificationOfPicNum* ref_list_mods) { - H264ModificationOfPicNum* pic_num_mod; - - if (num_ref_idx_active_minus1 >= 32) - return kInvalidStream; - - for (int i = 0; i < 32; ++i) { - pic_num_mod = &ref_list_mods[i]; - READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc); - TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4); - - switch (pic_num_mod->modification_of_pic_nums_idc) { - case 0: - case 1: - READ_UE_OR_RETURN(&pic_num_mod->abs_diff_pic_num_minus1); - break; - - case 2: - READ_UE_OR_RETURN(&pic_num_mod->long_term_pic_num); - break; - - case 3: - // Per spec, list cannot be empty. - if (i == 0) - return kInvalidStream; - return kOk; - - default: - return kInvalidStream; - } - } - - // If we got here, we didn't get loop end marker prematurely, - // so make sure it is there for our client. - int modification_of_pic_nums_idc; - READ_UE_OR_RETURN(&modification_of_pic_nums_idc); - TRUE_OR_RETURN(modification_of_pic_nums_idc == 3); - - return kOk; -} - -H264Parser::Result H264Parser::ParseRefPicListModifications( - H264SliceHeader* shdr) { - Result res; - - if (!shdr->IsISlice() && !shdr->IsSISlice()) { - READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l0); - if (shdr->ref_pic_list_modification_flag_l0) { - res = ParseRefPicListModification(shdr->num_ref_idx_l0_active_minus1, - shdr->ref_list_l0_modifications); - if (res != kOk) - return res; - } - } - - if (shdr->IsBSlice()) { - READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l1); - if (shdr->ref_pic_list_modification_flag_l1) { - res = ParseRefPicListModification(shdr->num_ref_idx_l1_active_minus1, - shdr->ref_list_l1_modifications); - if (res != kOk) - return res; - } - } - - return kOk; -} - -H264Parser::Result H264Parser::ParseWeightingFactors( - int num_ref_idx_active_minus1, - int chroma_array_type, - int luma_log2_weight_denom, - int chroma_log2_weight_denom, - H264WeightingFactors* w_facts) { - - int def_luma_weight = 1 << luma_log2_weight_denom; - int def_chroma_weight = 1 << chroma_log2_weight_denom; - - for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) { - READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag); - if (w_facts->luma_weight_flag) { - READ_SE_OR_RETURN(&w_facts->luma_weight[i]); - IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127); - - READ_SE_OR_RETURN(&w_facts->luma_offset[i]); - IN_RANGE_OR_RETURN(w_facts->luma_offset[i], -128, 127); - } else { - w_facts->luma_weight[i] = def_luma_weight; - w_facts->luma_offset[i] = 0; - } - - if (chroma_array_type != 0) { - READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag); - if (w_facts->chroma_weight_flag) { - for (int j = 0; j < 2; ++j) { - READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]); - IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127); - - READ_SE_OR_RETURN(&w_facts->chroma_offset[i][j]); - IN_RANGE_OR_RETURN(w_facts->chroma_offset[i][j], -128, 127); - } - } else { - for (int j = 0; j < 2; ++j) { - w_facts->chroma_weight[i][j] = def_chroma_weight; - w_facts->chroma_offset[i][j] = 0; - } - } - } - } - - return kOk; -} - -H264Parser::Result H264Parser::ParsePredWeightTable(const H264SPS& sps, - H264SliceHeader* shdr) { - READ_UE_OR_RETURN(&shdr->luma_log2_weight_denom); - TRUE_OR_RETURN(shdr->luma_log2_weight_denom < 8); - - if (sps.chroma_array_type != 0) - READ_UE_OR_RETURN(&shdr->chroma_log2_weight_denom); - TRUE_OR_RETURN(shdr->chroma_log2_weight_denom < 8); - - Result res = ParseWeightingFactors(shdr->num_ref_idx_l0_active_minus1, - sps.chroma_array_type, - shdr->luma_log2_weight_denom, - shdr->chroma_log2_weight_denom, - &shdr->pred_weight_table_l0); - if (res != kOk) - return res; - - if (shdr->IsBSlice()) { - res = ParseWeightingFactors(shdr->num_ref_idx_l1_active_minus1, - sps.chroma_array_type, - shdr->luma_log2_weight_denom, - shdr->chroma_log2_weight_denom, - &shdr->pred_weight_table_l1); - if (res != kOk) - return res; - } - - return kOk; -} - -H264Parser::Result H264Parser::ParseDecRefPicMarking(H264SliceHeader *shdr) { - if (shdr->idr_pic_flag) { - READ_BOOL_OR_RETURN(&shdr->no_output_of_prior_pics_flag); - READ_BOOL_OR_RETURN(&shdr->long_term_reference_flag); - } else { - READ_BOOL_OR_RETURN(&shdr->adaptive_ref_pic_marking_mode_flag); - - H264DecRefPicMarking* marking; - if (shdr->adaptive_ref_pic_marking_mode_flag) { - size_t i; - for (i = 0; i < arraysize(shdr->ref_pic_marking); ++i) { - marking = &shdr->ref_pic_marking[i]; - - READ_UE_OR_RETURN(&marking->memory_mgmnt_control_operation); - if (marking->memory_mgmnt_control_operation == 0) - break; - - if (marking->memory_mgmnt_control_operation == 1 || - marking->memory_mgmnt_control_operation == 3) - READ_UE_OR_RETURN(&marking->difference_of_pic_nums_minus1); - - if (marking->memory_mgmnt_control_operation == 2) - READ_UE_OR_RETURN(&marking->long_term_pic_num); - - if (marking->memory_mgmnt_control_operation == 3 || - marking->memory_mgmnt_control_operation == 6) - READ_UE_OR_RETURN(&marking->long_term_frame_idx); - - if (marking->memory_mgmnt_control_operation == 4) - READ_UE_OR_RETURN(&marking->max_long_term_frame_idx_plus1); - - if (marking->memory_mgmnt_control_operation > 6) - return kInvalidStream; - } - - if (i == arraysize(shdr->ref_pic_marking)) { - DVLOG(1) << "Ran out of dec ref pic marking fields"; - return kUnsupportedStream; - } - } - } - - return kOk; -} - -H264Parser::Result H264Parser::ParseSliceHeader(const H264NALU& nalu, - H264SliceHeader* shdr) { - // See 7.4.3. - const H264SPS* sps; - const H264PPS* pps; - Result res; - - memset(shdr, 0, sizeof(*shdr)); - - shdr->idr_pic_flag = (nalu.nal_unit_type == 5); - shdr->nal_ref_idc = nalu.nal_ref_idc; - shdr->nalu_data = nalu.data; - shdr->nalu_size = nalu.size; - - READ_UE_OR_RETURN(&shdr->first_mb_in_slice); - READ_UE_OR_RETURN(&shdr->slice_type); - TRUE_OR_RETURN(shdr->slice_type < 10); - - READ_UE_OR_RETURN(&shdr->pic_parameter_set_id); - - pps = GetPPS(shdr->pic_parameter_set_id); - TRUE_OR_RETURN(pps); - - sps = GetSPS(pps->seq_parameter_set_id); - TRUE_OR_RETURN(sps); - - if (sps->separate_colour_plane_flag) { - DVLOG(1) << "Interlaced streams not supported"; - return kUnsupportedStream; - } - - READ_BITS_OR_RETURN(sps->log2_max_frame_num_minus4 + 4, - &shdr->frame_num); - if (!sps->frame_mbs_only_flag) { - READ_BOOL_OR_RETURN(&shdr->field_pic_flag); - if (shdr->field_pic_flag) { - DVLOG(1) << "Interlaced streams not supported"; - return kUnsupportedStream; - } - } - - if (shdr->idr_pic_flag) - READ_UE_OR_RETURN(&shdr->idr_pic_id); - - if (sps->pic_order_cnt_type == 0) { - READ_BITS_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, - &shdr->pic_order_cnt_lsb); - if (pps->bottom_field_pic_order_in_frame_present_flag && - !shdr->field_pic_flag) - READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt_bottom); - } - - if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) { - READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[0]); - if (pps->bottom_field_pic_order_in_frame_present_flag && - !shdr->field_pic_flag) - READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[1]); - } - - if (pps->redundant_pic_cnt_present_flag) { - READ_UE_OR_RETURN(&shdr->redundant_pic_cnt); - TRUE_OR_RETURN(shdr->redundant_pic_cnt < 128); - } - - if (shdr->IsBSlice()) - READ_BOOL_OR_RETURN(&shdr->direct_spatial_mv_pred_flag); - - if (shdr->IsPSlice() || shdr->IsSPSlice() || shdr->IsBSlice()) { - READ_BOOL_OR_RETURN(&shdr->num_ref_idx_active_override_flag); - if (shdr->num_ref_idx_active_override_flag) { - READ_UE_OR_RETURN(&shdr->num_ref_idx_l0_active_minus1); - if (shdr->IsBSlice()) - READ_UE_OR_RETURN(&shdr->num_ref_idx_l1_active_minus1); - } else { - shdr->num_ref_idx_l0_active_minus1 = - pps->num_ref_idx_l0_default_active_minus1; - if (shdr->IsBSlice()) { - shdr->num_ref_idx_l1_active_minus1 = - pps->num_ref_idx_l1_default_active_minus1; - } - } - } - if (shdr->field_pic_flag) { - TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 32); - TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 32); - } else { - TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 16); - TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 16); - } - - if (nalu.nal_unit_type == H264NALU::kCodedSliceExtension) { - return kUnsupportedStream; - } else { - res = ParseRefPicListModifications(shdr); - if (res != kOk) - return res; - } - - if ((pps->weighted_pred_flag && (shdr->IsPSlice() || shdr->IsSPSlice())) || - (pps->weighted_bipred_idc == 1 && shdr->IsBSlice())) { - res = ParsePredWeightTable(*sps, shdr); - if (res != kOk) - return res; - } - - if (nalu.nal_ref_idc != 0) { - res = ParseDecRefPicMarking(shdr); - if (res != kOk) - return res; - } - - if (pps->entropy_coding_mode_flag && - !shdr->IsISlice() && !shdr->IsSISlice()) { - READ_UE_OR_RETURN(&shdr->cabac_init_idc); - TRUE_OR_RETURN(shdr->cabac_init_idc < 3); - } - - READ_SE_OR_RETURN(&shdr->slice_qp_delta); - - if (shdr->IsSPSlice() || shdr->IsSISlice()) { - if (shdr->IsSPSlice()) - READ_BOOL_OR_RETURN(&shdr->sp_for_switch_flag); - READ_SE_OR_RETURN(&shdr->slice_qs_delta); - } - - if (pps->deblocking_filter_control_present_flag) { - READ_UE_OR_RETURN(&shdr->disable_deblocking_filter_idc); - TRUE_OR_RETURN(shdr->disable_deblocking_filter_idc < 3); - - if (shdr->disable_deblocking_filter_idc != 1) { - READ_SE_OR_RETURN(&shdr->slice_alpha_c0_offset_div2); - IN_RANGE_OR_RETURN(shdr->slice_alpha_c0_offset_div2, -6, 6); - - READ_SE_OR_RETURN(&shdr->slice_beta_offset_div2); - IN_RANGE_OR_RETURN(shdr->slice_beta_offset_div2, -6, 6); - } - } - - if (pps->num_slice_groups_minus1 > 0) { - DVLOG(1) << "Slice groups not supported"; - return kUnsupportedStream; - } - - size_t epb = br_.NumEmulationPreventionBytesRead(); - shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br_.NumBitsLeft(); - - return kOk; -} - -H264Parser::Result H264Parser::ParseSEI(H264SEIMessage* sei_msg) { - int byte; - - memset(sei_msg, 0, sizeof(*sei_msg)); - - READ_BITS_OR_RETURN(8, &byte); - while (byte == 0xff) { - sei_msg->type += 255; - READ_BITS_OR_RETURN(8, &byte); - } - sei_msg->type += byte; - - READ_BITS_OR_RETURN(8, &byte); - while (byte == 0xff) { - sei_msg->payload_size += 255; - READ_BITS_OR_RETURN(8, &byte); - } - sei_msg->payload_size += byte; - - DVLOG(4) << "Found SEI message type: " << sei_msg->type - << " payload size: " << sei_msg->payload_size; - - switch (sei_msg->type) { - case H264SEIMessage::kSEIRecoveryPoint: - READ_UE_OR_RETURN(&sei_msg->recovery_point.recovery_frame_cnt); - READ_BOOL_OR_RETURN(&sei_msg->recovery_point.exact_match_flag); - READ_BOOL_OR_RETURN(&sei_msg->recovery_point.broken_link_flag); - READ_BITS_OR_RETURN(2, - &sei_msg->recovery_point.changing_slice_group_idc); - break; - - default: - DVLOG(4) << "Unsupported SEI message"; - break; - } - - return kOk; -} - -} // namespace content diff --git a/content/common/gpu/media/h264_parser.h b/content/common/gpu/media/h264_parser.h deleted file mode 100644 index a4ab521..0000000 --- a/content/common/gpu/media/h264_parser.h +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This file contains an implementation of an H264 Annex-B video stream parser. - -#ifndef CONTENT_COMMON_GPU_MEDIA_H264_PARSER_H_ -#define CONTENT_COMMON_GPU_MEDIA_H264_PARSER_H_ - -#include <sys/types.h> - -#include <map> - -#include "base/basictypes.h" -#include "content/common/content_export.h" -#include "content/common/gpu/media/h264_bit_reader.h" - -namespace content { - -// For explanations of each struct and its members, see H.264 specification -// at http://www.itu.int/rec/T-REC-H.264. -struct CONTENT_EXPORT H264NALU { - H264NALU(); - - enum Type { - kUnspecified = 0, - kNonIDRSlice = 1, - kIDRSlice = 5, - kSEIMessage = 6, - kSPS = 7, - kPPS = 8, - kEOSeq = 9, - kEOStream = 11, - kCodedSliceExtension = 20, - }; - - // After (without) start code; we don't own the underlying memory - // and a shallow copy should be made when copying this struct. - const uint8* data; - off_t size; // From after start code to start code of next NALU (or EOS). - - int nal_ref_idc; - int nal_unit_type; -}; - -enum { kH264ScalingList4x4Length = 16, kH264ScalingList8x8Length = 64, }; - -struct CONTENT_EXPORT H264SPS { - H264SPS(); - - int profile_idc; - int constraint_setx_flag; - int level_idc; - int seq_parameter_set_id; - - int chroma_format_idc; - bool separate_colour_plane_flag; - int bit_depth_luma_minus8; - int bit_depth_chroma_minus8; - bool qpprime_y_zero_transform_bypass_flag; - - bool seq_scaling_matrix_present_flag; - int scaling_list4x4[6][kH264ScalingList4x4Length]; - int scaling_list8x8[6][kH264ScalingList8x8Length]; - - int log2_max_frame_num_minus4; - int pic_order_cnt_type; - int log2_max_pic_order_cnt_lsb_minus4; - bool delta_pic_order_always_zero_flag; - int offset_for_non_ref_pic; - int offset_for_top_to_bottom_field; - int num_ref_frames_in_pic_order_cnt_cycle; - int expected_delta_per_pic_order_cnt_cycle; // calculated - int offset_for_ref_frame[255]; - int max_num_ref_frames; - bool gaps_in_frame_num_value_allowed_flag; - int pic_width_in_mbs_minus1; - int pic_height_in_map_units_minus1; - bool frame_mbs_only_flag; - bool mb_adaptive_frame_field_flag; - bool direct_8x8_inference_flag; - bool frame_cropping_flag; - int frame_crop_left_offset; - int frame_crop_right_offset; - int frame_crop_top_offset; - int frame_crop_bottom_offset; - bool vui_parameters_present_flag; - int chroma_array_type; -}; - -struct CONTENT_EXPORT H264PPS { - H264PPS(); - - int pic_parameter_set_id; - int seq_parameter_set_id; - bool entropy_coding_mode_flag; - bool bottom_field_pic_order_in_frame_present_flag; - int num_slice_groups_minus1; - // TODO(posciak): Slice groups not implemented, could be added at some point. - int num_ref_idx_l0_default_active_minus1; - int num_ref_idx_l1_default_active_minus1; - bool weighted_pred_flag; - int weighted_bipred_idc; - int pic_init_qp_minus26; - int pic_init_qs_minus26; - int chroma_qp_index_offset; - bool deblocking_filter_control_present_flag; - bool constrained_intra_pred_flag; - bool redundant_pic_cnt_present_flag; - bool transform_8x8_mode_flag; - - bool pic_scaling_matrix_present_flag; - int scaling_list4x4[6][kH264ScalingList4x4Length]; - int scaling_list8x8[6][kH264ScalingList8x8Length]; - - int second_chroma_qp_index_offset; -}; - -struct CONTENT_EXPORT H264ModificationOfPicNum { - int modification_of_pic_nums_idc; - union { - int abs_diff_pic_num_minus1; - int long_term_pic_num; - }; -}; - -struct CONTENT_EXPORT H264WeightingFactors { - bool luma_weight_flag; - bool chroma_weight_flag; - int luma_weight[32]; - int luma_offset[32]; - int chroma_weight[32][2]; - int chroma_offset[32][2]; -}; - -struct CONTENT_EXPORT H264DecRefPicMarking { - int memory_mgmnt_control_operation; - int difference_of_pic_nums_minus1; - int long_term_pic_num; - int long_term_frame_idx; - int max_long_term_frame_idx_plus1; -}; - -struct CONTENT_EXPORT H264SliceHeader { - H264SliceHeader(); - - enum { - kRefListSize = 32, - kRefListModSize = kRefListSize - }; - - enum Type { - kPSlice = 0, - kBSlice = 1, - kISlice = 2, - kSPSlice = 3, - kSISlice = 4, - }; - - bool IsPSlice() const; - bool IsBSlice() const; - bool IsISlice() const; - bool IsSPSlice() const; - bool IsSISlice() const; - - bool idr_pic_flag; // from NAL header - int nal_ref_idc; // from NAL header - const uint8* nalu_data; // from NAL header - off_t nalu_size; // from NAL header - off_t header_bit_size; // calculated - - int first_mb_in_slice; - int slice_type; - int pic_parameter_set_id; - int colour_plane_id; // TODO(posciak): use this! http://crbug.com/139878 - int frame_num; - bool field_pic_flag; - bool bottom_field_flag; - int idr_pic_id; - int pic_order_cnt_lsb; - int delta_pic_order_cnt_bottom; - int delta_pic_order_cnt[2]; - int redundant_pic_cnt; - bool direct_spatial_mv_pred_flag; - - bool num_ref_idx_active_override_flag; - int num_ref_idx_l0_active_minus1; - int num_ref_idx_l1_active_minus1; - bool ref_pic_list_modification_flag_l0; - bool ref_pic_list_modification_flag_l1; - H264ModificationOfPicNum ref_list_l0_modifications[kRefListModSize]; - H264ModificationOfPicNum ref_list_l1_modifications[kRefListModSize]; - - int luma_log2_weight_denom; - int chroma_log2_weight_denom; - - bool luma_weight_l0_flag; - bool chroma_weight_l0_flag; - H264WeightingFactors pred_weight_table_l0; - - bool luma_weight_l1_flag; - bool chroma_weight_l1_flag; - H264WeightingFactors pred_weight_table_l1; - - bool no_output_of_prior_pics_flag; - bool long_term_reference_flag; - - bool adaptive_ref_pic_marking_mode_flag; - H264DecRefPicMarking ref_pic_marking[kRefListSize]; - - int cabac_init_idc; - int slice_qp_delta; - bool sp_for_switch_flag; - int slice_qs_delta; - int disable_deblocking_filter_idc; - int slice_alpha_c0_offset_div2; - int slice_beta_offset_div2; -}; - -struct H264SEIRecoveryPoint { - int recovery_frame_cnt; - bool exact_match_flag; - bool broken_link_flag; - int changing_slice_group_idc; -}; - -struct CONTENT_EXPORT H264SEIMessage { - H264SEIMessage(); - - enum Type { - kSEIRecoveryPoint = 6, - }; - - int type; - int payload_size; - union { - // Placeholder; in future more supported types will contribute to more - // union members here. - H264SEIRecoveryPoint recovery_point; - }; -}; - -// Class to parse an Annex-B H.264 stream, -// as specified in chapters 7 and Annex B of the H.264 spec. -class CONTENT_EXPORT H264Parser { - public: - enum Result { - kOk, - kInvalidStream, // error in stream - kUnsupportedStream, // stream not supported by the parser - kEOStream, // end of stream - }; - - H264Parser(); - ~H264Parser(); - - void Reset(); - // Set current stream pointer to |stream| of |stream_size| in bytes, - // |stream| owned by caller. - void SetStream(const uint8* stream, off_t stream_size); - - // Read the stream to find the next NALU, identify it and return - // that information in |*nalu|. This advances the stream to the beginning - // of this NALU, but not past it, so subsequent calls to NALU-specific - // parsing functions (ParseSPS, etc.) will parse this NALU. - // If the caller wishes to skip the current NALU, it can call this function - // again, instead of any NALU-type specific parse functions below. - Result AdvanceToNextNALU(H264NALU* nalu); - - // NALU-specific parsing functions. - // These should be called after AdvanceToNextNALU(). - - // SPSes and PPSes are owned by the parser class and the memory for their - // structures is managed here, not by the caller, as they are reused - // across NALUs. - // - // Parse an SPS/PPS NALU and save their data in the parser, returning id - // of the parsed structure in |*pps_id|/|*sps_id|. - // To get a pointer to a given SPS/PPS structure, use GetSPS()/GetPPS(), - // passing the returned |*sps_id|/|*pps_id| as parameter. - // TODO(posciak,fischman): consider replacing returning Result from Parse*() - // methods with a scoped_ptr and adding an AtEOS() function to check for EOS - // if Parse*() return NULL. - Result ParseSPS(int* sps_id); - Result ParsePPS(int* pps_id); - - // Return a pointer to SPS/PPS with given |sps_id|/|pps_id| or NULL if not - // present. - const H264SPS* GetSPS(int sps_id); - const H264PPS* GetPPS(int pps_id); - - // Slice headers and SEI messages are not used across NALUs by the parser - // and can be discarded after current NALU, so the parser does not store - // them, nor does it manage their memory. - // The caller has to provide and manage it instead. - - // Parse a slice header, returning it in |*shdr|. |*nalu| must be set to - // the NALU returned from AdvanceToNextNALU() and corresponding to |*shdr|. - Result ParseSliceHeader(const H264NALU& nalu, H264SliceHeader* shdr); - - // Parse a SEI message, returning it in |*sei_msg|, provided and managed - // by the caller. - Result ParseSEI(H264SEIMessage* sei_msg); - - private: - // Exp-Golomb code parsing as specified in chapter 9.1 of the spec. - // Read one unsigned exp-Golomb code from the stream and return in |*val|. - Result ReadUE(int* val); - - // Read one signed exp-Golomb code from the stream and return in |*val|. - Result ReadSE(int* val); - - // Parse scaling lists (see spec). - Result ParseScalingList(int size, int* scaling_list, bool* use_default); - Result ParseSPSScalingLists(H264SPS* sps); - Result ParsePPSScalingLists(const H264SPS& sps, H264PPS* pps); - - // Parse reference picture lists' modifications (see spec). - Result ParseRefPicListModifications(H264SliceHeader* shdr); - Result ParseRefPicListModification(int num_ref_idx_active_minus1, - H264ModificationOfPicNum* ref_list_mods); - - // Parse prediction weight table (see spec). - Result ParsePredWeightTable(const H264SPS& sps, H264SliceHeader* shdr); - - // Parse weighting factors (see spec). - Result ParseWeightingFactors(int num_ref_idx_active_minus1, - int chroma_array_type, - int luma_log2_weight_denom, - int chroma_log2_weight_denom, - H264WeightingFactors* w_facts); - - // Parse decoded reference picture marking information (see spec). - Result ParseDecRefPicMarking(H264SliceHeader *shdr); - - // Pointer to the current NALU in the stream. - const uint8* stream_; - - // Bytes left in the stream after the current NALU. - off_t bytes_left_; - - H264BitReader br_; - - // PPSes and SPSes stored for future reference. - typedef std::map<int, H264SPS*> SPSById; - typedef std::map<int, H264PPS*> PPSById; - SPSById active_SPSes_; - PPSById active_PPSes_; - - DISALLOW_COPY_AND_ASSIGN(H264Parser); -}; - -} // namespace content - -#endif // CONTENT_COMMON_GPU_MEDIA_H264_PARSER_H_ diff --git a/content/common/gpu/media/h264_parser_unittest.cc b/content/common/gpu/media/h264_parser_unittest.cc deleted file mode 100644 index d52bb51..0000000 --- a/content/common/gpu/media/h264_parser_unittest.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "testing/gtest/include/gtest/gtest.h" - -#include "base/command_line.h" -#include "base/files/memory_mapped_file.h" -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "content/common/gpu/media/h264_parser.h" - -using content::H264Parser; -using content::H264NALU; - -const base::FilePath::CharType* test_stream_filename = - FILE_PATH_LITERAL("content/common/gpu/testdata/test-25fps.h264"); -// Number of NALUs in the stream to be parsed. -int num_nalus = 759; - -TEST(H264ParserTest, StreamFileParsing) { - base::FilePath fp(test_stream_filename); - base::MemoryMappedFile stream; - CHECK(stream.Initialize(fp)) << "Couldn't open stream file: " - << test_stream_filename; - DVLOG(1) << "Parsing file: " << test_stream_filename; - - H264Parser parser; - parser.SetStream(stream.data(), stream.length()); - - // Parse until the end of stream/unsupported stream/error in stream is found. - int num_parsed_nalus = 0; - while (true) { - content::H264SliceHeader shdr; - content::H264SEIMessage sei_msg; - H264NALU nalu; - H264Parser::Result res = parser.AdvanceToNextNALU(&nalu); - if (res == H264Parser::kEOStream) { - DVLOG(1) << "Number of successfully parsed NALUs before EOS: " - << num_parsed_nalus; - ASSERT_EQ(num_nalus, num_parsed_nalus); - return; - } - ASSERT_EQ(res, H264Parser::kOk); - - ++num_parsed_nalus; - - int id; - switch (nalu.nal_unit_type) { - case H264NALU::kIDRSlice: - case H264NALU::kNonIDRSlice: - ASSERT_EQ(parser.ParseSliceHeader(nalu, &shdr), H264Parser::kOk); - break; - - case H264NALU::kSPS: - ASSERT_EQ(parser.ParseSPS(&id), H264Parser::kOk); - break; - - case H264NALU::kPPS: - ASSERT_EQ(parser.ParsePPS(&id), H264Parser::kOk); - break; - - case H264NALU::kSEIMessage: - ASSERT_EQ(parser.ParseSEI(&sei_msg), H264Parser::kOk); - break; - - default: - // Skip unsupported NALU. - DVLOG(4) << "Skipping unsupported NALU"; - break; - } - } -} - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - CommandLine::Init(argc, argv); - - const CommandLine::SwitchMap& switches = - CommandLine::ForCurrentProcess()->GetSwitches(); - for (CommandLine::SwitchMap::const_iterator it = switches.begin(); - it != switches.end(); ++it) { - if (it->first == "test_stream") { - test_stream_filename = it->second.c_str(); - } else if (it->first == "num_nalus") { - CHECK(base::StringToInt(it->second, &num_nalus)); - } else { - LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; - } - } - - return RUN_ALL_TESTS(); -} diff --git a/content/common/gpu/media/v4l2_video_decode_accelerator.cc b/content/common/gpu/media/v4l2_video_decode_accelerator.cc index 5d4f01a..e13f88e 100644 --- a/content/common/gpu/media/v4l2_video_decode_accelerator.cc +++ b/content/common/gpu/media/v4l2_video_decode_accelerator.cc @@ -18,8 +18,8 @@ #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" #include "base/posix/eintr_wrapper.h" -#include "content/common/gpu/media/h264_parser.h" #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" +#include "media/filters/h264_parser.h" #include "ui/gl/scoped_binders.h" namespace content { @@ -330,7 +330,7 @@ bool V4L2VideoDecodeAccelerator::Initialize( // Initialize format-specific bits. if (video_profile_ >= media::H264PROFILE_MIN && video_profile_ <= media::H264PROFILE_MAX) { - decoder_h264_parser_.reset(new content::H264Parser()); + decoder_h264_parser_.reset(new media::H264Parser()); } if (!decoder_thread_.Start()) { @@ -652,8 +652,8 @@ bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment( // For H264, we need to feed HW one frame at a time. This is going to take // some parsing of our input stream. decoder_h264_parser_->SetStream(data, size); - content::H264NALU nalu; - content::H264Parser::Result result; + media::H264NALU nalu; + media::H264Parser::Result result; *endpos = 0; // Keep on peeking the next NALs while they don't indicate a frame @@ -661,17 +661,17 @@ bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment( for (;;) { bool end_of_frame = false; result = decoder_h264_parser_->AdvanceToNextNALU(&nalu); - if (result == content::H264Parser::kInvalidStream || - result == content::H264Parser::kUnsupportedStream) + if (result == media::H264Parser::kInvalidStream || + result == media::H264Parser::kUnsupportedStream) return false; - if (result == content::H264Parser::kEOStream) { + if (result == media::H264Parser::kEOStream) { // We've reached the end of the buffer before finding a frame boundary. decoder_partial_frame_pending_ = true; return true; } switch (nalu.nal_unit_type) { - case content::H264NALU::kNonIDRSlice: - case content::H264NALU::kIDRSlice: + case media::H264NALU::kNonIDRSlice: + case media::H264NALU::kIDRSlice: if (nalu.size < 1) return false; // For these two, if the "first_mb_in_slice" field is zero, start a @@ -684,10 +684,10 @@ bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment( break; } break; - case content::H264NALU::kSPS: - case content::H264NALU::kPPS: - case content::H264NALU::kEOSeq: - case content::H264NALU::kEOStream: + case media::H264NALU::kSPS: + case media::H264NALU::kPPS: + case media::H264NALU::kEOSeq: + case media::H264NALU::kEOStream: // These unconditionally signal a frame boundary. end_of_frame = true; break; @@ -1415,7 +1415,7 @@ void V4L2VideoDecodeAccelerator::ResetDoneTask() { // Reset format-specific bits. if (video_profile_ >= media::H264PROFILE_MIN && video_profile_ <= media::H264PROFILE_MAX) { - decoder_h264_parser_.reset(new content::H264Parser()); + decoder_h264_parser_.reset(new media::H264Parser()); } // Jobs drained, we're finished resetting. diff --git a/content/common/gpu/media/v4l2_video_decode_accelerator.h b/content/common/gpu/media/v4l2_video_decode_accelerator.h index 4e7b6e0..8b5ba49 100644 --- a/content/common/gpu/media/v4l2_video_decode_accelerator.h +++ b/content/common/gpu/media/v4l2_video_decode_accelerator.h @@ -26,11 +26,13 @@ namespace base { class MessageLoopProxy; -} +} // namespace base -namespace content { +namespace media { class H264Parser; +} // namespace media +namespace content { // This class handles video accelerators directly through a V4L2 device exported // by the hardware blocks. // @@ -350,7 +352,7 @@ class CONTENT_EXPORT V4L2VideoDecodeAccelerator std::queue<linked_ptr<BitstreamBufferRef> > decoder_input_queue_; // For H264 decode, hardware requires that we send it frame-sized chunks. // We'll need to parse the stream. - scoped_ptr<content::H264Parser> decoder_h264_parser_; + scoped_ptr<media::H264Parser> decoder_h264_parser_; // Set if the decoder has a pending incomplete frame in an input buffer. bool decoder_partial_frame_pending_; diff --git a/content/common/gpu/media/vaapi_h264_decoder.cc b/content/common/gpu/media/vaapi_h264_decoder.cc index 402369b..260a4e5 100644 --- a/content/common/gpu/media/vaapi_h264_decoder.cc +++ b/content/common/gpu/media/vaapi_h264_decoder.cc @@ -219,10 +219,10 @@ void VaapiH264Decoder::UnassignSurfaceFromPoC(int poc) { } bool VaapiH264Decoder::SendPPS() { - const H264PPS* pps = parser_.GetPPS(curr_pps_id_); + const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_); DCHECK(pps); - const H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); + const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); DCHECK(sps); DCHECK(curr_pic_.get()); @@ -306,7 +306,7 @@ bool VaapiH264Decoder::SendPPS() { } bool VaapiH264Decoder::SendIQMatrix() { - const H264PPS* pps = parser_.GetPPS(curr_pps_id_); + const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_); DCHECK(pps); VAIQMatrixBufferH264 iq_matrix_buf; @@ -323,7 +323,7 @@ bool VaapiH264Decoder::SendIQMatrix() { iq_matrix_buf.ScalingList8x8[i][j] = pps->scaling_list8x8[i][j]; } } else { - const H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); + const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); DCHECK(sps); for (int i = 0; i < 6; ++i) { for (int j = 0; j < 16; ++j) @@ -341,11 +341,11 @@ bool VaapiH264Decoder::SendIQMatrix() { &iq_matrix_buf); } -bool VaapiH264Decoder::SendVASliceParam(H264SliceHeader* slice_hdr) { - const H264PPS* pps = parser_.GetPPS(slice_hdr->pic_parameter_set_id); +bool VaapiH264Decoder::SendVASliceParam(media::H264SliceHeader* slice_hdr) { + const media::H264PPS* pps = parser_.GetPPS(slice_hdr->pic_parameter_set_id); DCHECK(pps); - const H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); + const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); DCHECK(sps); VASliceParameterBufferH264 slice_param; @@ -440,7 +440,7 @@ bool VaapiH264Decoder::SendSliceData(const uint8* ptr, size_t size) { non_const_ptr); } -bool VaapiH264Decoder::PrepareRefPicLists(H264SliceHeader* slice_hdr) { +bool VaapiH264Decoder::PrepareRefPicLists(media::H264SliceHeader* slice_hdr) { ref_pic_list0_.clear(); ref_pic_list1_.clear(); @@ -459,7 +459,7 @@ bool VaapiH264Decoder::PrepareRefPicLists(H264SliceHeader* slice_hdr) { return true; } -bool VaapiH264Decoder::QueueSlice(H264SliceHeader* slice_hdr) { +bool VaapiH264Decoder::QueueSlice(media::H264SliceHeader* slice_hdr) { DCHECK(curr_pic_.get()); if (!PrepareRefPicLists(slice_hdr)) @@ -495,8 +495,7 @@ bool VaapiH264Decoder::DecodePicture() { return true; } - -bool VaapiH264Decoder::InitCurrPicture(H264SliceHeader* slice_hdr) { +bool VaapiH264Decoder::InitCurrPicture(media::H264SliceHeader* slice_hdr) { DCHECK(curr_pic_.get()); memset(curr_pic_.get(), 0, sizeof(H264Picture)); @@ -541,9 +540,10 @@ bool VaapiH264Decoder::InitCurrPicture(H264SliceHeader* slice_hdr) { return true; } -bool VaapiH264Decoder::CalculatePicOrderCounts(H264SliceHeader* slice_hdr) { +bool VaapiH264Decoder::CalculatePicOrderCounts( + media::H264SliceHeader* slice_hdr) { DCHECK_NE(curr_sps_id_, -1); - const H264SPS* sps = parser_.GetSPS(curr_sps_id_); + const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); int pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb; curr_pic_->pic_order_cnt_lsb = pic_order_cnt_lsb; @@ -750,7 +750,8 @@ struct LongTermPicNumAscCompare { } }; -void VaapiH264Decoder::ConstructReferencePicListsP(H264SliceHeader* slice_hdr) { +void VaapiH264Decoder::ConstructReferencePicListsP( + media::H264SliceHeader* slice_hdr) { // RefPicList0 (8.2.4.2.1) [[1] [2]], where: // [1] shortterm ref pics sorted by descending pic_num, // [2] longterm ref pics by ascending long_term_pic_num. @@ -783,7 +784,8 @@ struct POCDescCompare { } }; -void VaapiH264Decoder::ConstructReferencePicListsB(H264SliceHeader* slice_hdr) { +void VaapiH264Decoder::ConstructReferencePicListsB( + media::H264SliceHeader* slice_hdr) { // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where: // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC, // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC, @@ -886,11 +888,11 @@ static void ShiftRightAndInsert(H264Picture::PtrVector *v, (*v)[from] = pic; } -bool VaapiH264Decoder::ModifyReferencePicList(H264SliceHeader *slice_hdr, +bool VaapiH264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr, int list) { int num_ref_idx_lX_active_minus1; H264Picture::PtrVector* ref_pic_listx; - H264ModificationOfPicNum* list_mod; + media::H264ModificationOfPicNum* list_mod; // This can process either ref_pic_list0 or ref_pic_list1, depending on // the list argument. Set up pointers to proper list to be processed here. @@ -922,7 +924,7 @@ bool VaapiH264Decoder::ModifyReferencePicList(H264SliceHeader *slice_hdr, int pic_num_lx; bool done = false; H264Picture* pic; - for (int i = 0; i < H264SliceHeader::kRefListModSize && !done; ++i) { + for (int i = 0; i < media::H264SliceHeader::kRefListModSize && !done; ++i) { switch (list_mod->modification_of_pic_nums_idc) { case 0: case 1: @@ -954,7 +956,7 @@ bool VaapiH264Decoder::ModifyReferencePicList(H264SliceHeader *slice_hdr, pic_num_lx = pic_num_lx_no_wrap; DCHECK_LT(num_ref_idx_lX_active_minus1 + 1, - H264SliceHeader::kRefListModSize); + media::H264SliceHeader::kRefListModSize); pic = dpb_.GetShortRefPicByPicNum(pic_num_lx); if (!pic) { DVLOG(1) << "Malformed stream, no pic num " << pic_num_lx; @@ -974,7 +976,7 @@ bool VaapiH264Decoder::ModifyReferencePicList(H264SliceHeader *slice_hdr, case 2: // Modify long term reference picture position. DCHECK_LT(num_ref_idx_lX_active_minus1 + 1, - H264SliceHeader::kRefListModSize); + media::H264SliceHeader::kRefListModSize); pic = dpb_.GetLongRefPicByLongTermPicNum(list_mod->long_term_pic_num); if (!pic) { DVLOG(1) << "Malformed stream, no pic num " @@ -1074,7 +1076,7 @@ bool VaapiH264Decoder::Flush() { return true; } -bool VaapiH264Decoder::StartNewFrame(H264SliceHeader* slice_hdr) { +bool VaapiH264Decoder::StartNewFrame(media::H264SliceHeader* slice_hdr) { // TODO posciak: add handling of max_num_ref_frames per spec. // If the new frame is an IDR, output what's left to output and clear DPB @@ -1120,7 +1122,8 @@ bool VaapiH264Decoder::HandleMemoryManagementOps() { // 8.2.5.4 for (unsigned int i = 0; i < arraysize(curr_pic_->ref_pic_marking); ++i) { // Code below does not support interlaced stream (per-field pictures). - H264DecRefPicMarking* ref_pic_marking = &curr_pic_->ref_pic_marking[i]; + media::H264DecRefPicMarking* ref_pic_marking = + &curr_pic_->ref_pic_marking[i]; H264Picture* to_mark; int pic_num_x; @@ -1397,7 +1400,7 @@ static int LevelToMaxDpbMbs(int level) { } bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { - const H264SPS* sps = parser_.GetSPS(sps_id); + const media::H264SPS* sps = parser_.GetSPS(sps_id); DCHECK(sps); DVLOG(4) << "Processing SPS"; @@ -1461,7 +1464,7 @@ bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { } bool VaapiH264Decoder::ProcessPPS(int pps_id) { - const H264PPS* pps = parser_.GetPPS(pps_id); + const media::H264PPS* pps = parser_.GetPPS(pps_id); DCHECK(pps); curr_pps_id_ = pps->pic_parameter_set_id; @@ -1480,7 +1483,7 @@ bool VaapiH264Decoder::FinishPrevFrameIfPresent() { return true; } -bool VaapiH264Decoder::ProcessSlice(H264SliceHeader* slice_hdr) { +bool VaapiH264Decoder::ProcessSlice(media::H264SliceHeader* slice_hdr) { prev_frame_num_ = frame_num_; frame_num_ = slice_hdr->frame_num; @@ -1530,8 +1533,8 @@ void VaapiH264Decoder::SetStream(uint8* ptr, size_t size, int32 input_id) { } VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() { - H264Parser::Result par_res; - H264NALU nalu; + media::H264Parser::Result par_res; + media::H264NALU nalu; DCHECK_NE(state_, kError); while (1) { @@ -1547,20 +1550,20 @@ VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() { } par_res = parser_.AdvanceToNextNALU(&nalu); - if (par_res == H264Parser::kEOStream) + if (par_res == media::H264Parser::kEOStream) return kRanOutOfStreamData; - else if (par_res != H264Parser::kOk) + else if (par_res != media::H264Parser::kOk) SET_ERROR_AND_RETURN(); DVLOG(4) << "NALU found: " << static_cast<int>(nalu.nal_unit_type); switch (nalu.nal_unit_type) { - case H264NALU::kNonIDRSlice: + case media::H264NALU::kNonIDRSlice: // We can't resume from a non-IDR slice. if (state_ != kDecoding) break; // else fallthrough - case H264NALU::kIDRSlice: { + case media::H264NALU::kIDRSlice: { // TODO(posciak): the IDR may require an SPS that we don't have // available. For now we'd fail if that happens, but ideally we'd like // to keep going until the next SPS in the stream. @@ -1570,10 +1573,10 @@ VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() { } // If after reset, we should be able to recover from an IDR. - H264SliceHeader slice_hdr; + media::H264SliceHeader slice_hdr; par_res = parser_.ParseSliceHeader(nalu, &slice_hdr); - if (par_res != H264Parser::kOk) + if (par_res != media::H264Parser::kOk) SET_ERROR_AND_RETURN(); if (!ProcessSlice(&slice_hdr)) @@ -1583,14 +1586,14 @@ VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() { break; } - case H264NALU::kSPS: { + case media::H264NALU::kSPS: { int sps_id; if (!FinishPrevFrameIfPresent()) SET_ERROR_AND_RETURN(); par_res = parser_.ParseSPS(&sps_id); - if (par_res != H264Parser::kOk) + if (par_res != media::H264Parser::kOk) SET_ERROR_AND_RETURN(); bool need_new_buffers = false; @@ -1609,7 +1612,7 @@ VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() { break; } - case H264NALU::kPPS: { + case media::H264NALU::kPPS: { if (state_ != kDecoding) break; @@ -1619,7 +1622,7 @@ VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() { SET_ERROR_AND_RETURN(); par_res = parser_.ParsePPS(&pps_id); - if (par_res != H264Parser::kOk) + if (par_res != media::H264Parser::kOk) SET_ERROR_AND_RETURN(); if (!ProcessPPS(pps_id)) diff --git a/content/common/gpu/media/vaapi_h264_decoder.h b/content/common/gpu/media/vaapi_h264_decoder.h index 3bc63d3..e23d913 100644 --- a/content/common/gpu/media/vaapi_h264_decoder.h +++ b/content/common/gpu/media/vaapi_h264_decoder.h @@ -16,9 +16,9 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "content/common/gpu/media/h264_dpb.h" -#include "content/common/gpu/media/h264_parser.h" #include "content/common/gpu/media/vaapi_wrapper.h" #include "media/base/limits.h" +#include "media/filters/h264_parser.h" namespace content { @@ -130,26 +130,26 @@ class VaapiH264Decoder { // Process H264 stream structures. bool ProcessSPS(int sps_id, bool* need_new_buffers); bool ProcessPPS(int pps_id); - bool ProcessSlice(H264SliceHeader* slice_hdr); + bool ProcessSlice(media::H264SliceHeader* slice_hdr); // Initialize the current picture according to data in |slice_hdr|. - bool InitCurrPicture(H264SliceHeader* slice_hdr); + bool InitCurrPicture(media::H264SliceHeader* slice_hdr); // Calculate picture order counts for the new picture // on initialization of a new frame (see spec). - bool CalculatePicOrderCounts(H264SliceHeader* slice_hdr); + bool CalculatePicOrderCounts(media::H264SliceHeader* slice_hdr); // Update PicNum values in pictures stored in DPB on creation of new // frame (see spec). void UpdatePicNums(); // Prepare reference picture lists (ref_pic_list[01]_). - bool PrepareRefPicLists(H264SliceHeader* slice_hdr); + bool PrepareRefPicLists(media::H264SliceHeader* slice_hdr); // Construct initial reference picture lists for use in decoding of // P and B pictures (see 8.2.4 in spec). - void ConstructReferencePicListsP(H264SliceHeader* slice_hdr); - void ConstructReferencePicListsB(H264SliceHeader* slice_hdr); + void ConstructReferencePicListsP(media::H264SliceHeader* slice_hdr); + void ConstructReferencePicListsB(media::H264SliceHeader* slice_hdr); // Helper functions for reference list construction, per spec. int PicNumF(H264Picture *pic); @@ -159,7 +159,7 @@ class VaapiH264Decoder { // specified in spec (8.2.4). // // |list| indicates list number and should be either 0 or 1. - bool ModifyReferencePicList(H264SliceHeader *slice_hdr, int list); + bool ModifyReferencePicList(media::H264SliceHeader* slice_hdr, int list); // Perform reference picture memory management operations (marking/unmarking // of reference pictures, long term picture management, discarding, etc.). @@ -168,7 +168,7 @@ class VaapiH264Decoder { void ReferencePictureMarking(); // Start processing a new frame. - bool StartNewFrame(H264SliceHeader* slice_hdr); + bool StartNewFrame(media::H264SliceHeader* slice_hdr); // All data for a frame received, process it and decode. bool FinishPrevFrameIfPresent(); @@ -187,9 +187,9 @@ class VaapiH264Decoder { // These queue up data for HW decoder to be committed on running HW decode. bool SendPPS(); bool SendIQMatrix(); - bool SendVASliceParam(H264SliceHeader* slice_hdr); + bool SendVASliceParam(media::H264SliceHeader* slice_hdr); bool SendSliceData(const uint8* ptr, size_t size); - bool QueueSlice(H264SliceHeader* slice_hdr); + bool QueueSlice(media::H264SliceHeader* slice_hdr); // Helper methods for filling HW structures. void FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic); @@ -223,7 +223,7 @@ class VaapiH264Decoder { State state_; // Parser in use. - H264Parser parser_; + media::H264Parser parser_; // DPB in use. H264DPB dpb_; diff --git a/content/common/gpu/media/video_encode_accelerator_unittest.cc b/content/common/gpu/media/video_encode_accelerator_unittest.cc index 414925c..0bc4662 100644 --- a/content/common/gpu/media/video_encode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_encode_accelerator_unittest.cc @@ -13,10 +13,10 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "content/common/gpu/media/exynos_video_encode_accelerator.h" -#include "content/common/gpu/media/h264_parser.h" #include "content/common/gpu/media/video_accelerator_unittest_helpers.h" #include "media/base/bind_to_current_loop.h" #include "media/base/bitstream_buffer.h" +#include "media/filters/h264_parser.h" #include "media/video/video_encode_accelerator.h" #include "testing/gtest/include/gtest/gtest.h" @@ -181,7 +181,7 @@ class VEAClient : public VideoEncodeAccelerator::Client { // Byte size of the encoded stream (for bitrate calculation). size_t encoded_stream_size_; - content::H264Parser h264_parser_; + media::H264Parser h264_parser_; // All methods of this class should be run on the same thread. base::ThreadChecker thread_checker_; @@ -319,17 +319,17 @@ void VEAClient::BitstreamBufferReady(int32 bitstream_buffer_id, bool seen_idr_in_this_buffer = false; while (1) { - content::H264NALU nalu; - content::H264Parser::Result result; + media::H264NALU nalu; + media::H264Parser::Result result; result = h264_parser_.AdvanceToNextNALU(&nalu); - if (result == content::H264Parser::kEOStream) + if (result == media::H264Parser::kEOStream) break; - ASSERT_EQ(result, content::H264Parser::kOk); + ASSERT_EQ(result, media::H264Parser::kOk); switch (nalu.nal_unit_type) { - case content::H264NALU::kIDRSlice: + case media::H264NALU::kIDRSlice: ASSERT_TRUE(seen_sps_); ASSERT_TRUE(seen_pps_); seen_idr_ = seen_idr_in_this_buffer = true; @@ -337,7 +337,7 @@ void VEAClient::BitstreamBufferReady(int32 bitstream_buffer_id, // got a frame in time or not. keyframe_requested_at_ = kMaxFrameNum; // fallthrough - case content::H264NALU::kNonIDRSlice: + case media::H264NALU::kNonIDRSlice: ASSERT_TRUE(seen_idr_); ++num_encoded_slices_; @@ -354,10 +354,10 @@ void VEAClient::BitstreamBufferReady(int32 bitstream_buffer_id, EXPECT_LE(num_encoded_slices_, keyframe_requested_at_ + kMaxKeyframeDelay); break; - case content::H264NALU::kSPS: + case media::H264NALU::kSPS: seen_sps_ = true; break; - case content::H264NALU::kPPS: + case media::H264NALU::kPPS: ASSERT_TRUE(seen_sps_); seen_pps_ = true; break; |