rtp.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package aac
  2. import (
  3. "encoding/binary"
  4. "github.com/AlexxIT/go2rtc/pkg/core"
  5. "github.com/pion/rtp"
  6. )
  7. const RTPPacketVersionAAC = 0
  8. const ADTSHeaderSize = 7
  9. func RTPDepay(handler core.HandlerFunc) core.HandlerFunc {
  10. var timestamp uint32
  11. return func(packet *rtp.Packet) {
  12. // support ONLY 2 bytes header size!
  13. // streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1408
  14. // https://datatracker.ietf.org/doc/html/rfc3640
  15. headersSize := binary.BigEndian.Uint16(packet.Payload) >> 3
  16. //log.Printf("[RTP/AAC] units: %d, size: %4d, ts: %10d, %t", headersSize/2, len(packet.Payload), packet.Timestamp, packet.Marker)
  17. if len(packet.Payload) < int(2+headersSize) {
  18. // In very rare cases noname cameras may send data not according to the standard
  19. // https://github.com/AlexxIT/go2rtc/issues/1328
  20. if IsADTS(packet.Payload) {
  21. clone := *packet
  22. clone.Version = RTPPacketVersionAAC
  23. clone.Timestamp = timestamp
  24. clone.Payload = clone.Payload[ADTSHeaderSize:]
  25. handler(&clone)
  26. }
  27. return
  28. }
  29. headers := packet.Payload[2 : 2+headersSize]
  30. units := packet.Payload[2+headersSize:]
  31. for len(headers) >= 2 {
  32. unitSize := binary.BigEndian.Uint16(headers) >> 3
  33. if len(units) < int(unitSize) {
  34. return
  35. }
  36. unit := units[:unitSize]
  37. headers = headers[2:]
  38. units = units[unitSize:]
  39. timestamp += AUTime
  40. clone := *packet
  41. clone.Version = RTPPacketVersionAAC
  42. clone.Timestamp = timestamp
  43. if IsADTS(unit) {
  44. clone.Payload = unit[ADTSHeaderSize:]
  45. } else {
  46. clone.Payload = unit
  47. }
  48. handler(&clone)
  49. }
  50. }
  51. }
  52. func RTPPay(handler core.HandlerFunc) core.HandlerFunc {
  53. sequencer := rtp.NewRandomSequencer()
  54. return func(packet *rtp.Packet) {
  55. if packet.Version != RTPPacketVersionAAC {
  56. handler(packet)
  57. return
  58. }
  59. // support ONLY one unit in payload
  60. auSize := uint16(len(packet.Payload))
  61. // 2 bytes header size + 2 bytes first payload size
  62. payload := make([]byte, 2+2+auSize)
  63. payload[1] = 16 // header size in bits
  64. binary.BigEndian.PutUint16(payload[2:], auSize<<3)
  65. copy(payload[4:], packet.Payload)
  66. clone := rtp.Packet{
  67. Header: rtp.Header{
  68. Version: 2,
  69. Marker: true,
  70. SequenceNumber: sequencer.NextSequenceNumber(),
  71. Timestamp: packet.Timestamp,
  72. },
  73. Payload: payload,
  74. }
  75. handler(&clone)
  76. }
  77. }
  78. func ADTStoRTP(src []byte) (dst []byte) {
  79. dst = make([]byte, 2) // header bytes
  80. for i, n := 0, len(src)-ADTSHeaderSize; i < n; {
  81. auSize := ReadADTSSize(src[i:])
  82. dst = append(dst, byte(auSize>>5), byte(auSize<<3)) // size in bits
  83. i += int(auSize)
  84. }
  85. hdrSize := uint16(len(dst) - 2)
  86. binary.BigEndian.PutUint16(dst, hdrSize<<3) // size in bits
  87. return append(dst, src...)
  88. }
  89. func RTPTimeSize(b []byte) uint32 {
  90. // convert RTP header size to units count
  91. units := binary.BigEndian.Uint16(b) >> 4
  92. return uint32(units) * AUTime
  93. }
  94. func RTPToADTS(codec *core.Codec, handler core.HandlerFunc) core.HandlerFunc {
  95. adts := CodecToADTS(codec)
  96. return func(packet *rtp.Packet) {
  97. src := packet.Payload
  98. dst := make([]byte, 0, len(src))
  99. headersSize := binary.BigEndian.Uint16(src) >> 3
  100. headers := src[2 : 2+headersSize]
  101. units := src[2+headersSize:]
  102. for len(headers) > 0 {
  103. unitSize := binary.BigEndian.Uint16(headers) >> 3
  104. headers = headers[2:]
  105. unit := units[:unitSize]
  106. units = units[unitSize:]
  107. if !IsADTS(unit) {
  108. i := len(dst)
  109. dst = append(dst, adts...)
  110. WriteADTSSize(dst[i:], ADTSHeaderSize+uint16(len(unit)))
  111. }
  112. dst = append(dst, unit...)
  113. }
  114. clone := *packet
  115. clone.Version = RTPPacketVersionAAC
  116. clone.Payload = dst
  117. handler(&clone)
  118. }
  119. }
  120. func RTPToCodec(b []byte) *core.Codec {
  121. hdrSize := binary.BigEndian.Uint16(b) / 8
  122. return ADTSToCodec(b[2+hdrSize:])
  123. }