libswscale错误的dst图像指针cgo

问题描述

我正在尝试使用libswscale缩放图像,然后再使用cgo编码为h264。在这里,我编写了一个简单的演示(很抱歉,代码风格不好,我只想进行快速验证):

func scale(img []byte,scaleFactor int) {
    input,_,_ := image.Decode(bytes.NewReader(img))
    if a,ok := input.(*image.ycbcr); ok {
        width,height := a.Rect.Dx(),a.Rect.Dy()
        var format C.enum_AVPixelFormat = C.AV_PIX_FMT_YUV420P
        context := C.sws_getContext(C.int(width),C.int(height),format,C.int(width/scaleFactor),C.int(height/scaleFactor),C.int(0x10),nil,nil)
        in := make([]uint8,0)
        in = append(in,a.Y...)
        in = append(in,a.Cb...)
        in = append(in,a.Cr...)
        stride := []C.int{C.int(width),C.int(width / 2),0}
        outstride := []C.int{C.int(width / scaleFactor),C.int(width / scaleFactor / 2),0}
        out := make([]uint8,width*height/scaleFactor/scaleFactor*3/2)
        C.sws_scale(context,(**C.uint8_t)(unsafe.Pointer(&in[0])),(*C.int)(&stride[0]),(**C.uint8_t)(unsafe.Pointer(&out[0])),(*C.int)(&outstride[0]))
        min := image.Point{0,0}
        max := image.Point{width / scaleFactor,height / scaleFactor}
        output := image.Newycbcr(image.Rectangle{Min: min,Max: max},image.ycbcrSubsampleRatio420)
        panesize := width * height / scaleFactor / scaleFactor
        output.Y = out[:panesize]
        output.Cb = out[panesize : panesize*5/4]
        output.Cr = out[panesize*5/4:]
        opt := jpeg.Options{
            Quality: 90,}
        f,_ := os.Create("img.jpeg")
        jpeg.Encode(f,output,&opt)
    }
}

每次我运行代码片段时,都会出现一个错误提示bad dst image pointers,这是我的代码有什么问题。我是cgo的新手,所以代码可能对您来说很愚蠢,对此我深表歉意。 如果您有更优雅的方式来实现该功能,我将不知所措。任何建议将不胜感激。

解决方法

swscale需要一个二维数组。那是一个指向指针数组的指针。每个指针指向图像的不同平面(y,u,v)。您正在制作一个缓冲区,并将一个指针传递给该缓冲区的指针。 swscale没有指向U和V平面的指针。因此指针指向错误。

,

事实证明,我的输入和输出缓冲区都是错误的,它们都必须是二维数组,如@szatmary所述。这是工作代码

func Scale(img []byte,outw,outh int) []byte {
    input,_,_ := image.Decode(bytes.NewReader(img))
    if a,ok := input.(*image.YCbCr); ok {
        width,height := a.Rect.Dx(),a.Rect.Dy()
        var format C.enum_AVPixelFormat = C.AV_PIX_FMT_YUV420P
        context := C.sws_getContext(C.int(width),C.int(height),format,C.int(outw),C.int(outh),C.int(0x10),nil,nil)
        y := (*C.uint8_t)(C.malloc(C.ulong(len(a.Y))))
        C.memcpy(unsafe.Pointer(y),unsafe.Pointer(&a.Y[0]),(C.size_t)(len(a.Y)))
        cb := (*C.uint8_t)(C.malloc(C.ulong(len(a.Cb))))
        C.memcpy(unsafe.Pointer(cb),unsafe.Pointer(&a.Cb[0]),(C.size_t)(len(a.Cb)))
        cr := (*C.uint8_t)(C.malloc(C.ulong(len(a.Cr))))
        C.memcpy(unsafe.Pointer(cr),unsafe.Pointer(&a.Cr[0]),(C.size_t)(len(a.Cr)))
        in := []*C.uint8_t{y,cb,cr}
        stride := []C.int{C.int(a.YStride),C.int(a.CStride),0}
        outstride := []C.int{C.int(outw),C.int(outw / 2),0}
        paneSize := outw * outh
        a := (*C.uint8_t)(C.malloc(C.ulong(paneSize)))
        b := (*C.uint8_t)(C.malloc(C.ulong(paneSize >> 2)))
        c := (*C.uint8_t)(C.malloc(C.ulong(paneSize >> 2)))
        out := []*C.uint8_t{a,b,c}
        C.sws_scale(context,(**C.uint8_t)(unsafe.Pointer(&in[0])),(*C.int)(&stride[0]),(**C.uint8_t)(unsafe.Pointer(&out[0])),(*C.int)(&outstride[0]))
        min := image.Point{0,0}
        max := image.Point{outw,outh}
        output := image.NewYCbCr(image.Rectangle{Min: min,Max: max},image.YCbCrSubsampleRatio420)
        C.memcpy(unsafe.Pointer(&output.Y[0]),unsafe.Pointer(a),(C.size_t)(paneSize))
        C.memcpy(unsafe.Pointer(&output.Cb[0]),unsafe.Pointer(b),(C.size_t)(paneSize>>2))
        C.memcpy(unsafe.Pointer(&output.Cr[0]),unsafe.Pointer(c),(C.size_t)(paneSize>>2))
        opt := jpeg.Options{
            Quality: 75,}
        var buf bytes.Buffer
        w := bufio.NewWriter(&buf)
        jpeg.Encode(w,output,&opt)
        return buf.Bytes()
    }
    return nil
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...