From 7453318fd5af645b1422dece3b712b1e79833563 Mon Sep 17 00:00:00 2001 From: nareix Date: Wed, 8 Jun 2016 14:36:58 +0800 Subject: [PATCH] change repo to github.com/nareix/ffmpeg --- README.md | 77 ---------------------- aacdec.go | 82 ----------------------- aacenc.go | 93 -------------------------- audio.go | 189 ----------------------------------------------------- ffmpeg.h | 11 ---- h264dec.go | 88 ------------------------- h264enc.go | 146 ----------------------------------------- util.go | 48 -------------- 8 files changed, 734 deletions(-) delete mode 100644 README.md delete mode 100644 aacdec.go delete mode 100644 aacenc.go delete mode 100644 audio.go delete mode 100644 ffmpeg.h delete mode 100644 h264dec.go delete mode 100644 h264enc.go delete mode 100644 util.go diff --git a/README.md b/README.md deleted file mode 100644 index ac8920c..0000000 --- a/README.md +++ /dev/null @@ -1,77 +0,0 @@ - -codec -==== - -Golang aac/h264 encoder and decoder. - -H264 encoding example: - -```go -w := 400 -h := 400 -var nal [][]byte - -c, _ := codec.NewH264Encoder(w, h, image.YCbCrSubsampleRatio420) -nal = append(nal, c.Header) - -for i := 0; i < 60; i++ { - img := image.NewYCbCr(image.Rect(0,0,w,h), image.YCbCrSubsampleRatio420) - p, _ := c.Encode(img) - if len(p.Data) > 0 { - nal = append(nal, p.Data) - } -} -for { - // flush encoder - p, err := c.Encode(nil) - if err != nil { - break - } - nal = append(nal, p.Data) -} -``` - -H264 decoding example: - -```go -dec, err := codec.NewH264Decoder(nal[0]) -for i, n := range nal[1:] { - img, err := dec.Decode(n) - if err == nil { - fp, _ := os.Create(fmt.Sprintf("/tmp/dec-%d.jpg", i)) - jpeg.Encode(fp, img, nil) - fp.Close() - } -} -``` - -AAC encoding example: - -```go -var pkts [][]byte - -c, _ := codec.NewAACEncoder() -pkts = append(pkts, c.Header) - -for i := 0; i < 60; i++ { - var sample [8192]byte - p, _ := c.Encode(sample) - if len(p) > 0 { - pkts = append(pkts, p) - } -} -``` - -AAC decoding example: - -```go -dec, _ := codec.NewAACDecoder(pkts[0]) -for _, p := range pkts[1:] { - sample, err := dec.Decode(p) -} -``` - -License ----- - -All code is under WTFPL. You can use it for everything as you want :) diff --git a/aacdec.go b/aacdec.go deleted file mode 100644 index efa9653..0000000 --- a/aacdec.go +++ /dev/null @@ -1,82 +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 = av_frame_alloc(); - 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 int 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); - return avcodec_decode_audio4(m->ctx, m->f, &m->got, &pkt); - } - */ - "C" - "errors" - "unsafe" -) - -type AACDecoder struct { - m C.aacdec_t -} - -func NewAACDecoder(header []byte) (m *AACDecoder, err error) { - m = &AACDecoder{} - r := C.aacdec_new(&m.m, - (*C.uint8_t)(unsafe.Pointer(&header[0])), - (C.int)(len(header)), - ) - if int(r) < 0 { - err = errors.New("open codec failed") - } - return -} - -func (m *AACDecoder) Decode(data []byte) (sample []byte, err error) { - r := C.aacdec_decode( - &m.m, - (*C.uint8_t)(unsafe.Pointer(&data[0])), - (C.int)(len(data)), - ) - if int(r) < 0 { - err = errors.New("decode failed") - return - } - if int(m.m.got) == 0 { - err = errors.New("no data") - return - } - size := int(m.m.f.linesize[0]) * 2 - sample = make([]byte, size*2) - for i := 0; i < 2; i++ { - C.memcpy( - unsafe.Pointer(&sample[i*size]), - unsafe.Pointer(m.m.f.data[i]), - (C.size_t)(size), - ) - } - return -} diff --git a/aacenc.go b/aacenc.go deleted file mode 100644 index b350d1e..0000000 --- a/aacenc.go +++ /dev/null @@ -1,93 +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; - int samplerate; int bitrate; - int channels; - } aacenc_t ; - - static int aacenc_new(aacenc_t *m) { - 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; - m->ctx->bit_rate = m->bitrate; - m->ctx->channels = m->channels; - 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); - 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] = 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; - } - */ - "C" - "errors" - "unsafe" -) - -type AACEncoder struct { - m C.aacenc_t - Header []byte -} - -// 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 = 1 - 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[1024*4])) - 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/audio.go b/audio.go deleted file mode 100644 index 2456c38..0000000 --- a/audio.go +++ /dev/null @@ -1,189 +0,0 @@ -package codec - -import ( - /* - #include "ffmpeg.h" - int wrap_avcodec_decode_audio4(AVCodecContext *ctx, AVFrame *frame, void *data, int size, int *got) { - struct AVPacket pkt = {.data = data, .size = size}; - return avcodec_decode_audio4(ctx, frame, got, &pkt); - } - void set_sample_fmt(AVCodecContext *ctx, int sample_fmt) { - ctx->sample_fmt = sample_fmt; - } - int wrap_av_get_bytes_per_sample(int sample_fmt) { - return av_get_bytes_per_sample(sample_fmt); - } - */ - "C" - "unsafe" - "fmt" -) - -type SampleFormat int - -func (self SampleFormat) BytesPerSample() int { - return int(C.wrap_av_get_bytes_per_sample(C.int(self))) -} - -const ( - S16 = SampleFormat(C.AV_SAMPLE_FMT_S16) - FLTP = SampleFormat(C.AV_SAMPLE_FMT_FLTP) -) - -type AudioEncoder struct { - ff C.FFCtx - SampleRate int - BitRate int - ChannelCount int - SampleFormat SampleFormat - FrameSampleCount int -} - -func (self *AudioEncoder) Setup() (err error) { - ff := &self.ff - - ff.frame = C.av_frame_alloc() - if self.BitRate == 0 { - self.BitRate = 50000 - } - C.set_sample_fmt(ff.codecCtx, C.int(self.SampleFormat)) - ff.codecCtx.sample_rate = C.int(self.SampleRate) - ff.codecCtx.bit_rate = C.int(self.BitRate) - ff.codecCtx.channels = C.int(self.ChannelCount) - ff.codecCtx.strict_std_compliance = C.FF_COMPLIANCE_EXPERIMENTAL - if C.avcodec_open2(ff.codecCtx, ff.codec, nil) != 0 { - err = fmt.Errorf("avcodec_open2 failed") - return - } - self.SampleFormat = SampleFormat(int(ff.codecCtx.sample_fmt)) - self.ChannelCount = int(ff.codecCtx.channels) - self.FrameSampleCount = int(ff.codecCtx.frame_size) - - return -} - -func (self *AudioEncoder) Extradata() (data []byte) { - data = C.GoBytes(unsafe.Pointer(self.ff.codecCtx.extradata), self.ff.codecCtx.extradata_size) - return -} - -func (self *AudioEncoder) Encode(sample []byte, flush bool) (gotPkt bool, pkt []byte, err error) { - ff := &self.ff - nbSamples := self.FrameSampleCount - channelCount := int(ff.codecCtx.channels) - sampleSize := int(C.av_get_bytes_per_sample(ff.codecCtx.sample_fmt)) - expectedSize := nbSamples*sampleSize*channelCount - - frame := ff.frame - if flush { - frame = nil - } else { - if len(sample) != expectedSize { - err = fmt.Errorf("len(sample) should be %d", expectedSize) - return - } - - frame.nb_samples = C.int(nbSamples) - frame.format = C.int(ff.codecCtx.sample_fmt) - frame.channel_layout = ff.codecCtx.channel_layout - if C.av_sample_fmt_is_planar(ff.codecCtx.sample_fmt) != 0 { - for i := 0; i < self.ChannelCount; i++ { - frame.data[i] = (*C.uint8_t)(unsafe.Pointer(&sample[i*nbSamples*sampleSize])) - frame.linesize[i] = C.int(nbSamples*sampleSize) - } - } else { - frame.data[0] = (*C.uint8_t)(unsafe.Pointer(&sample[0])) - frame.linesize[0] = C.int(channelCount*nbSamples*sampleSize) - } - //frame.extended_data = &frame.data[0] - } - - cpkt := C.AVPacket{} - cgotpkt := C.int(0) - cerr := C.avcodec_encode_audio2(self.ff.codecCtx, &cpkt, frame, &cgotpkt) - if cerr < C.int(0) { - err = fmt.Errorf("avcodec_encode_audio2 failed: %d", cerr) - return - } - - if cgotpkt != 0 { - gotPkt = true - pkt = C.GoBytes(unsafe.Pointer(cpkt.data), cpkt.size) - C.av_free_packet(&cpkt) - } - - return -} - -type AudioDecoder struct { - ff C.FFCtx - ChannelCount int - SampleFormat SampleFormat - Extradata []byte -} - -func (self *AudioDecoder) Setup() (err error) { - ff := &self.ff - - ff.frame = C.av_frame_alloc() - - if len(self.Extradata) > 0 { - ff.codecCtx.extradata = (*C.uint8_t)(unsafe.Pointer(&self.Extradata[0])) - ff.codecCtx.extradata_size = C.int(len(self.Extradata)) - } - - ff.codecCtx.channels = C.int(self.ChannelCount) - if C.avcodec_open2(ff.codecCtx, ff.codec, nil) != 0 { - err = fmt.Errorf("avcodec_open2 failed") - return - } - self.SampleFormat = SampleFormat(int(ff.codecCtx.sample_fmt)) - self.ChannelCount = int(ff.codecCtx.channels) - - return -} - -func (self *AudioDecoder) Decode(frame []byte) (gotPkt bool, pkt []byte, err error) { - ff := &self.ff - - cgotpkt := C.int(0) - cerr := C.wrap_avcodec_decode_audio4(ff.codecCtx, ff.frame, unsafe.Pointer(&frame[0]), C.int(len(frame)), &cgotpkt) - if cerr < C.int(0) { - err = fmt.Errorf("avcodec_decode_audio4 failed: %d", cerr) - return - } - - if cgotpkt != C.int(0) { - gotPkt = true - //pkt = C.GoBytes(unsafe.Pointer(cpkt.data), cpkt.size) - size := C.av_samples_get_buffer_size(nil, ff.codecCtx.channels, ff.frame.nb_samples, ff.codecCtx.sample_fmt, C.int(1)) - pkt = C.GoBytes(unsafe.Pointer(ff.frame.data[0]), size) - } - - return -} - -func FindAudioEncoderByName(name string) (enc *AudioEncoder) { - ff := C.FFCtx{} - ff.codec = C.avcodec_find_encoder_by_name(C.CString(name)) - if ff.codec != nil { - ff.codecCtx = C.avcodec_alloc_context3(ff.codec) - if ff.codecCtx != nil { - return &AudioEncoder{ff: ff} - } - } - return nil -} - -func FindAudioDecoderByName(name string) (dec *AudioDecoder) { - ff := C.FFCtx{} - ff.codec = C.avcodec_find_decoder_by_name(C.CString(name)) - if ff.codec != nil { - ff.codecCtx = C.avcodec_alloc_context3(ff.codec) - if ff.codecCtx != nil { - return &AudioDecoder{ff: ff} - } - } - return nil -} - diff --git a/ffmpeg.h b/ffmpeg.h deleted file mode 100644 index b336d17..0000000 --- a/ffmpeg.h +++ /dev/null @@ -1,11 +0,0 @@ - -#include -#include -#include - -typedef struct { - AVCodec *codec; - AVCodecContext *codecCtx; - AVFrame *frame; -} FFCtx; - diff --git a/h264dec.go b/h264dec.go deleted file mode 100644 index 747051a..0000000 --- a/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 = av_frame_alloc(); - h->ctx->extradata = data; - h->ctx->extradata_size = len; - h->ctx->debug = 0x3; - return avcodec_open2(h->ctx, h->c, 0); - } - - static int h264dec_decode(h264dec_t *h, uint8_t *data, int len) { - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = data; - pkt.size = len; - return avcodec_decode_video2(h->ctx, h->f, &h->got, &pkt); - } - */ - "C" - "errors" - "image" - "unsafe" -) - -type H264Decoder struct { - m C.h264dec_t -} - -func NewH264Decoder(header []byte) (m *H264Decoder, err error) { - m = &H264Decoder{} - r := C.h264dec_new( - &m.m, - (*C.uint8_t)(unsafe.Pointer(&header[0])), - (C.int)(len(header)), - ) - if int(r) < 0 { - err = errors.New("open codec failed") - } - return -} - -func (m *H264Decoder) Decode(nal []byte) (f *image.YCbCr, err error) { - r := C.h264dec_decode( - &m.m, - (*C.uint8_t)(unsafe.Pointer(&nal[0])), - (C.int)(len(nal)), - ) - if int(r) < 0 { - err = errors.New("decode failed") - return - } - 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/h264enc.go b/h264enc.go deleted file mode 100644 index 21bdb9f..0000000 --- a/h264enc.go +++ /dev/null @@ -1,146 +0,0 @@ -package codec - -import ( - - /* - #include - #include - #include - #include - #include - #include - #include - - typedef struct { - int w, h; - int pixfmt; - char *preset[2]; - char *profile; - int bitrate; - int got; - AVCodec *c; - AVCodecContext *ctx; - AVFrame *f; - AVPacket pkt; - } h264enc_t; - - static int h264enc_new(h264enc_t *m) { - m->c = avcodec_find_encoder(CODEC_ID_H264); - m->ctx = avcodec_alloc_context3(m->c); - m->ctx->width = m->w; - m->ctx->height = m->h; - m->ctx->bit_rate = m->bitrate; - m->ctx->pix_fmt = m->pixfmt; - m->ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; - m->f = av_frame_alloc(); - return avcodec_open2(m->ctx, m->c, NULL); - } - - */ - "C" - "errors" - "image" - "strings" - "unsafe" - //"log" -) - -type H264Encoder struct { - m C.h264enc_t - Header []byte - Pixfmt image.YCbCrSubsampleRatio - W, H int -} - -func NewH264Encoder( - w, h int, - pixfmt image.YCbCrSubsampleRatio, - opts ...string, -) (m *H264Encoder, err error) { - m = &H264Encoder{} - m.m.w = (C.int)(w) - m.m.h = (C.int)(h) - m.W = w - m.H = h - m.Pixfmt = pixfmt - switch pixfmt { - case image.YCbCrSubsampleRatio444: - m.m.pixfmt = C.PIX_FMT_YUV444P - case image.YCbCrSubsampleRatio422: - m.m.pixfmt = C.PIX_FMT_YUV422P - case image.YCbCrSubsampleRatio420: - m.m.pixfmt = C.PIX_FMT_YUV420P - } - for _, opt := range opts { - a := strings.Split(opt, ",") - switch { - case a[0] == "preset" && len(a) == 3: - m.m.preset[0] = C.CString(a[1]) - m.m.preset[1] = C.CString(a[2]) - case a[0] == "profile" && len(a) == 2: - m.m.profile = C.CString(a[1]) - } - } - r := C.h264enc_new(&m.m) - if int(r) < 0 { - err = errors.New("open encoder failed") - return - } - m.Header = fromCPtr(unsafe.Pointer(m.m.ctx.extradata), (int)(m.m.ctx.extradata_size)) - //m.Header = fromCPtr(unsafe.Pointer(m.m.pps), (int)(m.m.ppslen)) - return -} - -type h264Out struct { - Data []byte - Key bool -} - -func (m *H264Encoder) Encode(img *image.YCbCr) (out h264Out, err error) { - var f *C.AVFrame - if img == nil { - f = nil - } else { - if img.SubsampleRatio != m.Pixfmt { - err = errors.New("image pixfmt not match") - return - } - if img.Rect.Dx() != m.W || img.Rect.Dy() != m.H { - err = errors.New("image size not match") - return - } - f = m.m.f - f.data[0] = (*C.uint8_t)(unsafe.Pointer(&img.Y[0])) - f.data[1] = (*C.uint8_t)(unsafe.Pointer(&img.Cb[0])) - f.data[2] = (*C.uint8_t)(unsafe.Pointer(&img.Cr[0])) - f.linesize[0] = (C.int)(img.YStride) - f.linesize[1] = (C.int)(img.CStride) - f.linesize[2] = (C.int)(img.CStride) - } - - C.av_init_packet(&m.m.pkt) - r := C.avcodec_encode_video2(m.m.ctx, &m.m.pkt, f, &m.m.got) - defer C.av_free_packet(&m.m.pkt) - if int(r) < 0 { - err = errors.New("encode failed") - return - } - if m.m.got == 0 { - err = errors.New("no picture") - return - } - if m.m.pkt.size == 0 { - err = errors.New("packet size == 0") - return - } - - out.Data = make([]byte, m.m.pkt.size) - C.memcpy( - unsafe.Pointer(&out.Data[0]), - unsafe.Pointer(m.m.pkt.data), - (C.size_t)(m.m.pkt.size), - ) - out.Key = (m.m.pkt.flags & C.AV_PKT_FLAG_KEY) != 0 - - return -} diff --git a/util.go b/util.go deleted file mode 100644 index 58ca3a7..0000000 --- a/util.go +++ /dev/null @@ -1,48 +0,0 @@ -/* - -Golang h264,aac decoder/encoder libav wrapper - - 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) -*/ -package codec - -import ( - "reflect" - "unsafe" - - /* - #cgo LDFLAGS: -lavformat -lavutil -lavcodec - - #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 -}