github.com/cnotch/ipchub@v1.1.0/av/format/rtp/demuxer.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 "fmt" 9 "runtime/debug" 10 "time" 11 12 "github.com/cnotch/ipchub/av/codec" 13 "github.com/cnotch/queue" 14 "github.com/cnotch/xlog" 15 ) 16 17 // 网络播放时 PTS(Presentation Time Stamp)的延时 18 const ( 19 ptsDelay = int64(time.Second) 20 ) 21 22 // Depacketizer 解包器 23 type Depacketizer interface { 24 Control(basePts *int64, p *Packet) error 25 Depacketize(basePts int64, p *Packet) error 26 } 27 28 type emptyDepacketizer struct{} 29 30 func (emptyDepacketizer) Control(basePts *int64, p *Packet) error { return nil } 31 func (emptyDepacketizer) Depacketize(basePts int64, p *Packet) error { return nil } 32 33 // Demuxer 帧转换器 34 type Demuxer struct { 35 closed bool 36 recvQueue *queue.SyncQueue 37 vdp Depacketizer 38 adp Depacketizer 39 logger *xlog.Logger 40 } 41 42 func emptyDepacketize(*int64, *Packet) error { return nil } 43 44 // NewDemuxer 创建 rtp.Packet 解封装处理器。 45 func NewDemuxer(video *codec.VideoMeta, audio *codec.AudioMeta, fw codec.FrameWriter, logger *xlog.Logger) (*Demuxer, error) { 46 demuxer := &Demuxer{ 47 recvQueue: queue.NewSyncQueue(), 48 closed: false, 49 logger: logger, 50 } 51 52 switch video.Codec { 53 case "H264": 54 demuxer.vdp = NewH264Depacketizer(video, fw) 55 case "H265": 56 demuxer.vdp = NewH265Depacketizer(video, fw) 57 default: 58 return nil, fmt.Errorf("rtp demuxer unsupport video codec type:%s", video.Codec) 59 } 60 if audio.Codec == "AAC" { 61 demuxer.adp = NewAacDepacketizer(audio, fw) 62 } else { 63 demuxer.adp = emptyDepacketizer{} 64 } 65 66 go demuxer.process() 67 return demuxer, nil 68 } 69 70 func (demuxer *Demuxer) process() { 71 defer func() { 72 defer func() { // 避免 handler 再 panic 73 recover() 74 }() 75 76 if r := recover(); r != nil { 77 demuxer.logger.Errorf("FrameConverter routine panic;r = %v \n %s", r, debug.Stack()) 78 } 79 80 // 尽早通知GC,回收内存 81 demuxer.recvQueue.Reset() 82 }() 83 84 var basePts int64 85 for !demuxer.closed { 86 p := demuxer.recvQueue.Pop() 87 if p == nil { 88 if !demuxer.closed { 89 demuxer.logger.Warn("FrameConverter:receive nil packet") 90 } 91 continue 92 } 93 94 packet := p.(*Packet) 95 var err error 96 switch packet.Channel { 97 case ChannelVideo: 98 err = demuxer.vdp.Depacketize(basePts, packet) 99 case ChannelVideoControl: 100 err = demuxer.vdp.Control(&basePts, packet) 101 case ChannelAudio: 102 err = demuxer.adp.Depacketize(basePts, packet) 103 case ChannelAudioControl: 104 err = demuxer.adp.Control(&basePts, packet) 105 } 106 107 if err != nil { 108 demuxer.logger.Errorf("rtp demuxer: depackeetize rtp frame error :%s", err.Error()) 109 // break 110 } 111 } 112 } 113 114 // Close . 115 func (demuxer *Demuxer) Close() error { 116 if demuxer.closed { 117 return nil 118 } 119 120 demuxer.closed = true 121 demuxer.recvQueue.Signal() 122 return nil 123 } 124 125 // WritePacket . 126 func (demuxer *Demuxer) WriteRtpPacket(packet *Packet) error { 127 demuxer.recvQueue.Push(packet) 128 return nil 129 }