| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 #include "content/common/gpu/media/h264_parser.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/memory/scoped_ptr.h" | |
| 9 #include "base/stl_util.h" | |
| 10 | |
| 11 namespace content { | |
| 12 | |
| 13 bool H264SliceHeader::IsPSlice() const { | |
| 14 return (slice_type % 5 == kPSlice); | |
| 15 } | |
| 16 | |
| 17 bool H264SliceHeader::IsBSlice() const { | |
| 18 return (slice_type % 5 == kBSlice); | |
| 19 } | |
| 20 | |
| 21 bool H264SliceHeader::IsISlice() const { | |
| 22 return (slice_type % 5 == kISlice); | |
| 23 } | |
| 24 | |
| 25 bool H264SliceHeader::IsSPSlice() const { | |
| 26 return (slice_type % 5 == kSPSlice); | |
| 27 } | |
| 28 | |
| 29 bool H264SliceHeader::IsSISlice() const { | |
| 30 return (slice_type % 5 == kSISlice); | |
| 31 } | |
| 32 | |
| 33 H264NALU::H264NALU() { | |
| 34 memset(this, 0, sizeof(*this)); | |
| 35 } | |
| 36 | |
| 37 H264SPS::H264SPS() { | |
| 38 memset(this, 0, sizeof(*this)); | |
| 39 } | |
| 40 | |
| 41 H264PPS::H264PPS() { | |
| 42 memset(this, 0, sizeof(*this)); | |
| 43 } | |
| 44 | |
| 45 H264SliceHeader::H264SliceHeader() { | |
| 46 memset(this, 0, sizeof(*this)); | |
| 47 } | |
| 48 | |
| 49 H264SEIMessage::H264SEIMessage() { | |
| 50 memset(this, 0, sizeof(*this)); | |
| 51 } | |
| 52 | |
| 53 #define READ_BITS_OR_RETURN(num_bits, out) \ | |
| 54 do { \ | |
| 55 int _out; \ | |
| 56 if (!br_.ReadBits(num_bits, &_out)) { \ | |
| 57 DVLOG(1) << "Error in stream: unexpected EOS while trying to read " #out; \ | |
| 58 return kInvalidStream; \ | |
| 59 } \ | |
| 60 *out = _out; \ | |
| 61 } while (0) | |
| 62 | |
| 63 #define READ_BOOL_OR_RETURN(out) \ | |
| 64 do { \ | |
| 65 int _out; \ | |
| 66 if (!br_.ReadBits(1, &_out)) { \ | |
| 67 DVLOG(1) << "Error in stream: unexpected EOS while trying to read " #out; \ | |
| 68 return kInvalidStream; \ | |
| 69 } \ | |
| 70 *out = _out != 0; \ | |
| 71 } while (0) | |
| 72 | |
| 73 #define READ_UE_OR_RETURN(out) \ | |
| 74 do { \ | |
| 75 if (ReadUE(out) != kOk) { \ | |
| 76 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \ | |
| 77 return kInvalidStream; \ | |
| 78 } \ | |
| 79 } while (0) | |
| 80 | |
| 81 #define READ_SE_OR_RETURN(out) \ | |
| 82 do { \ | |
| 83 if (ReadSE(out) != kOk) { \ | |
| 84 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \ | |
| 85 return kInvalidStream; \ | |
| 86 } \ | |
| 87 } while (0) | |
| 88 | |
| 89 #define IN_RANGE_OR_RETURN(val, min, max) \ | |
| 90 do { \ | |
| 91 if ((val) < (min) || (val) > (max)) { \ | |
| 92 DVLOG(1) << "Error in stream: invalid value, expected " #val " to be" \ | |
| 93 << " in range [" << (min) << ":" << (max) << "]" \ | |
| 94 << " found " << (val) << " instead"; \ | |
| 95 return kInvalidStream; \ | |
| 96 } \ | |
| 97 } while (0) | |
| 98 | |
| 99 #define TRUE_OR_RETURN(a) \ | |
| 100 do { \ | |
| 101 if (!(a)) { \ | |
| 102 DVLOG(1) << "Error in stream: invalid value, expected " << #a; \ | |
| 103 return kInvalidStream; \ | |
| 104 } \ | |
| 105 } while (0) | |
| 106 | |
| 107 H264Parser::H264Parser() { | |
| 108 Reset(); | |
| 109 } | |
| 110 | |
| 111 H264Parser::~H264Parser() { | |
| 112 STLDeleteValues(&active_SPSes_); | |
| 113 STLDeleteValues(&active_PPSes_); | |
| 114 } | |
| 115 | |
| 116 void H264Parser::Reset() { | |
| 117 stream_ = NULL; | |
| 118 bytes_left_ = 0; | |
| 119 } | |
| 120 | |
| 121 void H264Parser::SetStream(const uint8* stream, off_t stream_size) { | |
| 122 DCHECK(stream); | |
| 123 DCHECK_GT(stream_size, 0); | |
| 124 | |
| 125 stream_ = stream; | |
| 126 bytes_left_ = stream_size; | |
| 127 } | |
| 128 | |
| 129 const H264PPS* H264Parser::GetPPS(int pps_id) { | |
| 130 return active_PPSes_[pps_id]; | |
| 131 } | |
| 132 | |
| 133 const H264SPS* H264Parser::GetSPS(int sps_id) { | |
| 134 return active_SPSes_[sps_id]; | |
| 135 } | |
| 136 | |
| 137 static inline bool IsStartCode(const uint8* data) { | |
| 138 return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01; | |
| 139 } | |
| 140 | |
| 141 // Find offset from start of data to next NALU start code | |
| 142 // and size of found start code (3 or 4 bytes). | |
| 143 static bool FindStartCode(const uint8* data, off_t data_size, | |
| 144 off_t* offset, | |
| 145 off_t* start_code_size) { | |
| 146 off_t bytes_left = data_size; | |
| 147 | |
| 148 while (bytes_left > 3) { | |
| 149 if (IsStartCode(data)) { | |
| 150 // Found three-byte start code, set pointer at its beginning. | |
| 151 *offset = data_size - bytes_left; | |
| 152 *start_code_size = 3; | |
| 153 | |
| 154 // If there is a zero byte before this start code, | |
| 155 // then it's actually a four-byte start code, so backtrack one byte. | |
| 156 if (*offset > 0 && *(data - 1) == 0x00) { | |
| 157 --(*offset); | |
| 158 ++(*start_code_size); | |
| 159 } | |
| 160 | |
| 161 return true; | |
| 162 } | |
| 163 | |
| 164 ++data; | |
| 165 --bytes_left; | |
| 166 } | |
| 167 | |
| 168 // End of data. | |
| 169 return false; | |
| 170 } | |
| 171 | |
| 172 // Find the next NALU in stream, returning its start offset without the start | |
| 173 // code (i.e. at the beginning of NALU data). | |
| 174 // Size will include trailing zero bits, and will be from start offset to | |
| 175 // before the start code of the next NALU (or end of stream). | |
| 176 static bool LocateNALU(const uint8* stream, off_t stream_size, | |
| 177 off_t* nalu_start_off, off_t* nalu_size) { | |
| 178 off_t start_code_size; | |
| 179 | |
| 180 // Find start code of the next NALU. | |
| 181 if (!FindStartCode(stream, stream_size, nalu_start_off, &start_code_size)) { | |
| 182 DVLOG(4) << "Could not find start code, end of stream?"; | |
| 183 return false; | |
| 184 } | |
| 185 | |
| 186 // Discard its start code. | |
| 187 *nalu_start_off += start_code_size; | |
| 188 // Move the stream to the beginning of it (skip the start code). | |
| 189 stream_size -= *nalu_start_off; | |
| 190 stream += *nalu_start_off; | |
| 191 | |
| 192 // Find the start code of next NALU; if successful, NALU size is the number | |
| 193 // of bytes from after previous start code to before this one; | |
| 194 // if next start code is not found, it is still a valid NALU if there | |
| 195 // are still some bytes left after the first start code. | |
| 196 // nalu_size is the offset to the next start code | |
| 197 if (!FindStartCode(stream, stream_size, nalu_size, &start_code_size)) { | |
| 198 // end of stream (no next NALU), but still valid NALU if any bytes left | |
| 199 *nalu_size = stream_size; | |
| 200 if (*nalu_size < 1) { | |
| 201 DVLOG(3) << "End of stream"; | |
| 202 return false; | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 return true; | |
| 207 } | |
| 208 | |
| 209 H264Parser::Result H264Parser::ReadUE(int* val) { | |
| 210 int num_bits = -1; | |
| 211 int bit; | |
| 212 int rest; | |
| 213 | |
| 214 // Count the number of contiguous zero bits. | |
| 215 do { | |
| 216 READ_BITS_OR_RETURN(1, &bit); | |
| 217 num_bits++; | |
| 218 } while (bit == 0); | |
| 219 | |
| 220 if (num_bits > 31) | |
| 221 return kInvalidStream; | |
| 222 | |
| 223 // Calculate exp-Golomb code value of size num_bits. | |
| 224 *val = (1 << num_bits) - 1; | |
| 225 | |
| 226 if (num_bits > 0) { | |
| 227 READ_BITS_OR_RETURN(num_bits, &rest); | |
| 228 *val += rest; | |
| 229 } | |
| 230 | |
| 231 return kOk; | |
| 232 } | |
| 233 | |
| 234 H264Parser::Result H264Parser::ReadSE(int* val) { | |
| 235 int ue; | |
| 236 Result res; | |
| 237 | |
| 238 // See Chapter 9 in the spec. | |
| 239 res = ReadUE(&ue); | |
| 240 if (res != kOk) | |
| 241 return res; | |
| 242 | |
| 243 if (ue % 2 == 0) | |
| 244 *val = -(ue / 2); | |
| 245 else | |
| 246 *val = ue / 2 + 1; | |
| 247 | |
| 248 return kOk; | |
| 249 } | |
| 250 | |
| 251 H264Parser::Result H264Parser::AdvanceToNextNALU(H264NALU *nalu) { | |
| 252 int data; | |
| 253 off_t off_to_nalu_start; | |
| 254 | |
| 255 if (!LocateNALU(stream_, bytes_left_, &off_to_nalu_start, &nalu->size)) { | |
| 256 DVLOG(4) << "Could not find next NALU, bytes left in stream: " | |
| 257 << bytes_left_; | |
| 258 return kEOStream; | |
| 259 } | |
| 260 | |
| 261 nalu->data = stream_ + off_to_nalu_start; | |
| 262 | |
| 263 // Initialize bit reader at the start of found NALU. | |
| 264 if (!br_.Initialize(nalu->data, nalu->size)) | |
| 265 return kEOStream; | |
| 266 | |
| 267 DVLOG(4) << "Looking for NALU, Stream bytes left: " << bytes_left_ | |
| 268 << " off to next nalu: " << off_to_nalu_start; | |
| 269 | |
| 270 // Move parser state to after this NALU, so next time AdvanceToNextNALU | |
| 271 // is called, we will effectively be skipping it; | |
| 272 // other parsing functions will use the position saved | |
| 273 // in bit reader for parsing, so we don't have to remember it here. | |
| 274 stream_ += off_to_nalu_start + nalu->size; | |
| 275 bytes_left_ -= off_to_nalu_start + nalu->size; | |
| 276 | |
| 277 // Read NALU header, skip the forbidden_zero_bit, but check for it. | |
| 278 READ_BITS_OR_RETURN(1, &data); | |
| 279 TRUE_OR_RETURN(data == 0); | |
| 280 | |
| 281 READ_BITS_OR_RETURN(2, &nalu->nal_ref_idc); | |
| 282 READ_BITS_OR_RETURN(5, &nalu->nal_unit_type); | |
| 283 | |
| 284 DVLOG(4) << "NALU type: " << static_cast<int>(nalu->nal_unit_type) | |
| 285 << " at: " << reinterpret_cast<const void*>(nalu->data) | |
| 286 << " size: " << nalu->size | |
| 287 << " ref: " << static_cast<int>(nalu->nal_ref_idc); | |
| 288 | |
| 289 return kOk; | |
| 290 } | |
| 291 | |
| 292 // Default scaling lists (per spec). | |
| 293 static const int kDefault4x4Intra[kH264ScalingList4x4Length] = { | |
| 294 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, }; | |
| 295 | |
| 296 static const int kDefault4x4Inter[kH264ScalingList4x4Length] = { | |
| 297 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, }; | |
| 298 | |
| 299 static const int kDefault8x8Intra[kH264ScalingList8x8Length] = { | |
| 300 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, | |
| 301 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, | |
| 302 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, | |
| 303 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, }; | |
| 304 | |
| 305 static const int kDefault8x8Inter[kH264ScalingList8x8Length] = { | |
| 306 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, | |
| 307 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, | |
| 308 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, | |
| 309 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, }; | |
| 310 | |
| 311 static inline void DefaultScalingList4x4( | |
| 312 int i, | |
| 313 int scaling_list4x4[][kH264ScalingList4x4Length]) { | |
| 314 DCHECK_LT(i, 6); | |
| 315 | |
| 316 if (i < 3) | |
| 317 memcpy(scaling_list4x4[i], kDefault4x4Intra, sizeof(kDefault4x4Intra)); | |
| 318 else if (i < 6) | |
| 319 memcpy(scaling_list4x4[i], kDefault4x4Inter, sizeof(kDefault4x4Inter)); | |
| 320 } | |
| 321 | |
| 322 static inline void DefaultScalingList8x8( | |
| 323 int i, | |
| 324 int scaling_list8x8[][kH264ScalingList8x8Length]) { | |
| 325 DCHECK_LT(i, 6); | |
| 326 | |
| 327 if (i % 2 == 0) | |
| 328 memcpy(scaling_list8x8[i], kDefault8x8Intra, sizeof(kDefault8x8Intra)); | |
| 329 else | |
| 330 memcpy(scaling_list8x8[i], kDefault8x8Inter, sizeof(kDefault8x8Inter)); | |
| 331 } | |
| 332 | |
| 333 static void FallbackScalingList4x4( | |
| 334 int i, | |
| 335 const int default_scaling_list_intra[], | |
| 336 const int default_scaling_list_inter[], | |
| 337 int scaling_list4x4[][kH264ScalingList4x4Length]) { | |
| 338 static const int kScalingList4x4ByteSize = sizeof(scaling_list4x4[0][0]) * | |
| 339 kH264ScalingList4x4Length; | |
| 340 | |
| 341 switch (i) { | |
| 342 case 0: | |
| 343 memcpy(scaling_list4x4[i], default_scaling_list_intra, | |
| 344 kScalingList4x4ByteSize); | |
| 345 break; | |
| 346 | |
| 347 case 1: | |
| 348 memcpy(scaling_list4x4[i], scaling_list4x4[0], | |
| 349 kScalingList4x4ByteSize); | |
| 350 break; | |
| 351 | |
| 352 case 2: | |
| 353 memcpy(scaling_list4x4[i], scaling_list4x4[1], | |
| 354 kScalingList4x4ByteSize); | |
| 355 break; | |
| 356 | |
| 357 case 3: | |
| 358 memcpy(scaling_list4x4[i], default_scaling_list_inter, | |
| 359 kScalingList4x4ByteSize); | |
| 360 break; | |
| 361 | |
| 362 case 4: | |
| 363 memcpy(scaling_list4x4[i], scaling_list4x4[3], | |
| 364 kScalingList4x4ByteSize); | |
| 365 break; | |
| 366 | |
| 367 case 5: | |
| 368 memcpy(scaling_list4x4[i], scaling_list4x4[4], | |
| 369 kScalingList4x4ByteSize); | |
| 370 break; | |
| 371 | |
| 372 default: | |
| 373 NOTREACHED(); | |
| 374 break; | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 static void FallbackScalingList8x8( | |
| 379 int i, | |
| 380 const int default_scaling_list_intra[], | |
| 381 const int default_scaling_list_inter[], | |
| 382 int scaling_list8x8[][kH264ScalingList8x8Length]) { | |
| 383 static const int kScalingList8x8ByteSize = sizeof(scaling_list8x8[0][0]) * | |
| 384 kH264ScalingList8x8Length; | |
| 385 | |
| 386 switch (i) { | |
| 387 case 0: | |
| 388 memcpy(scaling_list8x8[i], default_scaling_list_intra, | |
| 389 kScalingList8x8ByteSize); | |
| 390 break; | |
| 391 | |
| 392 case 1: | |
| 393 memcpy(scaling_list8x8[i], default_scaling_list_inter, | |
| 394 kScalingList8x8ByteSize); | |
| 395 break; | |
| 396 | |
| 397 case 2: | |
| 398 memcpy(scaling_list8x8[i], scaling_list8x8[0], | |
| 399 kScalingList8x8ByteSize); | |
| 400 break; | |
| 401 | |
| 402 case 3: | |
| 403 memcpy(scaling_list8x8[i], scaling_list8x8[1], | |
| 404 kScalingList8x8ByteSize); | |
| 405 break; | |
| 406 | |
| 407 case 4: | |
| 408 memcpy(scaling_list8x8[i], scaling_list8x8[2], | |
| 409 kScalingList8x8ByteSize); | |
| 410 break; | |
| 411 | |
| 412 case 5: | |
| 413 memcpy(scaling_list8x8[i], scaling_list8x8[3], | |
| 414 kScalingList8x8ByteSize); | |
| 415 break; | |
| 416 | |
| 417 default: | |
| 418 NOTREACHED(); | |
| 419 break; | |
| 420 } | |
| 421 } | |
| 422 | |
| 423 H264Parser::Result H264Parser::ParseScalingList(int size, | |
| 424 int* scaling_list, | |
| 425 bool* use_default) { | |
| 426 // See chapter 7.3.2.1.1.1. | |
| 427 int last_scale = 8; | |
| 428 int next_scale = 8; | |
| 429 int delta_scale; | |
| 430 | |
| 431 *use_default = false; | |
| 432 | |
| 433 for (int j = 0; j < size; ++j) { | |
| 434 if (next_scale != 0) { | |
| 435 READ_SE_OR_RETURN(&delta_scale); | |
| 436 IN_RANGE_OR_RETURN(delta_scale, -128, 127); | |
| 437 next_scale = (last_scale + delta_scale + 256) & 0xff; | |
| 438 | |
| 439 if (j == 0 && next_scale == 0) { | |
| 440 *use_default = true; | |
| 441 return kOk; | |
| 442 } | |
| 443 } | |
| 444 | |
| 445 scaling_list[j] = (next_scale == 0) ? last_scale : next_scale; | |
| 446 last_scale = scaling_list[j]; | |
| 447 } | |
| 448 | |
| 449 return kOk; | |
| 450 } | |
| 451 | |
| 452 H264Parser::Result H264Parser::ParseSPSScalingLists(H264SPS* sps) { | |
| 453 // See 7.4.2.1.1. | |
| 454 bool seq_scaling_list_present_flag; | |
| 455 bool use_default; | |
| 456 Result res; | |
| 457 | |
| 458 // Parse scaling_list4x4. | |
| 459 for (int i = 0; i < 6; ++i) { | |
| 460 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag); | |
| 461 | |
| 462 if (seq_scaling_list_present_flag) { | |
| 463 res = ParseScalingList(arraysize(sps->scaling_list4x4[i]), | |
| 464 sps->scaling_list4x4[i], &use_default); | |
| 465 if (res != kOk) | |
| 466 return res; | |
| 467 | |
| 468 if (use_default) | |
| 469 DefaultScalingList4x4(i, sps->scaling_list4x4); | |
| 470 | |
| 471 } else { | |
| 472 FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter, | |
| 473 sps->scaling_list4x4); | |
| 474 } | |
| 475 } | |
| 476 | |
| 477 // Parse scaling_list8x8. | |
| 478 for (int i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) { | |
| 479 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag); | |
| 480 | |
| 481 if (seq_scaling_list_present_flag) { | |
| 482 res = ParseScalingList(arraysize(sps->scaling_list8x8[i]), | |
| 483 sps->scaling_list8x8[i], &use_default); | |
| 484 if (res != kOk) | |
| 485 return res; | |
| 486 | |
| 487 if (use_default) | |
| 488 DefaultScalingList8x8(i, sps->scaling_list8x8); | |
| 489 | |
| 490 } else { | |
| 491 FallbackScalingList8x8(i, kDefault8x8Intra, kDefault8x8Inter, | |
| 492 sps->scaling_list8x8); | |
| 493 } | |
| 494 } | |
| 495 | |
| 496 return kOk; | |
| 497 } | |
| 498 | |
| 499 H264Parser::Result H264Parser::ParsePPSScalingLists(const H264SPS& sps, | |
| 500 H264PPS* pps) { | |
| 501 // See 7.4.2.2. | |
| 502 bool pic_scaling_list_present_flag; | |
| 503 bool use_default; | |
| 504 Result res; | |
| 505 | |
| 506 for (int i = 0; i < 6; ++i) { | |
| 507 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag); | |
| 508 | |
| 509 if (pic_scaling_list_present_flag) { | |
| 510 res = ParseScalingList(arraysize(pps->scaling_list4x4[i]), | |
| 511 pps->scaling_list4x4[i], &use_default); | |
| 512 if (res != kOk) | |
| 513 return res; | |
| 514 | |
| 515 if (use_default) | |
| 516 DefaultScalingList4x4(i, pps->scaling_list4x4); | |
| 517 | |
| 518 } else { | |
| 519 if (sps.seq_scaling_matrix_present_flag) { | |
| 520 // Table 7-2 fallback rule A in spec. | |
| 521 FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter, | |
| 522 pps->scaling_list4x4); | |
| 523 } else { | |
| 524 // Table 7-2 fallback rule B in spec. | |
| 525 FallbackScalingList4x4(i, sps.scaling_list4x4[0], | |
| 526 sps.scaling_list4x4[3], pps->scaling_list4x4); | |
| 527 } | |
| 528 } | |
| 529 } | |
| 530 | |
| 531 if (pps->transform_8x8_mode_flag) { | |
| 532 for (int i = 0; i < ((sps.chroma_format_idc != 3) ? 2 : 6); ++i) { | |
| 533 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag); | |
| 534 | |
| 535 if (pic_scaling_list_present_flag) { | |
| 536 res = ParseScalingList(arraysize(pps->scaling_list8x8[i]), | |
| 537 pps->scaling_list8x8[i], &use_default); | |
| 538 if (res != kOk) | |
| 539 return res; | |
| 540 | |
| 541 if (use_default) | |
| 542 DefaultScalingList8x8(i, pps->scaling_list8x8); | |
| 543 | |
| 544 } else { | |
| 545 if (sps.seq_scaling_matrix_present_flag) { | |
| 546 // Table 7-2 fallback rule A in spec. | |
| 547 FallbackScalingList8x8(i, kDefault8x8Intra, | |
| 548 kDefault8x8Inter, pps->scaling_list8x8); | |
| 549 } else { | |
| 550 // Table 7-2 fallback rule B in spec. | |
| 551 FallbackScalingList8x8(i, sps.scaling_list8x8[0], | |
| 552 sps.scaling_list8x8[1], pps->scaling_list8x8); | |
| 553 } | |
| 554 } | |
| 555 } | |
| 556 } | |
| 557 return kOk; | |
| 558 } | |
| 559 | |
| 560 static void FillDefaultSeqScalingLists(H264SPS* sps) { | |
| 561 for (int i = 0; i < 6; ++i) | |
| 562 for (int j = 0; j < kH264ScalingList4x4Length; ++j) | |
| 563 sps->scaling_list4x4[i][j] = 16; | |
| 564 | |
| 565 for (int i = 0; i < 6; ++i) | |
| 566 for (int j = 0; j < kH264ScalingList8x8Length; ++j) | |
| 567 sps->scaling_list8x8[i][j] = 16; | |
| 568 } | |
| 569 | |
| 570 H264Parser::Result H264Parser::ParseSPS(int* sps_id) { | |
| 571 // See 7.4.2.1. | |
| 572 int data; | |
| 573 Result res; | |
| 574 | |
| 575 *sps_id = -1; | |
| 576 | |
| 577 scoped_ptr<H264SPS> sps(new H264SPS()); | |
| 578 | |
| 579 READ_BITS_OR_RETURN(8, &sps->profile_idc); | |
| 580 READ_BITS_OR_RETURN(6, &sps->constraint_setx_flag); | |
| 581 READ_BITS_OR_RETURN(2, &data); | |
| 582 READ_BITS_OR_RETURN(8, &sps->level_idc); | |
| 583 READ_UE_OR_RETURN(&sps->seq_parameter_set_id); | |
| 584 TRUE_OR_RETURN(sps->seq_parameter_set_id < 32); | |
| 585 | |
| 586 if (sps->profile_idc == 100 || sps->profile_idc == 110 || | |
| 587 sps->profile_idc == 122 || sps->profile_idc == 244 || | |
| 588 sps->profile_idc == 44 || sps->profile_idc == 83 || | |
| 589 sps->profile_idc == 86 || sps->profile_idc == 118 || | |
| 590 sps->profile_idc == 128) { | |
| 591 READ_UE_OR_RETURN(&sps->chroma_format_idc); | |
| 592 TRUE_OR_RETURN(sps->chroma_format_idc < 4); | |
| 593 | |
| 594 if (sps->chroma_format_idc == 3) | |
| 595 READ_BOOL_OR_RETURN(&sps->separate_colour_plane_flag); | |
| 596 | |
| 597 READ_UE_OR_RETURN(&sps->bit_depth_luma_minus8); | |
| 598 TRUE_OR_RETURN(sps->bit_depth_luma_minus8 < 7); | |
| 599 | |
| 600 READ_UE_OR_RETURN(&sps->bit_depth_chroma_minus8); | |
| 601 TRUE_OR_RETURN(sps->bit_depth_chroma_minus8 < 7); | |
| 602 | |
| 603 READ_BOOL_OR_RETURN(&sps->qpprime_y_zero_transform_bypass_flag); | |
| 604 READ_BOOL_OR_RETURN(&sps->seq_scaling_matrix_present_flag); | |
| 605 | |
| 606 if (sps->seq_scaling_matrix_present_flag) { | |
| 607 DVLOG(4) << "Scaling matrix present"; | |
| 608 res = ParseSPSScalingLists(sps.get()); | |
| 609 if (res != kOk) | |
| 610 return res; | |
| 611 } else { | |
| 612 FillDefaultSeqScalingLists(sps.get()); | |
| 613 } | |
| 614 } else { | |
| 615 sps->chroma_format_idc = 1; | |
| 616 FillDefaultSeqScalingLists(sps.get()); | |
| 617 } | |
| 618 | |
| 619 if (sps->separate_colour_plane_flag) | |
| 620 sps->chroma_array_type = 0; | |
| 621 else | |
| 622 sps->chroma_array_type = sps->chroma_format_idc; | |
| 623 | |
| 624 READ_UE_OR_RETURN(&sps->log2_max_frame_num_minus4); | |
| 625 TRUE_OR_RETURN(sps->log2_max_frame_num_minus4 < 13); | |
| 626 | |
| 627 READ_UE_OR_RETURN(&sps->pic_order_cnt_type); | |
| 628 TRUE_OR_RETURN(sps->pic_order_cnt_type < 3); | |
| 629 | |
| 630 sps->expected_delta_per_pic_order_cnt_cycle = 0; | |
| 631 if (sps->pic_order_cnt_type == 0) { | |
| 632 READ_UE_OR_RETURN(&sps->log2_max_pic_order_cnt_lsb_minus4); | |
| 633 TRUE_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 < 13); | |
| 634 } else if (sps->pic_order_cnt_type == 1) { | |
| 635 READ_BOOL_OR_RETURN(&sps->delta_pic_order_always_zero_flag); | |
| 636 READ_SE_OR_RETURN(&sps->offset_for_non_ref_pic); | |
| 637 READ_SE_OR_RETURN(&sps->offset_for_top_to_bottom_field); | |
| 638 READ_UE_OR_RETURN(&sps->num_ref_frames_in_pic_order_cnt_cycle); | |
| 639 TRUE_OR_RETURN(sps->num_ref_frames_in_pic_order_cnt_cycle < 255); | |
| 640 | |
| 641 for (int i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) { | |
| 642 READ_SE_OR_RETURN(&sps->offset_for_ref_frame[i]); | |
| 643 sps->expected_delta_per_pic_order_cnt_cycle += | |
| 644 sps->offset_for_ref_frame[i]; | |
| 645 } | |
| 646 } | |
| 647 | |
| 648 READ_UE_OR_RETURN(&sps->max_num_ref_frames); | |
| 649 READ_BOOL_OR_RETURN(&sps->gaps_in_frame_num_value_allowed_flag); | |
| 650 | |
| 651 if (sps->gaps_in_frame_num_value_allowed_flag) | |
| 652 return kUnsupportedStream; | |
| 653 | |
| 654 READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1); | |
| 655 READ_UE_OR_RETURN(&sps->pic_height_in_map_units_minus1); | |
| 656 | |
| 657 READ_BOOL_OR_RETURN(&sps->frame_mbs_only_flag); | |
| 658 if (!sps->frame_mbs_only_flag) | |
| 659 READ_BOOL_OR_RETURN(&sps->mb_adaptive_frame_field_flag); | |
| 660 | |
| 661 READ_BOOL_OR_RETURN(&sps->direct_8x8_inference_flag); | |
| 662 | |
| 663 READ_BOOL_OR_RETURN(&sps->frame_cropping_flag); | |
| 664 if (sps->frame_cropping_flag) { | |
| 665 READ_UE_OR_RETURN(&sps->frame_crop_left_offset); | |
| 666 READ_UE_OR_RETURN(&sps->frame_crop_right_offset); | |
| 667 READ_UE_OR_RETURN(&sps->frame_crop_top_offset); | |
| 668 READ_UE_OR_RETURN(&sps->frame_crop_bottom_offset); | |
| 669 } | |
| 670 | |
| 671 READ_BOOL_OR_RETURN(&sps->vui_parameters_present_flag); | |
| 672 if (sps->vui_parameters_present_flag) { | |
| 673 DVLOG(1) << "VUI parameters present in SPS, ignoring"; | |
| 674 } | |
| 675 | |
| 676 // If an SPS with the same id already exists, replace it. | |
| 677 *sps_id = sps->seq_parameter_set_id; | |
| 678 delete active_SPSes_[*sps_id]; | |
| 679 active_SPSes_[*sps_id] = sps.release(); | |
| 680 | |
| 681 return kOk; | |
| 682 } | |
| 683 | |
| 684 H264Parser::Result H264Parser::ParsePPS(int* pps_id) { | |
| 685 // See 7.4.2.2. | |
| 686 const H264SPS* sps; | |
| 687 Result res; | |
| 688 | |
| 689 *pps_id = -1; | |
| 690 | |
| 691 scoped_ptr<H264PPS> pps(new H264PPS()); | |
| 692 | |
| 693 READ_UE_OR_RETURN(&pps->pic_parameter_set_id); | |
| 694 READ_UE_OR_RETURN(&pps->seq_parameter_set_id); | |
| 695 TRUE_OR_RETURN(pps->seq_parameter_set_id < 32); | |
| 696 | |
| 697 sps = GetSPS(pps->seq_parameter_set_id); | |
| 698 TRUE_OR_RETURN(sps); | |
| 699 | |
| 700 READ_BOOL_OR_RETURN(&pps->entropy_coding_mode_flag); | |
| 701 READ_BOOL_OR_RETURN(&pps->bottom_field_pic_order_in_frame_present_flag); | |
| 702 | |
| 703 READ_UE_OR_RETURN(&pps->num_slice_groups_minus1); | |
| 704 if (pps->num_slice_groups_minus1 > 1) { | |
| 705 DVLOG(1) << "Slice groups not supported"; | |
| 706 return kUnsupportedStream; | |
| 707 } | |
| 708 | |
| 709 READ_UE_OR_RETURN(&pps->num_ref_idx_l0_default_active_minus1); | |
| 710 TRUE_OR_RETURN(pps->num_ref_idx_l0_default_active_minus1 < 32); | |
| 711 | |
| 712 READ_UE_OR_RETURN(&pps->num_ref_idx_l1_default_active_minus1); | |
| 713 TRUE_OR_RETURN(pps->num_ref_idx_l1_default_active_minus1 < 32); | |
| 714 | |
| 715 READ_BOOL_OR_RETURN(&pps->weighted_pred_flag); | |
| 716 READ_BITS_OR_RETURN(2, &pps->weighted_bipred_idc); | |
| 717 TRUE_OR_RETURN(pps->weighted_bipred_idc < 3); | |
| 718 | |
| 719 READ_SE_OR_RETURN(&pps->pic_init_qp_minus26); | |
| 720 IN_RANGE_OR_RETURN(pps->pic_init_qp_minus26, -26, 25); | |
| 721 | |
| 722 READ_SE_OR_RETURN(&pps->pic_init_qs_minus26); | |
| 723 IN_RANGE_OR_RETURN(pps->pic_init_qs_minus26, -26, 25); | |
| 724 | |
| 725 READ_SE_OR_RETURN(&pps->chroma_qp_index_offset); | |
| 726 IN_RANGE_OR_RETURN(pps->chroma_qp_index_offset, -12, 12); | |
| 727 pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset; | |
| 728 | |
| 729 READ_BOOL_OR_RETURN(&pps->deblocking_filter_control_present_flag); | |
| 730 READ_BOOL_OR_RETURN(&pps->constrained_intra_pred_flag); | |
| 731 READ_BOOL_OR_RETURN(&pps->redundant_pic_cnt_present_flag); | |
| 732 | |
| 733 if (br_.HasMoreRBSPData()) { | |
| 734 READ_BOOL_OR_RETURN(&pps->transform_8x8_mode_flag); | |
| 735 READ_BOOL_OR_RETURN(&pps->pic_scaling_matrix_present_flag); | |
| 736 | |
| 737 if (pps->pic_scaling_matrix_present_flag) { | |
| 738 DVLOG(4) << "Picture scaling matrix present"; | |
| 739 res = ParsePPSScalingLists(*sps, pps.get()); | |
| 740 if (res != kOk) | |
| 741 return res; | |
| 742 } | |
| 743 | |
| 744 READ_SE_OR_RETURN(&pps->second_chroma_qp_index_offset); | |
| 745 } | |
| 746 | |
| 747 // If a PPS with the same id already exists, replace it. | |
| 748 *pps_id = pps->pic_parameter_set_id; | |
| 749 delete active_PPSes_[*pps_id]; | |
| 750 active_PPSes_[*pps_id] = pps.release(); | |
| 751 | |
| 752 return kOk; | |
| 753 } | |
| 754 | |
| 755 H264Parser::Result H264Parser::ParseRefPicListModification( | |
| 756 int num_ref_idx_active_minus1, | |
| 757 H264ModificationOfPicNum* ref_list_mods) { | |
| 758 H264ModificationOfPicNum* pic_num_mod; | |
| 759 | |
| 760 if (num_ref_idx_active_minus1 >= 32) | |
| 761 return kInvalidStream; | |
| 762 | |
| 763 for (int i = 0; i < 32; ++i) { | |
| 764 pic_num_mod = &ref_list_mods[i]; | |
| 765 READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc); | |
| 766 TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4); | |
| 767 | |
| 768 switch (pic_num_mod->modification_of_pic_nums_idc) { | |
| 769 case 0: | |
| 770 case 1: | |
| 771 READ_UE_OR_RETURN(&pic_num_mod->abs_diff_pic_num_minus1); | |
| 772 break; | |
| 773 | |
| 774 case 2: | |
| 775 READ_UE_OR_RETURN(&pic_num_mod->long_term_pic_num); | |
| 776 break; | |
| 777 | |
| 778 case 3: | |
| 779 // Per spec, list cannot be empty. | |
| 780 if (i == 0) | |
| 781 return kInvalidStream; | |
| 782 return kOk; | |
| 783 | |
| 784 default: | |
| 785 return kInvalidStream; | |
| 786 } | |
| 787 } | |
| 788 | |
| 789 // If we got here, we didn't get loop end marker prematurely, | |
| 790 // so make sure it is there for our client. | |
| 791 int modification_of_pic_nums_idc; | |
| 792 READ_UE_OR_RETURN(&modification_of_pic_nums_idc); | |
| 793 TRUE_OR_RETURN(modification_of_pic_nums_idc == 3); | |
| 794 | |
| 795 return kOk; | |
| 796 } | |
| 797 | |
| 798 H264Parser::Result H264Parser::ParseRefPicListModifications( | |
| 799 H264SliceHeader* shdr) { | |
| 800 Result res; | |
| 801 | |
| 802 if (!shdr->IsISlice() && !shdr->IsSISlice()) { | |
| 803 READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l0); | |
| 804 if (shdr->ref_pic_list_modification_flag_l0) { | |
| 805 res = ParseRefPicListModification(shdr->num_ref_idx_l0_active_minus1, | |
| 806 shdr->ref_list_l0_modifications); | |
| 807 if (res != kOk) | |
| 808 return res; | |
| 809 } | |
| 810 } | |
| 811 | |
| 812 if (shdr->IsBSlice()) { | |
| 813 READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l1); | |
| 814 if (shdr->ref_pic_list_modification_flag_l1) { | |
| 815 res = ParseRefPicListModification(shdr->num_ref_idx_l1_active_minus1, | |
| 816 shdr->ref_list_l1_modifications); | |
| 817 if (res != kOk) | |
| 818 return res; | |
| 819 } | |
| 820 } | |
| 821 | |
| 822 return kOk; | |
| 823 } | |
| 824 | |
| 825 H264Parser::Result H264Parser::ParseWeightingFactors( | |
| 826 int num_ref_idx_active_minus1, | |
| 827 int chroma_array_type, | |
| 828 int luma_log2_weight_denom, | |
| 829 int chroma_log2_weight_denom, | |
| 830 H264WeightingFactors* w_facts) { | |
| 831 | |
| 832 int def_luma_weight = 1 << luma_log2_weight_denom; | |
| 833 int def_chroma_weight = 1 << chroma_log2_weight_denom; | |
| 834 | |
| 835 for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) { | |
| 836 READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag); | |
| 837 if (w_facts->luma_weight_flag) { | |
| 838 READ_SE_OR_RETURN(&w_facts->luma_weight[i]); | |
| 839 IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127); | |
| 840 | |
| 841 READ_SE_OR_RETURN(&w_facts->luma_offset[i]); | |
| 842 IN_RANGE_OR_RETURN(w_facts->luma_offset[i], -128, 127); | |
| 843 } else { | |
| 844 w_facts->luma_weight[i] = def_luma_weight; | |
| 845 w_facts->luma_offset[i] = 0; | |
| 846 } | |
| 847 | |
| 848 if (chroma_array_type != 0) { | |
| 849 READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag); | |
| 850 if (w_facts->chroma_weight_flag) { | |
| 851 for (int j = 0; j < 2; ++j) { | |
| 852 READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]); | |
| 853 IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127); | |
| 854 | |
| 855 READ_SE_OR_RETURN(&w_facts->chroma_offset[i][j]); | |
| 856 IN_RANGE_OR_RETURN(w_facts->chroma_offset[i][j], -128, 127); | |
| 857 } | |
| 858 } else { | |
| 859 for (int j = 0; j < 2; ++j) { | |
| 860 w_facts->chroma_weight[i][j] = def_chroma_weight; | |
| 861 w_facts->chroma_offset[i][j] = 0; | |
| 862 } | |
| 863 } | |
| 864 } | |
| 865 } | |
| 866 | |
| 867 return kOk; | |
| 868 } | |
| 869 | |
| 870 H264Parser::Result H264Parser::ParsePredWeightTable(const H264SPS& sps, | |
| 871 H264SliceHeader* shdr) { | |
| 872 READ_UE_OR_RETURN(&shdr->luma_log2_weight_denom); | |
| 873 TRUE_OR_RETURN(shdr->luma_log2_weight_denom < 8); | |
| 874 | |
| 875 if (sps.chroma_array_type != 0) | |
| 876 READ_UE_OR_RETURN(&shdr->chroma_log2_weight_denom); | |
| 877 TRUE_OR_RETURN(shdr->chroma_log2_weight_denom < 8); | |
| 878 | |
| 879 Result res = ParseWeightingFactors(shdr->num_ref_idx_l0_active_minus1, | |
| 880 sps.chroma_array_type, | |
| 881 shdr->luma_log2_weight_denom, | |
| 882 shdr->chroma_log2_weight_denom, | |
| 883 &shdr->pred_weight_table_l0); | |
| 884 if (res != kOk) | |
| 885 return res; | |
| 886 | |
| 887 if (shdr->IsBSlice()) { | |
| 888 res = ParseWeightingFactors(shdr->num_ref_idx_l1_active_minus1, | |
| 889 sps.chroma_array_type, | |
| 890 shdr->luma_log2_weight_denom, | |
| 891 shdr->chroma_log2_weight_denom, | |
| 892 &shdr->pred_weight_table_l1); | |
| 893 if (res != kOk) | |
| 894 return res; | |
| 895 } | |
| 896 | |
| 897 return kOk; | |
| 898 } | |
| 899 | |
| 900 H264Parser::Result H264Parser::ParseDecRefPicMarking(H264SliceHeader *shdr) { | |
| 901 if (shdr->idr_pic_flag) { | |
| 902 READ_BOOL_OR_RETURN(&shdr->no_output_of_prior_pics_flag); | |
| 903 READ_BOOL_OR_RETURN(&shdr->long_term_reference_flag); | |
| 904 } else { | |
| 905 READ_BOOL_OR_RETURN(&shdr->adaptive_ref_pic_marking_mode_flag); | |
| 906 | |
| 907 H264DecRefPicMarking* marking; | |
| 908 if (shdr->adaptive_ref_pic_marking_mode_flag) { | |
| 909 size_t i; | |
| 910 for (i = 0; i < arraysize(shdr->ref_pic_marking); ++i) { | |
| 911 marking = &shdr->ref_pic_marking[i]; | |
| 912 | |
| 913 READ_UE_OR_RETURN(&marking->memory_mgmnt_control_operation); | |
| 914 if (marking->memory_mgmnt_control_operation == 0) | |
| 915 break; | |
| 916 | |
| 917 if (marking->memory_mgmnt_control_operation == 1 || | |
| 918 marking->memory_mgmnt_control_operation == 3) | |
| 919 READ_UE_OR_RETURN(&marking->difference_of_pic_nums_minus1); | |
| 920 | |
| 921 if (marking->memory_mgmnt_control_operation == 2) | |
| 922 READ_UE_OR_RETURN(&marking->long_term_pic_num); | |
| 923 | |
| 924 if (marking->memory_mgmnt_control_operation == 3 || | |
| 925 marking->memory_mgmnt_control_operation == 6) | |
| 926 READ_UE_OR_RETURN(&marking->long_term_frame_idx); | |
| 927 | |
| 928 if (marking->memory_mgmnt_control_operation == 4) | |
| 929 READ_UE_OR_RETURN(&marking->max_long_term_frame_idx_plus1); | |
| 930 | |
| 931 if (marking->memory_mgmnt_control_operation > 6) | |
| 932 return kInvalidStream; | |
| 933 } | |
| 934 | |
| 935 if (i == arraysize(shdr->ref_pic_marking)) { | |
| 936 DVLOG(1) << "Ran out of dec ref pic marking fields"; | |
| 937 return kUnsupportedStream; | |
| 938 } | |
| 939 } | |
| 940 } | |
| 941 | |
| 942 return kOk; | |
| 943 } | |
| 944 | |
| 945 H264Parser::Result H264Parser::ParseSliceHeader(const H264NALU& nalu, | |
| 946 H264SliceHeader* shdr) { | |
| 947 // See 7.4.3. | |
| 948 const H264SPS* sps; | |
| 949 const H264PPS* pps; | |
| 950 Result res; | |
| 951 | |
| 952 memset(shdr, 0, sizeof(*shdr)); | |
| 953 | |
| 954 shdr->idr_pic_flag = (nalu.nal_unit_type == 5); | |
| 955 shdr->nal_ref_idc = nalu.nal_ref_idc; | |
| 956 shdr->nalu_data = nalu.data; | |
| 957 shdr->nalu_size = nalu.size; | |
| 958 | |
| 959 READ_UE_OR_RETURN(&shdr->first_mb_in_slice); | |
| 960 READ_UE_OR_RETURN(&shdr->slice_type); | |
| 961 TRUE_OR_RETURN(shdr->slice_type < 10); | |
| 962 | |
| 963 READ_UE_OR_RETURN(&shdr->pic_parameter_set_id); | |
| 964 | |
| 965 pps = GetPPS(shdr->pic_parameter_set_id); | |
| 966 TRUE_OR_RETURN(pps); | |
| 967 | |
| 968 sps = GetSPS(pps->seq_parameter_set_id); | |
| 969 TRUE_OR_RETURN(sps); | |
| 970 | |
| 971 if (sps->separate_colour_plane_flag) { | |
| 972 DVLOG(1) << "Interlaced streams not supported"; | |
| 973 return kUnsupportedStream; | |
| 974 } | |
| 975 | |
| 976 READ_BITS_OR_RETURN(sps->log2_max_frame_num_minus4 + 4, | |
| 977 &shdr->frame_num); | |
| 978 if (!sps->frame_mbs_only_flag) { | |
| 979 READ_BOOL_OR_RETURN(&shdr->field_pic_flag); | |
| 980 if (shdr->field_pic_flag) { | |
| 981 DVLOG(1) << "Interlaced streams not supported"; | |
| 982 return kUnsupportedStream; | |
| 983 } | |
| 984 } | |
| 985 | |
| 986 if (shdr->idr_pic_flag) | |
| 987 READ_UE_OR_RETURN(&shdr->idr_pic_id); | |
| 988 | |
| 989 if (sps->pic_order_cnt_type == 0) { | |
| 990 READ_BITS_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, | |
| 991 &shdr->pic_order_cnt_lsb); | |
| 992 if (pps->bottom_field_pic_order_in_frame_present_flag && | |
| 993 !shdr->field_pic_flag) | |
| 994 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt_bottom); | |
| 995 } | |
| 996 | |
| 997 if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) { | |
| 998 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[0]); | |
| 999 if (pps->bottom_field_pic_order_in_frame_present_flag && | |
| 1000 !shdr->field_pic_flag) | |
| 1001 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[1]); | |
| 1002 } | |
| 1003 | |
| 1004 if (pps->redundant_pic_cnt_present_flag) { | |
| 1005 READ_UE_OR_RETURN(&shdr->redundant_pic_cnt); | |
| 1006 TRUE_OR_RETURN(shdr->redundant_pic_cnt < 128); | |
| 1007 } | |
| 1008 | |
| 1009 if (shdr->IsBSlice()) | |
| 1010 READ_BOOL_OR_RETURN(&shdr->direct_spatial_mv_pred_flag); | |
| 1011 | |
| 1012 if (shdr->IsPSlice() || shdr->IsSPSlice() || shdr->IsBSlice()) { | |
| 1013 READ_BOOL_OR_RETURN(&shdr->num_ref_idx_active_override_flag); | |
| 1014 if (shdr->num_ref_idx_active_override_flag) { | |
| 1015 READ_UE_OR_RETURN(&shdr->num_ref_idx_l0_active_minus1); | |
| 1016 if (shdr->IsBSlice()) | |
| 1017 READ_UE_OR_RETURN(&shdr->num_ref_idx_l1_active_minus1); | |
| 1018 } else { | |
| 1019 shdr->num_ref_idx_l0_active_minus1 = | |
| 1020 pps->num_ref_idx_l0_default_active_minus1; | |
| 1021 if (shdr->IsBSlice()) { | |
| 1022 shdr->num_ref_idx_l1_active_minus1 = | |
| 1023 pps->num_ref_idx_l1_default_active_minus1; | |
| 1024 } | |
| 1025 } | |
| 1026 } | |
| 1027 if (shdr->field_pic_flag) { | |
| 1028 TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 32); | |
| 1029 TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 32); | |
| 1030 } else { | |
| 1031 TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 16); | |
| 1032 TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 16); | |
| 1033 } | |
| 1034 | |
| 1035 if (nalu.nal_unit_type == H264NALU::kCodedSliceExtension) { | |
| 1036 return kUnsupportedStream; | |
| 1037 } else { | |
| 1038 res = ParseRefPicListModifications(shdr); | |
| 1039 if (res != kOk) | |
| 1040 return res; | |
| 1041 } | |
| 1042 | |
| 1043 if ((pps->weighted_pred_flag && (shdr->IsPSlice() || shdr->IsSPSlice())) || | |
| 1044 (pps->weighted_bipred_idc == 1 && shdr->IsBSlice())) { | |
| 1045 res = ParsePredWeightTable(*sps, shdr); | |
| 1046 if (res != kOk) | |
| 1047 return res; | |
| 1048 } | |
| 1049 | |
| 1050 if (nalu.nal_ref_idc != 0) { | |
| 1051 res = ParseDecRefPicMarking(shdr); | |
| 1052 if (res != kOk) | |
| 1053 return res; | |
| 1054 } | |
| 1055 | |
| 1056 if (pps->entropy_coding_mode_flag && | |
| 1057 !shdr->IsISlice() && !shdr->IsSISlice()) { | |
| 1058 READ_UE_OR_RETURN(&shdr->cabac_init_idc); | |
| 1059 TRUE_OR_RETURN(shdr->cabac_init_idc < 3); | |
| 1060 } | |
| 1061 | |
| 1062 READ_SE_OR_RETURN(&shdr->slice_qp_delta); | |
| 1063 | |
| 1064 if (shdr->IsSPSlice() || shdr->IsSISlice()) { | |
| 1065 if (shdr->IsSPSlice()) | |
| 1066 READ_BOOL_OR_RETURN(&shdr->sp_for_switch_flag); | |
| 1067 READ_SE_OR_RETURN(&shdr->slice_qs_delta); | |
| 1068 } | |
| 1069 | |
| 1070 if (pps->deblocking_filter_control_present_flag) { | |
| 1071 READ_UE_OR_RETURN(&shdr->disable_deblocking_filter_idc); | |
| 1072 TRUE_OR_RETURN(shdr->disable_deblocking_filter_idc < 3); | |
| 1073 | |
| 1074 if (shdr->disable_deblocking_filter_idc != 1) { | |
| 1075 READ_SE_OR_RETURN(&shdr->slice_alpha_c0_offset_div2); | |
| 1076 IN_RANGE_OR_RETURN(shdr->slice_alpha_c0_offset_div2, -6, 6); | |
| 1077 | |
| 1078 READ_SE_OR_RETURN(&shdr->slice_beta_offset_div2); | |
| 1079 IN_RANGE_OR_RETURN(shdr->slice_beta_offset_div2, -6, 6); | |
| 1080 } | |
| 1081 } | |
| 1082 | |
| 1083 if (pps->num_slice_groups_minus1 > 0) { | |
| 1084 DVLOG(1) << "Slice groups not supported"; | |
| 1085 return kUnsupportedStream; | |
| 1086 } | |
| 1087 | |
| 1088 size_t epb = br_.NumEmulationPreventionBytesRead(); | |
| 1089 shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br_.NumBitsLeft(); | |
| 1090 | |
| 1091 return kOk; | |
| 1092 } | |
| 1093 | |
| 1094 H264Parser::Result H264Parser::ParseSEI(H264SEIMessage* sei_msg) { | |
| 1095 int byte; | |
| 1096 | |
| 1097 memset(sei_msg, 0, sizeof(*sei_msg)); | |
| 1098 | |
| 1099 READ_BITS_OR_RETURN(8, &byte); | |
| 1100 while (byte == 0xff) { | |
| 1101 sei_msg->type += 255; | |
| 1102 READ_BITS_OR_RETURN(8, &byte); | |
| 1103 } | |
| 1104 sei_msg->type += byte; | |
| 1105 | |
| 1106 READ_BITS_OR_RETURN(8, &byte); | |
| 1107 while (byte == 0xff) { | |
| 1108 sei_msg->payload_size += 255; | |
| 1109 READ_BITS_OR_RETURN(8, &byte); | |
| 1110 } | |
| 1111 sei_msg->payload_size += byte; | |
| 1112 | |
| 1113 DVLOG(4) << "Found SEI message type: " << sei_msg->type | |
| 1114 << " payload size: " << sei_msg->payload_size; | |
| 1115 | |
| 1116 switch (sei_msg->type) { | |
| 1117 case H264SEIMessage::kSEIRecoveryPoint: | |
| 1118 READ_UE_OR_RETURN(&sei_msg->recovery_point.recovery_frame_cnt); | |
| 1119 READ_BOOL_OR_RETURN(&sei_msg->recovery_point.exact_match_flag); | |
| 1120 READ_BOOL_OR_RETURN(&sei_msg->recovery_point.broken_link_flag); | |
| 1121 READ_BITS_OR_RETURN(2, | |
| 1122 &sei_msg->recovery_point.changing_slice_group_idc); | |
| 1123 break; | |
| 1124 | |
| 1125 default: | |
| 1126 DVLOG(4) << "Unsupported SEI message"; | |
| 1127 break; | |
| 1128 } | |
| 1129 | |
| 1130 return kOk; | |
| 1131 } | |
| 1132 | |
| 1133 } // namespace content | |
| OLD | NEW |