github.com/cnotch/ipchub@v1.1.0/av/format/mpegts/muxer.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 mpegts 6 7 import ( 8 "fmt" 9 "runtime/debug" 10 11 "github.com/cnotch/ipchub/av/codec" 12 "github.com/cnotch/queue" 13 "github.com/cnotch/xlog" 14 ) 15 16 // Packetizer 封包器 17 type Packetizer interface { 18 Packetize(frame *codec.Frame) error 19 } 20 21 type emptyPacketizer struct{} 22 23 func (emptyPacketizer) Packetize(frame *codec.Frame) error { return nil } 24 25 // Muxer mpegts muxer from av.Frame(H264[+AAC]) 26 type Muxer struct { 27 recvQueue *queue.SyncQueue 28 closed bool 29 logger *xlog.Logger // 日志对象 30 } 31 32 // NewMuxer . 33 func NewMuxer(videoMeta *codec.VideoMeta, audioMeta *codec.AudioMeta, tsframeWriter FrameWriter, logger *xlog.Logger) (*Muxer, error) { 34 muxer := &Muxer{ 35 recvQueue: queue.NewSyncQueue(), 36 closed: false, 37 logger: logger, 38 } 39 var vp Packetizer = emptyPacketizer{} 40 var ap Packetizer = emptyPacketizer{} 41 42 switch videoMeta.Codec { 43 case "H264": 44 vp = NewH264Packetizer(videoMeta, tsframeWriter) 45 default: 46 return nil, fmt.Errorf("ts muxer unsupport video codec type:%s", videoMeta.Codec) 47 } 48 49 switch audioMeta.Codec { 50 case "AAC": 51 ap = NewAacPacketizer(audioMeta, tsframeWriter) 52 default: 53 return nil, fmt.Errorf("ts muxer unsupport audio codec type:%s", videoMeta.Codec) 54 } 55 56 go muxer.process(vp, ap) 57 return muxer, nil 58 } 59 60 // WriteFrame . 61 func (muxer *Muxer) WriteFrame(frame *codec.Frame) error { 62 muxer.recvQueue.Push(frame) 63 return nil 64 } 65 66 // Close . 67 func (muxer *Muxer) Close() error { 68 if muxer.closed { 69 return nil 70 } 71 72 muxer.closed = true 73 muxer.recvQueue.Signal() 74 return nil 75 } 76 77 func (muxer *Muxer) process(vp, ap Packetizer) { 78 defer func() { 79 defer func() { // 避免 handler 再 panic 80 recover() 81 }() 82 83 if r := recover(); r != nil { 84 muxer.logger.Errorf("ts muxer routine panic;r = %v \n %s", r, debug.Stack()) 85 } 86 87 // 尽早通知GC,回收内存 88 muxer.recvQueue.Reset() 89 }() 90 91 for !muxer.closed { 92 f := muxer.recvQueue.Pop() 93 if f == nil { 94 if !muxer.closed { 95 muxer.logger.Warn("tsmuxer: receive nil frame") 96 } 97 continue 98 } 99 100 frame := f.(*codec.Frame) 101 102 switch frame.MediaType { 103 case codec.MediaTypeVideo: 104 if err := vp.Packetize(frame); err != nil { 105 muxer.logger.Errorf("tsmuxer: muxVideoTag error - %s", err.Error()) 106 } 107 case codec.MediaTypeAudio: 108 if err := ap.Packetize(frame); err != nil { 109 muxer.logger.Errorf("tsmuxer: muxAudioTag error - %s", err.Error()) 110 } 111 default: 112 } 113 } 114 }