github.com/cnotch/ipchub@v1.1.0/av/format/rtp/packet.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 "bufio" 9 "encoding/binary" 10 "errors" 11 "io" 12 13 "github.com/pion/rtp" 14 ) 15 16 const ( 17 // TransferPrefix RTP 包网络传输时的前缀 18 TransferPrefix = byte(0x24) // $ 19 ) 20 21 // 预定义 RTP 通道类型 22 const ( 23 ChannelVideo = iota // 视频通道 24 ChannelVideoControl // 视频控制通道 25 ChannelAudio // 音频通道 26 ChannelAudioControl // 音频控制通道 27 ChannelCount // 支持的 RTP 通道类型数量 28 ChannelMin = ChannelVideo // 支持的 RTP 通道类型最小值 29 ) 30 31 // DefaultChannelConfig 默认的通道配置 32 var DefaultChannelConfig = []int{ 33 ChannelVideo, 34 ChannelVideoControl, 35 ChannelAudio, 36 ChannelAudioControl, 37 } 38 39 // ChannelName 通道名 40 func ChannelName(channel int) string { 41 switch channel { 42 case ChannelAudio: 43 return "audio" 44 case ChannelVideo: 45 return "video" 46 case ChannelAudioControl: 47 return "audio control" 48 case ChannelVideoControl: 49 return "video control" 50 } 51 return "unknow" 52 } 53 54 // Packet RTP 数据包 55 type Packet struct { 56 Channel byte // 通道 57 Data []byte // 数据 58 rtp.Header // Video 、Audio Channel'Header 59 } 60 61 // PacketWriter 包装 WritePacket 方法的接口 62 type PacketWriter interface { 63 WriteRtpPacket(packet *Packet) error 64 } 65 66 // ReadPacket 根据规范从 r 中读取 rtp 包. 67 // channelConfig 提供通道类型所在通道的配置信息 68 func ReadPacket(r *bufio.Reader, channelConfig []int) (*Packet, error) { 69 var err error 70 71 var prefix [4]byte 72 // 读前缀4字节 73 if _, err = io.ReadFull(r, prefix[:]); err != nil { 74 return nil, err 75 } 76 77 if prefix[0] != TransferPrefix { 78 return nil, errors.New("RTP Pack must start with `$`") 79 } 80 81 channel := int(prefix[1]) 82 rtpLen := int(binary.BigEndian.Uint16(prefix[2:])) 83 84 // 读取包数据 85 rtpBytes := make([]byte, rtpLen) 86 if _, err = io.ReadFull(r, rtpBytes); err != nil { 87 return nil, err 88 } 89 90 var p = new(Packet) 91 p.Data = rtpBytes 92 for i, v := range channelConfig { 93 if v == channel { 94 p.Channel = byte(i) 95 if p.Channel == ChannelVideo || p.Channel == ChannelAudio { 96 if err = p.Header.Unmarshal(p.Data); err != nil { 97 return nil, err 98 } 99 } 100 return p, nil 101 } 102 } 103 return nil, errors.New("RTP Packet illegal channel") 104 } 105 106 // Write 根据规范将 RTP 包输出到 w 107 // channelConfig 提供通道类型所在通道的配置信息 108 func (p *Packet) Write(w io.Writer, channelConfig []int) error { 109 if p.Channel >= ChannelCount { 110 return errors.New("unknow pack type") 111 } 112 113 ch := channelConfig[p.Channel] 114 if ch < 0 || ch > 255 { // 可能是未订阅,忽略 115 return nil 116 } 117 118 var prefix [4]byte 119 prefix[0] = TransferPrefix // 起始字节 120 prefix[1] = byte(ch) // channel 121 binary.BigEndian.PutUint16(prefix[2:], uint16(len(p.Data))) 122 123 // 写前4个字节 124 if _, err := w.Write(prefix[:]); err != nil { 125 return err 126 } 127 128 // 写包数据部分 129 if _, err := w.Write(p.Data); err != nil { 130 return err 131 } 132 133 return nil 134 } 135 136 // Size 包在 RTP 中的传输总大小 137 func (p *Packet) Size() int { 138 return len(p.Data) + 4 139 } 140 141 // Payload 数据包中实际的载荷 142 // 如果是控制通道,返回nil 143 func (p *Packet) Payload() []byte { 144 if p.Channel == ChannelVideo || p.Channel == ChannelAudio { 145 return p.Data[p.PayloadOffset:] 146 } 147 return nil 148 }