Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: media/filters/vp9_parser.cc

Issue 1318863003: Add accelerated VP9 decode infrastructure and an implementation for VA-API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 6
7 #include "media/filters/vp9_parser.h" 7 #include "media/filters/vp9_parser.h"
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 10
(...skipping 12 matching lines...) Expand all
23 // Helper function for Vp9Parser::ReadTiles. Defined as get_max_log2_tile_cols 23 // Helper function for Vp9Parser::ReadTiles. Defined as get_max_log2_tile_cols
24 // in spec. 24 // in spec.
25 int GetMaxLog2TileCols(int sb64_cols) { 25 int GetMaxLog2TileCols(int sb64_cols) {
26 const int kMinTileWidthB64 = 4; 26 const int kMinTileWidthB64 = 4;
27 int max_log2 = 1; 27 int max_log2 = 1;
28 while ((sb64_cols >> max_log2) >= kMinTileWidthB64) 28 while ((sb64_cols >> max_log2) >= kMinTileWidthB64)
29 max_log2++; 29 max_log2++;
30 return max_log2 - 1; 30 return max_log2 - 1;
31 } 31 }
32 32
33 const int kMaxLoopFilter = 63;
kcwu 2015/09/02 10:09:45 put before functions
Pawel Osciak 2015/09/08 06:43:49 Hmm, I considered that, but didn't want to have tw
kcwu 2015/09/08 09:08:41 Two anonymous namespaces? I mean put it at line 12
Pawel Osciak 2015/09/08 11:08:08 Ah, misunderstood then. Sure.
34
33 } // namespace 35 } // namespace
34 36
35 namespace media { 37 namespace media {
36 38
37 Vp9Parser::Vp9Parser() : stream_(nullptr), size_(0) { 39 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size)
40 : ptr(ptr), size(size) {}
41
42 Vp9Parser::Vp9Parser() : stream_(nullptr), bytes_left_(0) {
43 memset(&segmentation_, 0, sizeof(segmentation_));
44 memset(&loop_filter_, 0, sizeof(loop_filter_));
38 memset(&ref_slots_, 0, sizeof(ref_slots_)); 45 memset(&ref_slots_, 0, sizeof(ref_slots_));
39 } 46 }
40 47
48 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) {
49 DCHECK(stream);
50 stream_ = stream;
51 bytes_left_ = stream_size;
52 frames_.clear();
53 }
54
41 uint8_t Vp9Parser::ReadProfile() { 55 uint8_t Vp9Parser::ReadProfile() {
42 uint8_t profile = 0; 56 uint8_t profile = 0;
43 57
44 // LSB first. 58 // LSB first.
45 if (reader_.ReadBool()) 59 if (reader_.ReadBool())
46 profile |= 1; 60 profile |= 1;
47 if (reader_.ReadBool()) 61 if (reader_.ReadBool())
48 profile |= 2; 62 profile |= 2;
49 if (profile > 2 && reader_.ReadBool()) 63 if (profile > 2 && reader_.ReadBool())
50 profile += 1; 64 profile += 1;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 fhdr->display_width = reader_.ReadLiteral(16) + 1; 149 fhdr->display_width = reader_.ReadLiteral(16) + 1;
136 fhdr->display_height = reader_.ReadLiteral(16) + 1; 150 fhdr->display_height = reader_.ReadLiteral(16) + 1;
137 } else { 151 } else {
138 fhdr->display_width = fhdr->width; 152 fhdr->display_width = fhdr->width;
139 fhdr->display_height = fhdr->height; 153 fhdr->display_height = fhdr->height;
140 } 154 }
141 } 155 }
142 156
143 Vp9InterpFilter Vp9Parser::ReadInterpFilter() { 157 Vp9InterpFilter Vp9Parser::ReadInterpFilter() {
144 if (reader_.ReadBool()) 158 if (reader_.ReadBool())
145 return Vp9InterpFilter::INTERP_FILTER_SELECT; 159 return Vp9InterpFilter::SWICHABLE;
146 160
147 // The mapping table for next two bits. 161 // The mapping table for next two bits.
148 const Vp9InterpFilter table[] = { 162 const Vp9InterpFilter table[] = {
149 Vp9InterpFilter::EIGHTTAP_SMOOTH, Vp9InterpFilter::EIGHTTAP, 163 Vp9InterpFilter::EIGHTTAP_SMOOTH, Vp9InterpFilter::EIGHTTAP,
150 Vp9InterpFilter::EIGHTTAP_SHARP, Vp9InterpFilter::BILINEAR, 164 Vp9InterpFilter::EIGHTTAP_SHARP, Vp9InterpFilter::BILINEAR,
151 }; 165 };
152 return table[reader_.ReadLiteral(2)]; 166 return table[reader_.ReadLiteral(2)];
153 } 167 }
154 168
155 void Vp9Parser::ReadLoopFilter(Vp9LoopFilter* loop_filter) { 169 void Vp9Parser::ReadLoopFilter() {
156 loop_filter->filter_level = reader_.ReadLiteral(6); 170 loop_filter_.filter_level = reader_.ReadLiteral(6);
157 loop_filter->sharpness_level = reader_.ReadLiteral(3); 171 loop_filter_.sharpness_level = reader_.ReadLiteral(3);
172 loop_filter_.mode_ref_delta_update = false;
158 173
159 loop_filter->mode_ref_delta_enabled = reader_.ReadBool(); 174 loop_filter_.mode_ref_delta_enabled = reader_.ReadBool();
160 if (loop_filter->mode_ref_delta_enabled) { 175 if (loop_filter_.mode_ref_delta_enabled) {
161 loop_filter->mode_ref_delta_update = reader_.ReadBool(); 176 loop_filter_.mode_ref_delta_update = reader_.ReadBool();
162 if (loop_filter->mode_ref_delta_update) { 177 if (loop_filter_.mode_ref_delta_update) {
163 for (size_t i = 0; i < Vp9LoopFilter::kNumRefDeltas; i++) { 178 for (size_t i = 0; i < Vp9LoopFilter::VP9_FRAME_MAX; i++) {
164 loop_filter->update_ref_deltas[i] = reader_.ReadBool(); 179 loop_filter_.update_ref_deltas[i] = reader_.ReadBool();
165 if (loop_filter->update_ref_deltas[i]) 180 if (loop_filter_.update_ref_deltas[i])
166 loop_filter->ref_deltas[i] = reader_.ReadSignedLiteral(6); 181 loop_filter_.ref_deltas[i] = reader_.ReadSignedLiteral(6);
167 } 182 }
168 183
169 for (size_t i = 0; i < Vp9LoopFilter::kNumModeDeltas; i++) { 184 for (size_t i = 0; i < Vp9LoopFilter::kNumModeDeltas; i++) {
170 loop_filter->update_mode_deltas[i] = reader_.ReadBool(); 185 loop_filter_.update_mode_deltas[i] = reader_.ReadBool();
171 if (loop_filter->update_mode_deltas[i]) 186 if (loop_filter_.update_mode_deltas[i])
172 loop_filter->mode_deltas[i] = reader_.ReadLiteral(6); 187 loop_filter_.mode_deltas[i] = reader_.ReadLiteral(6);
173 } 188 }
174 } 189 }
175 } 190 }
176 } 191 }
177 192
178 void Vp9Parser::ReadQuantization(Vp9QuantizationParams* quants) { 193 void Vp9Parser::ReadQuantization(Vp9QuantizationParams* quants) {
179 quants->base_qindex = reader_.ReadLiteral(8); 194 quants->base_qindex = reader_.ReadLiteral(8);
180 195
181 if (reader_.ReadBool()) 196 if (reader_.ReadBool())
182 quants->y_dc_delta = reader_.ReadSignedLiteral(4); 197 quants->y_dc_delta = reader_.ReadSignedLiteral(4);
183 198
184 if (reader_.ReadBool()) 199 if (reader_.ReadBool())
185 quants->uv_ac_delta = reader_.ReadSignedLiteral(4); 200 quants->uv_ac_delta = reader_.ReadSignedLiteral(4);
186 201
187 if (reader_.ReadBool()) 202 if (reader_.ReadBool())
188 quants->uv_dc_delta = reader_.ReadSignedLiteral(4); 203 quants->uv_dc_delta = reader_.ReadSignedLiteral(4);
189 } 204 }
190 205
191 void Vp9Parser::ReadSegmentationMap(Vp9Segmentation* segment) { 206 void Vp9Parser::ReadSegmentationMap() {
192 for (size_t i = 0; i < Vp9Segmentation::kNumTreeProbs; i++) { 207 for (size_t i = 0; i < Vp9Segmentation::kNumTreeProbs; i++) {
193 segment->tree_probs[i] = 208 segmentation_.tree_probs[i] =
194 reader_.ReadBool() ? reader_.ReadLiteral(8) : kVp9MaxProb; 209 reader_.ReadBool() ? reader_.ReadLiteral(8) : kVp9MaxProb;
195 } 210 }
196 211
197 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) 212 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++)
198 segment->pred_probs[i] = kVp9MaxProb; 213 segmentation_.pred_probs[i] = kVp9MaxProb;
199 214
200 segment->temporal_update = reader_.ReadBool(); 215 segmentation_.temporal_update = reader_.ReadBool();
201 if (segment->temporal_update) { 216 if (segmentation_.temporal_update) {
202 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) { 217 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) {
203 if (reader_.ReadBool()) 218 if (reader_.ReadBool())
204 segment->pred_probs[i] = reader_.ReadLiteral(8); 219 segmentation_.pred_probs[i] = reader_.ReadLiteral(8);
205 } 220 }
206 } 221 }
207 } 222 }
208 223
209 void Vp9Parser::ReadSegmentationData(Vp9Segmentation* segment) { 224 void Vp9Parser::ReadSegmentationData() {
210 segment->abs_delta = reader_.ReadBool(); 225 segmentation_.abs_delta = reader_.ReadBool();
211 226
212 const int kFeatureDataBits[] = {7, 6, 2, 0}; 227 const int kFeatureDataBits[] = {7, 6, 2, 0};
213 const bool kFeatureDataSigned[] = {true, true, false, false}; 228 const bool kFeatureDataSigned[] = {true, true, false, false};
214 229
215 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; i++) { 230 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; i++) {
216 for (size_t j = 0; j < Vp9Segmentation::kNumFeatures; j++) { 231 for (size_t j = 0; j < Vp9Segmentation::SEG_LVL_MAX; j++) {
217 int8_t data = 0; 232 int8_t data = 0;
218 segment->feature_enabled[i][j] = reader_.ReadBool(); 233 segmentation_.feature_enabled[i][j] = reader_.ReadBool();
219 if (segment->feature_enabled[i][j]) { 234 if (segmentation_.feature_enabled[i][j]) {
220 data = reader_.ReadLiteral(kFeatureDataBits[j]); 235 data = reader_.ReadLiteral(kFeatureDataBits[j]);
221 if (kFeatureDataSigned[j]) 236 if (kFeatureDataSigned[j])
222 if (reader_.ReadBool()) 237 if (reader_.ReadBool())
223 data = -data; 238 data = -data;
224 } 239 }
225 segment->feature_data[i][j] = data; 240 segmentation_.feature_data[i][j] = data;
226 } 241 }
227 } 242 }
228 } 243 }
229 244
230 void Vp9Parser::ReadSegmentation(Vp9Segmentation* segment) { 245 void Vp9Parser::ReadSegmentation() {
231 segment->enabled = reader_.ReadBool(); 246 segmentation_.update_map = false;
247 segmentation_.update_data = false;
232 248
233 if (!segment->enabled) { 249 segmentation_.enabled = reader_.ReadBool();
250 if (!segmentation_.enabled)
234 return; 251 return;
235 }
236 252
237 segment->update_map = reader_.ReadBool(); 253 segmentation_.update_map = reader_.ReadBool();
238 if (segment->update_map) 254 if (segmentation_.update_map)
239 ReadSegmentationMap(segment); 255 ReadSegmentationMap();
240 256
241 segment->update_data = reader_.ReadBool(); 257 segmentation_.update_data = reader_.ReadBool();
242 if (segment->update_data) 258 if (segmentation_.update_data)
243 ReadSegmentationData(segment); 259 ReadSegmentationData();
244 } 260 }
245 261
246 void Vp9Parser::ReadTiles(Vp9FrameHeader* fhdr) { 262 void Vp9Parser::ReadTiles(Vp9FrameHeader* fhdr) {
247 int sb64_cols = (fhdr->width + 63) / 64; 263 int sb64_cols = (fhdr->width + 63) / 64;
248 264
249 int min_log2_tile_cols = GetMinLog2TileCols(sb64_cols); 265 int min_log2_tile_cols = GetMinLog2TileCols(sb64_cols);
250 int max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols); 266 int max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols);
251 267
252 int max_ones = max_log2_tile_cols - min_log2_tile_cols; 268 int max_ones = max_log2_tile_cols - min_log2_tile_cols;
253 fhdr->log2_tile_cols = min_log2_tile_cols; 269 fhdr->log2_tile_cols = min_log2_tile_cols;
254 while (max_ones-- && reader_.ReadBool()) 270 while (max_ones-- && reader_.ReadBool())
255 fhdr->log2_tile_cols++; 271 fhdr->log2_tile_cols++;
256 272
257 if (reader_.ReadBool()) 273 if (reader_.ReadBool())
258 fhdr->log2_tile_rows = reader_.ReadLiteral(2) - 1; 274 fhdr->log2_tile_rows = reader_.ReadLiteral(2) - 1;
259 } 275 }
260 276
261 bool Vp9Parser::ParseUncompressedHeader(Vp9FrameHeader* fhdr) { 277 bool Vp9Parser::ParseUncompressedHeader(const uint8_t* stream,
262 reader_.Initialize(stream_, size_); 278 off_t frame_size,
279 Vp9FrameHeader* fhdr) {
280 reader_.Initialize(stream, frame_size);
281
282 fhdr->data = stream;
283 fhdr->frame_size = frame_size;
263 284
264 // frame marker 285 // frame marker
265 if (reader_.ReadLiteral(2) != 0x2) 286 if (reader_.ReadLiteral(2) != 0x2)
266 return false; 287 return false;
267 288
268 fhdr->profile = ReadProfile(); 289 fhdr->profile = ReadProfile();
269 if (fhdr->profile >= kVp9MaxProfile) { 290 if (fhdr->profile >= kVp9MaxProfile) {
270 DVLOG(1) << "Unsupported bitstream profile"; 291 DVLOG(1) << "Unsupported bitstream profile";
271 return false; 292 return false;
272 } 293 }
(...skipping 15 matching lines...) Expand all
288 fhdr->show_frame = reader_.ReadBool(); 309 fhdr->show_frame = reader_.ReadBool();
289 fhdr->error_resilient_mode = reader_.ReadBool(); 310 fhdr->error_resilient_mode = reader_.ReadBool();
290 311
291 if (fhdr->IsKeyframe()) { 312 if (fhdr->IsKeyframe()) {
292 if (!VerifySyncCode()) 313 if (!VerifySyncCode())
293 return false; 314 return false;
294 315
295 if (!ReadBitDepthColorSpaceSampling(fhdr)) 316 if (!ReadBitDepthColorSpaceSampling(fhdr))
296 return false; 317 return false;
297 318
298 for (size_t i = 0; i < kVp9NumRefFrames; i++) 319 fhdr->refresh_flags = 0xff;
299 fhdr->refresh_flag[i] = true;
300 320
301 ReadFrameSize(fhdr); 321 ReadFrameSize(fhdr);
302 ReadDisplayFrameSize(fhdr); 322 ReadDisplayFrameSize(fhdr);
303 } else { 323 } else {
304 if (!fhdr->show_frame) 324 if (!fhdr->show_frame)
305 fhdr->intra_only = reader_.ReadBool(); 325 fhdr->intra_only = reader_.ReadBool();
306 326
307 if (!fhdr->error_resilient_mode) 327 if (!fhdr->error_resilient_mode)
308 fhdr->reset_context = reader_.ReadLiteral(2); 328 fhdr->reset_context = reader_.ReadLiteral(2);
309 329
310 if (fhdr->intra_only) { 330 if (fhdr->intra_only) {
311 if (!VerifySyncCode()) 331 if (!VerifySyncCode())
312 return false; 332 return false;
313 333
314 if (fhdr->profile > 0) { 334 if (fhdr->profile > 0) {
315 if (!ReadBitDepthColorSpaceSampling(fhdr)) 335 if (!ReadBitDepthColorSpaceSampling(fhdr))
316 return false; 336 return false;
317 } else { 337 } else {
318 fhdr->bit_depth = 8; 338 fhdr->bit_depth = 8;
319 fhdr->color_space = Vp9ColorSpace::BT_601; 339 fhdr->color_space = Vp9ColorSpace::BT_601;
320 fhdr->subsampling_x = fhdr->subsampling_y = 1; 340 fhdr->subsampling_x = fhdr->subsampling_y = 1;
321 } 341 }
322 342
323 for (size_t i = 0; i < kVp9NumRefFrames; i++) 343 fhdr->refresh_flags = reader_.ReadLiteral(8);
kcwu 2015/08/31 09:58:34 s/8/kVp9NumRefFrames/
Pawel Osciak 2015/09/08 06:43:48 I intentionally used 8 explicitly to keep the conv
324 fhdr->refresh_flag[i] = reader_.ReadBool(); 344
325 ReadFrameSize(fhdr); 345 ReadFrameSize(fhdr);
326 ReadDisplayFrameSize(fhdr); 346 ReadDisplayFrameSize(fhdr);
327 } else { 347 } else {
328 for (size_t i = 0; i < kVp9NumRefFrames; i++) 348 fhdr->refresh_flags = reader_.ReadLiteral(8);
kcwu 2015/08/31 09:58:34 s/8/kVp9NumRefFrames/
329 fhdr->refresh_flag[i] = reader_.ReadBool();
330 349
331 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { 350 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
332 fhdr->frame_refs[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2); 351 fhdr->frame_refs[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2);
333 fhdr->ref_sign_biases[i] = reader_.ReadBool(); 352 fhdr->ref_sign_biases[i] = reader_.ReadBool();
334 } 353 }
335 354
336 if (!ReadFrameSizeFromRefs(fhdr)) 355 if (!ReadFrameSizeFromRefs(fhdr))
337 return false; 356 return false;
338 ReadDisplayFrameSize(fhdr); 357 ReadDisplayFrameSize(fhdr);
339 358
340 fhdr->allow_high_precision_mv = reader_.ReadBool(); 359 fhdr->allow_high_precision_mv = reader_.ReadBool();
341 fhdr->interp_filter = ReadInterpFilter(); 360 fhdr->interp_filter = ReadInterpFilter();
342 } 361 }
343 } 362 }
344 363
345 if (fhdr->error_resilient_mode) { 364 if (fhdr->error_resilient_mode) {
346 fhdr->frame_parallel_decoding_mode = true; 365 fhdr->frame_parallel_decoding_mode = true;
347 } else { 366 } else {
348 fhdr->refresh_frame_context = reader_.ReadBool(); 367 fhdr->refresh_frame_context = reader_.ReadBool();
349 fhdr->frame_parallel_decoding_mode = reader_.ReadBool(); 368 fhdr->frame_parallel_decoding_mode = reader_.ReadBool();
350 } 369 }
351 370
352 fhdr->frame_context_idx = reader_.ReadLiteral(2); 371 fhdr->frame_context_idx = reader_.ReadLiteral(2);
353 372
354 ReadLoopFilter(&fhdr->loop_filter); 373 if (fhdr->IsKeyframe() || fhdr->intra_only)
374 SetupPastIndependence();
375
376 ReadLoopFilter();
355 ReadQuantization(&fhdr->quant_params); 377 ReadQuantization(&fhdr->quant_params);
356 ReadSegmentation(&fhdr->segment); 378 ReadSegmentation();
357 379
358 ReadTiles(fhdr); 380 ReadTiles(fhdr);
359 381
360 fhdr->first_partition_size = reader_.ReadLiteral(16); 382 fhdr->first_partition_size = reader_.ReadLiteral(16);
361 if (fhdr->first_partition_size == 0) { 383 if (fhdr->first_partition_size == 0) {
362 DVLOG(1) << "invalid header size"; 384 DVLOG(1) << "invalid header size";
363 return false; 385 return false;
364 } 386 }
365 387
366 if (!reader_.IsValid()) { 388 if (!reader_.IsValid()) {
367 DVLOG(1) << "parser reads beyond the end of buffer"; 389 DVLOG(1) << "parser reads beyond the end of buffer";
368 return false; 390 return false;
369 } 391 }
370 fhdr->uncompressed_header_size = reader_.GetBytesRead(); 392 fhdr->uncompressed_header_size = reader_.GetBytesRead();
371 393
394 UpdateSlots(fhdr);
395
396 SetupSegmentationDequant(fhdr->quant_params);
kcwu 2015/08/31 09:58:34 Does these depend on UpdateSlots() ? If not, I'd p
Pawel Osciak 2015/09/08 06:43:48 Done.
397 SetupLoopFilter();
398
372 return true; 399 return true;
373 } 400 }
374 401
375 void Vp9Parser::UpdateSlots(const Vp9FrameHeader* fhdr) { 402 void Vp9Parser::UpdateSlots(const Vp9FrameHeader* fhdr) {
376 for (size_t i = 0; i < kVp9NumRefFrames; i++) { 403 for (size_t i = 0; i < kVp9NumRefFrames; i++) {
377 if (fhdr->refresh_flag[i]) { 404 if (fhdr->RefreshFlag(i)) {
378 ref_slots_[i].width = fhdr->width; 405 ref_slots_[i].width = fhdr->width;
379 ref_slots_[i].height = fhdr->height; 406 ref_slots_[i].height = fhdr->height;
380 } 407 }
381 } 408 }
382 } 409 }
383 410
384 bool Vp9Parser::ParseFrame(const uint8_t* stream, 411 Vp9Parser::Result Vp9Parser::ParseNextFrame(Vp9FrameHeader* fhdr) {
385 size_t frame_size, 412 if (frames_.empty()) {
386 Vp9FrameHeader* fhdr) { 413 // No frames to be decoded, if there is no more stream, request more.
387 DCHECK(stream); 414 if (!stream_)
388 stream_ = stream; 415 return kEOStream;
389 size_ = frame_size; 416
417 // New stream to be parsed, parse it and fill frames_.
418 if (!ParseSuperframe()) {
419 DVLOG(1) << "Failed parsing superframes";
420 return kInvalidStream;
421 }
422 }
423
424 DCHECK(!frames_.empty());
425 FrameInfo frame_info = frames_.front();
426 frames_.pop_front();
427
390 memset(fhdr, 0, sizeof(*fhdr)); 428 memset(fhdr, 0, sizeof(*fhdr));
391 429 if (!ParseUncompressedHeader(frame_info.ptr, frame_info.size, fhdr))
392 if (!ParseUncompressedHeader(fhdr)) 430 return kInvalidStream;
431
432 return kOk;
433 }
434
435 bool Vp9Parser::ParseSuperframe() {
436 const uint8_t* stream = stream_;
437 off_t bytes_left = bytes_left_;
438
439 DCHECK(frames_.empty());
440
441 // Make sure we don't parse stream_ more than once.
442 stream_ = nullptr;
443 bytes_left_ = 0;
444
445 if (bytes_left < 1)
393 return false; 446 return false;
394 447
395 UpdateSlots(fhdr); 448 // If this is a superframe, the last byte in the stream will contain the
449 // superframe marker. If not, the whole buffer contains a single frame.
450 uint8_t marker = *(stream + bytes_left - 1);
451 if ((marker & 0xe0) != 0xc0) {
452 frames_.push_back(FrameInfo(stream, bytes_left));
453 return true;
454 }
455
456 DVLOG(1) << "Parsing a superframe";
457
458 // The bytes immediately before the superframe marker constitute superframe
459 // index, which stores information about sizes of each frame in it.
460 // Calculate its size and set index_ptr to the beginning of it.
461 size_t num_frames = (marker & 0x7) + 1;
462 size_t mag = ((marker >> 3) & 0x3) + 1;
463 off_t index_size = 2 + mag * num_frames;
464
465 if (bytes_left < index_size)
466 return false;
467
468 const uint8_t* index_ptr = stream + bytes_left - index_size;
469 if (marker != *index_ptr)
470 return false;
471
472 ++index_ptr;
473 bytes_left -= index_size;
474
475 // Parse frame information contained in the index and add a pointer to and
476 // size of each frame to frames_.
477 for (size_t i = 0; i < num_frames; ++i) {
478 uint32_t size = 0;
479 for (size_t j = 0; j < mag; ++j) {
480 size |= *index_ptr << (j * 8);
481 ++index_ptr;
482 }
483
484 if (size > bytes_left) {
485 DVLOG(1) << "Not enough data in the buffer for frame " << i;
486 return false;
487 }
488
489 frames_.push_back(FrameInfo(stream, size));
490 stream += size;
491 bytes_left -= size;
492
493 DVLOG(1) << "Frame " << i << ", size: " << size;
494 }
396 495
397 return true; 496 return true;
kcwu 2015/08/31 09:58:34 should we check bytes_left == 0?
Pawel Osciak 2015/09/08 06:43:48 We could, but I intentionally allow it, instead of
398 } 497 }
399 498
499 void Vp9Parser::ResetLoopfilter() {
500 loop_filter_.mode_ref_delta_enabled = true;
501 loop_filter_.mode_ref_delta_update = true;
502
503 const int8_t default_ref_deltas[] = {1, 0, -1, -1};
504 static_assert(
505 arraysize(default_ref_deltas) == arraysize(loop_filter_.ref_deltas),
506 "ref_deltas arrays of incorrect size");
507 for (size_t i = 0; i < arraysize(loop_filter_.ref_deltas); ++i)
508 loop_filter_.ref_deltas[i] = default_ref_deltas[i];
509
510 memset(loop_filter_.mode_deltas, 0, sizeof(loop_filter_.mode_deltas));
511 }
512
513 void Vp9Parser::SetupPastIndependence() {
514 memset(&segmentation_, 0, sizeof(segmentation_));
515 ResetLoopfilter();
516 }
517
518 const size_t QINDEX_RANGE = 256;
519 const int16_t kDcQLookup[QINDEX_RANGE] = {
520 4, 8, 8, 9, 10, 11, 12, 12,
521 13, 14, 15, 16, 17, 18, 19, 19,
522 20, 21, 22, 23, 24, 25, 26, 26,
523 27, 28, 29, 30, 31, 32, 32, 33,
524 34, 35, 36, 37, 38, 38, 39, 40,
525 41, 42, 43, 43, 44, 45, 46, 47,
526 48, 48, 49, 50, 51, 52, 53, 53,
527 54, 55, 56, 57, 57, 58, 59, 60,
528 61, 62, 62, 63, 64, 65, 66, 66,
529 67, 68, 69, 70, 70, 71, 72, 73,
530 74, 74, 75, 76, 77, 78, 78, 79,
531 80, 81, 81, 82, 83, 84, 85, 85,
532 87, 88, 90, 92, 93, 95, 96, 98,
533 99, 101, 102, 104, 105, 107, 108, 110,
534 111, 113, 114, 116, 117, 118, 120, 121,
535 123, 125, 127, 129, 131, 134, 136, 138,
536 140, 142, 144, 146, 148, 150, 152, 154,
537 156, 158, 161, 164, 166, 169, 172, 174,
538 177, 180, 182, 185, 187, 190, 192, 195,
539 199, 202, 205, 208, 211, 214, 217, 220,
540 223, 226, 230, 233, 237, 240, 243, 247,
541 250, 253, 257, 261, 265, 269, 272, 276,
542 280, 284, 288, 292, 296, 300, 304, 309,
543 313, 317, 322, 326, 330, 335, 340, 344,
544 349, 354, 359, 364, 369, 374, 379, 384,
545 389, 395, 400, 406, 411, 417, 423, 429,
546 435, 441, 447, 454, 461, 467, 475, 482,
547 489, 497, 505, 513, 522, 530, 539, 549,
548 559, 569, 579, 590, 602, 614, 626, 640,
549 654, 668, 684, 700, 717, 736, 755, 775,
550 796, 819, 843, 869, 896, 925, 955, 988,
551 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336,
552 };
553
554 const int16_t kAcQLookup[QINDEX_RANGE] = {
555 4, 8, 9, 10, 11, 12, 13, 14,
556 15, 16, 17, 18, 19, 20, 21, 22,
557 23, 24, 25, 26, 27, 28, 29, 30,
558 31, 32, 33, 34, 35, 36, 37, 38,
559 39, 40, 41, 42, 43, 44, 45, 46,
560 47, 48, 49, 50, 51, 52, 53, 54,
561 55, 56, 57, 58, 59, 60, 61, 62,
562 63, 64, 65, 66, 67, 68, 69, 70,
563 71, 72, 73, 74, 75, 76, 77, 78,
564 79, 80, 81, 82, 83, 84, 85, 86,
565 87, 88, 89, 90, 91, 92, 93, 94,
566 95, 96, 97, 98, 99, 100, 101, 102,
567 104, 106, 108, 110, 112, 114, 116, 118,
568 120, 122, 124, 126, 128, 130, 132, 134,
569 136, 138, 140, 142, 144, 146, 148, 150,
570 152, 155, 158, 161, 164, 167, 170, 173,
571 176, 179, 182, 185, 188, 191, 194, 197,
572 200, 203, 207, 211, 215, 219, 223, 227,
573 231, 235, 239, 243, 247, 251, 255, 260,
574 265, 270, 275, 280, 285, 290, 295, 300,
575 305, 311, 317, 323, 329, 335, 341, 347,
576 353, 359, 366, 373, 380, 387, 394, 401,
577 408, 416, 424, 432, 440, 448, 456, 465,
578 474, 483, 492, 501, 510, 520, 530, 540,
579 550, 560, 571, 582, 593, 604, 615, 627,
580 639, 651, 663, 676, 689, 702, 715, 729,
581 743, 757, 771, 786, 801, 816, 832, 848,
582 864, 881, 898, 915, 933, 951, 969, 988,
583 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151,
584 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343,
585 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567,
586 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
587 };
588
589 static_assert(arraysize(kDcQLookup) == arraysize(kAcQLookup),
590 "quantizer lookup arrays of incorrect size");
591
592 #define CLAMP_Q(q) std::min(std::max(0ul, q), arraysize(kDcQLookup) - 1)
593
594 size_t Vp9Parser::GetQIndex(const Vp9QuantizationParams& quant,
595 size_t segid) const {
596 if (segmentation_.FeatureEnabled(segid, Vp9Segmentation::SEG_LVL_ALT_Q)) {
597 int8_t feature_data =
598 segmentation_.FeatureData(segid, Vp9Segmentation::SEG_LVL_ALT_Q);
599 size_t q_index = segmentation_.abs_delta ? feature_data
600 : quant.base_qindex + feature_data;
601 return CLAMP_Q(q_index);
602 }
603
604 return quant.base_qindex;
605 }
606
607 void Vp9Parser::SetupSegmentationDequant(const Vp9QuantizationParams& quant) {
608 if (segmentation_.enabled) {
609 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; ++i) {
610 const size_t q_index = GetQIndex(quant, i);
611 segmentation_.y_dequant[i][0] =
612 kDcQLookup[CLAMP_Q(q_index + quant.y_dc_delta)];
613 segmentation_.y_dequant[i][1] = kAcQLookup[CLAMP_Q(q_index)];
614 segmentation_.uv_dequant[i][0] =
615 kDcQLookup[CLAMP_Q(q_index + quant.uv_dc_delta)];
616 segmentation_.uv_dequant[i][1] =
617 kAcQLookup[CLAMP_Q(q_index + quant.uv_ac_delta)];
618 }
619 } else {
620 const size_t q_index = quant.base_qindex;
621 segmentation_.y_dequant[0][0] =
622 kDcQLookup[CLAMP_Q(q_index + quant.y_dc_delta)];
623 segmentation_.y_dequant[0][1] = kAcQLookup[CLAMP_Q(q_index)];
624 segmentation_.uv_dequant[0][0] =
625 kDcQLookup[CLAMP_Q(q_index + quant.uv_dc_delta)];
626 segmentation_.uv_dequant[0][1] =
627 kAcQLookup[CLAMP_Q(q_index + quant.uv_ac_delta)];
628 }
629 }
630 #undef CLAMP_Q
631
632 #define CLAMP_LF(l) std::min(std::max(0, l), kMaxLoopFilter)
633 void Vp9Parser::SetupLoopFilter() {
634 if (!loop_filter_.filter_level)
635 return;
636
637 int scale = loop_filter_.filter_level < 32 ? 1 : 2;
638
639 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; ++i) {
640 int level = loop_filter_.filter_level;
641
642 if (segmentation_.FeatureEnabled(i, Vp9Segmentation::SEG_LVL_ALT_LF)) {
643 int feature_data =
644 segmentation_.FeatureData(i, Vp9Segmentation::SEG_LVL_ALT_LF);
645 level = CLAMP_LF(segmentation_.abs_delta ? feature_data
646 : level + feature_data);
647 }
648
649 if (!loop_filter_.mode_ref_delta_enabled) {
650 memset(loop_filter_.lvl[i], level, sizeof(loop_filter_.lvl[i]));
651 } else {
652 loop_filter_.lvl[i][Vp9LoopFilter::VP9_FRAME_INTRA][0] = CLAMP_LF(
653 level +
654 loop_filter_.ref_deltas[Vp9LoopFilter::VP9_FRAME_INTRA] * scale);
655 loop_filter_.lvl[i][Vp9LoopFilter::VP9_FRAME_INTRA][1] = 0;
656
657 for (size_t type = Vp9LoopFilter::VP9_FRAME_LAST;
658 type < Vp9LoopFilter::VP9_FRAME_MAX; ++type) {
659 for (size_t mode = 0; mode < Vp9LoopFilter::kNumModeDeltas; ++mode) {
660 loop_filter_.lvl[i][type][mode] =
661 CLAMP_LF(level + loop_filter_.ref_deltas[type] * scale +
662 loop_filter_.mode_deltas[mode] * scale);
663 }
664 }
665 }
666 }
667 }
668 #undef CLAMP_LF
669
400 } // namespace media 670 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698