github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/h265/sps.go (about) 1 package h265 2 3 import ( 4 "fmt" 5 6 "github.com/bluenviron/mediacommon/pkg/bits" 7 "github.com/bluenviron/mediacommon/pkg/codecs/h264" 8 ) 9 10 const ( 11 maxNegativePics = 255 12 maxPositivePics = 255 13 maxShortTermRefPics = 64 14 ) 15 16 var subWidthC = []uint32{ 17 1, 18 2, 19 2, 20 1, 21 } 22 23 var subHeightC = []uint32{ 24 1, 25 2, 26 1, 27 1, 28 } 29 30 // SPS_DefaultDisplayWindow is a default display window. 31 type SPS_DefaultDisplayWindow struct { //nolint:revive 32 LeftOffset uint32 33 RightOffset uint32 34 TopOffset uint32 35 BottomOffset uint32 36 } 37 38 func (w *SPS_DefaultDisplayWindow) unmarshal(buf []byte, pos *int) error { 39 var err error 40 w.LeftOffset, err = bits.ReadGolombUnsigned(buf, pos) 41 if err != nil { 42 return err 43 } 44 45 w.RightOffset, err = bits.ReadGolombUnsigned(buf, pos) 46 if err != nil { 47 return err 48 } 49 50 w.TopOffset, err = bits.ReadGolombUnsigned(buf, pos) 51 if err != nil { 52 return err 53 } 54 55 w.BottomOffset, err = bits.ReadGolombUnsigned(buf, pos) 56 if err != nil { 57 return err 58 } 59 60 return nil 61 } 62 63 // SPS_TimingInfo is a timing info. 64 type SPS_TimingInfo struct { //nolint:revive 65 NumUnitsInTick uint32 66 TimeScale uint32 67 POCProportionalToTimingFlag bool 68 69 // POCProportionalToTimingFlag == true 70 NumTicksPOCDiffOneMinus1 uint32 71 } 72 73 func (t *SPS_TimingInfo) unmarshal(buf []byte, pos *int) error { 74 err := bits.HasSpace(buf, *pos, 32+32+1) 75 if err != nil { 76 return err 77 } 78 79 t.NumUnitsInTick = uint32(bits.ReadBitsUnsafe(buf, pos, 32)) 80 t.TimeScale = uint32(bits.ReadBitsUnsafe(buf, pos, 32)) 81 t.POCProportionalToTimingFlag = bits.ReadFlagUnsafe(buf, pos) 82 83 if t.POCProportionalToTimingFlag { 84 t.NumTicksPOCDiffOneMinus1, err = bits.ReadGolombUnsigned(buf, pos) 85 if err != nil { 86 return err 87 } 88 } 89 90 return nil 91 } 92 93 // SPS_VUI is a video usability information. 94 type SPS_VUI struct { //nolint:revive 95 AspectRatioInfoPresentFlag bool 96 97 // AspectRatioInfoPresentFlag == true 98 AspectRatioIdc uint8 99 SarWidth uint16 100 SarHeight uint16 101 102 OverscanInfoPresentFlag bool 103 104 // OverscanInfoPresentFlag == true 105 OverscanAppropriateFlag bool 106 VideoSignalTypePresentFlag bool 107 108 // VideoSignalTypePresentFlag == true 109 VideoFormat uint8 110 VideoFullRangeFlag bool 111 ColourDescriptionPresentFlag bool 112 113 // ColourDescriptionPresentFlag == true 114 ColourPrimaries uint8 115 TransferCharacteristics uint8 116 MatrixCoefficients uint8 117 118 ChromaLocInfoPresentFlag bool 119 120 // ChromaLocInfoPresentFlag == true 121 ChromaSampleLocTypeTopField uint32 122 ChromaSampleLocTypeBottomField uint32 123 124 NeutralChromaIndicationFlag bool 125 FieldSeqFlag bool 126 FrameFieldInfoPresentFlag bool 127 DefaultDisplayWindow *SPS_DefaultDisplayWindow 128 TimingInfo *SPS_TimingInfo 129 } 130 131 func (v *SPS_VUI) unmarshal(buf []byte, pos *int) error { 132 var err error 133 v.AspectRatioInfoPresentFlag, err = bits.ReadFlag(buf, pos) 134 if err != nil { 135 return err 136 } 137 138 if v.AspectRatioInfoPresentFlag { 139 tmp, err := bits.ReadBits(buf, pos, 8) 140 if err != nil { 141 return err 142 } 143 v.AspectRatioIdc = uint8(tmp) 144 145 if v.AspectRatioIdc == 255 { // EXTENDED_SAR 146 err := bits.HasSpace(buf, *pos, 32) 147 if err != nil { 148 return err 149 } 150 151 v.SarWidth = uint16(bits.ReadBitsUnsafe(buf, pos, 16)) 152 v.SarHeight = uint16(bits.ReadBitsUnsafe(buf, pos, 16)) 153 } 154 } 155 156 v.OverscanInfoPresentFlag, err = bits.ReadFlag(buf, pos) 157 if err != nil { 158 return err 159 } 160 161 if v.OverscanInfoPresentFlag { 162 v.OverscanAppropriateFlag, err = bits.ReadFlag(buf, pos) 163 if err != nil { 164 return err 165 } 166 } 167 168 v.VideoSignalTypePresentFlag, err = bits.ReadFlag(buf, pos) 169 if err != nil { 170 return err 171 } 172 173 if v.VideoSignalTypePresentFlag { 174 err := bits.HasSpace(buf, *pos, 5) 175 if err != nil { 176 return err 177 } 178 179 v.VideoFormat = uint8(bits.ReadBitsUnsafe(buf, pos, 3)) 180 v.VideoFullRangeFlag = bits.ReadFlagUnsafe(buf, pos) 181 v.ColourDescriptionPresentFlag = bits.ReadFlagUnsafe(buf, pos) 182 183 if v.ColourDescriptionPresentFlag { 184 err := bits.HasSpace(buf, *pos, 24) 185 if err != nil { 186 return err 187 } 188 189 v.ColourPrimaries = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) 190 v.TransferCharacteristics = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) 191 v.MatrixCoefficients = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) 192 } 193 } 194 195 v.ChromaLocInfoPresentFlag, err = bits.ReadFlag(buf, pos) 196 if err != nil { 197 return err 198 } 199 200 if v.ChromaLocInfoPresentFlag { 201 v.ChromaSampleLocTypeTopField, err = bits.ReadGolombUnsigned(buf, pos) 202 if err != nil { 203 return err 204 } 205 206 v.ChromaSampleLocTypeBottomField, err = bits.ReadGolombUnsigned(buf, pos) 207 if err != nil { 208 return err 209 } 210 } 211 212 v.NeutralChromaIndicationFlag, err = bits.ReadFlag(buf, pos) 213 if err != nil { 214 return err 215 } 216 217 v.FieldSeqFlag, err = bits.ReadFlag(buf, pos) 218 if err != nil { 219 return err 220 } 221 222 v.FrameFieldInfoPresentFlag, err = bits.ReadFlag(buf, pos) 223 if err != nil { 224 return err 225 } 226 227 defaultDisplayWindowFlag, err := bits.ReadFlag(buf, pos) 228 if err != nil { 229 return err 230 } 231 232 if defaultDisplayWindowFlag { 233 v.DefaultDisplayWindow = &SPS_DefaultDisplayWindow{} 234 err := v.DefaultDisplayWindow.unmarshal(buf, pos) 235 if err != nil { 236 return err 237 } 238 } else { 239 v.DefaultDisplayWindow = nil 240 } 241 242 timingInfoPresentFlag, err := bits.ReadFlag(buf, pos) 243 if err != nil { 244 return err 245 } 246 247 if timingInfoPresentFlag { 248 v.TimingInfo = &SPS_TimingInfo{} 249 err := v.TimingInfo.unmarshal(buf, pos) 250 if err != nil { 251 return err 252 } 253 } else { 254 v.TimingInfo = nil 255 } 256 257 return nil 258 } 259 260 // SPS_ProfileTierLevel is a profile level tier of a SPS. 261 type SPS_ProfileTierLevel struct { //nolint:revive 262 GeneralProfileSpace uint8 263 GeneralTierFlag uint8 264 GeneralProfileIdc uint8 265 GeneralProfileCompatibilityFlag [32]bool 266 GeneralProgressiveSourceFlag bool 267 GeneralInterlacedSourceFlag bool 268 GeneralNonPackedConstraintFlag bool 269 GeneralFrameOnlyConstraintFlag bool 270 GeneralMax12bitConstraintFlag bool 271 GeneralMax10bitConstraintFlag bool 272 GeneralMax8bitConstraintFlag bool 273 GeneralMax422ChromeConstraintFlag bool 274 GeneralMax420ChromaConstraintFlag bool 275 GeneralMaxMonochromeConstraintFlag bool 276 GeneralIntraConstraintFlag bool 277 GeneralOnePictureOnlyConstraintFlag bool 278 GeneralLowerBitRateConstraintFlag bool 279 GeneralMax14BitConstraintFlag bool 280 GeneralLevelIdc uint8 281 SubLayerProfilePresentFlag []bool 282 SubLayerLevelPresentFlag []bool 283 } 284 285 func (p *SPS_ProfileTierLevel) unmarshal(buf []byte, pos *int, maxSubLayersMinus1 uint8) error { 286 err := bits.HasSpace(buf, *pos, 8+32+12+34+8) 287 if err != nil { 288 return err 289 } 290 291 p.GeneralProfileSpace = uint8(bits.ReadBitsUnsafe(buf, pos, 2)) 292 p.GeneralTierFlag = uint8(bits.ReadBitsUnsafe(buf, pos, 1)) 293 p.GeneralProfileIdc = uint8(bits.ReadBitsUnsafe(buf, pos, 5)) 294 295 for j := 0; j < 32; j++ { 296 p.GeneralProfileCompatibilityFlag[j] = bits.ReadFlagUnsafe(buf, pos) 297 } 298 299 p.GeneralProgressiveSourceFlag = bits.ReadFlagUnsafe(buf, pos) 300 p.GeneralInterlacedSourceFlag = bits.ReadFlagUnsafe(buf, pos) 301 p.GeneralNonPackedConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 302 p.GeneralFrameOnlyConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 303 p.GeneralMax12bitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 304 p.GeneralMax10bitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 305 p.GeneralMax8bitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 306 p.GeneralMax422ChromeConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 307 p.GeneralMax420ChromaConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 308 p.GeneralMaxMonochromeConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 309 p.GeneralIntraConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 310 p.GeneralOnePictureOnlyConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 311 p.GeneralLowerBitRateConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 312 313 if p.GeneralProfileIdc == 5 || 314 p.GeneralProfileIdc == 9 || 315 p.GeneralProfileIdc == 10 || 316 p.GeneralProfileIdc == 11 || 317 p.GeneralProfileCompatibilityFlag[5] || 318 p.GeneralProfileCompatibilityFlag[9] || 319 p.GeneralProfileCompatibilityFlag[10] || 320 p.GeneralProfileCompatibilityFlag[11] { 321 p.GeneralMax14BitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) 322 *pos += 34 323 } else { 324 *pos += 35 325 } 326 327 p.GeneralLevelIdc = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) 328 329 if maxSubLayersMinus1 > 0 { 330 p.SubLayerProfilePresentFlag = make([]bool, maxSubLayersMinus1) 331 p.SubLayerLevelPresentFlag = make([]bool, maxSubLayersMinus1) 332 333 err := bits.HasSpace(buf, *pos, int(2*maxSubLayersMinus1)) 334 if err != nil { 335 return err 336 } 337 338 for j := uint8(0); j < maxSubLayersMinus1; j++ { 339 p.SubLayerProfilePresentFlag[j] = bits.ReadFlagUnsafe(buf, pos) 340 p.SubLayerLevelPresentFlag[j] = bits.ReadFlagUnsafe(buf, pos) 341 } 342 } 343 344 if maxSubLayersMinus1 > 0 { 345 err := bits.HasSpace(buf, *pos, int(8-maxSubLayersMinus1)*2) 346 if err != nil { 347 return err 348 } 349 350 *pos += int(8-maxSubLayersMinus1) * 2 351 } 352 353 for i := uint8(0); i < maxSubLayersMinus1; i++ { 354 if p.SubLayerProfilePresentFlag[i] { 355 return fmt.Errorf("SubLayerProfilePresentFlag not supported yet") 356 } 357 358 if p.SubLayerLevelPresentFlag[i] { 359 return fmt.Errorf("SubLayerLevelPresentFlag not supported yet") 360 } 361 } 362 363 return nil 364 } 365 366 // SPS_ConformanceWindow is a conformance window of a SPS. 367 type SPS_ConformanceWindow struct { //nolint:revive 368 LeftOffset uint32 369 RightOffset uint32 370 TopOffset uint32 371 BottomOffset uint32 372 } 373 374 func (c *SPS_ConformanceWindow) unmarshal(buf []byte, pos *int) error { 375 var err error 376 c.LeftOffset, err = bits.ReadGolombUnsigned(buf, pos) 377 if err != nil { 378 return err 379 } 380 381 c.RightOffset, err = bits.ReadGolombUnsigned(buf, pos) 382 if err != nil { 383 return err 384 } 385 386 c.TopOffset, err = bits.ReadGolombUnsigned(buf, pos) 387 if err != nil { 388 return err 389 } 390 391 c.BottomOffset, err = bits.ReadGolombUnsigned(buf, pos) 392 if err != nil { 393 return err 394 } 395 396 return nil 397 } 398 399 // SPS_ShortTermRefPicSet is a short-term reference picture set. 400 type SPS_ShortTermRefPicSet struct { //nolint:revive 401 InterRefPicSetPredictionFlag bool 402 DeltaIdxMinus1 uint32 403 DeltaRpsSign bool 404 AbsDeltaRpsMinus1 uint32 405 NumNegativePics uint32 406 NumPositivePics uint32 407 DeltaPocS0Minus1 []uint32 408 UsedByCurrPicS0Flag []bool 409 DeltaPocS1Minus1 []uint32 410 UsedByCurrPicS1Flag []bool 411 } 412 413 func (r *SPS_ShortTermRefPicSet) unmarshal(buf []byte, pos *int, stRpsIdx uint32, 414 numShortTermRefPicSets uint32, shortTermRefPicSets []*SPS_ShortTermRefPicSet, 415 ) error { 416 var err error 417 418 if stRpsIdx != 0 { 419 r.InterRefPicSetPredictionFlag, err = bits.ReadFlag(buf, pos) 420 if err != nil { 421 return err 422 } 423 } 424 425 if r.InterRefPicSetPredictionFlag { 426 if stRpsIdx == numShortTermRefPicSets { 427 r.DeltaIdxMinus1, err = bits.ReadGolombUnsigned(buf, pos) 428 if err != nil { 429 return err 430 } 431 } 432 433 r.DeltaRpsSign, err = bits.ReadFlag(buf, pos) 434 if err != nil { 435 return err 436 } 437 438 r.AbsDeltaRpsMinus1, err = bits.ReadGolombUnsigned(buf, pos) 439 if err != nil { 440 return err 441 } 442 443 refRpsIdx := stRpsIdx - (r.DeltaIdxMinus1 + 1) 444 numDeltaPocs := shortTermRefPicSets[refRpsIdx].NumNegativePics + shortTermRefPicSets[refRpsIdx].NumPositivePics 445 446 for j := uint32(0); j <= numDeltaPocs; j++ { 447 usedByCurrPicFlag, err := bits.ReadFlag(buf, pos) 448 if err != nil { 449 return err 450 } 451 452 if usedByCurrPicFlag { 453 _, err := bits.ReadGolombUnsigned(buf, pos) // use_delta_flag 454 if err != nil { 455 return err 456 } 457 } 458 } 459 } else { 460 r.NumNegativePics, err = bits.ReadGolombUnsigned(buf, pos) 461 if err != nil { 462 return err 463 } 464 465 r.NumPositivePics, err = bits.ReadGolombUnsigned(buf, pos) 466 if err != nil { 467 return err 468 } 469 470 if r.NumNegativePics > 0 { 471 if r.NumNegativePics > maxNegativePics { 472 return fmt.Errorf("num_negative_pics exceeds %d", maxNegativePics) 473 } 474 475 r.DeltaPocS0Minus1 = make([]uint32, r.NumNegativePics) 476 r.UsedByCurrPicS0Flag = make([]bool, r.NumNegativePics) 477 478 for i := uint32(0); i < r.NumNegativePics; i++ { 479 r.DeltaPocS0Minus1[i], err = bits.ReadGolombUnsigned(buf, pos) 480 if err != nil { 481 return err 482 } 483 484 r.UsedByCurrPicS0Flag[i], err = bits.ReadFlag(buf, pos) 485 if err != nil { 486 return err 487 } 488 } 489 } 490 491 if r.NumPositivePics > 0 { 492 if r.NumPositivePics > maxPositivePics { 493 return fmt.Errorf("num_positive_pics exceeds %d", maxPositivePics) 494 } 495 496 r.DeltaPocS1Minus1 = make([]uint32, r.NumPositivePics) 497 r.UsedByCurrPicS1Flag = make([]bool, r.NumPositivePics) 498 499 for i := uint32(0); i < r.NumPositivePics; i++ { 500 r.DeltaPocS1Minus1[i], err = bits.ReadGolombUnsigned(buf, pos) 501 if err != nil { 502 return err 503 } 504 505 r.UsedByCurrPicS1Flag[i], err = bits.ReadFlag(buf, pos) 506 if err != nil { 507 return err 508 } 509 } 510 } 511 } 512 513 return nil 514 } 515 516 // SPS is a H265 sequence parameter set. 517 // Specification: ITU-T Rec. H.265, 7.3.2.2.1 518 type SPS struct { 519 VPSID uint8 520 MaxSubLayersMinus1 uint8 521 TemporalIDNestingFlag bool 522 ProfileTierLevel SPS_ProfileTierLevel 523 ID uint8 524 ChromaFormatIdc uint32 525 SeparateColourPlaneFlag bool 526 PicWidthInLumaSamples uint32 527 PicHeightInLumaSamples uint32 528 ConformanceWindow *SPS_ConformanceWindow 529 BitDepthLumaMinus8 uint32 530 BitDepthChromaMinus8 uint32 531 Log2MaxPicOrderCntLsbMinus4 uint32 532 SubLayerOrderingInfoPresentFlag bool 533 MaxDecPicBufferingMinus1 []uint32 534 MaxNumReorderPics []uint32 535 MaxLatencyIncreasePlus1 []uint32 536 Log2MinLumaCodingBlockSizeMinus3 uint32 537 Log2DiffMaxMinLumaCodingBlockSize uint32 538 Log2MinLumaTransformBlockSizeMinus2 uint32 539 Log2DiffMaxMinLumaTransformBlockSize uint32 540 MaxTransformHierarchyDepthInter uint32 541 MaxTransformHierarchyDepthIntra uint32 542 ScalingListEnabledFlag bool 543 ScalingListDataPresentFlag bool 544 AmpEnabledFlag bool 545 SampleAdaptiveOffsetEnabledFlag bool 546 PcmEnabledFlag bool 547 548 // PcmEnabledFlag == true 549 PcmSampleBitDepthLumaMinus1 uint8 550 PcmSampleBitDepthChromaMinus1 uint8 551 Log2MinPcmLumaCodingBlockSizeMinus3 uint32 552 Log2DiffMaxMinPcmLumaCodingBlockSize uint32 553 PcmLoopFilterDisabledFlag bool 554 555 ShortTermRefPicSets []*SPS_ShortTermRefPicSet 556 LongTermRefPicsPresentFlag bool 557 TemporalMvpEnabledFlag bool 558 StrongIntraSmoothingEnabledFlag bool 559 VUI *SPS_VUI 560 } 561 562 // Unmarshal decodes a SPS from bytes. 563 func (s *SPS) Unmarshal(buf []byte) error { 564 if len(buf) < 2 { 565 return fmt.Errorf("not enough bits") 566 } 567 568 if NALUType((buf[0]>>1)&0b111111) != NALUType_SPS_NUT { 569 return fmt.Errorf("not a SPS") 570 } 571 572 buf = h264.EmulationPreventionRemove(buf[1:]) 573 pos := 8 574 575 err := bits.HasSpace(buf, pos, 8) 576 if err != nil { 577 return err 578 } 579 580 s.VPSID = uint8(bits.ReadBitsUnsafe(buf, &pos, 4)) 581 s.MaxSubLayersMinus1 = uint8(bits.ReadBitsUnsafe(buf, &pos, 3)) 582 s.TemporalIDNestingFlag = bits.ReadFlagUnsafe(buf, &pos) 583 584 err = s.ProfileTierLevel.unmarshal(buf, &pos, s.MaxSubLayersMinus1) 585 if err != nil { 586 return err 587 } 588 589 tmp2, err := bits.ReadGolombUnsigned(buf, &pos) 590 if err != nil { 591 return err 592 } 593 s.ID = uint8(tmp2) 594 595 s.ChromaFormatIdc, err = bits.ReadGolombUnsigned(buf, &pos) 596 if err != nil { 597 return err 598 } 599 600 if s.ChromaFormatIdc == 3 { 601 s.SeparateColourPlaneFlag, err = bits.ReadFlag(buf, &pos) 602 if err != nil { 603 return err 604 } 605 } 606 607 s.PicWidthInLumaSamples, err = bits.ReadGolombUnsigned(buf, &pos) 608 if err != nil { 609 return err 610 } 611 612 s.PicHeightInLumaSamples, err = bits.ReadGolombUnsigned(buf, &pos) 613 if err != nil { 614 return err 615 } 616 617 conformanceWindowFlag, err := bits.ReadFlag(buf, &pos) 618 if err != nil { 619 return err 620 } 621 622 if conformanceWindowFlag { 623 s.ConformanceWindow = &SPS_ConformanceWindow{} 624 err := s.ConformanceWindow.unmarshal(buf, &pos) 625 if err != nil { 626 return err 627 } 628 } else { 629 s.ConformanceWindow = nil 630 } 631 632 s.BitDepthLumaMinus8, err = bits.ReadGolombUnsigned(buf, &pos) 633 if err != nil { 634 return err 635 } 636 637 s.BitDepthChromaMinus8, err = bits.ReadGolombUnsigned(buf, &pos) 638 if err != nil { 639 return err 640 } 641 642 s.Log2MaxPicOrderCntLsbMinus4, err = bits.ReadGolombUnsigned(buf, &pos) 643 if err != nil { 644 return err 645 } 646 647 s.SubLayerOrderingInfoPresentFlag, err = bits.ReadFlag(buf, &pos) 648 if err != nil { 649 return err 650 } 651 652 var start uint8 653 if s.SubLayerOrderingInfoPresentFlag { 654 start = 0 655 } else { 656 start = s.MaxSubLayersMinus1 657 } 658 659 s.MaxDecPicBufferingMinus1 = make([]uint32, s.MaxSubLayersMinus1+1) 660 s.MaxNumReorderPics = make([]uint32, s.MaxSubLayersMinus1+1) 661 s.MaxLatencyIncreasePlus1 = make([]uint32, s.MaxSubLayersMinus1+1) 662 663 for i := start; i <= s.MaxSubLayersMinus1; i++ { 664 s.MaxDecPicBufferingMinus1[i], err = bits.ReadGolombUnsigned(buf, &pos) 665 if err != nil { 666 return err 667 } 668 669 s.MaxNumReorderPics[i], err = bits.ReadGolombUnsigned(buf, &pos) 670 if err != nil { 671 return err 672 } 673 674 s.MaxLatencyIncreasePlus1[i], err = bits.ReadGolombUnsigned(buf, &pos) 675 if err != nil { 676 return err 677 } 678 } 679 680 s.Log2MinLumaCodingBlockSizeMinus3, err = bits.ReadGolombUnsigned(buf, &pos) 681 if err != nil { 682 return err 683 } 684 685 s.Log2DiffMaxMinLumaCodingBlockSize, err = bits.ReadGolombUnsigned(buf, &pos) 686 if err != nil { 687 return err 688 } 689 690 s.Log2MinLumaTransformBlockSizeMinus2, err = bits.ReadGolombUnsigned(buf, &pos) 691 if err != nil { 692 return err 693 } 694 695 s.Log2DiffMaxMinLumaTransformBlockSize, err = bits.ReadGolombUnsigned(buf, &pos) 696 if err != nil { 697 return err 698 } 699 700 s.MaxTransformHierarchyDepthInter, err = bits.ReadGolombUnsigned(buf, &pos) 701 if err != nil { 702 return err 703 } 704 705 s.MaxTransformHierarchyDepthIntra, err = bits.ReadGolombUnsigned(buf, &pos) 706 if err != nil { 707 return err 708 } 709 710 s.ScalingListEnabledFlag, err = bits.ReadFlag(buf, &pos) 711 if err != nil { 712 return err 713 } 714 715 if s.ScalingListEnabledFlag { 716 s.ScalingListDataPresentFlag, err = bits.ReadFlag(buf, &pos) 717 if err != nil { 718 return err 719 } 720 721 if s.ScalingListDataPresentFlag { 722 return fmt.Errorf("ScalingListDataPresentFlag not supported yet") 723 } 724 } 725 726 s.AmpEnabledFlag, err = bits.ReadFlag(buf, &pos) 727 if err != nil { 728 return err 729 } 730 731 s.SampleAdaptiveOffsetEnabledFlag, err = bits.ReadFlag(buf, &pos) 732 if err != nil { 733 return err 734 } 735 736 s.PcmEnabledFlag, err = bits.ReadFlag(buf, &pos) 737 if err != nil { 738 return err 739 } 740 741 if s.PcmEnabledFlag { 742 err := bits.HasSpace(buf, pos, 8) 743 if err != nil { 744 return err 745 } 746 747 s.PcmSampleBitDepthLumaMinus1 = uint8(bits.ReadBitsUnsafe(buf, &pos, 4)) 748 s.PcmSampleBitDepthChromaMinus1 = uint8(bits.ReadBitsUnsafe(buf, &pos, 4)) 749 750 s.Log2MinPcmLumaCodingBlockSizeMinus3, err = bits.ReadGolombUnsigned(buf, &pos) 751 if err != nil { 752 return err 753 } 754 755 s.Log2DiffMaxMinPcmLumaCodingBlockSize, err = bits.ReadGolombUnsigned(buf, &pos) 756 if err != nil { 757 return err 758 } 759 760 s.PcmLoopFilterDisabledFlag, err = bits.ReadFlag(buf, &pos) 761 if err != nil { 762 return err 763 } 764 } 765 766 numShortTermRefPicSets, err := bits.ReadGolombUnsigned(buf, &pos) 767 if err != nil { 768 return err 769 } 770 771 if numShortTermRefPicSets > 0 { 772 if numShortTermRefPicSets > maxShortTermRefPics { 773 return fmt.Errorf("num_short_term_ref_pic_sets exceeds %d", maxShortTermRefPics) 774 } 775 776 s.ShortTermRefPicSets = make([]*SPS_ShortTermRefPicSet, numShortTermRefPicSets) 777 778 for i := uint32(0); i < numShortTermRefPicSets; i++ { 779 s.ShortTermRefPicSets[i] = &SPS_ShortTermRefPicSet{} 780 err := s.ShortTermRefPicSets[i].unmarshal(buf, &pos, i, numShortTermRefPicSets, s.ShortTermRefPicSets) 781 if err != nil { 782 return err 783 } 784 } 785 } else { 786 s.ShortTermRefPicSets = nil 787 } 788 789 s.LongTermRefPicsPresentFlag, err = bits.ReadFlag(buf, &pos) 790 if err != nil { 791 return err 792 } 793 794 if s.LongTermRefPicsPresentFlag { 795 numLongTermRefPicsSPS, err := bits.ReadGolombUnsigned(buf, &pos) 796 if err != nil { 797 return err 798 } 799 800 if numLongTermRefPicsSPS > 0 { 801 return fmt.Errorf("long term ref pics inside SPS are not supported yet") 802 } 803 } 804 805 s.TemporalMvpEnabledFlag, err = bits.ReadFlag(buf, &pos) 806 if err != nil { 807 return err 808 } 809 810 s.StrongIntraSmoothingEnabledFlag, err = bits.ReadFlag(buf, &pos) 811 if err != nil { 812 return err 813 } 814 815 vuiParametersPresentFlag, err := bits.ReadFlag(buf, &pos) 816 if err != nil { 817 return err 818 } 819 820 if vuiParametersPresentFlag { 821 s.VUI = &SPS_VUI{} 822 err := s.VUI.unmarshal(buf, &pos) 823 if err != nil { 824 return err 825 } 826 } else { 827 s.VUI = nil 828 } 829 830 return nil 831 } 832 833 // Width returns the video width. 834 func (s SPS) Width() int { 835 width := s.PicWidthInLumaSamples 836 837 if s.ConformanceWindow != nil { 838 cropUnitX := subWidthC[s.ChromaFormatIdc] 839 width -= (s.ConformanceWindow.LeftOffset + s.ConformanceWindow.RightOffset) * cropUnitX 840 } 841 842 return int(width) 843 } 844 845 // Height returns the video height. 846 func (s SPS) Height() int { 847 height := s.PicHeightInLumaSamples 848 849 if s.ConformanceWindow != nil { 850 cropUnitY := subHeightC[s.ChromaFormatIdc] 851 height -= (s.ConformanceWindow.TopOffset + s.ConformanceWindow.BottomOffset) * cropUnitY 852 } 853 854 return int(height) 855 } 856 857 // FPS returns the frames per second of the video. 858 func (s SPS) FPS() float64 { 859 if s.VUI == nil || s.VUI.TimingInfo == nil { 860 return 0 861 } 862 863 return float64(s.VUI.TimingInfo.TimeScale) / float64(s.VUI.TimingInfo.NumUnitsInTick) 864 }