| 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 | 
|---|