joy4/aacenc.go
2013-03-11 11:02:25 +08:00

94 lines
2.1 KiB
Go

package codec
import (
/*
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <string.h>
typedef struct {
AVCodec *c;
AVCodecContext *ctx;
AVFrame *f;
int got;
uint8_t buf[1024*10]; int size;
int samplerate; int bitrate;
int channels;
} aacenc_t ;
static int aacenc_new(aacenc_t *m) {
m->c = avcodec_find_encoder(CODEC_ID_AAC);
m->ctx = avcodec_alloc_context3(m->c);
m->ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
m->ctx->sample_rate = m->samplerate;
m->ctx->bit_rate = m->bitrate;
m->ctx->channels = m->channels;
m->ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
m->f = avcodec_alloc_frame();
int r = avcodec_open2(m->ctx, m->c, 0);
av_log(m->ctx, AV_LOG_DEBUG, "extra %d\n", m->ctx->extradata_size);
return r;
}
static void aacenc_encode(aacenc_t *m) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = m->buf;
pkt.size = sizeof(m->buf);
m->f->nb_samples = 1024;
m->f->extended_data = m->f->data;
m->f->linesize[0] = 4096;
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;
}
*/
"C"
"unsafe"
"errors"
)
type AACEncoder struct {
m C.aacenc_t
Header []byte
}
// only supported fltp,stereo,44100khz. 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
r := C.aacenc_new(&m.m)
if int(r) != 0 {
err = errors.New("open codec failed")
return
}
m.Header = make([]byte, (int)(m.m.ctx.extradata_size))
C.memcpy(
unsafe.Pointer(&m.Header[0]),
unsafe.Pointer(&m.m.ctx.extradata),
(C.size_t)(len(m.Header)),
)
return
}
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]))
C.aacenc_encode(&m.m)
if int(m.m.got) == 0 {
err = errors.New("no data")
return
}
ret = make([]byte, (int)(m.m.size))
C.memcpy(
unsafe.Pointer(&ret[0]),
unsafe.Pointer(&m.m.buf[0]),
(C.size_t)(m.m.size),
)
return
}