This commit is contained in:
nareix 2016-05-25 07:44:06 +08:00
parent 8e14c48c2a
commit 790569a35a
3 changed files with 166 additions and 54 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}
*/