av1_packet.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package codecs
  2. import (
  3. "github.com/pion/rtp/pkg/obu"
  4. )
  5. const (
  6. zMask = byte(0b10000000)
  7. zBitshift = 7
  8. yMask = byte(0b01000000)
  9. yBitshift = 6
  10. wMask = byte(0b00110000)
  11. wBitshift = 4
  12. nMask = byte(0b00001000)
  13. nBitshift = 3
  14. av1PayloaderHeadersize = 1
  15. )
  16. // AV1Payloader payloads AV1 packets
  17. type AV1Payloader struct{}
  18. // Payload fragments a AV1 packet across one or more byte arrays
  19. // See AV1Packet for description of AV1 Payload Header
  20. func (p *AV1Payloader) Payload(mtu uint16, payload []byte) (payloads [][]byte) {
  21. maxFragmentSize := int(mtu) - av1PayloaderHeadersize - 2
  22. payloadDataRemaining := len(payload)
  23. payloadDataIndex := 0
  24. // Make sure the fragment/payload size is correct
  25. if min(maxFragmentSize, payloadDataRemaining) <= 0 {
  26. return payloads
  27. }
  28. for payloadDataRemaining > 0 {
  29. currentFragmentSize := min(maxFragmentSize, payloadDataRemaining)
  30. leb128Size := 1
  31. if currentFragmentSize >= 127 {
  32. leb128Size = 2
  33. }
  34. out := make([]byte, av1PayloaderHeadersize+leb128Size+currentFragmentSize)
  35. leb128Value := obu.EncodeLEB128(uint(currentFragmentSize))
  36. if leb128Size == 1 {
  37. out[1] = byte(leb128Value)
  38. } else {
  39. out[1] = byte(leb128Value >> 8)
  40. out[2] = byte(leb128Value)
  41. }
  42. copy(out[av1PayloaderHeadersize+leb128Size:], payload[payloadDataIndex:payloadDataIndex+currentFragmentSize])
  43. payloads = append(payloads, out)
  44. payloadDataRemaining -= currentFragmentSize
  45. payloadDataIndex += currentFragmentSize
  46. if len(payloads) > 1 {
  47. out[0] ^= zMask
  48. }
  49. if payloadDataRemaining != 0 {
  50. out[0] ^= yMask
  51. }
  52. }
  53. return payloads
  54. }
  55. // AV1Packet represents a depacketized AV1 RTP Packet
  56. //
  57. // 0 1 2 3 4 5 6 7
  58. // +-+-+-+-+-+-+-+-+
  59. // |Z|Y| W |N|-|-|-|
  60. // +-+-+-+-+-+-+-+-+
  61. //
  62. // https://aomediacodec.github.io/av1-rtp-spec/#44-av1-aggregation-header
  63. type AV1Packet struct {
  64. // Z: MUST be set to 1 if the first OBU element is an
  65. // OBU fragment that is a continuation of an OBU fragment
  66. // from the previous packet, and MUST be set to 0 otherwise.
  67. Z bool
  68. // Y: MUST be set to 1 if the last OBU element is an OBU fragment
  69. // that will continue in the next packet, and MUST be set to 0 otherwise.
  70. Y bool
  71. // W: two bit field that describes the number of OBU elements in the packet.
  72. // This field MUST be set equal to 0 or equal to the number of OBU elements
  73. // contained in the packet. If set to 0, each OBU element MUST be preceded by
  74. // a length field. If not set to 0 (i.e., W = 1, 2 or 3) the last OBU element
  75. // MUST NOT be preceded by a length field. Instead, the length of the last OBU
  76. // element contained in the packet can be calculated as follows:
  77. // Length of the last OBU element =
  78. // length of the RTP payload
  79. // - length of aggregation header
  80. // - length of previous OBU elements including length fields
  81. W byte
  82. // N: MUST be set to 1 if the packet is the first packet of a coded video sequence, and MUST be set to 0 otherwise.
  83. N bool
  84. // Each AV1 RTP Packet is a collection of OBU Elements. Each OBU Element may be a full OBU, or just a fragment of one.
  85. // AV1Frame provides the tools to construct a collection of OBUs from a collection of OBU Elements
  86. OBUElements [][]byte
  87. }
  88. // Unmarshal parses the passed byte slice and stores the result in the AV1Packet this method is called upon
  89. func (p *AV1Packet) Unmarshal(payload []byte) ([]byte, error) {
  90. if payload == nil {
  91. return nil, errNilPacket
  92. } else if len(payload) < 2 {
  93. return nil, errShortPacket
  94. }
  95. p.Z = ((payload[0] & zMask) >> zBitshift) != 0
  96. p.Y = ((payload[0] & yMask) >> yBitshift) != 0
  97. p.N = ((payload[0] & nMask) >> nBitshift) != 0
  98. p.W = (payload[0] & wMask) >> wBitshift
  99. if p.Z && p.N {
  100. return nil, errIsKeyframeAndFragment
  101. }
  102. currentIndex := uint(1)
  103. p.OBUElements = [][]byte{}
  104. var (
  105. obuElementLength, bytesRead uint
  106. err error
  107. )
  108. for i := 1; ; i++ {
  109. if currentIndex == uint(len(payload)) {
  110. break
  111. }
  112. // If W bit is set the last OBU Element will have no length header
  113. if byte(i) == p.W {
  114. bytesRead = 0
  115. obuElementLength = uint(len(payload)) - currentIndex
  116. } else {
  117. obuElementLength, bytesRead, err = obu.ReadLeb128(payload[currentIndex:])
  118. if err != nil {
  119. return nil, err
  120. }
  121. }
  122. currentIndex += bytesRead
  123. if uint(len(payload)) < currentIndex+obuElementLength {
  124. return nil, errShortPacket
  125. }
  126. p.OBUElements = append(p.OBUElements, payload[currentIndex:currentIndex+obuElementLength])
  127. currentIndex += obuElementLength
  128. }
  129. return payload[1:], nil
  130. }