DeepStream--保存NvBufSurface图片

本文详细描述了如何在NVIDIAGPU上使用NvBufSurface结构存储图像数据,特别关注NVBUF_MEM_CUDA_DEVICE类型的内存转移,并提供了将这些硬件内存保存到本地文件的函数实现,包括NV12、RGBA和RGB格式的转换和保存过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        NvBufSurface保存了图像信息,是硬件内存,怎么将硬件内存保存到本地文件?NvBufSurface的memorytype有很多种,类型不一样,获取的方式也不一样,今天主要说的是DGPU上的NVBUF_MEM_CUDA_DEVICE类型。如下是nvidia支持的内存类型。

typedef enum

{

  /** Specifies the default memory type, i.e. \ref NVBUF_MEM_CUDA_DEVICE

   for dGPU, \ref NVBUF_MEM_SURFACE_ARRAY for Jetson. Use \ref NVBUF_MEM_DEFAULT

   to allocate whichever type of memory is appropriate for the platform. */

  NVBUF_MEM_DEFAULT,

  /** Specifies CUDA Host memory type. */

  NVBUF_MEM_CUDA_PINNED,

  /** Specifies CUDA Device memory type. */

  NVBUF_MEM_CUDA_DEVICE,

  /** Specifies CUDA Unified memory type. */

  NVBUF_MEM_CUDA_UNIFIED,

  /** Specifies NVRM Surface Array type. Valid only for Jetson. */

  NVBUF_MEM_SURFACE_ARRAY,

  /** Specifies NVRM Handle type. Valid only for Jetson. */

  NVBUF_MEM_HANDLE,

  /** Specifies memory allocated by malloc(). */

  NVBUF_MEM_SYSTEM,

} NvBufSurfaceMemType;

      DGPU方法  

      保存图片的流程主要是用cudaMemcpy将Device内存拷贝到CPU内存,再根据颜色格式,保存到本地文件。代码如下,支持nv12/rgba/rgb格式的保存。

void
save_nv12(char* src, int width, int height, int pitch, FILE* fp)
{
    for (int i = 0;i < height;i++)
    {
        fwrite(src, 1, width, fp);
        src += pitch;
    }
    for (int i = 0;i < height / 2;i++)
    {
        fwrite(src, 1, width, fp);
        src += pitch;
    }
}

void
save_rgba(char* src, int width, int height, int pitch, FILE* fp)
{
    int datalen = width * 4;
    for (int i = 0;i < height;i++) {
        fwrite(src, 1, datalen, fp);
        src += pitch;
    }
}

void
save_rgb(char* src, int width, int height, int pitch, FILE* fp)
{
    int datalen = width * 3;
    for (int i = 0;i < height;i++) {
        fwrite(src, 1, datalen, fp);
        src += pitch;
    }
}

int
save_NvBufSurface(NvBufSurface * surface, char* filename)
{
    int nRst = 0;
    char* src_data = NULL;
    NvBufSurfaceColorFormat colorFormat;
    int width, height, dataSize, pitch;
    char full_filename[256] = {0};
    for (uint32_t i = 0; i < surface->batchSize; i++) {
      colorFormat = surface->surfaceList[i].colorFormat;
      width = surface->surfaceList[i].width;
      height = surface->surfaceList[i].height;
      dataSize = surface->surfaceList[i].dataSize;
      pitch = surface->surfaceList[i].pitch;
      //printf("colorFormat:%d, w:%d,h:%d,size:%d, pitch:%d\n", colorFormat, width, height, dataSize, pitch);
      if(colorFormat == NVBUF_COLOR_FORMAT_NV12){
        sprintf(full_filename,"%s_%d.yuv", filename, i);
      } else if (colorFormat == NVBUF_COLOR_FORMAT_RGBA){
        sprintf(full_filename,"%s_%d.rgb", filename, i);
      } else if (colorFormat == NVBUF_COLOR_FORMAT_RGB){
        sprintf(full_filename,"%s_%d.rgb", filename, i);
      }
      //save data to file.
      FILE* fp = fopen(full_filename, "wb");
      if(!fp) {
        printf("fopen %s failed\n", full_filename);
        return -1;
      }
      src_data = (char*) malloc(dataSize);
      if(!src_data){ 
        fclose(fp); 
        fp = NULL;
        printf("mallloc failed\n");
        return -1;
      }
      cudaMemcpy((void*)src_data, (void*)surface->surfaceList[i].dataPtr, dataSize, cudaMemcpyDeviceToHost);

      if(colorFormat == NVBUF_COLOR_FORMAT_NV12){
        save_nv12(src_data, width, height, pitch, fp);
      } else if (colorFormat == NVBUF_COLOR_FORMAT_RGBA){
        save_rgba(src_data, width, height, pitch, fp);
      } else if (colorFormat == NVBUF_COLOR_FORMAT_RGB){
        save_rgb(src_data, width, height, pitch, fp);
      }

      fclose(fp);
      fp =  NULL;
      free(src_data); 
      src_data = NULL;
    }
    return nRst;
}

sample:
    static int n = 0;
    char sbuf[32] = {0};
    sprintf(sbuf, "%d", n);
    if(n++ % 300 == 0)
    save_NvBufSurface(surface, sbuf);



用法:

static int n = 0;
char sbuf[32] = {0};
sprintf(sbuf, "%d", n);

save_NvBufSurface(&nvdspreprocess->batch_outsurf, sbuf);

保存的数据是原始数据,可以用ffplay进行预览。命令如下:

ffplay -pixel_format nv12 -s 1920x1080 1.yuv

ffplay -pixel_format rgba -s 1920x1080 1.rgb

Jetson的方法

#include <iostream>
#include <fstream>
      
      char* nv12_data = NULL; 

      if(nv12_data == NULL){
        nv12_data = (char*) malloc(width * height * 3/2);
      }
      char* pnv12 = nv12_data;
      NvBufSurfaceMappedAddr *mAddr = &(surface->surfaceList[0].mappedAddr);
      NvBufSurfacePlaneParams *planeParams = &(surface->surfaceList[frame_meta->batch_id].planeParams);
      int bs = 0;
      char filename[64];
      sprintf(filename, "output_%dx%d_bs-%d.nv12", width, height, bs);
      std::ofstream outputfile(filename);

      for (int p = 0; p < planeParams->num_planes; p++)
      {
        printf("%d,bp:%d,w:%d,h:%d\n", p,
          planeParams->bytesPerPix[p], planeParams->width[p], planeParams->height[p]);
        size_t bytes_to_write = planeParams->bytesPerPix[p] * planeParams->width[p];
        char *data = (char *) mAddr->addr[p];
        for (int j = 0; j < planeParams->height[p]; j++)
        {
          outputfile.write(data, bytes_to_write);
          memcpy(pnv12, data, bytes_to_write);
          data += planeParams->pitch[p];
          pnv12 += bytes_to_write;
        }
      }
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山西茄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值