我想编写一个处理视频的小型go应用程序,并决定使用该库goav,它是go的FFmpeg绑定。但是,它不支持直接从内存读取视频。作为解决方法,我决定直接调用C函数。
我要调用的函数的签名如下。
AVIOContext *avio_alloc_context(
unsigned char *buffer,
int buffer_size,
int write_flag,
void *opaque,
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
int64_t (*seek)(void *opaque, int64_t offset, int whence));
我为此编写的go代码-
package video
// #include<libavformat/avio.h>
import "C"
import (
"bytes"
"github.com/giorgisio/goav/avformat"
"github.com/giorgisio/goav/avutil"
"unsafe"
)
func DecodeStream(data *bytes.Buffer) {
bufferSize := 8192
formatContext := avformat.AvformatAllocContext()
buffer := (*C.uchar)(avutil.AvMalloc(uintptr(bufferSize)))
ioContext := C.avio_alloc_context(
buffer,
C.int(bufferSize),
C.int(0),
unsafe.Pointer(data),
&[0]byte{},
&[0]byte{},
&[0]byte{},
) // <- error in this line
formatContext.SetPb((*avformat.AvIOContext)(unsafe.Pointer(ioContext)))
if formatContext.AvformatFindStreamInfo(nil) < 0 {
panic("Couldn't find stream info")
}
println("DURATION: ", formatContext.Duration())
}
但是,我收到此错误runtime error: cgo argument has Go pointer to Go pointer
。
我也尝试将&[0]byte{}
替换为nil
。似乎无法摆脱!
答案 0 :(得分:0)
运行时错误实际上是在抱怨unsafe.Pointer(data)
参数。 bytes.Buffer
类型具有内部(Go)指针,并且如果这些指针指向包含Go指针本身的Go对象,则cgo不允许将指针传递给C。
以下cgo文档中详细介绍了这些规则:https://golang.org/cmd/cgo/#hdr-Passing_pointers
简短的摘要是,在修改Go指针时,需要注意Go垃圾收集器。 Go编译器确保已编译的代码适当地通知垃圾回收器,但是C编译器不知道这样做。因此,为了防止出现GC问题,cgo根本不允许这样传递指针。