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