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 }