OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 // |
| 5 // This file contains an implementation of a VP9 bitstream parser. |
| 6 |
| 7 #include "media/filters/vp9_parser.h" |
| 8 |
| 9 #include "base/logging.h" |
| 10 |
| 11 namespace { |
| 12 |
| 13 // Helper function for Vp9Parser::ReadTiles. Defined as get_min_log2_tile_cols |
| 14 // in spec. |
| 15 int GetMinLog2TileCols(int sb64_cols) { |
| 16 const int kMaxTileWidthB64 = 64; |
| 17 int min_log2 = 0; |
| 18 while ((kMaxTileWidthB64 << min_log2) < sb64_cols) |
| 19 min_log2++; |
| 20 return min_log2; |
| 21 } |
| 22 |
| 23 // Helper function for Vp9Parser::ReadTiles. Defined as get_max_log2_tile_cols |
| 24 // in spec. |
| 25 int GetMaxLog2TileCols(int sb64_cols) { |
| 26 const int kMinTileWidthB64 = 4; |
| 27 int max_log2 = 1; |
| 28 while ((sb64_cols >> max_log2) >= kMinTileWidthB64) |
| 29 max_log2++; |
| 30 return max_log2 - 1; |
| 31 } |
| 32 |
| 33 } // namespace |
| 34 |
| 35 namespace media { |
| 36 |
| 37 Vp9Parser::Vp9Parser() : stream_(nullptr), size_(0) { |
| 38 memset(&ref_slots_, 0, sizeof(ref_slots_)); |
| 39 } |
| 40 |
| 41 uint8_t Vp9Parser::ReadProfile() { |
| 42 uint8_t profile = 0; |
| 43 |
| 44 // LSB first. |
| 45 if (reader_.ReadBool()) |
| 46 profile |= 1; |
| 47 if (reader_.ReadBool()) |
| 48 profile |= 2; |
| 49 if (profile > 2 && reader_.ReadBool()) |
| 50 profile += 1; |
| 51 return profile; |
| 52 } |
| 53 |
| 54 bool Vp9Parser::VerifySyncCode() { |
| 55 const int kSyncCode = 0x498342; |
| 56 if (reader_.ReadLiteral(8 * 3) != kSyncCode) { |
| 57 DVLOG(1) << "Invalid frame sync code"; |
| 58 return false; |
| 59 } |
| 60 return true; |
| 61 } |
| 62 |
| 63 bool Vp9Parser::ReadBitDepthColorSpaceSampling(Vp9FrameHeader* fhdr) { |
| 64 if (fhdr->profile == 2 || fhdr->profile == 3) { |
| 65 fhdr->bit_depth = reader_.ReadBool() ? 12 : 10; |
| 66 } else { |
| 67 fhdr->bit_depth = 8; |
| 68 } |
| 69 |
| 70 fhdr->color_space = static_cast<Vp9ColorSpace>(reader_.ReadLiteral(3)); |
| 71 if (fhdr->color_space != Vp9ColorSpace::SRGB) { |
| 72 fhdr->yuv_range = reader_.ReadBool(); |
| 73 if (fhdr->profile == 1 || fhdr->profile == 3) { |
| 74 fhdr->subsampling_x = reader_.ReadBool() ? 1 : 0; |
| 75 fhdr->subsampling_y = reader_.ReadBool() ? 1 : 0; |
| 76 if (fhdr->subsampling_x == 1 && fhdr->subsampling_y == 1) { |
| 77 DVLOG(1) << "4:2:0 color not supported in profile 1 or 3"; |
| 78 return false; |
| 79 } |
| 80 bool reserved = reader_.ReadBool(); |
| 81 if (reserved) { |
| 82 DVLOG(1) << "reserved bit set"; |
| 83 return false; |
| 84 } |
| 85 } else { |
| 86 fhdr->subsampling_x = fhdr->subsampling_y = 1; |
| 87 } |
| 88 } else { |
| 89 if (fhdr->profile == 1 || fhdr->profile == 3) { |
| 90 fhdr->subsampling_x = fhdr->subsampling_y = 0; |
| 91 |
| 92 bool reserved = reader_.ReadBool(); |
| 93 if (reserved) { |
| 94 DVLOG(1) << "reserved bit set"; |
| 95 return false; |
| 96 } |
| 97 } else { |
| 98 DVLOG(1) << "4:4:4 color not supported in profile 0 or 2"; |
| 99 return false; |
| 100 } |
| 101 } |
| 102 |
| 103 return true; |
| 104 } |
| 105 |
| 106 void Vp9Parser::ReadFrameSize(Vp9FrameHeader* fhdr) { |
| 107 fhdr->width = reader_.ReadLiteral(16) + 1; |
| 108 fhdr->height = reader_.ReadLiteral(16) + 1; |
| 109 } |
| 110 |
| 111 bool Vp9Parser::ReadFrameSizeFromRefs(Vp9FrameHeader* fhdr) { |
| 112 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { |
| 113 if (reader_.ReadBool()) { |
| 114 fhdr->width = ref_slots_[i].width; |
| 115 fhdr->height = ref_slots_[i].height; |
| 116 |
| 117 const int kMaxDimension = 1 << 16; |
| 118 if (fhdr->width == 0 || fhdr->width > kMaxDimension || |
| 119 fhdr->height == 0 || fhdr->height > kMaxDimension) { |
| 120 DVLOG(1) << "The size of reference frame is out of range: " |
| 121 << ref_slots_[i].width << "," << ref_slots_[i].height; |
| 122 return false; |
| 123 } |
| 124 return true; |
| 125 } |
| 126 } |
| 127 |
| 128 fhdr->width = reader_.ReadLiteral(16) + 1; |
| 129 fhdr->height = reader_.ReadLiteral(16) + 1; |
| 130 return true; |
| 131 } |
| 132 |
| 133 void Vp9Parser::ReadDisplayFrameSize(Vp9FrameHeader* fhdr) { |
| 134 if (reader_.ReadBool()) { |
| 135 fhdr->display_width = reader_.ReadLiteral(16) + 1; |
| 136 fhdr->display_height = reader_.ReadLiteral(16) + 1; |
| 137 } else { |
| 138 fhdr->display_width = fhdr->width; |
| 139 fhdr->display_height = fhdr->height; |
| 140 } |
| 141 } |
| 142 |
| 143 Vp9InterpFilter Vp9Parser::ReadInterpFilter() { |
| 144 if (reader_.ReadBool()) |
| 145 return Vp9InterpFilter::INTERP_FILTER_SELECT; |
| 146 |
| 147 // The mapping table for next two bits. |
| 148 const Vp9InterpFilter table[] = { |
| 149 Vp9InterpFilter::EIGHTTAP_SMOOTH, Vp9InterpFilter::EIGHTTAP, |
| 150 Vp9InterpFilter::EIGHTTAP_SHARP, Vp9InterpFilter::BILINEAR, |
| 151 }; |
| 152 return table[reader_.ReadLiteral(2)]; |
| 153 } |
| 154 |
| 155 void Vp9Parser::ReadLoopFilter(Vp9LoopFilter* loop_filter) { |
| 156 loop_filter->filter_level = reader_.ReadLiteral(6); |
| 157 loop_filter->sharpness_level = reader_.ReadLiteral(3); |
| 158 |
| 159 loop_filter->mode_ref_delta_enabled = reader_.ReadBool(); |
| 160 if (loop_filter->mode_ref_delta_enabled) { |
| 161 loop_filter->mode_ref_delta_update = reader_.ReadBool(); |
| 162 if (loop_filter->mode_ref_delta_update) { |
| 163 for (size_t i = 0; i < Vp9LoopFilter::kNumRefDeltas; i++) { |
| 164 loop_filter->update_ref_deltas[i] = reader_.ReadBool(); |
| 165 if (loop_filter->update_ref_deltas[i]) |
| 166 loop_filter->ref_deltas[i] = reader_.ReadSignedLiteral(6); |
| 167 } |
| 168 |
| 169 for (size_t i = 0; i < Vp9LoopFilter::kNumModeDeltas; i++) { |
| 170 loop_filter->update_mode_deltas[i] = reader_.ReadBool(); |
| 171 if (loop_filter->update_mode_deltas[i]) |
| 172 loop_filter->mode_deltas[i] = reader_.ReadLiteral(6); |
| 173 } |
| 174 } |
| 175 } |
| 176 } |
| 177 |
| 178 void Vp9Parser::ReadQuantization(Vp9QuantizationParams* quants) { |
| 179 quants->base_qindex = reader_.ReadLiteral(8); |
| 180 |
| 181 if (reader_.ReadBool()) |
| 182 quants->y_dc_delta = reader_.ReadSignedLiteral(4); |
| 183 |
| 184 if (reader_.ReadBool()) |
| 185 quants->uv_ac_delta = reader_.ReadSignedLiteral(4); |
| 186 |
| 187 if (reader_.ReadBool()) |
| 188 quants->uv_dc_delta = reader_.ReadSignedLiteral(4); |
| 189 } |
| 190 |
| 191 void Vp9Parser::ReadSegmentationMap(Vp9Segmentation* segment) { |
| 192 for (size_t i = 0; i < Vp9Segmentation::kNumTreeProbs; i++) { |
| 193 segment->tree_probs[i] = |
| 194 reader_.ReadBool() ? reader_.ReadLiteral(8) : kVp9MaxProb; |
| 195 } |
| 196 |
| 197 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) |
| 198 segment->pred_probs[i] = kVp9MaxProb; |
| 199 |
| 200 segment->temporal_update = reader_.ReadBool(); |
| 201 if (segment->temporal_update) { |
| 202 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) { |
| 203 if (reader_.ReadBool()) |
| 204 segment->pred_probs[i] = reader_.ReadLiteral(8); |
| 205 } |
| 206 } |
| 207 } |
| 208 |
| 209 void Vp9Parser::ReadSegmentationData(Vp9Segmentation* segment) { |
| 210 segment->abs_delta = reader_.ReadBool(); |
| 211 |
| 212 const int kFeatureDataBits[] = {7, 6, 2, 0}; |
| 213 const bool kFeatureDataSigned[] = {true, true, false, false}; |
| 214 |
| 215 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; i++) { |
| 216 for (size_t j = 0; j < Vp9Segmentation::kNumFeatures; j++) { |
| 217 int8_t data = 0; |
| 218 segment->feature_enabled[i][j] = reader_.ReadBool(); |
| 219 if (segment->feature_enabled[i][j]) { |
| 220 data = reader_.ReadLiteral(kFeatureDataBits[j]); |
| 221 if (kFeatureDataSigned[j]) |
| 222 if (reader_.ReadBool()) |
| 223 data = -data; |
| 224 } |
| 225 segment->feature_data[i][j] = data; |
| 226 } |
| 227 } |
| 228 } |
| 229 |
| 230 void Vp9Parser::ReadSegmentation(Vp9Segmentation* segment) { |
| 231 segment->enabled = reader_.ReadBool(); |
| 232 |
| 233 if (!segment->enabled) { |
| 234 return; |
| 235 } |
| 236 |
| 237 segment->update_map = reader_.ReadBool(); |
| 238 if (segment->update_map) |
| 239 ReadSegmentationMap(segment); |
| 240 |
| 241 segment->update_data = reader_.ReadBool(); |
| 242 if (segment->update_data) |
| 243 ReadSegmentationData(segment); |
| 244 } |
| 245 |
| 246 void Vp9Parser::ReadTiles(Vp9FrameHeader* fhdr) { |
| 247 int sb64_cols = (fhdr->width + 63) / 64; |
| 248 |
| 249 int min_log2_tile_cols = GetMinLog2TileCols(sb64_cols); |
| 250 int max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols); |
| 251 |
| 252 int max_ones = max_log2_tile_cols - min_log2_tile_cols; |
| 253 fhdr->log2_tile_cols = min_log2_tile_cols; |
| 254 while (max_ones-- && reader_.ReadBool()) |
| 255 fhdr->log2_tile_cols++; |
| 256 |
| 257 if (reader_.ReadBool()) |
| 258 fhdr->log2_tile_rows = reader_.ReadLiteral(2) - 1; |
| 259 } |
| 260 |
| 261 bool Vp9Parser::ParseUncompressedHeader(Vp9FrameHeader* fhdr) { |
| 262 reader_.Initialize(stream_, size_); |
| 263 |
| 264 // frame marker |
| 265 if (reader_.ReadLiteral(2) != 0x2) |
| 266 return false; |
| 267 |
| 268 fhdr->profile = ReadProfile(); |
| 269 if (fhdr->profile >= kVp9MaxProfile) { |
| 270 DVLOG(1) << "Unsupported bitstream profile"; |
| 271 return false; |
| 272 } |
| 273 |
| 274 fhdr->show_existing_frame = reader_.ReadBool(); |
| 275 if (fhdr->show_existing_frame) { |
| 276 fhdr->frame_to_show = reader_.ReadLiteral(3); |
| 277 fhdr->show_frame = true; |
| 278 |
| 279 if (!reader_.IsValid()) { |
| 280 DVLOG(1) << "parser reads beyond the end of buffer"; |
| 281 return false; |
| 282 } |
| 283 fhdr->uncompressed_header_size = reader_.GetBytesRead(); |
| 284 return true; |
| 285 } |
| 286 |
| 287 fhdr->frame_type = static_cast<Vp9FrameHeader::FrameType>(reader_.ReadBool()); |
| 288 fhdr->show_frame = reader_.ReadBool(); |
| 289 fhdr->error_resilient_mode = reader_.ReadBool(); |
| 290 |
| 291 if (fhdr->IsKeyframe()) { |
| 292 if (!VerifySyncCode()) |
| 293 return false; |
| 294 |
| 295 if (!ReadBitDepthColorSpaceSampling(fhdr)) |
| 296 return false; |
| 297 |
| 298 for (size_t i = 0; i < kVp9NumRefFrames; i++) |
| 299 fhdr->refresh_flag[i] = true; |
| 300 |
| 301 ReadFrameSize(fhdr); |
| 302 ReadDisplayFrameSize(fhdr); |
| 303 } else { |
| 304 if (!fhdr->show_frame) |
| 305 fhdr->intra_only = reader_.ReadBool(); |
| 306 |
| 307 if (!fhdr->error_resilient_mode) |
| 308 fhdr->reset_context = reader_.ReadLiteral(2); |
| 309 |
| 310 if (fhdr->intra_only) { |
| 311 if (!VerifySyncCode()) |
| 312 return false; |
| 313 |
| 314 if (fhdr->profile > 0) { |
| 315 if (!ReadBitDepthColorSpaceSampling(fhdr)) |
| 316 return false; |
| 317 } else { |
| 318 fhdr->bit_depth = 8; |
| 319 fhdr->color_space = Vp9ColorSpace::BT_601; |
| 320 fhdr->subsampling_x = fhdr->subsampling_y = 1; |
| 321 } |
| 322 |
| 323 for (size_t i = 0; i < kVp9NumRefFrames; i++) |
| 324 fhdr->refresh_flag[i] = reader_.ReadBool(); |
| 325 ReadFrameSize(fhdr); |
| 326 ReadDisplayFrameSize(fhdr); |
| 327 } else { |
| 328 for (size_t i = 0; i < kVp9NumRefFrames; i++) |
| 329 fhdr->refresh_flag[i] = reader_.ReadBool(); |
| 330 |
| 331 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { |
| 332 fhdr->frame_refs[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2); |
| 333 fhdr->ref_sign_biases[i] = reader_.ReadBool(); |
| 334 } |
| 335 |
| 336 if (!ReadFrameSizeFromRefs(fhdr)) |
| 337 return false; |
| 338 ReadDisplayFrameSize(fhdr); |
| 339 |
| 340 fhdr->allow_high_precision_mv = reader_.ReadBool(); |
| 341 fhdr->interp_filter = ReadInterpFilter(); |
| 342 } |
| 343 } |
| 344 |
| 345 if (fhdr->error_resilient_mode) { |
| 346 fhdr->frame_parallel_decoding_mode = true; |
| 347 } else { |
| 348 fhdr->refresh_frame_context = reader_.ReadBool(); |
| 349 fhdr->frame_parallel_decoding_mode = reader_.ReadBool(); |
| 350 } |
| 351 |
| 352 fhdr->frame_context_idx = reader_.ReadLiteral(2); |
| 353 |
| 354 ReadLoopFilter(&fhdr->loop_filter); |
| 355 ReadQuantization(&fhdr->quant_params); |
| 356 ReadSegmentation(&fhdr->segment); |
| 357 |
| 358 ReadTiles(fhdr); |
| 359 |
| 360 fhdr->first_partition_size = reader_.ReadLiteral(16); |
| 361 if (fhdr->first_partition_size == 0) { |
| 362 DVLOG(1) << "invalid header size"; |
| 363 return false; |
| 364 } |
| 365 |
| 366 if (!reader_.IsValid()) { |
| 367 DVLOG(1) << "parser reads beyond the end of buffer"; |
| 368 return false; |
| 369 } |
| 370 fhdr->uncompressed_header_size = reader_.GetBytesRead(); |
| 371 |
| 372 return true; |
| 373 } |
| 374 |
| 375 void Vp9Parser::UpdateSlots(const Vp9FrameHeader* fhdr) { |
| 376 for (size_t i = 0; i < kVp9NumRefFrames; i++) { |
| 377 if (fhdr->refresh_flag[i]) { |
| 378 ref_slots_[i].width = fhdr->width; |
| 379 ref_slots_[i].height = fhdr->height; |
| 380 } |
| 381 } |
| 382 } |
| 383 |
| 384 bool Vp9Parser::ParseFrame(const uint8_t* stream, |
| 385 size_t frame_size, |
| 386 Vp9FrameHeader* fhdr) { |
| 387 DCHECK(stream); |
| 388 stream_ = stream; |
| 389 size_ = frame_size; |
| 390 memset(fhdr, 0, sizeof(*fhdr)); |
| 391 |
| 392 if (!ParseUncompressedHeader(fhdr)) |
| 393 return false; |
| 394 |
| 395 UpdateSlots(fhdr); |
| 396 |
| 397 return true; |
| 398 } |
| 399 |
| 400 } // namespace media |
OLD | NEW |