簡體   English   中英

如何使用指向 C 數據的指針在 Golang 中寫入文件?

[英]How do I write to a file in Golang using a pointer to the C data?

我正在使用 FFmpeg 為 windows 平台編寫一個應用程序,它是 golang 包裝器 goav,但我無法理解如何使用 C 指針來訪問數組。

我正在嘗試將來自 C 的 uint8 指針指向的幀數據寫入 golang 中的 .ppm 文件。

完成此操作后,為了證明 FFmpeg 正在執行我期望的操作,我想將幀設置為 OpenGl 中的紋理,以制作具有酷炫過渡的視頻播放器; 任何能做到這一點的好和有效的指針都會非常有幫助! 我猜我需要編寫一些着色器代碼來繪制 ppm 作為紋理...

PPM 文件結構看起來非常簡單,只是標題,然后是幀中每個像素的每個紅色、綠色和藍色值的字節數據,從左上角到右下角

我開始了解如何在 C 和 Go 類型之間轉換指針,但是如何訪問數據並在 Go 中寫入與 C 相同的結果? 在 CI 中,只需為數據設置指針偏移量並說明要寫入的數據量:

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

我已經去掉了 C 代碼、包裝器和我的代碼的所有相關部分,如下所示:

C 代碼 - libavutil/frame.h

#include <stdint.h>

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

Golang goav 包裝器

package avutil

/*
    #cgo pkg-config: libavutil
    #include <libavutil/frame.h>
    #include <stdlib.h>
*/
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)))
}

我的 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()
}

那么,如何使用指向數據的指針寫入文件,就像您在 C 中所做的那樣,並獲得相同的結果?

第一幀應該是黑色的,所以全是 0,但我得到了一個毛刺模糊,所以它必須訪問一些隨機數據

更新:我的修復使用 C 函數來保存:

package avutil

/*
    #cgo pkg-config: libavutil
    #include <libavutil/frame.h>
    #include <stdlib.h>
    #include <stdio.h>

    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; y<height; y++)
            fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);

        // Close file
        fclose(pFile);
    }
    uint8_t* GetData(AVFrame *pFrame) {
        return pFrame->data[0];
    }
*/
import "C"

我更新了 goav 包裝器包中的 avutil 文件,在頂部使用此保存函數,然后將框架上下文傳遞給它,以便它可以從中獲取數據指針。 我還將此 Go 函數添加到該 avutil 文件中以調用 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))
}

我遇到了同樣的問題:AC 函數分配了空間並給出了指向該空間的指針和要讀取的大小。 我通過執行以下操作解決了它:

buffer := *(*[]byte)(unsafe.Pointer(&content))

這將指針轉換為內容地址處的 Golang 字節數組。 buffer填充來自os.Read數據,C 函數處理數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM