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  }