How to use encodeFromFd to replace encodeFromBuffer?

Since the thread NvJPEGEncoder::encodeFromBuffer trigger segmentation fault is locked. I open this new thread.

I’ve tried the following code

    NvJPEGEncoder* jpegencoder = NvJPEGEncoder::createJPEGEncoder("jpegenc");
    NvBuffer bufferEnc(V4L2_PIX_FMT_YUV420M, roundedWidth, roundedHeight, 0);
    bufferEnc.allocateMemory();

    unsigned char* p_YEnc = bufferEnc.planes[0].data;
    unsigned char* p_UEnc = bufferEnc.planes[1].data;
    unsigned char* p_VEnc = bufferEnc.planes[2].data;
    err = cudaMemcpy2D(p_YEnc, roundedWidth, srcYPtr, 1920, roundedWidth, roundedHeight, cudaMemcpyHostToHost);
    err = cudaMemcpy2D(p_UEnc, roundedWidth/2, srcUPtr, 1920/2, roundedWidth/2, roundedHeight/2, cudaMemcpyHostToHost);
    err = cudaMemcpy2D(p_VEnc, roundedWidth/2, srcVPtr, 1920/2, roundedWidth/2, roundedHeight/2, cudaMemcpyHostToHost);
    
    unsigned char* outputBuf2 = outputBuf;
    unsigned long outputBufSize = sizeof(outputBuf);
    int ret = jpegencoder->encodeFromFd(bufferEnc.planes[0].fd, JCS_YCbCr, &outputBuf2, outputBufSize, 75);

and I got error:

[ERROR] (NvJpegEncoder.cpp:77) <jpegenc> Not encoding because fd = -1

But there seems no example showing me how to do a similar thing. Is there another example showing how to create a fd from some data in CPU?

Hi,
You would need to allocate NvBufSurface. It is demonstrated in 05_jpeg_encode. Please check the code of case 2.

Thank you,

I tried

    int roundedWidth = 250;
    int roundedHeight = 250;
    int roundedX1 = 1000;
    int roundedY1 = 250;

    NvBufSurfaceAllocateParams inputParams = {{0}};
    inputParams.params.width = roundedWidth;
    inputParams.params.height = roundedHeight;
    inputParams.params.layout = NVBUF_LAYOUT_PITCH;
    inputParams.params.colorFormat = NVBUF_COLOR_FORMAT_NV12;
    inputParams.params.memType = NVBUF_MEM_DEFAULT;
    inputParams.memtag = NvBufSurfaceTag_JPEG;
    NvBufSurface *nvbuf_surf = 0;
    int bufCreate = NvBufSurfaceAllocate(&nvbuf_surf, 1, &inputParams);
    printf("bufCreate: %d\n", bufCreate);
    

    NvJPEGEncoder* jpegencoder = NvJPEGEncoder::createJPEGEncoder("jpegenc");
    

    //copy data yuv to nvbuf_surf
    unsigned char* p_YNvBuf = (unsigned char*)nvbuf_surf->surfaceList[0].dataPtr;
    unsigned char* p_UNvBuf = (unsigned char*)nvbuf_surf->surfaceList[0].dataPtr + roundedWidth*roundedHeight;
    unsigned char* p_VNvBuf = (unsigned char*)nvbuf_surf->surfaceList[0].dataPtr + roundedWidth*roundedHeight*5/4;
    memset(p_YNvBuf, 0, roundedWidth*roundedHeight);
    
    p_YNvBuf[0]=0;
    p_YNvBuf[1]=0;
    p_YNvBuf[2]=0;
    
    nvbuf_surf->numFilled = 1;
    printf("nvbuf_surf->surfaceList[0].dataPtr: %p\n", nvbuf_surf->surfaceList[0].dataPtr);
    printf("nvbuf_surf->surfaceList[0].dataSize: %d\n", nvbuf_surf->surfaceList[0].dataSize);

    unsigned char* outputBuf2 = outputBuf;
    unsigned long outputBufSize = sizeof(outputBuf);
    int ret = jpegencoder->encodeFromFd(nvbuf_surf->surfaceList[0].bufferDesc, JCS_YCbCr, &outputBuf2, outputBufSize, 75);
    

But when I try to write data into surfaceList[0].dataPtr, no matter with memset or cudaMemcpy2D, I got a crash in encodeFromFd. Did I allocate correctly? Did I copy data correctly?

Hi,
NVBUF_COLOR_FORMAT_NV12 is a 2-surface format. If your data is in 3-plane Y, U and V, please allocate NVBUF_COLOR_FORMAT_YUV420. And please refer to read_dmabuf() in

/usr/src/jetson_multimedia_api/samples/common/classes/NvUtils.cpp

You would need to map the surface, synchronize it for CPU access, write data, and synchronize it for device access(hardware blocks such as VIC, NVENC).

Thank you.

Here is some working code. In case someone need it in the future.


    NvBufSurfaceAllocateParams inputParams = {{0}};
    inputParams.params.width = roundedWidth;
    inputParams.params.height = roundedHeight;
    inputParams.params.layout = NVBUF_LAYOUT_PITCH;
    inputParams.params.colorFormat = NVBUF_COLOR_FORMAT_YUV420;
    inputParams.params.memType = NVBUF_MEM_DEFAULT;
    inputParams.memtag = NvBufSurfaceTag_JPEG;
    NvBufSurface *nvbuf_surf = 0;
    int bufCreate = NvBufSurfaceAllocate(&nvbuf_surf, 1, &inputParams);
    printf("bufCreate: %d\n", bufCreate);

    int plane = 0;
    int retMap = NvBufSurfaceMap(nvbuf_surf, 0, plane, NVBUF_MAP_READ_WRITE);
    printf("NvBufSurfaceMap: %d\n", retMap);
    NvBufSurfaceSyncForCpu (nvbuf_surf, 0, plane);
    dstYPtr = (unsigned char*)nvbuf_surf->surfaceList->mappedAddr.addr[plane];
    err = cudaMemcpy2D(dstYPtr, nvbuf_surf->surfaceList->planeParams.pitch[plane], srcYPtr, 1920, roundedWidth, roundedHeight, cudaMemcpyHostToHost);
    retMap = NvBufSurfaceUnMap(nvbuf_surf, 0, plane);
    printf("NvBufSurfaceUnMap: %d\n", retMap);

    plane = 1;
    retMap = NvBufSurfaceMap(nvbuf_surf, 0, plane, NVBUF_MAP_READ_WRITE);
    printf("NvBufSurfaceMap: %d\n", retMap);
    NvBufSurfaceSyncForCpu (nvbuf_surf, 0, plane);
    dstUPtr = (unsigned char*)nvbuf_surf->surfaceList->mappedAddr.addr[plane];
    err = cudaMemcpy2D(dstUPtr, nvbuf_surf->surfaceList->planeParams.pitch[plane], srcUPtr, 1920/2, roundedWidth/2, roundedHeight/2, cudaMemcpyHostToHost);
    retMap = NvBufSurfaceUnMap(nvbuf_surf, 0, plane);
    printf("NvBufSurfaceUnMap: %d\n", retMap);

    plane = 2;
    retMap = NvBufSurfaceMap(nvbuf_surf, 0, plane, NVBUF_MAP_READ_WRITE);
    printf("NvBufSurfaceMap: %d\n", retMap);
    NvBufSurfaceSyncForCpu (nvbuf_surf, 0, plane);
    dstVPtr = (unsigned char*)nvbuf_surf->surfaceList->mappedAddr.addr[plane];
    err = cudaMemcpy2D(dstVPtr, nvbuf_surf->surfaceList->planeParams.pitch[plane], srcVPtr, 1920/2, roundedWidth/2, roundedHeight/2, cudaMemcpyHostToHost);
    retMap = NvBufSurfaceUnMap(nvbuf_surf, 0, plane);
    printf("NvBufSurfaceUnMap: %d\n", retMap);

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.