7 #include <packager/media/codecs/vp8_parser.h>
9 #include <absl/log/check.h>
10 #include <absl/log/log.h>
12 #include <packager/macros/logging.h>
13 #include <packager/media/base/bit_reader.h>
14 #include <packager/media/base/rcheck.h>
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};
27 bool VerifySyncCode(
const uint8_t* data) {
28 return data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a;
31 bool ReadSegmentation(BitReader* reader) {
33 RCHECK(reader->ReadBits(1, &enabled));
38 RCHECK(reader->ReadBits(1, &update_map));
40 RCHECK(reader->ReadBits(1, &update_data));
43 RCHECK(reader->SkipBits(1));
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));
50 for (uint32_t i = 0; i < MB_FEATURE_TREE_PROBS; ++i)
51 RCHECK(reader->SkipBitsConditional(
true, 8));
56 bool ReadLoopFilter(BitReader* reader) {
57 RCHECK(reader->SkipBits(10));
59 bool mode_ref_delta_enabled;
60 RCHECK(reader->ReadBits(1, &mode_ref_delta_enabled));
61 if (!mode_ref_delta_enabled)
63 bool mode_ref_delta_update;
64 RCHECK(reader->ReadBits(1, &mode_ref_delta_update));
65 if (!mode_ref_delta_update)
68 for (uint32_t i = 0; i < MAX_REF_LF_DELTAS + MAX_MODE_LF_DELTAS; ++i)
69 RCHECK(reader->SkipBitsConditional(
true, 6 + 1));
73 bool ReadQuantization(BitReader* reader) {
75 RCHECK(reader->ReadBits(7, &yac_index));
76 VLOG(4) <<
"yac_index: " << yac_index;
77 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
78 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
79 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
80 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
81 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
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));
92 if (!refresh_altref_frame)
93 RCHECK(reader->SkipBits(2));
94 RCHECK(reader->SkipBits(2));
100 VP8Parser::VP8Parser() : width_(0), height_(0) {}
101 VP8Parser::~VP8Parser() {}
103 bool VP8Parser::Parse(
const uint8_t* data,
105 std::vector<VPxFrameInfo>* vpx_frames) {
114 bool is_interframe = data[0] & 1;
117 uint8_t profile = (data[0] >> 1) & 3;
121 uint32_t header_size = (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
122 RCHECK(header_size <= data_size);
124 if (!is_interframe) {
128 RCHECK(VerifySyncCode(&data[3]));
131 width_ = data[6] | ((data[7] & 0x3f) << 8);
132 height_ = data[8] | ((data[9] & 0x3f) << 8);
137 RCHECK(ReadSegmentation(&reader));
138 RCHECK(ReadLoopFilter(&reader));
140 RCHECK(ReadQuantization(&reader));
143 RCHECK(ReadRefreshFrame(&reader));
154 writable_codec_config()->set_profile(profile);
157 writable_codec_config()->set_bit_depth(8);
158 writable_codec_config()->SetChromaSubsampling(
159 VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA);
162 vpx_frame.frame_size = data_size;
163 vpx_frame.uncompressed_header_size =
165 vpx_frame.is_keyframe = !is_interframe;
166 vpx_frame.width = width_;
167 vpx_frame.height = height_;
170 vpx_frames->push_back(vpx_frame);
172 VLOG(3) <<
"\n frame_size: " << vpx_frame.frame_size
173 <<
"\n uncompressed_header_size: "
174 << vpx_frame.uncompressed_header_size
176 <<
"\n header_size: " << header_size
177 <<
"\n width: " << vpx_frame.width
178 <<
"\n height: " << vpx_frame.height;
182 bool VP8Parser::IsKeyframe(
const uint8_t* data,
size_t data_size) {
188 if ((data[0] & 0x01) != 0)
190 return VerifySyncCode(&data[3]);
All the methods that are virtual are virtual for mocking.