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