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