package goffmpeg
|
|
/*
|
#cgo LDFLAGS: -ldl
|
#include <stdlib.h>
|
#include "libcffmpeg.h"
|
*/
|
import "C"
|
import (
|
"errors"
|
"fmt"
|
"unsafe"
|
)
|
|
const (
|
// ScaleFastBilinear SWS_FAST_BILINEAR
|
ScaleFastBilinear = 1
|
// ScaleBilinear SWS_BILINEAR
|
ScaleBilinear = 2
|
// ScaleBicubic SWS_BICUBIC
|
ScaleBicubic = 4
|
// ScaleX SWS_X
|
ScaleX = 8
|
// ScalePoint SWS_POINT
|
ScalePoint = 0x10
|
// ScaleArea SWS_AREA
|
ScaleArea = 0x20
|
// ScaleBicublin SWS_BICUBLIN
|
ScaleBicublin = 0x40
|
// ScaleGauss SWS_GAUSS
|
ScaleGauss = 0x80
|
// ScaleSinc SWS_SINC
|
ScaleSinc = 0x100
|
// ScaleLancZos SWS_LANCZOS
|
ScaleLancZos = 0x200
|
// ScaleSpline SWS_SPLINE
|
ScaleSpline = 0x400
|
)
|
|
var libcffmpeg C.libcffmpeg
|
|
// InitFFmpeg init ffmepg
|
func InitFFmpeg(soFileGo string) error {
|
soFile := C.CString(soFileGo)
|
defer C.free(unsafe.Pointer(soFile))
|
lib := C.init_libcffmpeg(soFile)
|
if lib == nil {
|
fmt.Println("open error: ", soFileGo)
|
return errors.New("init ffmpeg error")
|
}
|
libcffmpeg = lib
|
return nil
|
}
|
|
// FreeFFmpeg free ffmpeg
|
func FreeFFmpeg() {
|
if libcffmpeg != nil {
|
C.release_libcffmpeg(libcffmpeg)
|
}
|
}
|
|
// Config config
|
type Config struct {
|
Scale int
|
Width int
|
Height int
|
GB bool
|
CPU bool
|
}
|
|
// GoFFMPEG handle for c
|
type GoFFMPEG struct {
|
ffmpeg C.cffmpeg
|
}
|
|
// New 2nd new
|
func New(conf Config) *GoFFMPEG {
|
f := C.wrap_fn_create()
|
if f == nil {
|
return nil
|
}
|
if conf.Scale != 0 && conf.Width != 0 && conf.Height != 0 {
|
C.wrap_fn_scale(f, C.int(conf.Width), C.int(conf.Height), C.int(conf.Scale))
|
}
|
if conf.GB {
|
C.wrap_fn_run_gb28181(f)
|
}
|
if conf.CPU {
|
C.wrap_fn_use_cpu(f)
|
}
|
|
return &GoFFMPEG{
|
ffmpeg: f,
|
}
|
}
|
|
// Free free handle
|
func (h *GoFFMPEG) Free() {
|
C.wrap_fn_destroy(h.ffmpeg)
|
}
|
|
// Run ffmpeg
|
func (h *GoFFMPEG) Run(input string) {
|
in := C.CString(input)
|
defer C.free(unsafe.Pointer(in))
|
|
C.wrap_fn_run(h.ffmpeg, in)
|
}
|
|
// DecodeJPEG decode jpeg file
|
func (h *GoFFMPEG) DecodeJPEG(input string) ([]byte, int, int) {
|
in := C.CString(input)
|
defer C.free(unsafe.Pointer(in))
|
|
var width C.int
|
var height C.int
|
p := C.wrap_fn_decode_jpeg(h.ffmpeg, in, &width, &height)
|
defer C.free(p)
|
|
if width > 0 && height > 0 {
|
data := C.GoBytes(p, width*height*3)
|
wid := int(width)
|
hei := int(height)
|
return data, wid, hei
|
}
|
return nil, 0, 0
|
}
|
|
// FireRecorder fire recorder
|
func (h *GoFFMPEG) FireRecorder(sid string, id int64) {
|
csid := C.CString(sid)
|
defer C.free(unsafe.Pointer(csid))
|
C.wrap_fn_fire_recorder(h.ffmpeg, csid, C.long(id))
|
}
|
|
// BuildRecorder build recorder
|
func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd int) {
|
out := C.CString(output)
|
defer C.free(unsafe.Pointer(out))
|
csid := C.CString(sid)
|
defer C.free(unsafe.Pointer(csid))
|
|
C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd))
|
}
|
|
// GetInfoRecorder info
|
func (h *GoFFMPEG) GetInfoRecorder() (int, string) {
|
var i C.int = -1
|
var l C.int
|
|
p := C.wrap_fn_info_recorder(h.ffmpeg, &i, &l)
|
// if p == nil {
|
// return -1, ""
|
// }
|
path := C.GoString(p)
|
C.free(unsafe.Pointer(p))
|
|
// fmt.Println("Go get info : ", path, " len: ", l)
|
|
return int(i), path
|
}
|
|
// GetRecID get rec id
|
func (h *GoFFMPEG) GetRecID(p string) string {
|
pt := C.CString(p)
|
defer C.free(unsafe.Pointer(pt))
|
var i C.int
|
|
cid := C.wrap_fn_rec_id(h.ffmpeg, pt, &i)
|
|
id := C.GoString(cid)
|
C.free(unsafe.Pointer(cid))
|
|
return id
|
}
|
|
// BuildDecoder build decoder
|
func (h *GoFFMPEG) BuildDecoder() {
|
C.wrap_fn_decoder(h.ffmpeg)
|
}
|
|
// GetPicDecoder get pic from decoder
|
func (h *GoFFMPEG) GetPicDecoder() ([]byte, int, int, int64) {
|
var width C.int
|
var height C.int
|
var fid C.long
|
|
p := C.wrap_fn_decoder_pic(h.ffmpeg, &width, &height, &fid)
|
if width == 0 && height == 0 {
|
return nil, 0, 0, 0
|
}
|
defer C.free(unsafe.Pointer(p))
|
d := C.GoBytes(p, width*height*3)
|
wid := int(width)
|
hei := int(height)
|
gfid := int64(fid)
|
return d, wid, hei, gfid
|
}
|
|
//GetAVPacket get AVPacket
|
func (h *GoFFMPEG) GetAVPacket() ([]byte, int, int) {
|
var key C.int
|
var size C.int
|
|
p := C.wrap_fn_get_avpacket(h.ffmpeg, &size, &key)
|
if size <= 0 {
|
return nil, 0, -1
|
}
|
defer C.free(unsafe.Pointer(p))
|
d := C.GoBytes(p, size)
|
s := int(size)
|
k := int(key)
|
|
return d, s, k
|
}
|
|
///////////////for encoder
|
|
// GoEncoder encoder
|
type GoEncoder struct {
|
enc C.cencoder
|
}
|
|
// NewEncoder encoder
|
func NewEncoder(w, h, fps, br, sFlag, gi int) *GoEncoder {
|
if w <= 0 || h <= 0 {
|
return nil
|
}
|
|
return &GoEncoder{
|
enc: C.wrap_fn_create_encoder(C.int(w), C.int(h), C.int(fps), C.int(br), C.int(sFlag), C.int(gi)),
|
}
|
}
|
|
// Free free
|
func (e *GoEncoder) Free() {
|
C.wrap_fn_destroy_encoder(e.enc)
|
}
|
|
// Encode pic
|
func (e *GoEncoder) Encode(in []byte, w, h int) ([]byte, int, bool) {
|
|
var size C.int
|
var key C.int
|
cin := C.CBytes(in)
|
defer C.free(cin)
|
|
p := C.wrap_fn_encode(e.enc, cin, C.int(w), C.int(h), &size, &key)
|
defer C.free(p)
|
if p != nil && size > 0 {
|
b := C.GoBytes(p, size)
|
|
isKey := false
|
if key > 0 {
|
isKey = true
|
}
|
return b, int(size), isKey
|
}
|
return nil, 0, false
|
}
|