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  }