github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/h264/sps.go (about)

     1  package h264
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/bluenviron/mediacommon/pkg/bits"
     7  )
     8  
     9  const (
    10  	maxRefFrames = 255
    11  )
    12  
    13  func readScalingList(buf []byte, pos *int, size int) ([]int32, bool, error) {
    14  	lastScale := int32(8)
    15  	nextScale := int32(8)
    16  	scalingList := make([]int32, size)
    17  	var useDefaultScalingMatrixFlag bool
    18  
    19  	for j := 0; j < size; j++ {
    20  		if nextScale != 0 {
    21  			deltaScale, err := bits.ReadGolombSigned(buf, pos)
    22  			if err != nil {
    23  				return nil, false, err
    24  			}
    25  
    26  			nextScale = (lastScale + deltaScale + 256) % 256
    27  			useDefaultScalingMatrixFlag = (j == 0 && nextScale == 0)
    28  		}
    29  
    30  		if nextScale == 0 {
    31  			scalingList[j] = lastScale
    32  		} else {
    33  			scalingList[j] = nextScale
    34  		}
    35  
    36  		lastScale = scalingList[j]
    37  	}
    38  
    39  	return scalingList, useDefaultScalingMatrixFlag, nil
    40  }
    41  
    42  // SPS_HRD is a hypotetical reference decoder.
    43  type SPS_HRD struct { //nolint:revive
    44  	CpbCntMinus1                       uint32
    45  	BitRateScale                       uint8
    46  	CpbSizeScale                       uint8
    47  	BitRateValueMinus1                 []uint32
    48  	CpbSizeValueMinus1                 []uint32
    49  	CbrFlag                            []bool
    50  	InitialCpbRemovalDelayLengthMinus1 uint8
    51  	CpbRemovalDelayLengthMinus1        uint8
    52  	DpbOutputDelayLengthMinus1         uint8
    53  	TimeOffsetLength                   uint8
    54  }
    55  
    56  func (h *SPS_HRD) unmarshal(buf []byte, pos *int) error {
    57  	var err error
    58  	h.CpbCntMinus1, err = bits.ReadGolombUnsigned(buf, pos)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	err = bits.HasSpace(buf, *pos, 8)
    64  	if err != nil {
    65  		return err
    66  	}
    67  
    68  	h.BitRateScale = uint8(bits.ReadBitsUnsafe(buf, pos, 4))
    69  	h.CpbSizeScale = uint8(bits.ReadBitsUnsafe(buf, pos, 4))
    70  
    71  	for i := uint32(0); i <= h.CpbCntMinus1; i++ {
    72  		v, err := bits.ReadGolombUnsigned(buf, pos)
    73  		if err != nil {
    74  			return err
    75  		}
    76  		h.BitRateValueMinus1 = append(h.BitRateValueMinus1, v)
    77  
    78  		v, err = bits.ReadGolombUnsigned(buf, pos)
    79  		if err != nil {
    80  			return err
    81  		}
    82  		h.CpbSizeValueMinus1 = append(h.CpbSizeValueMinus1, v)
    83  
    84  		vb, err := bits.ReadFlag(buf, pos)
    85  		if err != nil {
    86  			return err
    87  		}
    88  		h.CbrFlag = append(h.CbrFlag, vb)
    89  	}
    90  
    91  	err = bits.HasSpace(buf, *pos, 5+5+5+5)
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	h.InitialCpbRemovalDelayLengthMinus1 = uint8(bits.ReadBitsUnsafe(buf, pos, 5))
    97  	h.CpbRemovalDelayLengthMinus1 = uint8(bits.ReadBitsUnsafe(buf, pos, 5))
    98  	h.DpbOutputDelayLengthMinus1 = uint8(bits.ReadBitsUnsafe(buf, pos, 5))
    99  	h.TimeOffsetLength = uint8(bits.ReadBitsUnsafe(buf, pos, 5))
   100  
   101  	return nil
   102  }
   103  
   104  // SPS_TimingInfo is a timing info.
   105  type SPS_TimingInfo struct { //nolint:revive
   106  	NumUnitsInTick     uint32
   107  	TimeScale          uint32
   108  	FixedFrameRateFlag bool
   109  }
   110  
   111  func (t *SPS_TimingInfo) unmarshal(buf []byte, pos *int) error {
   112  	err := bits.HasSpace(buf, *pos, 32+32+1)
   113  	if err != nil {
   114  		return err
   115  	}
   116  
   117  	t.NumUnitsInTick = uint32(bits.ReadBitsUnsafe(buf, pos, 32))
   118  	t.TimeScale = uint32(bits.ReadBitsUnsafe(buf, pos, 32))
   119  	t.FixedFrameRateFlag = bits.ReadFlagUnsafe(buf, pos)
   120  
   121  	return nil
   122  }
   123  
   124  // SPS_BitstreamRestriction are bitstream restriction infos.
   125  type SPS_BitstreamRestriction struct { //nolint:revive
   126  	MotionVectorsOverPicBoundariesFlag bool
   127  	MaxBytesPerPicDenom                uint32
   128  	MaxBitsPerMbDenom                  uint32
   129  	Log2MaxMvLengthHorizontal          uint32
   130  	Log2MaxMvLengthVertical            uint32
   131  	MaxNumReorderFrames                uint32
   132  	MaxDecFrameBuffering               uint32
   133  }
   134  
   135  func (r *SPS_BitstreamRestriction) unmarshal(buf []byte, pos *int) error {
   136  	var err error
   137  	r.MotionVectorsOverPicBoundariesFlag, err = bits.ReadFlag(buf, pos)
   138  	if err != nil {
   139  		return err
   140  	}
   141  
   142  	r.MaxBytesPerPicDenom, err = bits.ReadGolombUnsigned(buf, pos)
   143  	if err != nil {
   144  		return err
   145  	}
   146  
   147  	r.MaxBitsPerMbDenom, err = bits.ReadGolombUnsigned(buf, pos)
   148  	if err != nil {
   149  		return err
   150  	}
   151  
   152  	r.Log2MaxMvLengthHorizontal, err = bits.ReadGolombUnsigned(buf, pos)
   153  	if err != nil {
   154  		return err
   155  	}
   156  
   157  	r.Log2MaxMvLengthVertical, err = bits.ReadGolombUnsigned(buf, pos)
   158  	if err != nil {
   159  		return err
   160  	}
   161  
   162  	r.MaxNumReorderFrames, err = bits.ReadGolombUnsigned(buf, pos)
   163  	if err != nil {
   164  		return err
   165  	}
   166  
   167  	r.MaxDecFrameBuffering, err = bits.ReadGolombUnsigned(buf, pos)
   168  	if err != nil {
   169  		return err
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  // SPS_VUI is a video usability information.
   176  type SPS_VUI struct { //nolint:revive
   177  	AspectRatioInfoPresentFlag bool
   178  
   179  	// AspectRatioInfoPresentFlag == true
   180  	AspectRatioIdc uint8
   181  	SarWidth       uint16
   182  	SarHeight      uint16
   183  
   184  	OverscanInfoPresentFlag bool
   185  
   186  	// OverscanInfoPresentFlag == true
   187  	OverscanAppropriateFlag    bool
   188  	VideoSignalTypePresentFlag bool
   189  
   190  	// VideoSignalTypePresentFlag == true
   191  	VideoFormat                  uint8
   192  	VideoFullRangeFlag           bool
   193  	ColourDescriptionPresentFlag bool
   194  
   195  	// ColourDescriptionPresentFlag == true
   196  	ColourPrimaries         uint8
   197  	TransferCharacteristics uint8
   198  	MatrixCoefficients      uint8
   199  
   200  	ChromaLocInfoPresentFlag bool
   201  
   202  	// ChromaLocInfoPresentFlag == true
   203  	ChromaSampleLocTypeTopField    uint32
   204  	ChromaSampleLocTypeBottomField uint32
   205  
   206  	TimingInfo *SPS_TimingInfo
   207  	NalHRD     *SPS_HRD
   208  	VclHRD     *SPS_HRD
   209  
   210  	LowDelayHrdFlag      bool
   211  	PicStructPresentFlag bool
   212  	BitstreamRestriction *SPS_BitstreamRestriction
   213  }
   214  
   215  func (v *SPS_VUI) unmarshal(buf []byte, pos *int) error {
   216  	var err error
   217  	v.AspectRatioInfoPresentFlag, err = bits.ReadFlag(buf, pos)
   218  	if err != nil {
   219  		return err
   220  	}
   221  
   222  	if v.AspectRatioInfoPresentFlag {
   223  		tmp, err := bits.ReadBits(buf, pos, 8)
   224  		if err != nil {
   225  			return err
   226  		}
   227  		v.AspectRatioIdc = uint8(tmp)
   228  
   229  		if v.AspectRatioIdc == 255 { // Extended_SAR
   230  			err := bits.HasSpace(buf, *pos, 32)
   231  			if err != nil {
   232  				return err
   233  			}
   234  
   235  			v.SarWidth = uint16(bits.ReadBitsUnsafe(buf, pos, 16))
   236  			v.SarHeight = uint16(bits.ReadBitsUnsafe(buf, pos, 16))
   237  		}
   238  	}
   239  
   240  	v.OverscanInfoPresentFlag, err = bits.ReadFlag(buf, pos)
   241  	if err != nil {
   242  		return err
   243  	}
   244  
   245  	if v.OverscanInfoPresentFlag {
   246  		v.OverscanAppropriateFlag, err = bits.ReadFlag(buf, pos)
   247  		if err != nil {
   248  			return err
   249  		}
   250  	}
   251  
   252  	v.VideoSignalTypePresentFlag, err = bits.ReadFlag(buf, pos)
   253  	if err != nil {
   254  		return err
   255  	}
   256  
   257  	if v.VideoSignalTypePresentFlag {
   258  		err := bits.HasSpace(buf, *pos, 5)
   259  		if err != nil {
   260  			return err
   261  		}
   262  
   263  		v.VideoFormat = uint8(bits.ReadBitsUnsafe(buf, pos, 3))
   264  		v.VideoFullRangeFlag = bits.ReadFlagUnsafe(buf, pos)
   265  		v.ColourDescriptionPresentFlag = bits.ReadFlagUnsafe(buf, pos)
   266  
   267  		if v.ColourDescriptionPresentFlag {
   268  			err := bits.HasSpace(buf, *pos, 24)
   269  			if err != nil {
   270  				return err
   271  			}
   272  
   273  			v.ColourPrimaries = uint8(bits.ReadBitsUnsafe(buf, pos, 8))
   274  			v.TransferCharacteristics = uint8(bits.ReadBitsUnsafe(buf, pos, 8))
   275  			v.MatrixCoefficients = uint8(bits.ReadBitsUnsafe(buf, pos, 8))
   276  		}
   277  	}
   278  
   279  	v.ChromaLocInfoPresentFlag, err = bits.ReadFlag(buf, pos)
   280  	if err != nil {
   281  		return err
   282  	}
   283  
   284  	if v.ChromaLocInfoPresentFlag {
   285  		v.ChromaSampleLocTypeTopField, err = bits.ReadGolombUnsigned(buf, pos)
   286  		if err != nil {
   287  			return err
   288  		}
   289  
   290  		v.ChromaSampleLocTypeBottomField, err = bits.ReadGolombUnsigned(buf, pos)
   291  		if err != nil {
   292  			return err
   293  		}
   294  	}
   295  
   296  	timingInfoPresentFlag, err := bits.ReadFlag(buf, pos)
   297  	if err != nil {
   298  		return err
   299  	}
   300  
   301  	if timingInfoPresentFlag {
   302  		v.TimingInfo = &SPS_TimingInfo{}
   303  		err := v.TimingInfo.unmarshal(buf, pos)
   304  		if err != nil {
   305  			return err
   306  		}
   307  	}
   308  
   309  	nalHrdParametersPresentFlag, err := bits.ReadFlag(buf, pos)
   310  	if err != nil {
   311  		return err
   312  	}
   313  
   314  	if nalHrdParametersPresentFlag {
   315  		v.NalHRD = &SPS_HRD{}
   316  		err := v.NalHRD.unmarshal(buf, pos)
   317  		if err != nil {
   318  			return err
   319  		}
   320  	}
   321  
   322  	vclHrdParametersPresentFlag, err := bits.ReadFlag(buf, pos)
   323  	if err != nil {
   324  		return err
   325  	}
   326  
   327  	if vclHrdParametersPresentFlag {
   328  		v.VclHRD = &SPS_HRD{}
   329  		err := v.VclHRD.unmarshal(buf, pos)
   330  		if err != nil {
   331  			return err
   332  		}
   333  	}
   334  
   335  	if nalHrdParametersPresentFlag || vclHrdParametersPresentFlag {
   336  		v.LowDelayHrdFlag, err = bits.ReadFlag(buf, pos)
   337  		if err != nil {
   338  			return err
   339  		}
   340  	}
   341  
   342  	v.PicStructPresentFlag, err = bits.ReadFlag(buf, pos)
   343  	if err != nil {
   344  		return err
   345  	}
   346  
   347  	bitstreamRestrictionFlag, err := bits.ReadFlag(buf, pos)
   348  	if err != nil {
   349  		return err
   350  	}
   351  
   352  	if bitstreamRestrictionFlag {
   353  		v.BitstreamRestriction = &SPS_BitstreamRestriction{}
   354  		err := v.BitstreamRestriction.unmarshal(buf, pos)
   355  		if err != nil {
   356  			return err
   357  		}
   358  	}
   359  
   360  	return nil
   361  }
   362  
   363  // SPS_FrameCropping is the frame cropping part of a SPS.
   364  type SPS_FrameCropping struct { //nolint:revive
   365  	LeftOffset   uint32
   366  	RightOffset  uint32
   367  	TopOffset    uint32
   368  	BottomOffset uint32
   369  }
   370  
   371  func (c *SPS_FrameCropping) unmarshal(buf []byte, pos *int) error {
   372  	var err error
   373  	c.LeftOffset, err = bits.ReadGolombUnsigned(buf, pos)
   374  	if err != nil {
   375  		return err
   376  	}
   377  
   378  	c.RightOffset, err = bits.ReadGolombUnsigned(buf, pos)
   379  	if err != nil {
   380  		return err
   381  	}
   382  
   383  	c.TopOffset, err = bits.ReadGolombUnsigned(buf, pos)
   384  	if err != nil {
   385  		return err
   386  	}
   387  
   388  	c.BottomOffset, err = bits.ReadGolombUnsigned(buf, pos)
   389  	if err != nil {
   390  		return err
   391  	}
   392  
   393  	return nil
   394  }
   395  
   396  // SPS is a H264 sequence parameter set.
   397  // Specification: ITU-T Rec. H.264, 7.3.2.1.1
   398  type SPS struct {
   399  	ProfileIdc         uint8
   400  	ConstraintSet0Flag bool
   401  	ConstraintSet1Flag bool
   402  	ConstraintSet2Flag bool
   403  	ConstraintSet3Flag bool
   404  	ConstraintSet4Flag bool
   405  	ConstraintSet5Flag bool
   406  	LevelIdc           uint8
   407  	ID                 uint32
   408  
   409  	// only for selected ProfileIdcs
   410  	ChromaFormatIdc                 uint32
   411  	SeparateColourPlaneFlag         bool
   412  	BitDepthLumaMinus8              uint32
   413  	BitDepthChromaMinus8            uint32
   414  	QpprimeYZeroTransformBypassFlag bool
   415  
   416  	// seqScalingListPresentFlag == true
   417  	ScalingList4x4                 [][]int32
   418  	UseDefaultScalingMatrix4x4Flag []bool
   419  	ScalingList8x8                 [][]int32
   420  	UseDefaultScalingMatrix8x8Flag []bool
   421  
   422  	Log2MaxFrameNumMinus4 uint32
   423  	PicOrderCntType       uint32
   424  
   425  	// PicOrderCntType == 0
   426  	Log2MaxPicOrderCntLsbMinus4 uint32
   427  
   428  	// PicOrderCntType == 1
   429  	DeltaPicOrderAlwaysZeroFlag bool
   430  	OffsetForNonRefPic          int32
   431  	OffsetForTopToBottomField   int32
   432  	OffsetForRefFrames          []int32
   433  
   434  	MaxNumRefFrames                uint32
   435  	GapsInFrameNumValueAllowedFlag bool
   436  	PicWidthInMbsMinus1            uint32
   437  	PicHeightInMapUnitsMinus1      uint32
   438  	FrameMbsOnlyFlag               bool
   439  
   440  	// FrameMbsOnlyFlag == false
   441  	MbAdaptiveFrameFieldFlag bool
   442  
   443  	Direct8x8InferenceFlag bool
   444  	FrameCropping          *SPS_FrameCropping
   445  	VUI                    *SPS_VUI
   446  }
   447  
   448  // Unmarshal decodes a SPS from bytes.
   449  func (s *SPS) Unmarshal(buf []byte) error {
   450  	if len(buf) < 1 {
   451  		return fmt.Errorf("not enough bits")
   452  	}
   453  
   454  	if NALUType(buf[0]&0x1F) != NALUTypeSPS {
   455  		return fmt.Errorf("not a SPS")
   456  	}
   457  
   458  	buf = EmulationPreventionRemove(buf[1:])
   459  
   460  	if len(buf) < 3 {
   461  		return fmt.Errorf("not enough bits")
   462  	}
   463  
   464  	s.ProfileIdc = buf[0]
   465  	s.ConstraintSet0Flag = (buf[1] >> 7) == 1
   466  	s.ConstraintSet1Flag = (buf[1] >> 6 & 0x01) == 1
   467  	s.ConstraintSet2Flag = (buf[1] >> 5 & 0x01) == 1
   468  	s.ConstraintSet3Flag = (buf[1] >> 4 & 0x01) == 1
   469  	s.ConstraintSet4Flag = (buf[1] >> 3 & 0x01) == 1
   470  	s.ConstraintSet5Flag = (buf[1] >> 2 & 0x01) == 1
   471  	s.LevelIdc = buf[2]
   472  
   473  	buf = buf[3:]
   474  	pos := 0
   475  
   476  	var err error
   477  	s.ID, err = bits.ReadGolombUnsigned(buf, &pos)
   478  	if err != nil {
   479  		return err
   480  	}
   481  
   482  	switch s.ProfileIdc {
   483  	case 100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135:
   484  		s.ChromaFormatIdc, err = bits.ReadGolombUnsigned(buf, &pos)
   485  		if err != nil {
   486  			return err
   487  		}
   488  
   489  		if s.ChromaFormatIdc == 3 {
   490  			s.SeparateColourPlaneFlag, err = bits.ReadFlag(buf, &pos)
   491  			if err != nil {
   492  				return err
   493  			}
   494  		} else {
   495  			s.SeparateColourPlaneFlag = false
   496  		}
   497  
   498  		s.BitDepthLumaMinus8, err = bits.ReadGolombUnsigned(buf, &pos)
   499  		if err != nil {
   500  			return err
   501  		}
   502  
   503  		s.BitDepthChromaMinus8, err = bits.ReadGolombUnsigned(buf, &pos)
   504  		if err != nil {
   505  			return err
   506  		}
   507  
   508  		s.QpprimeYZeroTransformBypassFlag, err = bits.ReadFlag(buf, &pos)
   509  		if err != nil {
   510  			return err
   511  		}
   512  
   513  		seqScalingMatrixPresentFlag, err := bits.ReadFlag(buf, &pos)
   514  		if err != nil {
   515  			return err
   516  		}
   517  
   518  		if seqScalingMatrixPresentFlag {
   519  			var lim int
   520  			if s.ChromaFormatIdc != 3 {
   521  				lim = 8
   522  			} else {
   523  				lim = 12
   524  			}
   525  
   526  			for i := 0; i < lim; i++ {
   527  				seqScalingListPresentFlag, err := bits.ReadFlag(buf, &pos)
   528  				if err != nil {
   529  					return err
   530  				}
   531  
   532  				if seqScalingListPresentFlag {
   533  					if i < 6 {
   534  						scalingList, useDefaultScalingMatrixFlag, err := readScalingList(buf, &pos, 16)
   535  						if err != nil {
   536  							return err
   537  						}
   538  
   539  						s.ScalingList4x4 = append(s.ScalingList4x4, scalingList)
   540  						s.UseDefaultScalingMatrix4x4Flag = append(s.UseDefaultScalingMatrix4x4Flag,
   541  							useDefaultScalingMatrixFlag)
   542  					} else {
   543  						scalingList, useDefaultScalingMatrixFlag, err := readScalingList(buf, &pos, 64)
   544  						if err != nil {
   545  							return err
   546  						}
   547  
   548  						s.ScalingList8x8 = append(s.ScalingList8x8, scalingList)
   549  						s.UseDefaultScalingMatrix8x8Flag = append(s.UseDefaultScalingMatrix8x8Flag,
   550  							useDefaultScalingMatrixFlag)
   551  					}
   552  				}
   553  			}
   554  		}
   555  
   556  	default:
   557  		s.ChromaFormatIdc = 1
   558  		s.SeparateColourPlaneFlag = false
   559  		s.BitDepthLumaMinus8 = 0
   560  		s.BitDepthChromaMinus8 = 0
   561  		s.QpprimeYZeroTransformBypassFlag = false
   562  	}
   563  
   564  	s.Log2MaxFrameNumMinus4, err = bits.ReadGolombUnsigned(buf, &pos)
   565  	if err != nil {
   566  		return err
   567  	}
   568  
   569  	s.PicOrderCntType, err = bits.ReadGolombUnsigned(buf, &pos)
   570  	if err != nil {
   571  		return err
   572  	}
   573  
   574  	switch s.PicOrderCntType {
   575  	case 0:
   576  		s.Log2MaxPicOrderCntLsbMinus4, err = bits.ReadGolombUnsigned(buf, &pos)
   577  		if err != nil {
   578  			return err
   579  		}
   580  
   581  		s.DeltaPicOrderAlwaysZeroFlag = false
   582  		s.OffsetForNonRefPic = 0
   583  		s.OffsetForTopToBottomField = 0
   584  		s.OffsetForRefFrames = nil
   585  
   586  	case 1:
   587  		s.Log2MaxPicOrderCntLsbMinus4 = 0
   588  
   589  		s.DeltaPicOrderAlwaysZeroFlag, err = bits.ReadFlag(buf, &pos)
   590  		if err != nil {
   591  			return err
   592  		}
   593  
   594  		s.OffsetForNonRefPic, err = bits.ReadGolombSigned(buf, &pos)
   595  		if err != nil {
   596  			return err
   597  		}
   598  
   599  		s.OffsetForTopToBottomField, err = bits.ReadGolombSigned(buf, &pos)
   600  		if err != nil {
   601  			return err
   602  		}
   603  
   604  		numRefFramesInPicOrderCntCycle, err := bits.ReadGolombUnsigned(buf, &pos)
   605  		if err != nil {
   606  			return err
   607  		}
   608  
   609  		if numRefFramesInPicOrderCntCycle > maxRefFrames {
   610  			return fmt.Errorf("num_ref_frames_in_pic_order_cnt_cycle exceeds %d", maxRefFrames)
   611  		}
   612  
   613  		s.OffsetForRefFrames = make([]int32, numRefFramesInPicOrderCntCycle)
   614  		for i := uint32(0); i < numRefFramesInPicOrderCntCycle; i++ {
   615  			v, err := bits.ReadGolombSigned(buf, &pos)
   616  			if err != nil {
   617  				return err
   618  			}
   619  
   620  			s.OffsetForRefFrames[i] = v
   621  		}
   622  
   623  	case 2:
   624  		s.Log2MaxPicOrderCntLsbMinus4 = 0
   625  		s.DeltaPicOrderAlwaysZeroFlag = false
   626  		s.OffsetForNonRefPic = 0
   627  		s.OffsetForTopToBottomField = 0
   628  		s.OffsetForRefFrames = nil
   629  
   630  	default:
   631  		return fmt.Errorf("invalid pic_order_cnt_type: %d", s.PicOrderCntType)
   632  	}
   633  
   634  	s.MaxNumRefFrames, err = bits.ReadGolombUnsigned(buf, &pos)
   635  	if err != nil {
   636  		return err
   637  	}
   638  
   639  	s.GapsInFrameNumValueAllowedFlag, err = bits.ReadFlag(buf, &pos)
   640  	if err != nil {
   641  		return err
   642  	}
   643  
   644  	s.PicWidthInMbsMinus1, err = bits.ReadGolombUnsigned(buf, &pos)
   645  	if err != nil {
   646  		return err
   647  	}
   648  
   649  	s.PicHeightInMapUnitsMinus1, err = bits.ReadGolombUnsigned(buf, &pos)
   650  	if err != nil {
   651  		return err
   652  	}
   653  
   654  	s.FrameMbsOnlyFlag, err = bits.ReadFlag(buf, &pos)
   655  	if err != nil {
   656  		return err
   657  	}
   658  
   659  	if !s.FrameMbsOnlyFlag {
   660  		s.MbAdaptiveFrameFieldFlag, err = bits.ReadFlag(buf, &pos)
   661  		if err != nil {
   662  			return err
   663  		}
   664  	} else {
   665  		s.MbAdaptiveFrameFieldFlag = false
   666  	}
   667  
   668  	s.Direct8x8InferenceFlag, err = bits.ReadFlag(buf, &pos)
   669  	if err != nil {
   670  		return err
   671  	}
   672  
   673  	frameCroppingFlag, err := bits.ReadFlag(buf, &pos)
   674  	if err != nil {
   675  		return err
   676  	}
   677  
   678  	if frameCroppingFlag {
   679  		s.FrameCropping = &SPS_FrameCropping{}
   680  		err := s.FrameCropping.unmarshal(buf, &pos)
   681  		if err != nil {
   682  			return err
   683  		}
   684  	} else {
   685  		s.FrameCropping = nil
   686  	}
   687  
   688  	vuiParametersPresentFlag, err := bits.ReadFlag(buf, &pos)
   689  	if err != nil {
   690  		return err
   691  	}
   692  
   693  	if vuiParametersPresentFlag {
   694  		s.VUI = &SPS_VUI{}
   695  		err := s.VUI.unmarshal(buf, &pos)
   696  		if err != nil {
   697  			return err
   698  		}
   699  	} else {
   700  		s.VUI = nil
   701  	}
   702  
   703  	return nil
   704  }
   705  
   706  // Width returns the video width.
   707  func (s SPS) Width() int {
   708  	var subWidthC uint32
   709  	switch {
   710  	case s.ChromaFormatIdc == 1 && !s.SeparateColourPlaneFlag:
   711  		subWidthC = 2
   712  
   713  	case s.ChromaFormatIdc == 2 && !s.SeparateColourPlaneFlag:
   714  		subWidthC = 2
   715  
   716  	case s.ChromaFormatIdc == 3 && !s.SeparateColourPlaneFlag:
   717  		subWidthC = 1
   718  	}
   719  
   720  	var chromaArrayType uint32
   721  	if !s.SeparateColourPlaneFlag {
   722  		chromaArrayType = s.ChromaFormatIdc
   723  	} else {
   724  		chromaArrayType = 0
   725  	}
   726  
   727  	var cropUnitX uint32
   728  	if chromaArrayType == 0 {
   729  		cropUnitX = 0
   730  	} else {
   731  		cropUnitX = subWidthC
   732  	}
   733  
   734  	picWidthInSamplesL := ((s.PicWidthInMbsMinus1 + 1) * 16)
   735  
   736  	if s.FrameCropping != nil {
   737  		return int(picWidthInSamplesL - cropUnitX*(s.FrameCropping.LeftOffset+s.FrameCropping.RightOffset))
   738  	}
   739  
   740  	return int(picWidthInSamplesL)
   741  }
   742  
   743  // Height returns the video height.
   744  func (s SPS) Height() int {
   745  	var subHeightC uint32
   746  	switch {
   747  	case s.ChromaFormatIdc == 1 && !s.SeparateColourPlaneFlag:
   748  		subHeightC = 2
   749  
   750  	case s.ChromaFormatIdc == 2 && !s.SeparateColourPlaneFlag:
   751  		subHeightC = 1
   752  
   753  	case s.ChromaFormatIdc == 3 && !s.SeparateColourPlaneFlag:
   754  		subHeightC = 1
   755  	}
   756  
   757  	var frameMbsOnlyFlagUint32 uint32
   758  	if s.FrameMbsOnlyFlag {
   759  		frameMbsOnlyFlagUint32 = 1
   760  	}
   761  
   762  	var chromaArrayType uint32
   763  	if !s.SeparateColourPlaneFlag {
   764  		chromaArrayType = s.ChromaFormatIdc
   765  	} else {
   766  		chromaArrayType = 0
   767  	}
   768  
   769  	var cropUnitY uint32
   770  	if chromaArrayType == 0 {
   771  		cropUnitY = 2 - frameMbsOnlyFlagUint32
   772  	} else {
   773  		cropUnitY = subHeightC * (2 - frameMbsOnlyFlagUint32)
   774  	}
   775  
   776  	frameHeightInMbs := (2 - frameMbsOnlyFlagUint32) * (s.PicHeightInMapUnitsMinus1 + 1)
   777  
   778  	if s.FrameCropping != nil {
   779  		return int(16*frameHeightInMbs - cropUnitY*(s.FrameCropping.TopOffset+s.FrameCropping.BottomOffset))
   780  	}
   781  
   782  	picHeightInMbs := frameHeightInMbs // / (1 + s.FieldPicFlag)
   783  	picHeightInSamplesL := picHeightInMbs * 16
   784  
   785  	return int(picHeightInSamplesL)
   786  }
   787  
   788  // FPS returns the frames per second of the video.
   789  func (s SPS) FPS() float64 {
   790  	if s.VUI == nil || s.VUI.TimingInfo == nil {
   791  		return 0
   792  	}
   793  
   794  	return float64(s.VUI.TimingInfo.TimeScale) / (2 * float64(s.VUI.TimingInfo.NumUnitsInTick))
   795  }