Shaka Packager SDK
vp8_parser.cc
1 // Copyright 2015 Google LLC. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include <packager/media/codecs/vp8_parser.h>
8 
9 #include <absl/log/check.h>
10 #include <absl/log/log.h>
11 
12 #include <packager/macros/logging.h>
13 #include <packager/media/base/bit_reader.h>
14 #include <packager/media/base/rcheck.h>
15 
16 namespace shaka {
17 namespace media {
18 namespace {
19 
20 const uint32_t MB_FEATURE_TREE_PROBS = 3;
21 const uint32_t MAX_MB_SEGMENTS = 4;
22 const uint32_t MAX_REF_LF_DELTAS = 4;
23 const uint32_t MAX_MODE_LF_DELTAS = 4;
24 const uint32_t MB_LVL_MAX = 2;
25 const uint32_t MB_FEATURE_DATA_BITS[MB_LVL_MAX] = {7, 6};
26 
27 bool VerifySyncCode(const uint8_t* data) {
28  return data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a;
29 }
30 
31 bool ReadSegmentation(BitReader* reader) {
32  bool enabled;
33  RCHECK(reader->ReadBits(1, &enabled));
34  if (!enabled)
35  return true;
36 
37  bool update_map;
38  RCHECK(reader->ReadBits(1, &update_map));
39  bool update_data;
40  RCHECK(reader->ReadBits(1, &update_data));
41 
42  if (update_data) {
43  RCHECK(reader->SkipBits(1)); // abs_delta
44  for (uint32_t i = 0; i < MAX_MB_SEGMENTS; ++i)
45  for (uint32_t j = 0; j < MB_LVL_MAX; ++j) {
46  RCHECK(reader->SkipBitsConditional(true, MB_FEATURE_DATA_BITS[j] + 1));
47  }
48  }
49  if (update_map) {
50  for (uint32_t i = 0; i < MB_FEATURE_TREE_PROBS; ++i)
51  RCHECK(reader->SkipBitsConditional(true, 8));
52  }
53  return true;
54 }
55 
56 bool ReadLoopFilter(BitReader* reader) {
57  RCHECK(reader->SkipBits(10)); // filter_type, filter_evel, sharness_level
58 
59  bool mode_ref_delta_enabled;
60  RCHECK(reader->ReadBits(1, &mode_ref_delta_enabled));
61  if (!mode_ref_delta_enabled)
62  return true;
63  bool mode_ref_delta_update;
64  RCHECK(reader->ReadBits(1, &mode_ref_delta_update));
65  if (!mode_ref_delta_update)
66  return true;
67 
68  for (uint32_t i = 0; i < MAX_REF_LF_DELTAS + MAX_MODE_LF_DELTAS; ++i)
69  RCHECK(reader->SkipBitsConditional(true, 6 + 1));
70  return true;
71 }
72 
73 bool ReadQuantization(BitReader* reader) {
74  uint32_t yac_index;
75  RCHECK(reader->ReadBits(7, &yac_index));
76  VLOG(4) << "yac_index: " << yac_index;
77  RCHECK(reader->SkipBitsConditional(true, 4 + 1)); // y dc delta
78  RCHECK(reader->SkipBitsConditional(true, 4 + 1)); // y2 dc delta
79  RCHECK(reader->SkipBitsConditional(true, 4 + 1)); // y2 ac delta
80  RCHECK(reader->SkipBitsConditional(true, 4 + 1)); // chroma dc delta
81  RCHECK(reader->SkipBitsConditional(true, 4 + 1)); // chroma ac delta
82  return true;
83 }
84 
85 bool ReadRefreshFrame(BitReader* reader) {
86  bool refresh_golden_frame;
87  RCHECK(reader->ReadBits(1, &refresh_golden_frame));
88  bool refresh_altref_frame;
89  RCHECK(reader->ReadBits(1, &refresh_altref_frame));
90  if (!refresh_golden_frame)
91  RCHECK(reader->SkipBits(2)); // buffer copy flag
92  if (!refresh_altref_frame)
93  RCHECK(reader->SkipBits(2)); // buffer copy flag
94  RCHECK(reader->SkipBits(2)); // sign bias flags
95  return true;
96 }
97 
98 } // namespace
99 
100 VP8Parser::VP8Parser() : width_(0), height_(0) {}
101 VP8Parser::~VP8Parser() {}
102 
103 bool VP8Parser::Parse(const uint8_t* data,
104  size_t data_size,
105  std::vector<VPxFrameInfo>* vpx_frames) {
106  DCHECK(data);
107  DCHECK(vpx_frames);
108 
109  BitReader reader(data, data_size);
110  // The following 3 bytes are read directly from |data|.
111  RCHECK(reader.SkipBytes(3));
112 
113  // One bit for frame type.
114  bool is_interframe = data[0] & 1;
115  // 3-bit version number with 2 bits for profile and the other bit reserved for
116  // future variants.
117  uint8_t profile = (data[0] >> 1) & 3;
118  // One bit for show frame flag.
119  // Then 19 bits (the remaining 3 bits in the first byte + next two bytes) for
120  // header size.
121  uint32_t header_size = (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
122  RCHECK(header_size <= data_size);
123 
124  if (!is_interframe) {
125  // The following 7 bytes are read directly from |data|.
126  RCHECK(reader.SkipBytes(7));
127 
128  RCHECK(VerifySyncCode(&data[3]));
129 
130  // Bits 0b11000000 for data[7] and data[9] are scaling.
131  width_ = data[6] | ((data[7] & 0x3f) << 8);
132  height_ = data[8] | ((data[9] & 0x3f) << 8);
133 
134  RCHECK(reader.SkipBits(2)); // colorspace and pixel value clamping.
135  }
136 
137  RCHECK(ReadSegmentation(&reader));
138  RCHECK(ReadLoopFilter(&reader));
139  RCHECK(reader.SkipBits(2)); // partitions bits
140  RCHECK(ReadQuantization(&reader));
141 
142  if (is_interframe) {
143  RCHECK(ReadRefreshFrame(&reader));
144  RCHECK(reader.SkipBits(1)); // refresh_entropy_probs
145  RCHECK(reader.SkipBits(1)); // refresh last frame flag
146  } else {
147  RCHECK(reader.SkipBits(1)); // refresh_entropy_probs
148  }
149 
150  // The next field is entropy header (coef probability tree), which is encoded
151  // using bool entropy encoder, i.e. compressed. We don't consider it as part
152  // of uncompressed header.
153 
154  writable_codec_config()->set_profile(profile);
155  // VP8 uses an 8-bit YUV 4:2:0 format.
156  // http://tools.ietf.org/html/rfc6386 Section 2.
157  writable_codec_config()->set_bit_depth(8);
158  writable_codec_config()->SetChromaSubsampling(
159  VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA);
160 
161  VPxFrameInfo vpx_frame;
162  vpx_frame.frame_size = data_size;
163  vpx_frame.uncompressed_header_size =
164  vpx_frame.frame_size - reader.bits_available() / 8;
165  vpx_frame.is_keyframe = !is_interframe;
166  vpx_frame.width = width_;
167  vpx_frame.height = height_;
168 
169  vpx_frames->clear();
170  vpx_frames->push_back(vpx_frame);
171 
172  VLOG(3) << "\n frame_size: " << vpx_frame.frame_size
173  << "\n uncompressed_header_size: "
174  << vpx_frame.uncompressed_header_size
175  << "\n bits read: " << reader.bit_position()
176  << "\n header_size: " << header_size
177  << "\n width: " << vpx_frame.width
178  << "\n height: " << vpx_frame.height;
179  return true;
180 }
181 
182 bool VP8Parser::IsKeyframe(const uint8_t* data, size_t data_size) {
183  // Make sure the block is big enough for the minimal keyframe header size.
184  if (data_size < 10)
185  return false;
186 
187  // The LSb of the first byte must be a 0 for a keyframe.
188  if ((data[0] & 0x01) != 0)
189  return false;
190  return VerifySyncCode(&data[3]);
191 }
192 
193 } // namespace media
194 } // namespace shaka
A class to read bit streams.
Definition: bit_reader.h:20
size_t bit_position() const
Definition: bit_reader.h:97
bool SkipBits(size_t num_bits)
Definition: bit_reader.cc:26
bool SkipBytes(size_t num_bytes)
Definition: bit_reader.cc:65
size_t bits_available() const
Definition: bit_reader.h:92
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66