7#include <packager/media/codecs/vp8_parser.h>
13#include <absl/log/check.h>
14#include <absl/log/log.h>
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>
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};
32bool VerifySyncCode(
const uint8_t* data) {
33 return data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a;
36bool ReadSegmentation(BitReader* reader) {
38 RCHECK(reader->ReadBits(1, &enabled));
43 RCHECK(reader->ReadBits(1, &update_map));
45 RCHECK(reader->ReadBits(1, &update_data));
48 RCHECK(reader->SkipBits(1));
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));
55 for (uint32_t i = 0; i < MB_FEATURE_TREE_PROBS; ++i)
56 RCHECK(reader->SkipBitsConditional(
true, 8));
61bool ReadLoopFilter(BitReader* reader) {
62 RCHECK(reader->SkipBits(10));
64 bool mode_ref_delta_enabled;
65 RCHECK(reader->ReadBits(1, &mode_ref_delta_enabled));
66 if (!mode_ref_delta_enabled)
68 bool mode_ref_delta_update;
69 RCHECK(reader->ReadBits(1, &mode_ref_delta_update));
70 if (!mode_ref_delta_update)
73 for (uint32_t i = 0; i < MAX_REF_LF_DELTAS + MAX_MODE_LF_DELTAS; ++i)
74 RCHECK(reader->SkipBitsConditional(
true, 6 + 1));
78bool ReadQuantization(BitReader* reader) {
80 RCHECK(reader->ReadBits(7, &yac_index));
81 VLOG(4) <<
"yac_index: " << yac_index;
82 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
83 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
84 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
85 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
86 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
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));
97 if (!refresh_altref_frame)
98 RCHECK(reader->SkipBits(2));
99 RCHECK(reader->SkipBits(2));
105VP8Parser::VP8Parser() : width_(0), height_(0) {}
106VP8Parser::~VP8Parser() {}
108bool VP8Parser::Parse(
const uint8_t* data,
110 std::vector<VPxFrameInfo>* vpx_frames) {
119 bool is_interframe = data[0] & 1;
122 uint8_t profile = (data[0] >> 1) & 3;
126 uint32_t header_size = (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
127 RCHECK(header_size <= data_size);
129 if (!is_interframe) {
133 RCHECK(VerifySyncCode(&data[3]));
136 width_ = data[6] | ((data[7] & 0x3f) << 8);
137 height_ = data[8] | ((data[9] & 0x3f) << 8);
142 RCHECK(ReadSegmentation(&reader));
143 RCHECK(ReadLoopFilter(&reader));
145 RCHECK(ReadQuantization(&reader));
148 RCHECK(ReadRefreshFrame(&reader));
159 writable_codec_config()->set_profile(profile);
162 writable_codec_config()->set_bit_depth(8);
163 writable_codec_config()->SetChromaSubsampling(
164 VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA);
167 vpx_frame.frame_size = data_size;
168 vpx_frame.uncompressed_header_size =
170 vpx_frame.is_keyframe = !is_interframe;
171 vpx_frame.width = width_;
172 vpx_frame.height = height_;
175 vpx_frames->push_back(vpx_frame);
177 VLOG(3) <<
"\n frame_size: " << vpx_frame.frame_size
178 <<
"\n uncompressed_header_size: "
179 << vpx_frame.uncompressed_header_size
181 <<
"\n header_size: " << header_size
182 <<
"\n width: " << vpx_frame.width
183 <<
"\n height: " << vpx_frame.height;
187bool VP8Parser::IsKeyframe(
const uint8_t* data,
size_t data_size) {
193 if ((data[0] & 0x01) != 0)
195 return VerifySyncCode(&data[3]);
All the methods that are virtual are virtual for mocking.