add SPEEX codec

This commit is contained in:
nareix 2016-07-13 15:11:11 +08:00
parent 4b5f50e03f
commit e3a02beada
6 changed files with 69 additions and 13 deletions

View File

@ -617,6 +617,9 @@ func NewAudioDecoder(codec av.AudioCodecData) (dec *AudioDecoder, err error) {
return return
} }
case av.SPEEX:
id = C.AV_CODEC_ID_SPEEX
case av.PCM_MULAW: case av.PCM_MULAW:
id = C.AV_CODEC_ID_PCM_MULAW id = C.AV_CODEC_ID_PCM_MULAW
@ -680,17 +683,25 @@ func (self audioCodecData) ChannelLayout() av.ChannelLayout {
} }
func (self audioCodecData) PacketDuration(data []byte) (dur time.Duration, err error) { func (self audioCodecData) PacketDuration(data []byte) (dur time.Duration, err error) {
// TODO: implement it // TODO: implement it: ffmpeg get_audio_frame_duration
err = fmt.Errorf("ffmpeg: cannot get packet duration") err = fmt.Errorf("ffmpeg: cannot get packet duration")
return return
} }
func AudioCodecHandler(h *avutil.RegisterHandler) { func AudioCodecHandler(h *avutil.RegisterHandler) {
h.AudioDecoder = func(codec av.AudioCodecData) (av.AudioDecoder, error) { h.AudioDecoder = func(codec av.AudioCodecData) (av.AudioDecoder, error) {
return NewAudioDecoder(codec) if dec, err := NewAudioDecoder(codec); err != nil {
return nil, nil
} else {
return dec, err
}
} }
h.AudioEncoder = func(typ av.CodecType) (av.AudioEncoder, error) { h.AudioEncoder = func(typ av.CodecType) (av.AudioEncoder, error) {
return NewAudioEncoderByCodecType(typ) if enc, err := NewAudioEncoderByCodecType(typ); err != nil {
return nil, nil
} else {
return enc, err
}
} }
} }

View File

@ -2,6 +2,7 @@ package codec
import ( import (
"github.com/nareix/joy4/av" "github.com/nareix/joy4/av"
"github.com/nareix/joy4/codec/fake"
"time" "time"
) )
@ -41,11 +42,23 @@ func NewPCMAlawCodecData() av.AudioCodecData {
} }
} }
func NewNellyMoserCodecData() av.AudioCodecData { type SpeexCodecData struct {
return PCMUCodecData{typ: av.NELLYMOSER} fake.CodecData
} }
func NewSpeexCodecData() av.AudioCodecData { func (self SpeexCodecData) PacketDuration(data []byte) (time.Duration, error) {
return PCMUCodecData{typ: av.SPEEX} // libavcodec/libspeexdec.c
// samples = samplerate/50
// duration = 0.02s
return time.Millisecond*20, nil
}
func NewSpeexCodecData(sr int, cl av.ChannelLayout) SpeexCodecData {
codec := SpeexCodecData{}
codec.CodecType_ = av.SPEEX
codec.SampleFormat_ = av.S16
codec.SampleRate_ = sr
codec.ChannelLayout_ = cl
return codec
} }

View File

@ -5,10 +5,25 @@ import (
) )
type CodecData struct { type CodecData struct {
Typ av.CodecType CodecType_ av.CodecType
SampleRate_ int
SampleFormat_ av.SampleFormat
ChannelLayout_ av.ChannelLayout
} }
func (self CodecData) Type() av.CodecType { func (self CodecData) Type() av.CodecType {
return self.Typ return self.CodecType_
}
func (self CodecData) SampleFormat() av.SampleFormat {
return self.SampleFormat_
}
func (self CodecData) ChannelLayout() av.ChannelLayout {
return self.ChannelLayout_
}
func (self CodecData) SampleRate() int {
return self.SampleRate_
} }

View File

@ -6,6 +6,7 @@ import (
"github.com/nareix/joy4/av/avutil" "github.com/nareix/joy4/av/avutil"
"github.com/nareix/joy4/codec/h264parser" "github.com/nareix/joy4/codec/h264parser"
"github.com/nareix/joy4/codec" "github.com/nareix/joy4/codec"
"github.com/nareix/joy4/codec/fake"
"github.com/nareix/joy4/codec/aacparser" "github.com/nareix/joy4/codec/aacparser"
"github.com/nareix/pio" "github.com/nareix/pio"
"github.com/nareix/joy4/format/flv/flvio" "github.com/nareix/joy4/format/flv/flvio"
@ -78,7 +79,7 @@ func (self *Prober) PushTag(_tag flvio.Tag, timestamp int32) (err error) {
case flvio.SOUND_SPEEX: case flvio.SOUND_SPEEX:
if !self.GotAudio { if !self.GotAudio {
stream := codec.NewSpeexCodecData() stream := codec.NewSpeexCodecData(16000, tag.ChannelLayout())
self.AudioStreamIdx = len(self.Streams) self.AudioStreamIdx = len(self.Streams)
self.Streams = append(self.Streams, stream) self.Streams = append(self.Streams, stream)
self.GotAudio = true self.GotAudio = true
@ -87,7 +88,12 @@ func (self *Prober) PushTag(_tag flvio.Tag, timestamp int32) (err error) {
case flvio.SOUND_NELLYMOSER: case flvio.SOUND_NELLYMOSER:
if !self.GotAudio { if !self.GotAudio {
stream := codec.NewNellyMoserCodecData() stream := fake.CodecData{
CodecType_: av.NELLYMOSER,
SampleRate_: 16000,
SampleFormat_: av.S16,
ChannelLayout_: tag.ChannelLayout(),
}
self.AudioStreamIdx = len(self.Streams) self.AudioStreamIdx = len(self.Streams)
self.Streams = append(self.Streams, stream) self.Streams = append(self.Streams, stream)
self.GotAudio = true self.GotAudio = true
@ -275,8 +281,10 @@ func NewMuxer(w io.Writer) *Muxer {
return self return self
} }
var SupportedCodecTypes = []av.CodecType{av.H264, av.AAC, av.SPEEX}
func (self *Muxer) SupportedCodecTypes() []av.CodecType { func (self *Muxer) SupportedCodecTypes() []av.CodecType {
return []av.CodecType{av.H264, av.AAC, av.NELLYMOSER, av.SPEEX} return SupportedCodecTypes
} }
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) { func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {

View File

@ -5,6 +5,7 @@ import (
"time" "time"
"fmt" "fmt"
"github.com/nareix/pio" "github.com/nareix/pio"
"github.com/nareix/joy4/av"
) )
func TsToTime(ts int32) time.Duration { func TsToTime(ts int32) time.Duration {
@ -144,6 +145,14 @@ func (self Audiodata) Type() uint8 {
return TAG_AUDIO return TAG_AUDIO
} }
func (self Audiodata) ChannelLayout() av.ChannelLayout {
if self.SoundType == SOUND_MONO {
return av.CH_MONO
} else {
return av.CH_STEREO
}
}
func (self Audiodata) Len() int { func (self Audiodata) Len() int {
if self.SoundFormat == SOUND_AAC { if self.SoundFormat == SOUND_AAC {
return 2 + len(self.Data) return 2 + len(self.Data)

View File

@ -316,7 +316,7 @@ func createURL(tcurl, app, play string) (u *url.URL) {
} }
func (self *Conn) SupportedCodecTypes() []av.CodecType { func (self *Conn) SupportedCodecTypes() []av.CodecType {
return []av.CodecType{av.H264, av.AAC} return flv.SupportedCodecTypes
} }
func (self *Conn) recvConnect() (err error) { func (self *Conn) recvConnect() (err error) {