From 790569a35a7b30211a213775dd878bd43a7106a8 Mon Sep 17 00:00:00 2001 From: nareix Date: Wed, 25 May 2016 07:44:06 +0800 Subject: [PATCH] update --- aacenc.go | 16 ++--- aacparser/parser.go | 59 +++++++++++++++--- h264parser/parser.go | 145 +++++++++++++++++++++++++++++++------------ 3 files changed, 166 insertions(+), 54 deletions(-) diff --git a/aacenc.go b/aacenc.go index 7ce6c21..b350d1e 100644 --- a/aacenc.go +++ b/aacenc.go @@ -17,7 +17,7 @@ import ( } aacenc_t ; static int aacenc_new(aacenc_t *m) { - m->c = avcodec_find_encoder(CODEC_ID_AAC); + m->c = avcodec_find_encoder_by_name("aac"); m->ctx = avcodec_alloc_context3(m->c); m->ctx->sample_fmt = AV_SAMPLE_FMT_FLTP; m->ctx->sample_rate = m->samplerate; @@ -26,7 +26,7 @@ import ( m->ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; m->f = av_frame_alloc(); int r = avcodec_open2(m->ctx, m->c, 0); - av_log(m->ctx, AV_LOG_DEBUG, "extra %d\n", m->ctx->extradata_size); + //av_log(m->ctx, AV_LOG_DEBUG, "extra %d\n", m->ctx->extradata_size); return r; } @@ -37,7 +37,8 @@ import ( pkt.size = sizeof(m->buf); m->f->nb_samples = 1024; m->f->extended_data = m->f->data; - m->f->linesize[0] = 4096; + m->f->linesize[0] = 1024*4; + //m->f->linesize[1] = 1024*4; avcodec_encode_audio2(m->ctx, &pkt, m->f, &m->got); av_log(m->ctx, AV_LOG_DEBUG, "got %d size %d\n", m->got, pkt.size); m->size = pkt.size; @@ -53,12 +54,12 @@ type AACEncoder struct { Header []byte } -// only supported fltp,stereo,44100khz. If you need other config, it's easy to modify code +// only supported fltp,stereo,44100HZ. If you need other config, it's easy to modify code func NewAACEncoder() (m *AACEncoder, err error) { m = &AACEncoder{} m.m.samplerate = 44100 m.m.bitrate = 50000 - m.m.channels = 2 + m.m.channels = 1 r := C.aacenc_new(&m.m) if int(r) != 0 { err = errors.New("open codec failed") @@ -67,7 +68,7 @@ func NewAACEncoder() (m *AACEncoder, err error) { m.Header = make([]byte, (int)(m.m.ctx.extradata_size)) C.memcpy( unsafe.Pointer(&m.Header[0]), - unsafe.Pointer(&m.m.ctx.extradata), + unsafe.Pointer(m.m.ctx.extradata), (C.size_t)(len(m.Header)), ) return @@ -75,7 +76,7 @@ func NewAACEncoder() (m *AACEncoder, err error) { func (m *AACEncoder) Encode(sample []byte) (ret []byte, err error) { m.m.f.data[0] = (*C.uint8_t)(unsafe.Pointer(&sample[0])) - m.m.f.data[1] = (*C.uint8_t)(unsafe.Pointer(&sample[4096])) + //m.m.f.data[1] = (*C.uint8_t)(unsafe.Pointer(&sample[1024*4])) C.aacenc_encode(&m.m) if int(m.m.got) == 0 { err = errors.New("no data") @@ -89,3 +90,4 @@ func (m *AACEncoder) Encode(sample []byte) (ret []byte, err error) { ) return } + diff --git a/aacparser/parser.go b/aacparser/parser.go index 0a3a1f4..b4fab3d 100644 --- a/aacparser/parser.go +++ b/aacparser/parser.go @@ -2,6 +2,7 @@ package aacparser import ( "github.com/nareix/bits" + "github.com/nareix/av" "fmt" "bytes" "io" @@ -247,6 +248,16 @@ func (self MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) { return } +func ParseMPEG4AudioConfig(data []byte) (config MPEG4AudioConfig, err error) { + r := bytes.NewReader(data) + if config, err = ReadMPEG4AudioConfig(r); err != nil { + err = fmt.Errorf("CodecData invalid: parse MPEG4AudioConfig failed(%s)", err) + return + } + config = config.Complete() + return +} + func ReadMPEG4AudioConfig(r io.Reader) (config MPEG4AudioConfig, err error) { // copied from libavcodec/mpeg4audio.c avpriv_mpeg4audio_get_config() br := &bits.Reader{R: r} @@ -298,17 +309,51 @@ func WriteMPEG4AudioConfig(w io.Writer, config MPEG4AudioConfig) (err error) { return } -type CodecInfo struct { - MPEG4AudioConfig +type CodecData struct { + Config []byte + ConfigInfo MPEG4AudioConfig } -func ParseCodecData(config []byte) (info CodecInfo, err error) { - r := bytes.NewReader(config) - if info.MPEG4AudioConfig, err = ReadMPEG4AudioConfig(r); err != nil { - err = fmt.Errorf("CodecData invalid: parse MPEG4AudioConfig failed(%s)", err) +func (self CodecData) IsVideo() bool { + return false +} + +func (self CodecData) IsAudio() bool { + return true +} + +func (self CodecData) Type() int { + return av.AAC +} + +func (self CodecData) MPEG4AudioConfigBytes() []byte { + return self.Config +} + +func (self CodecData) ChannelCount() int { + return self.ConfigInfo.ChannelCount +} + +func (self CodecData) SampleRate() int { + return self.ConfigInfo.SampleRate +} + +func (self CodecData) SampleFormat() av.SampleFormat { + return av.FLTP +} + +func (self CodecData) MakeADTSHeader(samples int, payloadLength int) []byte { + return MakeADTSHeader(self.ConfigInfo, samples, payloadLength) +} + +func NewCodecDataFromMPEG4AudioConfigBytes(config []byte) (codec av.AACCodecData, err error) { + self := CodecData{} + self.Config = config + if self.ConfigInfo, err = ParseMPEG4AudioConfig(config); err != nil { + err = fmt.Errorf("parse MPEG4AudioConfig failed(%s)", err) return } - info.MPEG4AudioConfig = info.MPEG4AudioConfig.Complete() + codec = self return } diff --git a/h264parser/parser.go b/h264parser/parser.go index 5d05769..72ef921 100644 --- a/h264parser/parser.go +++ b/h264parser/parser.go @@ -2,6 +2,7 @@ package h264parser import ( + "github.com/nareix/av" "github.com/nareix/bits" "io" "fmt" @@ -492,25 +493,6 @@ func ParseSPS(data []byte) (self SPSInfo, err error) { return } -/* -func MakeAVCDecoderConfRecord( - SPS []byte, - PPS []byte, -) (self AVCDecoderConfRecord, err error) { - if len(SPS) < 4 { - err = fmt.Errorf("invalid SPS data") - return - } - self.AVCProfileIndication = int(SPS[1]) - self.ProfileCompatibility = int(SPS[2]) - self.AVCLevelIndication = int(SPS[3]) - self.SPS = [][]byte{SPS} - self.PPS = [][]byte{PPS} - self.LengthSizeMinusOne = 3 - return -} -*/ - func WriteAVCDecoderConfRecord(w io.Writer, self AVCDecoderConfRecord) (err error) { if err = bits.WriteUIntBE(w, 1, 8); err != nil { return @@ -555,42 +537,85 @@ func WriteAVCDecoderConfRecord(w io.Writer, self AVCDecoderConfRecord) (err erro return } -type CodecInfo struct { - Record AVCDecoderConfRecord +type CodecData struct { + Record []byte + RecordInfo AVCDecoderConfRecord SPSInfo SPSInfo } -// CodecData is AVCDecoderConfRecord -func ParseCodecData(config []byte) (info CodecInfo, err error) { - if info.Record, err = ParseAVCDecoderConfRecord(config); err != nil { +func (self CodecData) Type() int { + return av.H264 +} + +func (self CodecData) IsVideo() bool { + return true +} + +func (self CodecData) AVCDecoderConfRecordBytes() []byte { + return self.Record +} + +func (self CodecData) SPS() []byte { + return self.RecordInfo.SPS[0] +} + +func (self CodecData) PPS() []byte { + return self.RecordInfo.PPS[0] +} + +func (self CodecData) IsAudio() bool { + return false +} + +func (self CodecData) Width() int { + return int(self.SPSInfo.Width) +} + +func (self CodecData) Height() int { + return int(self.SPSInfo.Height) +} + +func NewCodecDataFromAVCDecoderConfRecord(record []byte) (codec av.H264CodecData, err error) { + self := CodecData{} + self.Record = record + if self.RecordInfo, err = ParseAVCDecoderConfRecord(record); err != nil { return } - if len(info.Record.SPS) < 1 { - err = fmt.Errorf("CodecData invalid: no SPS found in AVCDecoderConfRecord") + if len(self.RecordInfo.SPS) == 0 { + err = fmt.Errorf("no SPS found in AVCDecoderConfRecord") return } - if info.SPSInfo, err = ParseSPS(info.Record.SPS[0]); err != nil { - err = fmt.Errorf("CodecData invalid: parse SPS failed(%s)", err) + if len(self.RecordInfo.PPS) == 0 { + err = fmt.Errorf("no PPS found in AVCDecoderConfRecord") return } + if self.SPSInfo, err = ParseSPS(self.RecordInfo.SPS[0]); err != nil { + err = fmt.Errorf("parse SPS failed(%s)", err) + return + } + codec = self return } -func CreateCodecDataBySPSAndPPS(SPS, PPS []byte) (codecData []byte, err error) { - self := AVCDecoderConfRecord{} - self.AVCProfileIndication = uint(SPS[1]) - self.ProfileCompatibility = uint(SPS[2]) - self.AVCLevelIndication = uint(SPS[3]) - self.SPS = [][]byte{SPS} - self.PPS = [][]byte{PPS} - self.LengthSizeMinusOne = 3 - +func NewCodecDataFromSPSAndPPS(sps, pps []byte) (codec av.H264CodecData, err error) { + recordinfo := AVCDecoderConfRecord{} + recordinfo.AVCProfileIndication = uint(sps[1]) + recordinfo.ProfileCompatibility = uint(sps[2]) + recordinfo.AVCLevelIndication = uint(sps[3]) + recordinfo.SPS = [][]byte{sps} + recordinfo.PPS = [][]byte{pps} + recordinfo.LengthSizeMinusOne = 3 buf := &bytes.Buffer{} - if err = WriteAVCDecoderConfRecord(buf, self); err != nil { + if err = WriteAVCDecoderConfRecord(buf, recordinfo); err != nil { return } - codecData = buf.Bytes() - + self := CodecData{} + self.RecordInfo = recordinfo + self.Record = buf.Bytes() + if self.SPSInfo, err = ParseSPS(sps); err != nil { + return + } + codec = self return } @@ -726,3 +751,43 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { return } +/* +type CodecInfo struct { + Record AVCDecoderConfRecord + SPSInfo SPSInfo +} + +func ParseCodecData(config []byte) (info CodecInfo, err error) { + if info.Record, err = ParseAVCDecoderConfRecord(config); err != nil { + return + } + if len(info.Record.SPS) < 1 { + err = fmt.Errorf("CodecData invalid: no SPS found in AVCDecoderConfRecord") + return + } + if info.SPSInfo, err = ParseSPS(info.Record.SPS[0]); err != nil { + err = fmt.Errorf("CodecData invalid: parse SPS failed(%s)", err) + return + } + return +} + +func CreateCodecDataBySPSAndPPS(SPS, PPS []byte) (codecData []byte, err error) { + self := AVCDecoderConfRecord{} + self.AVCProfileIndication = uint(SPS[1]) + self.ProfileCompatibility = uint(SPS[2]) + self.AVCLevelIndication = uint(SPS[3]) + self.SPS = [][]byte{SPS} + self.PPS = [][]byte{PPS} + self.LengthSizeMinusOne = 3 + + buf := &bytes.Buffer{} + if err = WriteAVCDecoderConfRecord(buf, self); err != nil { + return + } + codecData = buf.Bytes() + + return +} +*/ +