¿Cómo escribo en un archivo en Golang utilizando un puntero a los datos de C?

Estoy escribiendo una aplicación para la plataforma de Windows usando FFmpeg y es Golang wrapper goav, pero tengo problemas para entender cómo usar los punteros C para obtener acceso a una matriz.

Estoy tratando de escribir los datos del marco, señalado por un puntero uint8 desde C, a un archivo .ppm en Golang.

Una vez que haya hecho esto, como prueba de concepto de que FFmpeg está haciendo lo que espero, quiero configurar los marcos a una textura en OpenGl para hacer un reproductor de video con transiciones geniales; ¡Cualquier ayuda para hacer eso de manera agradable y eficiente sería muy útil! Supongo que necesito escribir un código de sombreado para dibujar el ppm como textura …

La estructura de archivos PPM parece bastante simple solo el encabezado y luego un byte de datos para cada valor rojo, verde y azul de cada píxel en el marco desde la parte superior izquierda a la parte inferior derecha

Estoy empezando a entender cómo convertir los punteros entre los tipos C y Go, pero ¿cómo puedo acceder a los datos y escribirlos en Go con el mismo resultado que C? En CI solo hay que establecer el desplazamiento del puntero para los datos e indicar cuánto escribir:

for (y = 0; y data[0]+y*pFrame->linesize[0], 1, width*3, pFile); } 

He eliminado todas las partes relevantes del código C, la envoltura y mi código, como se muestra a continuación:

Código C – libavutil / frame.h

 #include  typedef struct AVFrame { #define AV_NUM_DATA_POINTERS 8 uint8_t *data[AV_NUM_DATA_POINTERS]; int linesize[AV_NUM_DATA_POINTERS]; } 

Golang envoltura de goav

 package avutil /* #cgo pkg-config: libavutil #include  #include  */ import "C" import ( "unsafe" ) type Frame C.struct_AVFrame func Data(f *Frame) *uint8 { return (*uint8)(unsafe.Pointer((*C.uint8_t)(unsafe.Pointer(&f.data)))) } func Linesize(f *Frame) int { return int(*(*C.int)(unsafe.Pointer(&f.linesize))) } 

Mi codigo de golang

 package main import "github.com/giorgisio/goav/avutil" func saveFrame(videoFrame *avutil.Frame, width int, height int, iFrame int) { var szFilename string var y int var file *os.File var err error szFilename = "" // Open file szFilename = fmt.Sprintf("frame%d.ppm", iFrame) if file, err = os.Create(szFilename); err != nil { log.Println("Error Reading") } // Write header fh := []byte(fmt.Sprintf("P6\n%d %d\n255\n", width, height)) file.Write(fh) var b byte = 0 // Write pixel data for y = 0; y < height; y++ { d := avutil.Data(videoFrame) // d should be a pointer to the first byte of data l := avutil.Linesize(videoFrame) // I'm basically lost trying to figure out how to correctly write // this to a file, the file is created, but when I open it in GIMP // the image is mostly black with glitchy fuzz - so it's not being // written properly; the header seems to be ok, it knows the height // and width at least. data := make([]byte, l*3) ptr := unsafe.Pointer(d) for i := 0; i < l; i++ { datum := (*uint8)(unsafe.Pointer(uintptr(ptr) + (uintptr(i)+(uintptr(y)*uintptr(l)))*unsafe.Sizeof(*d))) data = append(data, *datum) //fmt.Println(*datum) } n, err := file.Write(data) if err != nil { log.Println("Error Writing:", szFilename, "-", n) } } file.Close() } 

Entonces, ¿cómo puedo escribir en un archivo utilizando un puntero a los datos, como puede hacer en C, y obtener el mismo resultado?

El primer fotogtwig debe ser negro, así que todos los 0, pero tengo un problema con la imagen, por lo que debe estar accediendo a algunos datos aleatorios

Actualización: Mi corrección usando una función C para guardar:

 package avutil /* #cgo pkg-config: libavutil #include  #include  #include  void SaveFrame(const char* location, AVFrame *pFrame, int width, int height) { FILE *pFile; int y; // Open file pFile=fopen(location, "wb"); if(pFile==NULL) return; // Write header fprintf(pFile, "P6\n%d %d\n255\n", width, height); // Write pixel data for(y=0; ydata[0]+y*pFrame->linesize[0], 1, width*3, pFile); // Close file fclose(pFile); } uint8_t* GetData(AVFrame *pFrame) { return pFrame->data[0]; } */ import "C" 

Actualicé el archivo avutil, en el paquete de envoltorio de goav, con esta función de guardado en la parte superior, luego le pasé el contexto de marco para que pueda obtener el puntero de datos. También agregué esta función Ir a ese archivo avutil para llamar a la función C

 func SaveFrame(location string, f *Frame, width int, height int) { csLoc := C.CString(location) C.SaveFrame(csLoc, (*C.struct_AVFrame)(unsafe.Pointer(f)), C.int(width), C.int(height)) C.free(unsafe.Pointer(csLoc)) }