From a9f31fa0518b9c4303dcdadd5778d15380b06300 Mon Sep 17 00:00:00 2001 From: cfanfrank Date: Mon, 11 Mar 2013 11:00:20 +0800 Subject: [PATCH] first --- README.md | 20 ++------ codec/aacdec.go | 81 ------------------------------- codec/aacenc.go | 83 -------------------------------- codec/h264dec.go | 88 --------------------------------- codec/h264enc.go | 123 ----------------------------------------------- codec/util.go | 37 -------------- util.go | 16 ++++++ 7 files changed, 19 insertions(+), 429 deletions(-) delete mode 100644 codec/aacdec.go delete mode 100644 codec/aacenc.go delete mode 100644 codec/h264dec.go delete mode 100644 codec/h264enc.go delete mode 100644 codec/util.go create mode 100644 util.go diff --git a/README.md b/README.md index 8fd6013..2aadd74 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,8 @@ go-av == -Golang audio and video manipulation library. including mp4, rtmp, yuv/rgb image converter +Golang audio and video manipulation library -H264,AAC Codec -==== + * h264/aac encoder and decoder (using libav) ([HERE](http://github.com/go-av/codec)) + * mp4 reader and writer ([HERE](http://github.com/go-av/mp4)) -Requires `libav` installed. - - d, err = codec.NewAACEncoder() - data, err = d.Encode(samples) - - d, err = codec.NewAACDecoder(aaccfg) - samples, err = d.Decode(data) - - var img *image.YCbCr - d, err = codec.NewH264Encoder(640, 480) - img, err = d.Encode(img) - - d, err = codec.NewH264Decoder(pps) - img, err = d.Decode(nal) diff --git a/codec/aacdec.go b/codec/aacdec.go deleted file mode 100644 index 66cc9f4..0000000 --- a/codec/aacdec.go +++ /dev/null @@ -1,81 +0,0 @@ - -package codec - -import ( - /* - #include - #include - #include - #include - - typedef struct { - AVCodec *c; - AVCodecContext *ctx; - AVFrame *f; - int got; - } aacdec_t ; - - static int aacdec_new(aacdec_t *m, uint8_t *buf, int len) { - m->c = avcodec_find_decoder(CODEC_ID_AAC); - m->ctx = avcodec_alloc_context3(m->c); - m->f = avcodec_alloc_frame(); - m->ctx->extradata = buf; - m->ctx->extradata_size = len; - m->ctx->debug = 0x3; - av_log(m->ctx, AV_LOG_DEBUG, "m %p\n", m); - return avcodec_open2(m->ctx, m->c, 0); - } - - static void aacdec_decode(aacdec_t *m, uint8_t *data, int len) { - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = data; - pkt.size = len; - av_log(m->ctx, AV_LOG_DEBUG, "decode %p\n", m); - avcodec_decode_audio4(m->ctx, m->f, &m->got, &pkt); - av_log(m->ctx, AV_LOG_DEBUG, "got %d\n", m->got); - } - */ - "C" - "unsafe" - "errors" -) - -type AACDecoder struct { - m C.aacdec_t -} - -func NewAACDecoder(cfg []byte) (m *AACDecoder, err error) { - m = &AACDecoder{} - r := C.aacdec_new( - &m.m, - (*C.uint8_t)(unsafe.Pointer(&cfg[0])), - (C.int)(len(cfg)), - ) - if int(r) != 0 { - err = errors.New("avcodec open failed") - } - return -} - -func (m *AACDecoder) Decode(data []byte) (sample []byte, err error) { - C.aacdec_decode( - &m.m, - (*C.uint8_t)(unsafe.Pointer(&data[0])), - (C.int)(len(data)), - ) - if int(m.m.got) == 0 { - err = errors.New("no data") - return - } - sample = make([]byte, 8192) - for i := 0; i < 2; i++ { - C.memcpy( - unsafe.Pointer(&sample[i*4096]), - unsafe.Pointer(m.m.f.data[i]), - (C.size_t)(4096), - ) - } - return -} - diff --git a/codec/aacenc.go b/codec/aacenc.go deleted file mode 100644 index d205ee0..0000000 --- a/codec/aacenc.go +++ /dev/null @@ -1,83 +0,0 @@ - -package codec - -import ( - /* - #include - #include - #include - - typedef struct { - AVCodec *c; - AVCodecContext *ctx; - AVFrame *f; - int got; - uint8_t buf[1024*10]; int size; - } aacenc_t ; - - static void 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 = 44100; - m->ctx->bit_rate = 100000; - m->ctx->channels = 2; - m->ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; - m->f = avcodec_alloc_frame(); - avcodec_open2(m->ctx, m->c, 0); - av_log(m->ctx, AV_LOG_DEBUG, "extra %d\n", m->ctx->extradata_size); - } - - 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 - Cfg []byte // AAC Audio config -} - -// only supported fltp,stereo,44100khz. If you need other config, it's easy to modify code -func NewAACEncoder() (m *AACEncoder) { - m = &AACEncoder{} - C.aacenc_new(&m.m) - m.Cfg = make([]byte, (int)(m.m.ctx.extradata_size)) - C.memcpy( - unsafe.Pointer(&m.Cfg[0]), - unsafe.Pointer(&m.m.ctx.extradata), - (C.size_t)(len(m.Cfg)), - ) - 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 -} - diff --git a/codec/h264dec.go b/codec/h264dec.go deleted file mode 100644 index 16bd3d4..0000000 --- a/codec/h264dec.go +++ /dev/null @@ -1,88 +0,0 @@ - -package codec - -import ( - /* - #include - #include - #include - - typedef struct { - AVCodec *c; - AVCodecContext *ctx; - AVFrame *f; - int got; - } h264dec_t ; - - static int h264dec_new(h264dec_t *h, uint8_t *data, int len) { - h->c = avcodec_find_decoder(CODEC_ID_H264); - h->ctx = avcodec_alloc_context3(h->c); - h->f = avcodec_alloc_frame(); - h->ctx->extradata = data; - h->ctx->extradata_size = len; - h->ctx->debug = 0x3; - return avcodec_open2(h->ctx, h->c, 0); - } - - static void h264dec_decode(h264dec_t *h, uint8_t *data, int len) { - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = data; - pkt.size = len; - avcodec_decode_video2(h->ctx, h->f, &h->got, &pkt); - av_log(h->ctx, AV_LOG_DEBUG, "got %d\n", h->got); - } - */ - "C" - "unsafe" - "errors" - "image" -) - -type H264Decoder struct { - m C.h264dec_t -} - -func NewH264Decoder(pps []byte) (m *H264Decoder, err error) { - m = &H264Decoder{} - r := C.h264dec_new( - &m.m, - (*C.uint8_t)(unsafe.Pointer(&pps[0])), - (C.int)(len(pps)), - ) - if int(r) != 0 { - m = nil - err = errors.New("open codec failed") - } - return -} - -func (m *H264Decoder) Decode(nal []byte) (f *image.YCbCr, err error) { - C.h264dec_decode( - &m.m, - (*C.uint8_t)(unsafe.Pointer(&nal[0])), - (C.int)(len(nal)), - ) - if m.m.got == 0 { - err = errors.New("no picture") - return - } - - w := int(m.m.f.width) - h := int(m.m.f.height) - ys := int(m.m.f.linesize[0]) - cs := int(m.m.f.linesize[1]) - - f = &image.YCbCr{ - Y: fromCPtr(unsafe.Pointer(m.m.f.data[0]), ys*h), - Cb: fromCPtr(unsafe.Pointer(m.m.f.data[1]), cs*h/2), - Cr: fromCPtr(unsafe.Pointer(m.m.f.data[2]), cs*h/2), - YStride: ys, - CStride: cs, - SubsampleRatio: image.YCbCrSubsampleRatio420, - Rect: image.Rect(0, 0, w, h), - } - - return -} - diff --git a/codec/h264enc.go b/codec/h264enc.go deleted file mode 100644 index df821fb..0000000 --- a/codec/h264enc.go +++ /dev/null @@ -1,123 +0,0 @@ - -package codec - -import ( - -/* -#include -#include -#include -#include -#include - -typedef struct { - x264_t *x; - int w, h; - uint8_t *pps; int ppslen; - uint8_t *sei; int seilen; - x264_picture_t in; - x264_nal_t *nal; int nnal; int nallen; -} h264enc_t; - -static void h264enc_new(h264enc_t *m) { - x264_param_t p; - - x264_param_default(&p); - x264_param_default_preset(&p, "ultrafast", "zerolatency"); - x264_param_apply_profile(&p, "main"); - - p.rc.i_bitrate = 50; - p.rc.i_rc_method = X264_RC_ABR; - p.i_width = m->w; - p.i_height = m->h; - p.i_csp = X264_CSP_I420; - - m->x = x264_encoder_open(&p); - if (!m->x) { - return ; - } - - x264_nal_t *nal; - int nnal, i; - - uint8_t *pps; - m->ppslen = x264_encoder_headers(m->x, &nal, &nnal); - m->pps = pps = malloc(m->ppslen); - - for (i = 0; i < nnal; i++) { - //printf("nal#%d %d\n", i, nal[i].i_type); - if (nal[i].i_type != NAL_SEI) { - memcpy(pps, nal[i].p_payload, nal[i].i_payload); - pps += nal[i].i_payload; - } else { - m->seilen = nal[i].i_payload; - m->sei = malloc(m->seilen); - memcpy(m->sei, nal[i].p_payload, m->seilen); - } - } - m->ppslen = pps - m->pps; -} - -static void h264enc_encode(h264enc_t *m) { - x264_picture_t out; - - m->in.img.i_csp = X264_CSP_I420; - m->in.i_type = X264_TYPE_AUTO; - - x264_encoder_encode(m->x, &m->nal, &m->nnal, &m->in, &out); - m->nallen = 0; - int i; - if (m->seilen) - m->nallen += m->seilen; - for (i = 0; i < m->nnal; i++) { - m->nallen += m->nal[i].i_payload; - } -} - -static void h264enc_copy(h264enc_t *m, uint8_t *p) { - int i; - if (m->seilen) { - memcpy(p, m->sei, m->seilen); - p += m->seilen; - m->seilen = 0; - } - for (i = 0; i < m->nnal; i++) { - memcpy(p, m->nal[i].p_payload, m->nal[i].i_payload); - p += m->nal[i].i_payload; - } -} - -*/ - "C" - "unsafe" - "image" -) - -type H264Encoder struct { - m C.h264enc_t - PPS []byte -} - -func NewH264Encoder(w, h int) (m *H264Encoder) { - m = &H264Encoder{} - m.m.w = (C.int)(w) - m.m.h = (C.int)(h) - C.h264enc_new(&m.m) - m.PPS = fromCPtr(unsafe.Pointer(m.m.pps), (int)(m.m.ppslen)) - return -} - -func (m *H264Encoder) Encode(f *image.YCbCr) (nal []byte) { - C.x264_picture_init(&m.m.in); - m.m.in.img.plane[0] = (*C.uint8_t)(unsafe.Pointer(&f.Y[0])); - m.m.in.img.plane[1] = (*C.uint8_t)(unsafe.Pointer(&f.Cb[0])); - m.m.in.img.plane[2] = (*C.uint8_t)(unsafe.Pointer(&f.Cr[0])); - m.m.in.img.i_stride[0] = (C.int)(f.YStride); - m.m.in.img.i_stride[1] = (C.int)(f.CStride); - m.m.in.img.i_stride[2] = (C.int)(f.CStride); - C.h264enc_encode(&m.m) - nal = make([]byte, m.m.nallen) - C.h264enc_copy(&m.m, (*C.uint8_t)(unsafe.Pointer(&nal[0]))) - return -} - diff --git a/codec/util.go b/codec/util.go deleted file mode 100644 index 0a7806d..0000000 --- a/codec/util.go +++ /dev/null @@ -1,37 +0,0 @@ - -/* - Golang h264,aac decoder/encoder libav wrapper -*/ -package codec - -import ( - "unsafe" - "reflect" - - /* - #cgo darwin LDFLAGS: -lavformat -lavutil -lavcodec -lx264 - - #include - #include - - static void libav_init() { - av_register_all(); - av_log_set_level(AV_LOG_DEBUG); - } - */ - "C" -) - -func init() { - C.libav_init() -} - -func fromCPtr(buf unsafe.Pointer, size int) (ret []uint8) { - hdr := (*reflect.SliceHeader)((unsafe.Pointer(&ret))) - hdr.Cap = size - hdr.Len = size - hdr.Data = uintptr(buf) - return -} - - diff --git a/util.go b/util.go new file mode 100644 index 0000000..a5f1713 --- /dev/null +++ b/util.go @@ -0,0 +1,16 @@ + +package av + +const ( + H264 = 1 + AAC = 2 +) + +type Packet struct { + Codec int + Key bool + Pos float32 + Data []byte + Idx int +} +