github.com/cnotch/ipchub@v1.1.0/av/format/rtp/aac_depacketizer.go (about) 1 // Copyright (c) 2019,CAOHONGJU All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package rtp 6 7 import ( 8 "time" 9 10 "github.com/cnotch/ipchub/av/codec" 11 "github.com/cnotch/ipchub/av/codec/aac" 12 ) 13 14 type aacDepacketizer struct { 15 meta *codec.AudioMeta 16 w codec.FrameWriter 17 sizeLength int 18 indexLength int 19 syncClock SyncClock 20 } 21 22 // NewAacDepacketizer 实例化 AAC 解包器 23 func NewAacDepacketizer(meta *codec.AudioMeta, w codec.FrameWriter) Depacketizer { 24 aacdp := &aacDepacketizer{ 25 meta: meta, 26 w: w, 27 sizeLength: 13, 28 indexLength: 3, 29 } 30 aacdp.syncClock.RTPTimeUnit = float64(time.Second) / float64(meta.SampleRate) 31 return aacdp 32 } 33 34 func (aacdp *aacDepacketizer) Control(basePts *int64, p *Packet) error { 35 if ok := aacdp.syncClock.Decode(p.Data); ok { 36 if *basePts == 0 { 37 *basePts = aacdp.syncClock.NTPTime 38 } 39 } 40 return nil 41 } 42 43 // 以下是当 sizelength=13;indexlength=3;indexdeltalength=3 时 44 // Au-header = 13+3 bits(2byte) 的示意图 45 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 46 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| 47 // | AU-headers-length | 48 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| 49 // | AU-header(1) | 50 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| 51 // | AU-header(2) | 52 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| 53 // | ... | 54 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| 55 // | AU-header(n) | 56 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| 57 // | pading bits | 58 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| 59 // 当 sizelength=6;indexlength=2;indexdeltalength=2 时 60 // 单帧封装时,rtp payload的长度 = AU-header-lengths(两个字节) + AU-header(6+2) + AU的长度 61 func (aacdp *aacDepacketizer) Depacketize(basePts int64, packet *Packet) (err error) { 62 if aacdp.syncClock.NTPTime == 0 { // 未收到同步时钟信息,忽略任意包 63 return 64 } 65 return aacdp.depacketizeFor2ByteAUHeader(basePts, packet) 66 } 67 68 func (aacdp *aacDepacketizer) depacketizeFor2ByteAUHeader(basePts int64, packet *Packet) (err error) { 69 payload := packet.Payload() 70 71 // AU-headers-length 2bytes 72 auHeadersLength := uint16(0) | (uint16(payload[0]) << 8) | uint16(payload[1]) 73 // AU-headers-length / 16 74 auHeadersCount := auHeadersLength >> 4 75 // AU 帧数据偏移位置 76 framesPayloadOffset := 2 + int(auHeadersCount)<<1 77 78 auHeaders := payload[2:framesPayloadOffset] 79 framesPayload := payload[framesPayloadOffset:] 80 frameTimeStamp := packet.Timestamp 81 for i := 0; i < int(auHeadersCount); i++ { 82 auHeader := uint16(0) | (uint16(auHeaders[0]) << 8) | uint16(auHeaders[1]) 83 frameSize := auHeader >> aacdp.indexLength 84 pts := aacdp.rtp2ntp(frameTimeStamp) - basePts + ptsDelay 85 frame := &codec.Frame{ 86 MediaType: codec.MediaTypeAudio, 87 Dts: pts, 88 Pts: pts, 89 Payload: framesPayload[:frameSize], 90 } 91 if err = aacdp.w.WriteFrame(frame); err != nil { 92 return 93 } 94 95 // 下一帧 96 auHeaders = auHeaders[2:] 97 framesPayload = framesPayload[frameSize:] 98 frameTimeStamp += aac.SamplesPerFrame // 每帧采样数 99 } 100 101 return 102 } 103 104 func (aacdp *aacDepacketizer) depacketizeFor1ByteAUHeader(basePts int64, packet *Packet) (err error) { 105 payload := packet.Payload() 106 107 // AU-headers-length 2bytes 108 auHeadersLength := uint16(0) | (uint16(payload[0]) << 8) | uint16(payload[1]) 109 // AU-headers-length / 16 110 auHeadersCount := auHeadersLength >> 4 111 // AU 帧数据偏移位置 112 framesPayloadOffset := 2 + int(auHeadersCount) 113 114 auHeaders := payload[2:framesPayloadOffset] 115 framesPayload := payload[framesPayloadOffset:] 116 frameTimeStamp := packet.Timestamp 117 for i := 0; i < int(auHeadersCount); i++ { 118 auHeader := auHeaders[0] 119 frameSize := auHeader >> aacdp.indexLength 120 pts := aacdp.rtp2ntp(frameTimeStamp) - basePts + ptsDelay 121 frame := &codec.Frame{ 122 MediaType: codec.MediaTypeAudio, 123 Dts: pts, 124 Pts: pts, 125 Payload: framesPayload[:frameSize], 126 } 127 if err = aacdp.w.WriteFrame(frame); err != nil { 128 return 129 } 130 131 // 下一帧 132 auHeaders = auHeaders[1:] 133 framesPayload = framesPayload[frameSize:] 134 frameTimeStamp += aac.SamplesPerFrame // 每帧采样数 135 } 136 137 return 138 } 139 140 func (aacdp *aacDepacketizer) rtp2ntp(timestamp uint32) int64 { 141 return aacdp.syncClock.Rtp2Ntp(timestamp) 142 }