github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/av1/sequence_header.go (about)

     1  package av1
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/bluenviron/mediacommon/pkg/bits"
     7  )
     8  
     9  // SequenceHeader_ColorPrimaries is a ColorPrimaries value.
    10  type SequenceHeader_ColorPrimaries uint8 //nolint:revive
    11  
    12  const (
    13  	SequenceHeader_ColorPrimaries_CP_BT_709      SequenceHeader_ColorPrimaries = 1 //nolint:revive
    14  	SequenceHeader_ColorPrimaries_CP_UNSPECIFIED SequenceHeader_ColorPrimaries = 2 //nolint:revive
    15  )
    16  
    17  // SequenceHeader_TransferCharacteristics is a TransferCharacteristics value.
    18  type SequenceHeader_TransferCharacteristics uint8 //nolint:revive
    19  
    20  const (
    21  	SequenceHeader_TransferCharacteristics_TC_UNSPECIFIED SequenceHeader_TransferCharacteristics = 2  //nolint:revive
    22  	SequenceHeader_TransferCharacteristics_TC_SRGB        SequenceHeader_TransferCharacteristics = 13 //nolint:revive
    23  )
    24  
    25  // SequenceHeader_MatrixCoefficients is a MatrixCoefficients value.
    26  type SequenceHeader_MatrixCoefficients uint8 //nolint:revive
    27  
    28  const (
    29  	SequenceHeader_MatrixCoefficients_MC_IDENTITY    SequenceHeader_MatrixCoefficients = 0 //nolint:revive
    30  	SequenceHeader_MatrixCoefficients_MC_UNSPECIFIED SequenceHeader_MatrixCoefficients = 2 //nolint:revive
    31  )
    32  
    33  // SequenceHeader_ChromaSamplePosition is a ChromaSamplePosition value.
    34  type SequenceHeader_ChromaSamplePosition uint8 //nolint:revive
    35  
    36  const (
    37  	SequenceHeader_ChromaSamplePosition_CSP_UNKNOWN SequenceHeader_ChromaSamplePosition = 0 //nolint:revive
    38  )
    39  
    40  // SequenceHeader_SeqForceScreenContentTools is a SeqForceScreenContentTools value.
    41  type SequenceHeader_SeqForceScreenContentTools uint8 //nolint:revive
    42  
    43  const (
    44  	SequenceHeader_SeqForceScreenContentTools_SELECT_SCREEN_CONTENT_TOOLS SequenceHeader_SeqForceScreenContentTools = 2 //nolint:revive,lll
    45  )
    46  
    47  // SequenceHeader_SeqForceIntegerMv is a SeqForceIntegerMv value.
    48  type SequenceHeader_SeqForceIntegerMv uint8 //nolint:revive
    49  
    50  const (
    51  	SequenceHeader_SeqForceIntegerMv_SELECT_INTEGER_MV SequenceHeader_SeqForceIntegerMv = 2 //nolint:revive
    52  )
    53  
    54  // SequenceHeader_ColorConfig is a color configuration of a sequence header.
    55  type SequenceHeader_ColorConfig struct { //nolint:revive
    56  	HighBitDepth                bool
    57  	TwelveBit                   bool
    58  	BitDepth                    int
    59  	MonoChrome                  bool
    60  	ColorDescriptionPresentFlag bool
    61  	ColorPrimaries              SequenceHeader_ColorPrimaries
    62  	TransferCharacteristics     SequenceHeader_TransferCharacteristics
    63  	MatrixCoefficients          SequenceHeader_MatrixCoefficients
    64  	ColorRange                  bool
    65  	SubsamplingX                bool
    66  	SubsamplingY                bool
    67  	ChromaSamplePosition        SequenceHeader_ChromaSamplePosition
    68  }
    69  
    70  func (c *SequenceHeader_ColorConfig) unmarshal(seqProfile uint8, buf []byte, pos *int) error {
    71  	var err error
    72  	c.HighBitDepth, err = bits.ReadFlag(buf, pos)
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	if seqProfile == 2 && c.HighBitDepth {
    78  		c.TwelveBit, err = bits.ReadFlag(buf, pos)
    79  		if err != nil {
    80  			return err
    81  		}
    82  
    83  		if c.TwelveBit {
    84  			c.BitDepth = 12
    85  		} else {
    86  			c.BitDepth = 10
    87  		}
    88  	} else if seqProfile <= 2 {
    89  		if c.HighBitDepth {
    90  			c.BitDepth = 10
    91  		} else {
    92  			c.BitDepth = 8
    93  		}
    94  	}
    95  
    96  	if seqProfile == 1 {
    97  		c.MonoChrome = false
    98  	} else {
    99  		c.MonoChrome, err = bits.ReadFlag(buf, pos)
   100  		if err != nil {
   101  			return err
   102  		}
   103  	}
   104  
   105  	c.ColorDescriptionPresentFlag, err = bits.ReadFlag(buf, pos)
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	if c.ColorDescriptionPresentFlag {
   111  		err := bits.HasSpace(buf, *pos, 24)
   112  		if err != nil {
   113  			return err
   114  		}
   115  
   116  		c.ColorPrimaries = SequenceHeader_ColorPrimaries(bits.ReadBitsUnsafe(buf, pos, 8))
   117  		c.TransferCharacteristics = SequenceHeader_TransferCharacteristics(bits.ReadBitsUnsafe(buf, pos, 8))
   118  		c.MatrixCoefficients = SequenceHeader_MatrixCoefficients(bits.ReadBitsUnsafe(buf, pos, 8))
   119  	} else {
   120  		c.ColorPrimaries = SequenceHeader_ColorPrimaries_CP_UNSPECIFIED
   121  		c.TransferCharacteristics = SequenceHeader_TransferCharacteristics_TC_UNSPECIFIED
   122  		c.MatrixCoefficients = SequenceHeader_MatrixCoefficients_MC_UNSPECIFIED
   123  	}
   124  
   125  	switch {
   126  	case c.MonoChrome:
   127  		c.ColorRange, err = bits.ReadFlag(buf, pos)
   128  		if err != nil {
   129  			return err
   130  		}
   131  
   132  		c.SubsamplingX = true
   133  		c.SubsamplingY = true
   134  		c.ChromaSamplePosition = SequenceHeader_ChromaSamplePosition_CSP_UNKNOWN
   135  	case c.ColorPrimaries == SequenceHeader_ColorPrimaries_CP_BT_709 &&
   136  		c.TransferCharacteristics == SequenceHeader_TransferCharacteristics_TC_SRGB &&
   137  		c.MatrixCoefficients == SequenceHeader_MatrixCoefficients_MC_IDENTITY:
   138  		c.ColorRange = true
   139  		c.SubsamplingX = false
   140  		c.SubsamplingY = false
   141  	default:
   142  		c.ColorRange, err = bits.ReadFlag(buf, pos)
   143  		if err != nil {
   144  			return err
   145  		}
   146  
   147  		switch {
   148  		case seqProfile == 0:
   149  			c.SubsamplingX = true
   150  			c.SubsamplingY = true
   151  		case seqProfile == 1:
   152  			c.SubsamplingX = false
   153  			c.SubsamplingY = false
   154  		default:
   155  			if c.BitDepth == 12 {
   156  				c.SubsamplingX, err = bits.ReadFlag(buf, pos)
   157  				if err != nil {
   158  					return err
   159  				}
   160  
   161  				if c.SubsamplingX {
   162  					c.SubsamplingY, err = bits.ReadFlag(buf, pos)
   163  					if err != nil {
   164  						return err
   165  					}
   166  				} else {
   167  					c.SubsamplingY = false
   168  				}
   169  			} else {
   170  				c.SubsamplingX = true
   171  				c.SubsamplingY = false
   172  			}
   173  		}
   174  
   175  		if c.SubsamplingX && c.SubsamplingY {
   176  			tmp, err := bits.ReadBits(buf, pos, 2)
   177  			if err != nil {
   178  				return err
   179  			}
   180  			c.ChromaSamplePosition = SequenceHeader_ChromaSamplePosition(tmp)
   181  		}
   182  	}
   183  
   184  	return nil
   185  }
   186  
   187  // SequenceHeader is a AV1 Sequence header OBU.
   188  // Specification: https://aomediacodec.github.io/av1-spec/#sequence-header-obu-syntax
   189  type SequenceHeader struct {
   190  	SeqProfile                     uint8
   191  	StillPicture                   bool
   192  	ReducedStillPictureHeader      bool
   193  	TimingInfoPresentFlag          bool
   194  	DecoderModelInfoPresentFlag    bool
   195  	InitialDisplayDelayPresentFlag bool
   196  	OperatingPointsCntMinus1       uint8
   197  	OperatingPointIdc              []uint16
   198  	SeqLevelIdx                    []uint8
   199  	SeqTier                        []bool
   200  	DecoderModelPresentForThisOp   []bool
   201  	InitialDisplayPresentForThisOp []bool
   202  	InitialDisplayDelayMinus1      []uint8
   203  	MaxFrameWidthMinus1            uint32
   204  	MaxFrameHeightMinus1           uint32
   205  	FrameIDNumbersPresentFlag      bool
   206  	Use128x128Superblock           bool
   207  	EnableFilterIntra              bool
   208  	EnableIntraEdgeFilter          bool
   209  	EnableInterintraCompound       bool
   210  	EnableMaskedCompound           bool
   211  	EnableWarpedMotion             bool
   212  	EnableDualFilter               bool
   213  	EnableOrderHint                bool
   214  	EnableJntComp                  bool
   215  	EnableRefFrameMvs              bool
   216  	SeqChooseScreenContentTools    bool
   217  	SeqForceScreenContentTools     SequenceHeader_SeqForceScreenContentTools
   218  	SeqChooseIntegerMv             bool
   219  	SeqForceIntegerMv              SequenceHeader_SeqForceIntegerMv
   220  	OrderHintBitsMinus1            uint8
   221  	EnableSuperRes                 bool
   222  	EnableCdef                     bool
   223  	EnableRestoration              bool
   224  	ColorConfig                    SequenceHeader_ColorConfig
   225  }
   226  
   227  // Unmarshal decodes a SequenceHeader.
   228  func (h *SequenceHeader) Unmarshal(buf []byte) error {
   229  	var oh OBUHeader
   230  	err := oh.Unmarshal(buf)
   231  	if err != nil {
   232  		return err
   233  	}
   234  	buf = buf[1:]
   235  
   236  	if oh.HasSize {
   237  		size, sizeN, err := LEB128Unmarshal(buf)
   238  		if err != nil {
   239  			return err
   240  		}
   241  
   242  		buf = buf[sizeN:]
   243  		if len(buf) != int(size) {
   244  			return fmt.Errorf("wrong buffer size: expected %d, got %d", size, len(buf))
   245  		}
   246  	}
   247  
   248  	pos := 0
   249  
   250  	err = bits.HasSpace(buf, pos, 5)
   251  	if err != nil {
   252  		return err
   253  	}
   254  
   255  	h.SeqProfile = uint8(bits.ReadBitsUnsafe(buf, &pos, 3))
   256  	h.StillPicture = bits.ReadFlagUnsafe(buf, &pos)
   257  	h.ReducedStillPictureHeader = bits.ReadFlagUnsafe(buf, &pos)
   258  
   259  	if h.ReducedStillPictureHeader {
   260  		h.TimingInfoPresentFlag = false
   261  		h.DecoderModelInfoPresentFlag = false
   262  		h.InitialDisplayDelayPresentFlag = false
   263  		h.OperatingPointsCntMinus1 = 0
   264  		h.OperatingPointIdc = []uint16{0}
   265  
   266  		err = bits.HasSpace(buf, pos, 5)
   267  		if err != nil {
   268  			return err
   269  		}
   270  
   271  		h.SeqLevelIdx = []uint8{uint8(bits.ReadBitsUnsafe(buf, &pos, 5))}
   272  		h.SeqTier = []bool{false}
   273  		h.DecoderModelPresentForThisOp = []bool{false}
   274  		h.InitialDisplayPresentForThisOp = []bool{false}
   275  	} else {
   276  		h.TimingInfoPresentFlag, err = bits.ReadFlag(buf, &pos)
   277  		if err != nil {
   278  			return err
   279  		}
   280  
   281  		if h.TimingInfoPresentFlag {
   282  			return fmt.Errorf("timing_info_present_flag is not supported yet")
   283  		}
   284  		h.DecoderModelInfoPresentFlag = false
   285  
   286  		err := bits.HasSpace(buf, pos, 6)
   287  		if err != nil {
   288  			return err
   289  		}
   290  
   291  		h.InitialDisplayDelayPresentFlag = bits.ReadFlagUnsafe(buf, &pos)
   292  		h.OperatingPointsCntMinus1 = uint8(bits.ReadBitsUnsafe(buf, &pos, 5))
   293  
   294  		h.OperatingPointIdc = make([]uint16, h.OperatingPointsCntMinus1+1)
   295  		h.SeqLevelIdx = make([]uint8, h.OperatingPointsCntMinus1+1)
   296  		h.SeqTier = make([]bool, h.OperatingPointsCntMinus1+1)
   297  		h.DecoderModelPresentForThisOp = make([]bool, h.OperatingPointsCntMinus1+1)
   298  		h.InitialDisplayPresentForThisOp = make([]bool, h.OperatingPointsCntMinus1+1)
   299  		h.InitialDisplayDelayMinus1 = make([]uint8, h.OperatingPointsCntMinus1+1)
   300  
   301  		for i := uint8(0); i <= h.OperatingPointsCntMinus1; i++ {
   302  			err := bits.HasSpace(buf, pos, 17)
   303  			if err != nil {
   304  				return err
   305  			}
   306  
   307  			h.OperatingPointIdc[i] = uint16(bits.ReadBitsUnsafe(buf, &pos, 12))
   308  			h.SeqLevelIdx[i] = uint8(bits.ReadBitsUnsafe(buf, &pos, 5))
   309  
   310  			if h.SeqLevelIdx[i] > 7 {
   311  				var err error
   312  				h.SeqTier[i], err = bits.ReadFlag(buf, &pos)
   313  				if err != nil {
   314  					return err
   315  				}
   316  			} else {
   317  				h.SeqTier[i] = false
   318  			}
   319  
   320  			if h.DecoderModelInfoPresentFlag {
   321  				return fmt.Errorf("decoder_model_info_present_flag is not supported yet")
   322  			}
   323  			h.DecoderModelPresentForThisOp[i] = false
   324  
   325  			if h.InitialDisplayDelayPresentFlag {
   326  				var err error
   327  				h.InitialDisplayPresentForThisOp[i], err = bits.ReadFlag(buf, &pos)
   328  				if err != nil {
   329  					return err
   330  				}
   331  
   332  				if h.InitialDisplayPresentForThisOp[i] {
   333  					tmp, err := bits.ReadBits(buf, &pos, 4)
   334  					if err != nil {
   335  						return err
   336  					}
   337  					h.InitialDisplayDelayMinus1[i] = uint8(tmp)
   338  				}
   339  				return fmt.Errorf("initial_display_delay_present_flag is not supported yet")
   340  			}
   341  		}
   342  	}
   343  
   344  	err = bits.HasSpace(buf, pos, 8)
   345  	if err != nil {
   346  		return err
   347  	}
   348  
   349  	frameWidthBitsMinus1 := int(bits.ReadBitsUnsafe(buf, &pos, 4))
   350  	frameHeightBitsMinus1 := int(bits.ReadBitsUnsafe(buf, &pos, 4))
   351  
   352  	n1 := (frameWidthBitsMinus1 + 1)
   353  	n2 := (frameHeightBitsMinus1 + 1)
   354  
   355  	err = bits.HasSpace(buf, pos, n1+n2)
   356  	if err != nil {
   357  		return err
   358  	}
   359  
   360  	h.MaxFrameWidthMinus1 = uint32(bits.ReadBitsUnsafe(buf, &pos, n1))
   361  	h.MaxFrameHeightMinus1 = uint32(bits.ReadBitsUnsafe(buf, &pos, n2))
   362  
   363  	if h.ReducedStillPictureHeader {
   364  		h.FrameIDNumbersPresentFlag = false
   365  	} else {
   366  		var err error
   367  		h.FrameIDNumbersPresentFlag, err = bits.ReadFlag(buf, &pos)
   368  		if err != nil {
   369  			return err
   370  		}
   371  
   372  		if h.FrameIDNumbersPresentFlag {
   373  			return fmt.Errorf("frame_id_numbers_present_flag is not supported yet")
   374  		}
   375  	}
   376  
   377  	err = bits.HasSpace(buf, pos, 3)
   378  	if err != nil {
   379  		return err
   380  	}
   381  
   382  	h.Use128x128Superblock = bits.ReadFlagUnsafe(buf, &pos)
   383  	h.EnableFilterIntra = bits.ReadFlagUnsafe(buf, &pos)
   384  	h.EnableIntraEdgeFilter = bits.ReadFlagUnsafe(buf, &pos)
   385  
   386  	if h.ReducedStillPictureHeader {
   387  		h.EnableInterintraCompound = false
   388  		h.EnableMaskedCompound = false
   389  		h.EnableWarpedMotion = false
   390  		h.EnableDualFilter = false
   391  		h.EnableOrderHint = false
   392  		h.EnableJntComp = false
   393  		h.EnableRefFrameMvs = false
   394  		h.SeqForceScreenContentTools = SequenceHeader_SeqForceScreenContentTools_SELECT_SCREEN_CONTENT_TOOLS
   395  		h.SeqForceIntegerMv = SequenceHeader_SeqForceIntegerMv_SELECT_INTEGER_MV
   396  	} else {
   397  		err := bits.HasSpace(buf, pos, 5)
   398  		if err != nil {
   399  			return err
   400  		}
   401  
   402  		h.EnableInterintraCompound = bits.ReadFlagUnsafe(buf, &pos)
   403  		h.EnableMaskedCompound = bits.ReadFlagUnsafe(buf, &pos)
   404  		h.EnableWarpedMotion = bits.ReadFlagUnsafe(buf, &pos)
   405  		h.EnableDualFilter = bits.ReadFlagUnsafe(buf, &pos)
   406  		h.EnableOrderHint = bits.ReadFlagUnsafe(buf, &pos)
   407  
   408  		if h.EnableOrderHint {
   409  			err := bits.HasSpace(buf, pos, 2)
   410  			if err != nil {
   411  				return err
   412  			}
   413  
   414  			h.EnableJntComp = bits.ReadFlagUnsafe(buf, &pos)
   415  			h.EnableRefFrameMvs = bits.ReadFlagUnsafe(buf, &pos)
   416  		}
   417  
   418  		h.SeqChooseScreenContentTools, err = bits.ReadFlag(buf, &pos)
   419  		if err != nil {
   420  			return err
   421  		}
   422  
   423  		if h.SeqChooseScreenContentTools {
   424  			h.SeqForceScreenContentTools = SequenceHeader_SeqForceScreenContentTools_SELECT_SCREEN_CONTENT_TOOLS
   425  		} else {
   426  			tmp, err := bits.ReadBits(buf, &pos, 1)
   427  			if err != nil {
   428  				return err
   429  			}
   430  			h.SeqForceScreenContentTools = SequenceHeader_SeqForceScreenContentTools(tmp)
   431  		}
   432  
   433  		if h.SeqForceScreenContentTools > 0 {
   434  			var err error
   435  			h.SeqChooseIntegerMv, err = bits.ReadFlag(buf, &pos)
   436  			if err != nil {
   437  				return err
   438  			}
   439  
   440  			if h.SeqChooseIntegerMv {
   441  				h.SeqForceIntegerMv = SequenceHeader_SeqForceIntegerMv_SELECT_INTEGER_MV
   442  			} else {
   443  				tmp, err := bits.ReadBits(buf, &pos, 1)
   444  				if err != nil {
   445  					return err
   446  				}
   447  				h.SeqForceIntegerMv = SequenceHeader_SeqForceIntegerMv(tmp)
   448  			}
   449  		} else {
   450  			h.SeqForceIntegerMv = SequenceHeader_SeqForceIntegerMv_SELECT_INTEGER_MV
   451  		}
   452  
   453  		if h.EnableOrderHint {
   454  			tmp, err := bits.ReadBits(buf, &pos, 3)
   455  			if err != nil {
   456  				return err
   457  			}
   458  			h.OrderHintBitsMinus1 = uint8(tmp)
   459  		}
   460  	}
   461  
   462  	err = bits.HasSpace(buf, pos, 3)
   463  	if err != nil {
   464  		return err
   465  	}
   466  
   467  	h.EnableSuperRes = bits.ReadFlagUnsafe(buf, &pos)
   468  	h.EnableCdef = bits.ReadFlagUnsafe(buf, &pos)
   469  	h.EnableRestoration = bits.ReadFlagUnsafe(buf, &pos)
   470  
   471  	return h.ColorConfig.unmarshal(h.SeqProfile, buf, &pos)
   472  }
   473  
   474  // Width returns the video width.
   475  func (h SequenceHeader) Width() int {
   476  	return int(h.MaxFrameWidthMinus1 + 1)
   477  }
   478  
   479  // Height returns the video height.
   480  func (h SequenceHeader) Height() int {
   481  	return int(h.MaxFrameHeightMinus1 + 1)
   482  }