| | |
| | | "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 |
| | |
| | | } |
| | | } |
| | | |
| | | // 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 { |
| | | func New(GB, CPU bool) *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 { |
| | | if GB { |
| | | C.wrap_fn_run_gb28181(f) |
| | | } |
| | | if conf.CPU { |
| | | if CPU { |
| | | C.wrap_fn_use_cpu(f) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // NewWithLog log |
| | | func NewWithLog(conf Config, logfile string) *GoFFMPEG { |
| | | lf := C.CString(logfile) |
| | | func NewWithLog(GB, CPU bool, ffmpegLog string) *GoFFMPEG { |
| | | lf := C.CString(ffmpegLog) |
| | | defer C.free(unsafe.Pointer(lf)) |
| | | |
| | | f := C.wrap_fn_create2(lf) |
| | | 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 { |
| | | if GB { |
| | | C.wrap_fn_run_gb28181(f) |
| | | } |
| | | if conf.CPU { |
| | | if CPU { |
| | | C.wrap_fn_use_cpu(f) |
| | | } |
| | | |
| | |
| | | |
| | | // Free free handle |
| | | func (h *GoFFMPEG) Free() { |
| | | C.wrap_fn_destroy(h.ffmpeg) |
| | | if h.ffmpeg != nil { |
| | | C.wrap_fn_destroy(h.ffmpeg) |
| | | } |
| | | } |
| | | |
| | | // Run ffmpeg |
| | |
| | | defer C.free(unsafe.Pointer(in)) |
| | | |
| | | C.wrap_fn_run(h.ffmpeg, in) |
| | | } |
| | | |
| | | // 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, audio bool) { |
| | | out := C.CString(output) |
| | | defer C.free(unsafe.Pointer(out)) |
| | | csid := C.CString(sid) |
| | | defer C.free(unsafe.Pointer(csid)) |
| | | |
| | | a := 0 |
| | | if audio { |
| | | a = 1 |
| | | } |
| | | C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd), C.int(a)) |
| | | } |
| | | |
| | | // GetInfoRecorder info |
| | | func (h *GoFFMPEG) GetInfoRecorder() (string, int, string) { |
| | | var i C.int = -1 |
| | | |
| | | var id *C.char |
| | | var idl C.int |
| | | |
| | | var p *C.char |
| | | var pl C.int |
| | | |
| | | C.wrap_fn_info_recorder(h.ffmpeg, &i, &id, &idl, &p, &pl) |
| | | // if p == nil { |
| | | // return -1, "" |
| | | // } |
| | | gID := C.GoString(id) |
| | | C.free(unsafe.Pointer(id)) |
| | | path := C.GoString(p) |
| | | C.free(unsafe.Pointer(p)) |
| | | |
| | | // fmt.Println("Go get info : ", path, " len: ", l) |
| | | |
| | | return gID, int(i), path |
| | | } |
| | | |
| | | // 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 decoder |
| | | |
| | | // Decode decode jpeg file |
| | | // return val: -1 open error; -2, find stream error; -3, converter create error |
| | | func Decode(input string, gb bool) ([]byte, int, int) { |
| | | in := C.CString(input) |
| | | defer C.free(unsafe.Pointer(in)) |
| | | |
| | | withGB := 0 |
| | | if gb { |
| | | withGB = 1 |
| | | } |
| | | |
| | | var width C.int |
| | | var height C.int |
| | | p := C.wrap_fn_decode(in, C.int(withGB), &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, int(width), int(height) |
| | | } |
| | | |
| | | ///////////////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 |
| | | } |