package icsmediaconv import ( "fmt" "sync" "gitlab.com/ics_cinnamon/joy4/av" "gitlab.com/ics_cinnamon/joy4/cgo/ffmpeg" "gitlab.com/ics_cinnamon/joy4/codec" "gitlab.com/ics_cinnamon/voicegateway/icserror" "gitlab.com/ics_cinnamon/voicegateway/icslog" "gitlab.com/ics_cinnamon/voicegateway/icspacketparser" ) const ( ICS_PT_MULAW = 0 ICS_PT_ALAW = 8 ICS_PT_G729 = 18 ICS_PT_END = ICS_PT_G729 ) const PCM_8K_16BIT_10MS_SIZE = 160 type Converter struct { payloadtype icspacketparser.PayloadType codec av.AudioCodecData name string decoder *ffmpeg.AudioDecoder encoder *ffmpeg.AudioEncoder samplingRate int onePacketSize int //frame *av.AudioFrame isStart bool m *sync.Mutex ID int } func NewConverter(id int, pt icspacketparser.PayloadType, dec bool) (*Converter, *icserror.IcsError) { conv := &Converter{payloadtype: pt} conv.ID = id conv.isStart = false conv.m = &sync.Mutex{} if dec { //decoding switch pt { case ICS_PT_MULAW: conv.codec = codec.NewPCMMulawCodecData() conv.samplingRate = 8000 conv.onePacketSize = 80 //conv.onePacketSize = 160 case ICS_PT_ALAW: conv.codec = codec.NewPCMAlawCodecData() conv.samplingRate = 8000 conv.onePacketSize = 80 //conv.onePacketSize = 160 case ICS_PT_G729: conv.codec = codec.NewG729CodecData() conv.samplingRate = 8000 conv.onePacketSize = 10 default: return nil, icserror.ICSERRCONVNotSupportedCodec } var err error conv.decoder, err = ffmpeg.NewAudioDecoder(conv.codec) if err != nil { icserror.ICSERRCONVNotSupportedCodec.SetError(err) return nil, icserror.ICSERRCONVNotSupportedCodec } } else { //encoding switch pt { case ICS_PT_MULAW: conv.codec = codec.NewPCMMulawCodecData() conv.name = "mulaw" conv.samplingRate = 8000 conv.onePacketSize = 160 case ICS_PT_ALAW: conv.codec = codec.NewPCMAlawCodecData() conv.name = "alaw" conv.samplingRate = 8000 conv.onePacketSize = 160 case ICS_PT_G729: conv.codec = codec.NewG729CodecData() conv.name = "g729" conv.samplingRate = 8000 conv.onePacketSize = 10 default: return nil, icserror.ICSERRCONVNotSupportedCodec } var err error conv.encoder, err = ffmpeg.NewAudioEncoderByCodecType(conv.codec.Type()) if err != nil { fmt.Println("########111", err) icserror.ICSERRCONVNotSupportedCodec.SetError(err) return nil, icserror.ICSERRCONVNotSupportedCodec } conv.encoder.SetChannelLayout(av.CH_MONO) conv.encoder.SetSampleRate(conv.samplingRate) conv.encoder.SetSampleFormat(av.S16) // fmt.Println("########222", conv.name) } //ffmpeg.SetLogLevel(ffmpeg.QUIET) conv.Start() return conv, nil } func (c *Converter) Start() { c.m.Lock() c.isStart = true c.m.Unlock() } func (c *Converter) Stop() { c.m.Lock() c.isStart = false c.m.Unlock() } func (c *Converter) IsStart() bool { return c.isStart } func (c *Converter) Close() { c.Stop() if c.decoder != nil { c.decoder.Close() } if c.encoder != nil { c.encoder.Close() } l := icslog.GetIcsLog() l.Print(icslog.LOG_LEVEL_INFO, c.ID, "Closed Converter") } func (c *Converter) Decode(packet []byte) ([]byte, *icserror.IcsError) { if c == nil { return nil, icserror.ICSERRInvalidParam } //l := icslog.GetIcsLog() //l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "converter### Decode() packet length: %d", len(packet)) retBuf := make([]byte, PCM_8K_16BIT_10MS_SIZE*2) packetLen := len(packet) iter := 0 for packetLen >= c.onePacketSize { packetLen -= c.onePacketSize //fmt.Printf("### Decode() iter(%d) packetlen(%d)\n", iter, packetLen) buf := packet[c.onePacketSize*iter : c.onePacketSize*(iter+1)] //fmt.Printf("### Decode() iter(%d), buf length %d %v\n", iter, len(buf), buf) //l.Printf(icslog.LOG_LEVEL_DEBUG2, c.ID, "### Decode() iter(%d), buf length %d %v", iter, len(buf), buf) c.m.Lock() if c.IsStart() { ok, frame, errDec := c.decoder.Decode(buf) if !ok { icserror.ICSERRCONVDecodeFail.SetError(errDec) //icserror.ICSERRCONVDecodeFail.Print() c.m.Unlock() return nil, icserror.ICSERRCONVDecodeFail } //fmt.Println("###frame len", iter, PCM_8K_16BIT_10MS_SIZE*iter, PCM_8K_16BIT_10MS_SIZE*(iter+1)) //fmt.Println("###frame len", len(frame.Data[0]), len(frame.Data), frame) copy(retBuf[PCM_8K_16BIT_10MS_SIZE*iter:PCM_8K_16BIT_10MS_SIZE*(iter+1)], frame.Data[0][:PCM_8K_16BIT_10MS_SIZE]) } c.m.Unlock() /* f1, err := os.OpenFile("./tx.voice.raw", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } f1.Write(frame.Data[0][:PCM_8K_16BIT_10MS_SIZE]) f1.Sync() f1.Close() */ iter++ } //fmt.Println("###retBuf len", len(retBuf), retBuf) return retBuf, nil } func (c *Converter) Encode(packet []byte) ([]byte, *icserror.IcsError) { if c == nil { return nil, icserror.ICSERRInvalidParam } //l := icslog.GetIcsLog() //l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "converter### Decode() packet length: %d", len(packet)) retBuf := make([]byte, PCM_8K_16BIT_10MS_SIZE) //retBuf := make([]byte, PCM_8K_16BIT_10MS_SIZE*2) packetLen := len(packet) iter := 0 var onePacketSize int = c.onePacketSize if c.codec.Type() == av.PCM_ALAW || c.codec.Type() == av.PCM_MULAW { onePacketSize = onePacketSize //onePacketSize = onePacketSize / 2 } for packetLen >= onePacketSize { packetLen -= onePacketSize //for packetLen >= c.onePacketSize { //packetLen -= c.onePacketSize //fmt.Printf("### Decode() iter(%d) packetlen(%d)\n", iter, packetLen) buf := packet[onePacketSize*iter : onePacketSize*(iter+1)] //buf := packet[c.onePacketSize*iter : c.onePacketSize*(iter+1)] //fmt.Printf("### Decode() iter(%d), buf length %d %v\n", iter, len(buf), buf) //l.Printf(icslog.LOG_LEVEL_DEBUG2, c.ID, "### Decode() iter(%d), buf length %d %v", iter, len(buf), buf) tbuf := make([][]byte, 1) tbuf[0] = buf frame := av.AudioFrame{ SampleFormat: av.S16, ChannelLayout: av.CH_MONO, SampleCount: c.onePacketSize / 2, SampleRate: c.samplingRate, Data: tbuf, } //fmt.Printf(">>>%+v\n", frame) c.m.Lock() if c.IsStart() { pcmFrame, errEnc := c.encoder.Encode(frame) //ok, frame, errDec := c.decoder.Decode(buf) if errEnc != nil { icserror.ICSERRCONVEncodeFail.SetError(errEnc) //icserror.ICSERRCONVDecodeFail.Print() c.m.Unlock() return nil, icserror.ICSERRCONVEncodeFail } //fmt.Println("###frame len", iter, PCM_8K_16BIT_10MS_SIZE*iter, PCM_8K_16BIT_10MS_SIZE*(iter+1)) //fmt.Println("###frame len", len(frame.Data[0]), len(frame.Data), frame) copy(retBuf[(PCM_8K_16BIT_10MS_SIZE/2)*iter:(PCM_8K_16BIT_10MS_SIZE/2)*(iter+1)], pcmFrame[0][:(PCM_8K_16BIT_10MS_SIZE/2)]) //copy(retBuf[PCM_8K_16BIT_10MS_SIZE*iter:PCM_8K_16BIT_10MS_SIZE*(iter+1)], pcmFrame[0][:PCM_8K_16BIT_10MS_SIZE]) //fmt.Printf("%d$$$%v", len(pcmFrame[0]), pcmFrame[0]) } c.m.Unlock() iter++ } //fmt.Println("###retBuf len", len(retBuf), retBuf) return retBuf, nil }