OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // This file contains an implementation of a VP9 bitstream parser. | 5 // This file contains an implementation of a VP9 bitstream parser. |
6 // | |
7 // VERBOSE level: | |
8 // 1 something wrong in bitstream | |
9 // 2 parsing steps | |
10 // 3 parsed values (selected) | |
6 | 11 |
7 #include "media/filters/vp9_parser.h" | 12 #include "media/filters/vp9_parser.h" |
8 | 13 |
9 #include <algorithm> | 14 #include <algorithm> |
10 | 15 |
16 #include "base/bind.h" | |
11 #include "base/logging.h" | 17 #include "base/logging.h" |
12 #include "base/macros.h" | 18 #include "base/macros.h" |
13 #include "base/numerics/safe_conversions.h" | 19 #include "base/numerics/safe_conversions.h" |
14 | 20 #include "media/filters/vp9_compressed_header_parser.h" |
15 namespace { | 21 #include "media/filters/vp9_uncompressed_header_parser.h" |
16 | |
17 const int kMaxLoopFilterLevel = 63; | |
18 | |
19 // Helper function for Vp9Parser::ReadTiles. Defined as get_min_log2_tile_cols | |
20 // in spec. | |
21 int GetMinLog2TileCols(int sb64_cols) { | |
22 const int kMaxTileWidthB64 = 64; | |
23 int min_log2 = 0; | |
24 while ((kMaxTileWidthB64 << min_log2) < sb64_cols) | |
25 min_log2++; | |
26 return min_log2; | |
27 } | |
28 | |
29 // Helper function for Vp9Parser::ReadTiles. Defined as get_max_log2_tile_cols | |
30 // in spec. | |
31 int GetMaxLog2TileCols(int sb64_cols) { | |
32 const int kMinTileWidthB64 = 4; | |
33 int max_log2 = 1; | |
34 while ((sb64_cols >> max_log2) >= kMinTileWidthB64) | |
35 max_log2++; | |
36 return max_log2 - 1; | |
37 } | |
38 | |
39 } // namespace | |
40 | 22 |
41 namespace media { | 23 namespace media { |
42 | 24 |
43 bool Vp9FrameHeader::IsKeyframe() const { | 25 bool Vp9FrameHeader::IsKeyframe() const { |
44 // When show_existing_frame is true, the frame header does not precede an | 26 // When show_existing_frame is true, the frame header does not precede an |
45 // actual frame to be decoded, so frame_type does not apply (and is not read | 27 // actual frame to be decoded, so frame_type does not apply (and is not read |
46 // from the stream). | 28 // from the stream). |
47 return !show_existing_frame && frame_type == KEYFRAME; | 29 return !show_existing_frame && frame_type == KEYFRAME; |
48 } | 30 } |
49 | 31 |
32 bool Vp9FrameHeader::IsIntra() const { | |
33 return !show_existing_frame && (frame_type == KEYFRAME || intra_only); | |
34 } | |
35 | |
50 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size) | 36 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size) |
51 : ptr(ptr), size(size) {} | 37 : ptr(ptr), size(size) {} |
52 | 38 |
53 Vp9Parser::Vp9Parser() { | 39 Vp9FrameContextManager::Vp9FrameContextManager() |
40 : initialized_(false), | |
Pawel Osciak
2016/08/08 08:13:37
Perhaps we could initialize in class body?
kcwu
2016/08/09 04:29:43
Done.
| |
41 needs_client_update_(false), | |
42 weak_ptr_factory_(this) {} | |
43 | |
44 Vp9FrameContextManager::~Vp9FrameContextManager() {} | |
45 | |
46 bool Vp9FrameContextManager::IsValidFrameContext( | |
47 const Vp9FrameContext& context) { | |
48 // probs should be in [1, 255] range. | |
49 static_assert(sizeof(Vp9Prob) == 1, | |
50 "following checks assuming Vp9Prob is single byte"); | |
51 if (memchr(context.tx_probs_8x8, 0, sizeof(context.tx_probs_8x8))) | |
52 return false; | |
53 if (memchr(context.tx_probs_16x16, 0, sizeof(context.tx_probs_16x16))) | |
54 return false; | |
55 if (memchr(context.tx_probs_32x32, 0, sizeof(context.tx_probs_32x32))) | |
56 return false; | |
57 | |
58 for (auto& a : context.coef_probs) { | |
59 for (auto& ai : a) { | |
60 for (auto& aj : ai) { | |
61 for (auto& ak : aj) { | |
62 int max_l = (ak == aj[0]) ? 3 : 6; | |
63 for (int l = 0; l < max_l; l++) { | |
64 for (auto& x : ak[l]) { | |
65 if (x == 0) | |
66 return false; | |
67 } | |
68 } | |
69 } | |
70 } | |
71 } | |
72 } | |
73 if (memchr(context.skip_prob, 0, sizeof(context.skip_prob))) | |
74 return false; | |
75 if (memchr(context.inter_mode_probs, 0, sizeof(context.inter_mode_probs))) | |
76 return false; | |
77 if (memchr(context.interp_filter_probs, 0, | |
78 sizeof(context.interp_filter_probs))) | |
79 return false; | |
80 if (memchr(context.is_inter_prob, 0, sizeof(context.is_inter_prob))) | |
81 return false; | |
82 if (memchr(context.comp_mode_prob, 0, sizeof(context.comp_mode_prob))) | |
83 return false; | |
84 if (memchr(context.single_ref_prob, 0, sizeof(context.single_ref_prob))) | |
85 return false; | |
86 if (memchr(context.comp_ref_prob, 0, sizeof(context.comp_ref_prob))) | |
87 return false; | |
88 if (memchr(context.y_mode_probs, 0, sizeof(context.y_mode_probs))) | |
89 return false; | |
90 if (memchr(context.uv_mode_probs, 0, sizeof(context.uv_mode_probs))) | |
91 return false; | |
92 if (memchr(context.partition_probs, 0, sizeof(context.partition_probs))) | |
93 return false; | |
94 if (memchr(context.mv_joint_probs, 0, sizeof(context.mv_joint_probs))) | |
95 return false; | |
96 if (memchr(context.mv_sign_prob, 0, sizeof(context.mv_sign_prob))) | |
97 return false; | |
98 if (memchr(context.mv_class_probs, 0, sizeof(context.mv_class_probs))) | |
99 return false; | |
100 if (memchr(context.mv_class0_bit_prob, 0, sizeof(context.mv_class0_bit_prob))) | |
101 return false; | |
102 if (memchr(context.mv_bits_prob, 0, sizeof(context.mv_bits_prob))) | |
103 return false; | |
104 if (memchr(context.mv_class0_fr_probs, 0, sizeof(context.mv_class0_fr_probs))) | |
105 return false; | |
106 if (memchr(context.mv_fr_probs, 0, sizeof(context.mv_fr_probs))) | |
107 return false; | |
108 if (memchr(context.mv_class0_hp_prob, 0, sizeof(context.mv_class0_hp_prob))) | |
109 return false; | |
110 if (memchr(context.mv_hp_prob, 0, sizeof(context.mv_hp_prob))) | |
111 return false; | |
112 | |
113 return true; | |
114 } | |
115 | |
116 const Vp9FrameContext& Vp9FrameContextManager::frame_context() const { | |
117 DCHECK(initialized_); | |
118 DCHECK(!needs_client_update_); | |
119 return frame_context_; | |
120 } | |
121 | |
122 void Vp9FrameContextManager::Reset() { | |
123 initialized_ = false; | |
124 needs_client_update_ = false; | |
125 weak_ptr_factory_.InvalidateWeakPtrs(); | |
126 } | |
127 | |
128 Vp9FrameContextManager::ContextRefreshCallback | |
129 Vp9FrameContextManager::SetNeedsClientUpdate() { | |
130 DCHECK(!needs_client_update_); | |
131 initialized_ = true; | |
132 needs_client_update_ = true; | |
133 | |
134 return base::Bind(&Vp9FrameContextManager::UpdateFromClient, | |
135 weak_ptr_factory_.GetWeakPtr()); | |
136 } | |
137 | |
138 void Vp9FrameContextManager::Update(const Vp9FrameContext& frame_context) { | |
139 // DCHECK because we can trust values from our parser. | |
140 DCHECK(IsValidFrameContext(frame_context)); | |
141 initialized_ = true; | |
142 frame_context_ = frame_context; | |
143 | |
144 // For frame context we are updating, it may be still awaiting previous | |
145 // ContextRefreshCallback. Because we overwrite the value of context here and | |
146 // previous ContextRefreshCallback no longer matters, invalidate the weak ptr | |
147 // to prevent previous ContextRefreshCallback run. | |
148 // With this optimization, we may be able to parse more frames while previous | |
149 // are still decoding. | |
150 weak_ptr_factory_.InvalidateWeakPtrs(); | |
151 needs_client_update_ = false; | |
152 } | |
153 | |
154 void Vp9FrameContextManager::UpdateFromClient( | |
155 const Vp9FrameContext& frame_context) { | |
156 DVLOG(2) << "Got external frame_context update"; | |
157 DCHECK(needs_client_update_); | |
158 if (!IsValidFrameContext(frame_context)) { | |
159 DLOG(ERROR) << "Invalid prob value in frame_context"; | |
160 return; | |
161 } | |
162 needs_client_update_ = false; | |
163 initialized_ = true; | |
164 frame_context_ = frame_context; | |
165 } | |
166 | |
167 void Vp9Parser::Context::Reset() { | |
168 memset(&segmentation, 0, sizeof(segmentation)); | |
169 memset(&loop_filter, 0, sizeof(loop_filter)); | |
170 memset(&ref_slots, 0, sizeof(ref_slots)); | |
171 for (auto& manager : frame_context_managers) | |
172 manager.Reset(); | |
173 } | |
174 | |
175 Vp9Parser::Vp9Parser(bool parsing_compressed_header) | |
176 : parsing_compressed_header_(parsing_compressed_header) { | |
54 Reset(); | 177 Reset(); |
55 } | 178 } |
56 | 179 |
57 Vp9Parser::~Vp9Parser() {} | 180 Vp9Parser::~Vp9Parser() {} |
58 | 181 |
59 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) { | 182 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) { |
60 DCHECK(stream); | 183 DCHECK(stream); |
61 stream_ = stream; | 184 stream_ = stream; |
62 bytes_left_ = stream_size; | 185 bytes_left_ = stream_size; |
63 frames_.clear(); | 186 frames_.clear(); |
64 } | 187 } |
65 | 188 |
66 void Vp9Parser::Reset() { | 189 void Vp9Parser::Reset() { |
67 stream_ = nullptr; | 190 stream_ = nullptr; |
68 bytes_left_ = 0; | 191 bytes_left_ = 0; |
69 frames_.clear(); | 192 frames_.clear(); |
70 | 193 |
71 memset(&segmentation_, 0, sizeof(segmentation_)); | 194 context_.Reset(); |
72 memset(&loop_filter_, 0, sizeof(loop_filter_)); | 195 } |
73 memset(&ref_slots_, 0, sizeof(ref_slots_)); | 196 |
74 } | 197 Vp9Parser::Result Vp9Parser::ParseNextFrame( |
75 | 198 Vp9FrameHeader* fhdr, |
76 uint8_t Vp9Parser::ReadProfile() { | 199 Vp9FrameContextManager::ContextRefreshCallback* context_refresh_cb) { |
77 uint8_t profile = 0; | 200 DCHECK(fhdr); |
78 | 201 DCHECK(!parsing_compressed_header_ || context_refresh_cb); |
79 // LSB first. | 202 DVLOG(2) << "ParseNextFrame"; |
80 if (reader_.ReadBool()) | 203 |
81 profile |= 1; | 204 // If |curr_frame_info_| is valid, uncompressed header was parsed into |
82 if (reader_.ReadBool()) | 205 // |curr_frame_header_| and we are awaiting context update to proceed with |
83 profile |= 2; | 206 // compressed header parsing. |
84 if (profile > 2 && reader_.ReadBool()) | 207 if (!curr_frame_info_.IsValid()) { |
85 profile += 1; | 208 if (frames_.empty()) { |
86 return profile; | 209 // No frames to be decoded, if there is no more stream, request more. |
87 } | 210 if (!stream_) |
88 | 211 return kEOStream; |
89 bool Vp9Parser::VerifySyncCode() { | 212 |
90 const int kSyncCode = 0x498342; | 213 // New stream to be parsed, parse it and fill frames_. |
91 if (reader_.ReadLiteral(8 * 3) != kSyncCode) { | 214 frames_ = ParseSuperframe(); |
92 DVLOG(1) << "Invalid frame sync code"; | 215 if (frames_.empty()) { |
93 return false; | 216 DVLOG(1) << "Failed parsing superframes"; |
94 } | 217 return kInvalidStream; |
95 return true; | 218 } |
96 } | 219 } |
97 | 220 |
98 bool Vp9Parser::ReadBitDepthColorSpaceSampling(Vp9FrameHeader* fhdr) { | 221 curr_frame_info_ = frames_.front(); |
99 if (fhdr->profile == 2 || fhdr->profile == 3) { | 222 frames_.pop_front(); |
100 fhdr->bit_depth = reader_.ReadBool() ? 12 : 10; | 223 |
101 } else { | 224 memset(&curr_frame_header_, 0, sizeof(curr_frame_header_)); |
102 fhdr->bit_depth = 8; | 225 |
103 } | 226 Vp9UncompressedHeaderParser uncompressed_parser(&context_); |
104 | 227 if (!uncompressed_parser.Parse(curr_frame_info_.ptr, curr_frame_info_.size, |
105 fhdr->color_space = static_cast<Vp9ColorSpace>(reader_.ReadLiteral(3)); | 228 &curr_frame_header_)) |
106 if (fhdr->color_space != Vp9ColorSpace::SRGB) { | 229 return kInvalidStream; |
107 fhdr->yuv_range = reader_.ReadBool(); | 230 |
108 if (fhdr->profile == 1 || fhdr->profile == 3) { | 231 if (curr_frame_header_.header_size_in_bytes == 0) { |
109 fhdr->subsampling_x = reader_.ReadBool() ? 1 : 0; | 232 // Verify padding bits are zero. |
110 fhdr->subsampling_y = reader_.ReadBool() ? 1 : 0; | 233 for (off_t i = curr_frame_header_.uncompressed_header_size; |
111 if (fhdr->subsampling_x == 1 && fhdr->subsampling_y == 1) { | 234 i < curr_frame_info_.size; i++) { |
112 DVLOG(1) << "4:2:0 color not supported in profile 1 or 3"; | 235 if (curr_frame_info_.ptr[i] != 0) { |
113 return false; | 236 DVLOG(1) << "Padding bits are not zeros."; |
114 } | 237 return kInvalidStream; |
115 bool reserved = reader_.ReadBool(); | 238 } |
116 if (reserved) { | 239 } |
117 DVLOG(1) << "reserved bit set"; | 240 *fhdr = curr_frame_header_; |
118 return false; | 241 curr_frame_info_.Reset(); |
119 } | 242 return kOk; |
120 } else { | 243 } |
121 fhdr->subsampling_x = fhdr->subsampling_y = 1; | 244 if (curr_frame_header_.uncompressed_header_size + |
122 } | 245 curr_frame_header_.header_size_in_bytes > |
123 } else { | 246 base::checked_cast<size_t>(curr_frame_info_.size)) { |
124 if (fhdr->profile == 1 || fhdr->profile == 3) { | 247 DVLOG(1) << "header_size_in_bytes=" |
125 fhdr->subsampling_x = fhdr->subsampling_y = 0; | 248 << curr_frame_header_.header_size_in_bytes |
126 | 249 << " is larger than bytes left in buffer: " |
127 bool reserved = reader_.ReadBool(); | 250 << curr_frame_info_.size - |
128 if (reserved) { | 251 curr_frame_header_.uncompressed_header_size; |
129 DVLOG(1) << "reserved bit set"; | 252 return kInvalidStream; |
130 return false; | 253 } |
131 } | 254 } |
132 } else { | 255 |
133 DVLOG(1) << "4:4:4 color not supported in profile 0 or 2"; | 256 if (parsing_compressed_header_) { |
134 return false; | 257 Vp9FrameContextManager& context_to_load = |
135 } | 258 context_.frame_context_managers[curr_frame_header_.frame_context_idx]; |
136 } | 259 if (!context_to_load.initialized()) { |
137 | 260 // 8.2 Frame order constraints |
138 return true; | 261 // must load an initialized set of probabilities. |
139 } | 262 DVLOG(1) << "loading uninitialized frame context, index=" |
140 | 263 << curr_frame_header_.frame_context_idx; |
141 void Vp9Parser::ReadFrameSize(Vp9FrameHeader* fhdr) { | 264 return kInvalidStream; |
142 fhdr->width = reader_.ReadLiteral(16) + 1; | 265 } |
143 fhdr->height = reader_.ReadLiteral(16) + 1; | 266 if (context_to_load.needs_client_update()) { |
144 } | 267 DVLOG(3) << "waiting frame_context_idx=" |
145 | 268 << static_cast<int>(curr_frame_header_.frame_context_idx) |
146 bool Vp9Parser::ReadFrameSizeFromRefs(Vp9FrameHeader* fhdr) { | 269 << " to update"; |
147 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | 270 return kAwaitingRefresh; |
148 if (reader_.ReadBool()) { | 271 } |
149 fhdr->width = ref_slots_[i].width; | 272 curr_frame_header_.initial_frame_context = |
150 fhdr->height = ref_slots_[i].height; | 273 curr_frame_header_.frame_context = context_to_load.frame_context(); |
151 | 274 |
152 const int kMaxDimension = 1 << 16; | 275 Vp9CompressedHeaderParser compressed_parser; |
153 if (fhdr->width == 0 || fhdr->width > kMaxDimension || | 276 if (!compressed_parser.Parse( |
154 fhdr->height == 0 || fhdr->height > kMaxDimension) { | 277 curr_frame_info_.ptr + curr_frame_header_.uncompressed_header_size, |
155 DVLOG(1) << "The size of reference frame is out of range: " | 278 curr_frame_header_.header_size_in_bytes, &curr_frame_header_)) { |
156 << ref_slots_[i].width << "," << ref_slots_[i].height; | 279 return kInvalidStream; |
157 return false; | 280 } |
158 } | 281 |
159 return true; | 282 if (curr_frame_header_.refresh_frame_context) { |
160 } | 283 Vp9FrameContextManager& frame_context_manager = |
161 } | 284 context_.frame_context_managers[curr_frame_header_.frame_context_idx]; |
162 | 285 |
163 fhdr->width = reader_.ReadLiteral(16) + 1; | 286 // In frame parallel mode, we can refresh the context without decoding |
164 fhdr->height = reader_.ReadLiteral(16) + 1; | 287 // tile data. |
165 return true; | 288 if (curr_frame_header_.frame_parallel_decoding_mode) { |
166 } | 289 frame_context_manager.Update(curr_frame_header_.frame_context); |
167 | |
168 void Vp9Parser::ReadDisplayFrameSize(Vp9FrameHeader* fhdr) { | |
169 if (reader_.ReadBool()) { | |
170 fhdr->display_width = reader_.ReadLiteral(16) + 1; | |
171 fhdr->display_height = reader_.ReadLiteral(16) + 1; | |
172 } else { | |
173 fhdr->display_width = fhdr->width; | |
174 fhdr->display_height = fhdr->height; | |
175 } | |
176 } | |
177 | |
178 Vp9InterpFilter Vp9Parser::ReadInterpFilter() { | |
179 if (reader_.ReadBool()) | |
180 return Vp9InterpFilter::SWICHABLE; | |
181 | |
182 // The mapping table for next two bits. | |
183 const Vp9InterpFilter table[] = { | |
184 Vp9InterpFilter::EIGHTTAP_SMOOTH, Vp9InterpFilter::EIGHTTAP, | |
185 Vp9InterpFilter::EIGHTTAP_SHARP, Vp9InterpFilter::BILINEAR, | |
186 }; | |
187 return table[reader_.ReadLiteral(2)]; | |
188 } | |
189 | |
190 void Vp9Parser::ReadLoopFilter() { | |
191 loop_filter_.filter_level = reader_.ReadLiteral(6); | |
192 loop_filter_.sharpness_level = reader_.ReadLiteral(3); | |
193 loop_filter_.mode_ref_delta_update = false; | |
194 | |
195 loop_filter_.mode_ref_delta_enabled = reader_.ReadBool(); | |
196 if (loop_filter_.mode_ref_delta_enabled) { | |
197 loop_filter_.mode_ref_delta_update = reader_.ReadBool(); | |
198 if (loop_filter_.mode_ref_delta_update) { | |
199 for (size_t i = 0; i < Vp9LoopFilter::VP9_FRAME_MAX; i++) { | |
200 loop_filter_.update_ref_deltas[i] = reader_.ReadBool(); | |
201 if (loop_filter_.update_ref_deltas[i]) | |
202 loop_filter_.ref_deltas[i] = reader_.ReadSignedLiteral(6); | |
203 } | |
204 | |
205 for (size_t i = 0; i < Vp9LoopFilter::kNumModeDeltas; i++) { | |
206 loop_filter_.update_mode_deltas[i] = reader_.ReadBool(); | |
207 if (loop_filter_.update_mode_deltas[i]) | |
208 loop_filter_.mode_deltas[i] = reader_.ReadLiteral(6); | |
209 } | |
210 } | |
211 } | |
212 } | |
213 | |
214 void Vp9Parser::ReadQuantization(Vp9QuantizationParams* quants) { | |
215 quants->base_qindex = reader_.ReadLiteral(8); | |
216 | |
217 if (reader_.ReadBool()) | |
218 quants->y_dc_delta = reader_.ReadSignedLiteral(4); | |
219 | |
220 if (reader_.ReadBool()) | |
221 quants->uv_dc_delta = reader_.ReadSignedLiteral(4); | |
222 | |
223 if (reader_.ReadBool()) | |
224 quants->uv_ac_delta = reader_.ReadSignedLiteral(4); | |
225 } | |
226 | |
227 void Vp9Parser::ReadSegmentationMap() { | |
228 for (size_t i = 0; i < Vp9Segmentation::kNumTreeProbs; i++) { | |
229 segmentation_.tree_probs[i] = | |
230 reader_.ReadBool() ? reader_.ReadLiteral(8) : kVp9MaxProb; | |
231 } | |
232 | |
233 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) | |
234 segmentation_.pred_probs[i] = kVp9MaxProb; | |
235 | |
236 segmentation_.temporal_update = reader_.ReadBool(); | |
237 if (segmentation_.temporal_update) { | |
238 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) { | |
239 if (reader_.ReadBool()) | |
240 segmentation_.pred_probs[i] = reader_.ReadLiteral(8); | |
241 } | |
242 } | |
243 } | |
244 | |
245 void Vp9Parser::ReadSegmentationData() { | |
246 segmentation_.abs_delta = reader_.ReadBool(); | |
247 | |
248 const int kFeatureDataBits[] = {8, 6, 2, 0}; | |
249 const bool kFeatureDataSigned[] = {true, true, false, false}; | |
250 | |
251 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; i++) { | |
252 for (size_t j = 0; j < Vp9Segmentation::SEG_LVL_MAX; j++) { | |
253 int16_t data = 0; | |
254 segmentation_.feature_enabled[i][j] = reader_.ReadBool(); | |
255 if (segmentation_.feature_enabled[i][j]) { | |
256 data = reader_.ReadLiteral(kFeatureDataBits[j]); | |
257 if (kFeatureDataSigned[j]) | |
258 if (reader_.ReadBool()) | |
259 data = -data; | |
260 } | |
261 segmentation_.feature_data[i][j] = data; | |
262 } | |
263 } | |
264 } | |
265 | |
266 void Vp9Parser::ReadSegmentation() { | |
267 segmentation_.update_map = false; | |
268 segmentation_.update_data = false; | |
269 | |
270 segmentation_.enabled = reader_.ReadBool(); | |
271 if (!segmentation_.enabled) | |
272 return; | |
273 | |
274 segmentation_.update_map = reader_.ReadBool(); | |
275 if (segmentation_.update_map) | |
276 ReadSegmentationMap(); | |
277 | |
278 segmentation_.update_data = reader_.ReadBool(); | |
279 if (segmentation_.update_data) | |
280 ReadSegmentationData(); | |
281 } | |
282 | |
283 void Vp9Parser::ReadTiles(Vp9FrameHeader* fhdr) { | |
284 int sb64_cols = (fhdr->width + 63) / 64; | |
285 | |
286 int min_log2_tile_cols = GetMinLog2TileCols(sb64_cols); | |
287 int max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols); | |
288 | |
289 int max_ones = max_log2_tile_cols - min_log2_tile_cols; | |
290 fhdr->log2_tile_cols = min_log2_tile_cols; | |
291 while (max_ones-- && reader_.ReadBool()) | |
292 fhdr->log2_tile_cols++; | |
293 | |
294 fhdr->log2_tile_rows = reader_.ReadBool() ? 1 : 0; | |
295 if (fhdr->log2_tile_rows > 0 && reader_.ReadBool()) | |
296 fhdr->log2_tile_rows++; | |
297 } | |
298 | |
299 bool Vp9Parser::ParseUncompressedHeader(const uint8_t* stream, | |
300 off_t frame_size, | |
301 Vp9FrameHeader* fhdr) { | |
302 reader_.Initialize(stream, frame_size); | |
303 | |
304 fhdr->data = stream; | |
305 fhdr->frame_size = frame_size; | |
306 | |
307 // frame marker | |
308 if (reader_.ReadLiteral(2) != 0x2) | |
309 return false; | |
310 | |
311 fhdr->profile = ReadProfile(); | |
312 if (fhdr->profile >= kVp9MaxProfile) { | |
313 DVLOG(1) << "Unsupported bitstream profile"; | |
314 return false; | |
315 } | |
316 | |
317 fhdr->show_existing_frame = reader_.ReadBool(); | |
318 if (fhdr->show_existing_frame) { | |
319 fhdr->frame_to_show = reader_.ReadLiteral(3); | |
320 fhdr->show_frame = true; | |
321 | |
322 if (!reader_.IsValid()) { | |
323 DVLOG(1) << "parser reads beyond the end of buffer"; | |
324 return false; | |
325 } | |
326 fhdr->uncompressed_header_size = reader_.GetBytesRead(); | |
327 return true; | |
328 } | |
329 | |
330 fhdr->frame_type = static_cast<Vp9FrameHeader::FrameType>(reader_.ReadBool()); | |
331 fhdr->show_frame = reader_.ReadBool(); | |
332 fhdr->error_resilient_mode = reader_.ReadBool(); | |
333 | |
334 if (fhdr->IsKeyframe()) { | |
335 if (!VerifySyncCode()) | |
336 return false; | |
337 | |
338 if (!ReadBitDepthColorSpaceSampling(fhdr)) | |
339 return false; | |
340 | |
341 fhdr->refresh_flags = 0xff; | |
342 | |
343 ReadFrameSize(fhdr); | |
344 ReadDisplayFrameSize(fhdr); | |
345 } else { | |
346 if (!fhdr->show_frame) | |
347 fhdr->intra_only = reader_.ReadBool(); | |
348 | |
349 if (!fhdr->error_resilient_mode) | |
350 fhdr->reset_context = reader_.ReadLiteral(2); | |
351 | |
352 if (fhdr->intra_only) { | |
353 if (!VerifySyncCode()) | |
354 return false; | |
355 | |
356 if (fhdr->profile > 0) { | |
357 if (!ReadBitDepthColorSpaceSampling(fhdr)) | |
358 return false; | |
359 } else { | 290 } else { |
360 fhdr->bit_depth = 8; | 291 *context_refresh_cb = frame_context_manager.SetNeedsClientUpdate(); |
361 fhdr->color_space = Vp9ColorSpace::BT_601; | 292 } |
362 fhdr->subsampling_x = fhdr->subsampling_y = 1; | 293 } |
363 } | 294 } |
364 | 295 |
365 fhdr->refresh_flags = reader_.ReadLiteral(8); | 296 SetupSegmentationDequant(); |
366 | |
367 ReadFrameSize(fhdr); | |
368 ReadDisplayFrameSize(fhdr); | |
369 } else { | |
370 fhdr->refresh_flags = reader_.ReadLiteral(8); | |
371 | |
372 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | |
373 fhdr->frame_refs[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2); | |
374 fhdr->ref_sign_biases[i] = reader_.ReadBool(); | |
375 } | |
376 | |
377 if (!ReadFrameSizeFromRefs(fhdr)) | |
378 return false; | |
379 ReadDisplayFrameSize(fhdr); | |
380 | |
381 fhdr->allow_high_precision_mv = reader_.ReadBool(); | |
382 fhdr->interp_filter = ReadInterpFilter(); | |
383 } | |
384 } | |
385 | |
386 if (fhdr->error_resilient_mode) { | |
387 fhdr->frame_parallel_decoding_mode = true; | |
388 } else { | |
389 fhdr->refresh_frame_context = reader_.ReadBool(); | |
390 fhdr->frame_parallel_decoding_mode = reader_.ReadBool(); | |
391 } | |
392 | |
393 fhdr->frame_context_idx = reader_.ReadLiteral(2); | |
394 | |
395 if (fhdr->IsKeyframe() || fhdr->intra_only) | |
396 SetupPastIndependence(); | |
397 | |
398 ReadLoopFilter(); | |
399 ReadQuantization(&fhdr->quant_params); | |
400 ReadSegmentation(); | |
401 | |
402 ReadTiles(fhdr); | |
403 | |
404 fhdr->first_partition_size = reader_.ReadLiteral(16); | |
405 if (fhdr->first_partition_size == 0) { | |
406 DVLOG(1) << "invalid header size"; | |
407 return false; | |
408 } | |
409 | |
410 if (!reader_.IsValid()) { | |
411 DVLOG(1) << "parser reads beyond the end of buffer"; | |
412 return false; | |
413 } | |
414 fhdr->uncompressed_header_size = reader_.GetBytesRead(); | |
415 | |
416 SetupSegmentationDequant(fhdr->quant_params); | |
417 SetupLoopFilter(); | 297 SetupLoopFilter(); |
418 | 298 UpdateSlots(); |
419 UpdateSlots(fhdr); | 299 |
420 | 300 *fhdr = curr_frame_header_; |
421 return true; | 301 curr_frame_info_.Reset(); |
422 } | |
423 | |
424 void Vp9Parser::UpdateSlots(const Vp9FrameHeader* fhdr) { | |
425 for (size_t i = 0; i < kVp9NumRefFrames; i++) { | |
426 if (fhdr->RefreshFlag(i)) { | |
427 ref_slots_[i].width = fhdr->width; | |
428 ref_slots_[i].height = fhdr->height; | |
429 } | |
430 } | |
431 } | |
432 | |
433 Vp9Parser::Result Vp9Parser::ParseNextFrame(Vp9FrameHeader* fhdr) { | |
434 if (frames_.empty()) { | |
435 // No frames to be decoded, if there is no more stream, request more. | |
436 if (!stream_) | |
437 return kEOStream; | |
438 | |
439 // New stream to be parsed, parse it and fill frames_. | |
440 if (!ParseSuperframe()) { | |
441 DVLOG(1) << "Failed parsing superframes"; | |
442 return kInvalidStream; | |
443 } | |
444 } | |
445 | |
446 DCHECK(!frames_.empty()); | |
447 FrameInfo frame_info = frames_.front(); | |
448 frames_.pop_front(); | |
449 | |
450 memset(fhdr, 0, sizeof(*fhdr)); | |
451 if (!ParseUncompressedHeader(frame_info.ptr, frame_info.size, fhdr)) | |
452 return kInvalidStream; | |
453 | |
454 return kOk; | 302 return kOk; |
455 } | 303 } |
456 | 304 |
457 bool Vp9Parser::ParseSuperframe() { | 305 // Annex B Superframes |
306 std::deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSuperframe() { | |
458 const uint8_t* stream = stream_; | 307 const uint8_t* stream = stream_; |
459 off_t bytes_left = bytes_left_; | 308 off_t bytes_left = bytes_left_; |
460 | 309 |
461 DCHECK(frames_.empty()); | |
462 | |
463 // Make sure we don't parse stream_ more than once. | 310 // Make sure we don't parse stream_ more than once. |
464 stream_ = nullptr; | 311 stream_ = nullptr; |
465 bytes_left_ = 0; | 312 bytes_left_ = 0; |
466 | 313 |
467 if (bytes_left < 1) | 314 if (bytes_left < 1) |
468 return false; | 315 return std::deque<FrameInfo>(); |
469 | 316 |
470 // If this is a superframe, the last byte in the stream will contain the | 317 // If this is a superframe, the last byte in the stream will contain the |
471 // superframe marker. If not, the whole buffer contains a single frame. | 318 // superframe marker. If not, the whole buffer contains a single frame. |
472 uint8_t marker = *(stream + bytes_left - 1); | 319 uint8_t marker = *(stream + bytes_left - 1); |
473 if ((marker & 0xe0) != 0xc0) { | 320 if ((marker & 0xe0) != 0xc0) { |
474 frames_.push_back(FrameInfo(stream, bytes_left)); | 321 return {FrameInfo(stream, bytes_left)}; |
475 return true; | |
476 } | 322 } |
477 | 323 |
478 DVLOG(1) << "Parsing a superframe"; | 324 DVLOG(1) << "Parsing a superframe"; |
479 | 325 |
480 // The bytes immediately before the superframe marker constitute superframe | 326 // The bytes immediately before the superframe marker constitute superframe |
481 // index, which stores information about sizes of each frame in it. | 327 // index, which stores information about sizes of each frame in it. |
482 // Calculate its size and set index_ptr to the beginning of it. | 328 // Calculate its size and set index_ptr to the beginning of it. |
483 size_t num_frames = (marker & 0x7) + 1; | 329 size_t num_frames = (marker & 0x7) + 1; |
484 size_t mag = ((marker >> 3) & 0x3) + 1; | 330 size_t mag = ((marker >> 3) & 0x3) + 1; |
485 off_t index_size = 2 + mag * num_frames; | 331 off_t index_size = 2 + mag * num_frames; |
486 | 332 |
487 if (bytes_left < index_size) | 333 if (bytes_left < index_size) |
488 return false; | 334 return std::deque<FrameInfo>(); |
489 | 335 |
490 const uint8_t* index_ptr = stream + bytes_left - index_size; | 336 const uint8_t* index_ptr = stream + bytes_left - index_size; |
491 if (marker != *index_ptr) | 337 if (marker != *index_ptr) |
492 return false; | 338 return std::deque<FrameInfo>(); |
493 | 339 |
494 ++index_ptr; | 340 ++index_ptr; |
495 bytes_left -= index_size; | 341 bytes_left -= index_size; |
496 | 342 |
497 // Parse frame information contained in the index and add a pointer to and | 343 // Parse frame information contained in the index and add a pointer to and |
498 // size of each frame to frames_. | 344 // size of each frame to frames. |
345 std::deque<FrameInfo> frames; | |
499 for (size_t i = 0; i < num_frames; ++i) { | 346 for (size_t i = 0; i < num_frames; ++i) { |
500 uint32_t size = 0; | 347 uint32_t size = 0; |
501 for (size_t j = 0; j < mag; ++j) { | 348 for (size_t j = 0; j < mag; ++j) { |
502 size |= *index_ptr << (j * 8); | 349 size |= *index_ptr << (j * 8); |
503 ++index_ptr; | 350 ++index_ptr; |
504 } | 351 } |
505 | 352 |
506 if (base::checked_cast<off_t>(size) > bytes_left) { | 353 if (base::checked_cast<off_t>(size) > bytes_left) { |
507 DVLOG(1) << "Not enough data in the buffer for frame " << i; | 354 DVLOG(1) << "Not enough data in the buffer for frame " << i; |
508 return false; | 355 return std::deque<FrameInfo>(); |
509 } | 356 } |
510 | 357 |
511 frames_.push_back(FrameInfo(stream, size)); | 358 frames.push_back(FrameInfo(stream, size)); |
512 stream += size; | 359 stream += size; |
513 bytes_left -= size; | 360 bytes_left -= size; |
514 | 361 |
515 DVLOG(1) << "Frame " << i << ", size: " << size; | 362 DVLOG(1) << "Frame " << i << ", size: " << size; |
516 } | 363 } |
517 | 364 |
518 return true; | 365 return frames; |
519 } | 366 } |
520 | 367 |
521 void Vp9Parser::ResetLoopfilter() { | 368 // 8.6.1 |
522 loop_filter_.mode_ref_delta_enabled = true; | |
523 loop_filter_.mode_ref_delta_update = true; | |
524 | |
525 const int8_t default_ref_deltas[] = {1, 0, -1, -1}; | |
526 static_assert( | |
527 arraysize(default_ref_deltas) == arraysize(loop_filter_.ref_deltas), | |
528 "ref_deltas arrays of incorrect size"); | |
529 for (size_t i = 0; i < arraysize(loop_filter_.ref_deltas); ++i) | |
530 loop_filter_.ref_deltas[i] = default_ref_deltas[i]; | |
531 | |
532 memset(loop_filter_.mode_deltas, 0, sizeof(loop_filter_.mode_deltas)); | |
533 } | |
534 | |
535 void Vp9Parser::SetupPastIndependence() { | |
536 memset(&segmentation_, 0, sizeof(segmentation_)); | |
537 ResetLoopfilter(); | |
538 } | |
539 | |
540 const size_t QINDEX_RANGE = 256; | 369 const size_t QINDEX_RANGE = 256; |
541 const int16_t kDcQLookup[QINDEX_RANGE] = { | 370 const int16_t kDcQLookup[QINDEX_RANGE] = { |
542 4, 8, 8, 9, 10, 11, 12, 12, | 371 4, 8, 8, 9, 10, 11, 12, 12, |
543 13, 14, 15, 16, 17, 18, 19, 19, | 372 13, 14, 15, 16, 17, 18, 19, 19, |
544 20, 21, 22, 23, 24, 25, 26, 26, | 373 20, 21, 22, 23, 24, 25, 26, 26, |
545 27, 28, 29, 30, 31, 32, 32, 33, | 374 27, 28, 29, 30, 31, 32, 32, 33, |
546 34, 35, 36, 37, 38, 38, 39, 40, | 375 34, 35, 36, 37, 38, 38, 39, 40, |
547 41, 42, 43, 43, 44, 45, 46, 47, | 376 41, 42, 43, 43, 44, 45, 46, 47, |
548 48, 48, 49, 50, 51, 52, 53, 53, | 377 48, 48, 49, 50, 51, 52, 53, 53, |
549 54, 55, 56, 57, 57, 58, 59, 60, | 378 54, 55, 56, 57, 57, 58, 59, 60, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
604 864, 881, 898, 915, 933, 951, 969, 988, | 433 864, 881, 898, 915, 933, 951, 969, 988, |
605 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, | 434 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, |
606 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, | 435 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, |
607 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, | 436 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, |
608 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, | 437 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, |
609 }; | 438 }; |
610 | 439 |
611 static_assert(arraysize(kDcQLookup) == arraysize(kAcQLookup), | 440 static_assert(arraysize(kDcQLookup) == arraysize(kAcQLookup), |
612 "quantizer lookup arrays of incorrect size"); | 441 "quantizer lookup arrays of incorrect size"); |
613 | 442 |
614 #define CLAMP_Q(q) \ | 443 static size_t ClampQ(size_t q) { |
615 std::min(std::max(static_cast<size_t>(0), q), arraysize(kDcQLookup) - 1) | 444 return std::min(std::max(static_cast<size_t>(0), q), |
445 arraysize(kDcQLookup) - 1); | |
446 } | |
616 | 447 |
448 // 8.6.1 Dequantization functions | |
617 size_t Vp9Parser::GetQIndex(const Vp9QuantizationParams& quant, | 449 size_t Vp9Parser::GetQIndex(const Vp9QuantizationParams& quant, |
618 size_t segid) const { | 450 size_t segid) const { |
619 if (segmentation_.FeatureEnabled(segid, Vp9Segmentation::SEG_LVL_ALT_Q)) { | 451 const Vp9SegmentationParams& segmentation = context_.segmentation; |
452 | |
453 if (segmentation.FeatureEnabled(segid, | |
454 Vp9SegmentationParams::SEG_LVL_ALT_Q)) { | |
620 int16_t feature_data = | 455 int16_t feature_data = |
621 segmentation_.FeatureData(segid, Vp9Segmentation::SEG_LVL_ALT_Q); | 456 segmentation.FeatureData(segid, Vp9SegmentationParams::SEG_LVL_ALT_Q); |
622 size_t q_index = segmentation_.abs_delta ? feature_data | 457 size_t q_index = segmentation.abs_or_delta_update |
623 : quant.base_qindex + feature_data; | 458 ? feature_data |
624 return CLAMP_Q(q_index); | 459 : quant.base_q_idx + feature_data; |
460 return ClampQ(q_index); | |
625 } | 461 } |
626 | 462 |
627 return quant.base_qindex; | 463 return quant.base_q_idx; |
628 } | 464 } |
629 | 465 |
630 void Vp9Parser::SetupSegmentationDequant(const Vp9QuantizationParams& quant) { | 466 // 8.6.1 Dequantization functions |
631 if (segmentation_.enabled) { | 467 void Vp9Parser::SetupSegmentationDequant() { |
632 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; ++i) { | 468 const Vp9QuantizationParams& quant = curr_frame_header_.quant_params; |
469 Vp9SegmentationParams& segmentation = context_.segmentation; | |
470 | |
471 DLOG_IF(ERROR, curr_frame_header_.bit_depth > 8) | |
472 << "bit_depth > 8 is not supported " | |
473 "yet, kDcQLookup and kAcQLookup " | |
474 "need extended"; | |
475 if (segmentation.enabled) { | |
476 for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; ++i) { | |
633 const size_t q_index = GetQIndex(quant, i); | 477 const size_t q_index = GetQIndex(quant, i); |
634 segmentation_.y_dequant[i][0] = | 478 segmentation.y_dequant[i][0] = |
635 kDcQLookup[CLAMP_Q(q_index + quant.y_dc_delta)]; | 479 kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)]; |
636 segmentation_.y_dequant[i][1] = kAcQLookup[CLAMP_Q(q_index)]; | 480 segmentation.y_dequant[i][1] = kAcQLookup[ClampQ(q_index)]; |
637 segmentation_.uv_dequant[i][0] = | 481 segmentation.uv_dequant[i][0] = |
638 kDcQLookup[CLAMP_Q(q_index + quant.uv_dc_delta)]; | 482 kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)]; |
639 segmentation_.uv_dequant[i][1] = | 483 segmentation.uv_dequant[i][1] = |
640 kAcQLookup[CLAMP_Q(q_index + quant.uv_ac_delta)]; | 484 kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)]; |
641 } | 485 } |
642 } else { | 486 } else { |
643 const size_t q_index = quant.base_qindex; | 487 const size_t q_index = quant.base_q_idx; |
644 segmentation_.y_dequant[0][0] = | 488 segmentation.y_dequant[0][0] = |
645 kDcQLookup[CLAMP_Q(q_index + quant.y_dc_delta)]; | 489 kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)]; |
646 segmentation_.y_dequant[0][1] = kAcQLookup[CLAMP_Q(q_index)]; | 490 segmentation.y_dequant[0][1] = kAcQLookup[ClampQ(q_index)]; |
647 segmentation_.uv_dequant[0][0] = | 491 segmentation.uv_dequant[0][0] = |
648 kDcQLookup[CLAMP_Q(q_index + quant.uv_dc_delta)]; | 492 kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)]; |
649 segmentation_.uv_dequant[0][1] = | 493 segmentation.uv_dequant[0][1] = |
650 kAcQLookup[CLAMP_Q(q_index + quant.uv_ac_delta)]; | 494 kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)]; |
651 } | 495 } |
652 } | 496 } |
653 #undef CLAMP_Q | |
654 | 497 |
655 #define CLAMP_LF(l) std::min(std::max(0, l), kMaxLoopFilterLevel) | 498 static int ClampLf(int lf) { |
499 const int kMaxLoopFilterLevel = 63; | |
500 return std::min(std::max(0, lf), kMaxLoopFilterLevel); | |
501 } | |
502 | |
503 // 8.8.1 Loop filter frame init process | |
656 void Vp9Parser::SetupLoopFilter() { | 504 void Vp9Parser::SetupLoopFilter() { |
657 if (!loop_filter_.filter_level) | 505 Vp9LoopFilterParams& loop_filter = context_.loop_filter; |
506 if (!loop_filter.level) | |
658 return; | 507 return; |
659 | 508 |
660 int scale = loop_filter_.filter_level < 32 ? 1 : 2; | 509 int scale = loop_filter.level < 32 ? 1 : 2; |
661 | 510 |
662 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; ++i) { | 511 for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; ++i) { |
663 int level = loop_filter_.filter_level; | 512 int level = loop_filter.level; |
513 Vp9SegmentationParams& segmentation = context_.segmentation; | |
664 | 514 |
665 if (segmentation_.FeatureEnabled(i, Vp9Segmentation::SEG_LVL_ALT_LF)) { | 515 if (segmentation.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_ALT_LF)) { |
666 int feature_data = | 516 int feature_data = |
667 segmentation_.FeatureData(i, Vp9Segmentation::SEG_LVL_ALT_LF); | 517 segmentation.FeatureData(i, Vp9SegmentationParams::SEG_LVL_ALT_LF); |
668 level = CLAMP_LF(segmentation_.abs_delta ? feature_data | 518 level = ClampLf(segmentation.abs_or_delta_update ? feature_data |
669 : level + feature_data); | 519 : level + feature_data); |
670 } | 520 } |
671 | 521 |
672 if (!loop_filter_.mode_ref_delta_enabled) { | 522 if (!loop_filter.delta_enabled) { |
673 memset(loop_filter_.lvl[i], level, sizeof(loop_filter_.lvl[i])); | 523 memset(loop_filter.lvl[i], level, sizeof(loop_filter.lvl[i])); |
674 } else { | 524 } else { |
675 loop_filter_.lvl[i][Vp9LoopFilter::VP9_FRAME_INTRA][0] = CLAMP_LF( | 525 loop_filter.lvl[i][Vp9RefType::VP9_FRAME_INTRA][0] = ClampLf( |
676 level + | 526 level + loop_filter.ref_deltas[Vp9RefType::VP9_FRAME_INTRA] * scale); |
677 loop_filter_.ref_deltas[Vp9LoopFilter::VP9_FRAME_INTRA] * scale); | 527 loop_filter.lvl[i][Vp9RefType::VP9_FRAME_INTRA][1] = 0; |
678 loop_filter_.lvl[i][Vp9LoopFilter::VP9_FRAME_INTRA][1] = 0; | |
679 | 528 |
680 for (size_t type = Vp9LoopFilter::VP9_FRAME_LAST; | 529 for (size_t type = Vp9RefType::VP9_FRAME_LAST; |
681 type < Vp9LoopFilter::VP9_FRAME_MAX; ++type) { | 530 type < Vp9RefType::VP9_FRAME_MAX; ++type) { |
682 for (size_t mode = 0; mode < Vp9LoopFilter::kNumModeDeltas; ++mode) { | 531 for (size_t mode = 0; mode < Vp9LoopFilterParams::kNumModeDeltas; |
683 loop_filter_.lvl[i][type][mode] = | 532 ++mode) { |
684 CLAMP_LF(level + loop_filter_.ref_deltas[type] * scale + | 533 loop_filter.lvl[i][type][mode] = |
685 loop_filter_.mode_deltas[mode] * scale); | 534 ClampLf(level + loop_filter.ref_deltas[type] * scale + |
535 loop_filter.mode_deltas[mode] * scale); | |
686 } | 536 } |
687 } | 537 } |
688 } | 538 } |
689 } | 539 } |
690 } | 540 } |
691 #undef CLAMP_LF | 541 |
542 void Vp9Parser::UpdateSlots() { | |
543 // 8.10 Reference frame update process | |
544 for (size_t i = 0; i < kVp9NumRefFrames; i++) { | |
545 if (curr_frame_header_.RefreshFlag(i)) { | |
546 ReferenceSlot& ref = context_.ref_slots[i]; | |
547 ref.initialized = true; | |
548 | |
549 ref.frame_width = curr_frame_header_.frame_width; | |
550 ref.frame_height = curr_frame_header_.frame_height; | |
551 ref.subsampling_x = curr_frame_header_.subsampling_x; | |
552 ref.subsampling_y = curr_frame_header_.subsampling_y; | |
553 ref.bit_depth = curr_frame_header_.bit_depth; | |
554 | |
555 ref.profile = curr_frame_header_.profile; | |
556 ref.color_space = curr_frame_header_.color_space; | |
557 } | |
558 } | |
559 } | |
692 | 560 |
693 } // namespace media | 561 } // namespace media |
OLD | NEW |