簡體   English   中英

想要一些關於如何使用 nvjpegEncodeYUV() 的指南

[英]Want some guide about how to use nvjpegEncodeYUV()

我正在嘗試基於以下示例代碼實現一些 jpeg 編碼 cuda 代碼: https ://docs.nvidia.com/cuda/nvjpeg/index.html#nvjpeg-encode-examples

我發布了所有代碼、測試結果和 Makefile 和輸入文件。

我正在使用 NVIDIA 2080 HW + cuda 11.2 進行測試

但是正如您可以從這個問題中找到的那樣,結果是失敗。 第一次失敗來自 nvjpegEncodeYUV() 返回的錯誤代碼是 2。這抱怨一些無效的參數。 但我不知道出了什么問題……你能幫我找出問題所在嗎?

#include <iterator>
#include <fstream>
#include <iostream>
#include <vector>

#include <cassert>
#include <unistd.h>

#include "nppdefs.h"
#include "nppi_support_functions.h"
#include "nppi_color_conversion.h"
#include "nvjpeg.h"

#include "cuda_runtime.h"


#define DEFAULT_RAWFILE  "./uyvy422.raw"

//file >>> buff_UYVY
int read_raw(const char *file2read, unsigned char *buff_UYVY)
{
  if (!file2read) {
    std::cout << "file2read empty!!" << std::endl;
    return 1;
  }

  if (!buff_UYVY) {
    std::cout << "buff_UYVY empty!!" << std::endl;
    return 1;
  }

  std::string   file_uyvy(file2read);
  std::ifstream stream_uyvy;
  stream_uyvy.open(file_uyvy, std::ios::in | std::ios::binary);

  if (!stream_uyvy.is_open())
  {
    std::cerr << "[ERROR] cannot open the raw file " << file_uyvy
      << std::endl;
    std::cerr << std::endl;
    assert(0);
  }
  stream_uyvy.read((char*)buff_UYVY, 1920*1080*2);
  stream_uyvy.close();

  return 0;
}


int main(int argc, char*argv[])
{
  unsigned char *buff_UYVY =
    new unsigned char[1920 * 1080 * 2];

  //file >>> buff_UYVY
  int ret;
  if (argv[1]) {
    ret = read_raw(argv[1], buff_UYVY);
  } else {
    ret = read_raw(DEFAULT_RAWFILE, buff_UYVY);
  }
  if (ret != 0) {
    std::cout << "read_raw() failed!!" << std::endl;
    return ret;
  }
  if (!buff_UYVY) {
    std::cout << "buff_UYVY empty!!" << std::endl;
    return 1;
  }

  cudaError_t err_cu_api;
  Npp8u* gpu_buff_CbYCr422;

  err_cu_api = cudaMalloc((void**)&gpu_buff_CbYCr422,
                          1920*1080*2);
  err_cu_api = cudaMemcpy((void*)gpu_buff_CbYCr422,
                          (const void*)buff_UYVY,
                          1920*1080*2,
                          cudaMemcpyHostToDevice);

  //////////////////////////////////////////////////////////////////////////////
  //https://docs.nvidia.com/cuda/nvjpeg/index.html#nvjpeg-encode-examples

  nvjpegStatus_t status;
  nvjpegHandle_t nv_handle;
  nvjpegEncoderState_t nv_enc_state;
  nvjpegEncoderParams_t nv_enc_params;
  cudaStream_t stream = 0;

  // initialize nvjpeg structures
  status = nvjpegCreateSimple(&nv_handle);
  std::cout << "nvjpegCreateSimple : " << status << std::endl;
  status = nvjpegEncoderStateCreate(nv_handle, &nv_enc_state, stream);
  std::cout << "nvjpegEncoderStateCreate : " << status << std::endl;
  status = nvjpegEncoderParamsCreate(nv_handle, &nv_enc_params, stream);
  std::cout << "nvjpegEncoderParamsCreate : " << status << std::endl;

  nvjpegImage_t imgdesc =
  {
    {
      gpu_buff_CbYCr422,
      gpu_buff_CbYCr422 + 1920*1080,
      gpu_buff_CbYCr422 + 1920*1080*2,
      gpu_buff_CbYCr422 + 1920*1080*3
    },
    {
      1920,
      1920,
      1920,
      1920
    }
  };

  // Compress image
  status = nvjpegEncodeYUV(nv_handle, nv_enc_state, nv_enc_params,
                  &imgdesc, NVJPEG_CSS_422, 1920, 1080,
                  stream);
  std::cout << "nvjpegEncodeYUV : " << status << std::endl;

  // get compressed stream size
  size_t length;
  status = nvjpegEncodeRetrieveBitstream(nv_handle, nv_enc_state, NULL,
                                                &length, stream);
  std::cout << "nvjpegEncodeRetrieveBitstream : " << status << std::endl;
  // get stream itself
  cudaStreamSynchronize(stream);
  std::vector<char> jpeg(length);
  status = nvjpegEncodeRetrieveBitstream(nv_handle, nv_enc_state,
                                (unsigned char*)jpeg.data(), &length, 0);
  std::cout << "nvjpegEncodeRetrieveBitstream : " << status << std::endl;

  // write stream to file
  cudaStreamSynchronize(stream);
  std::ofstream output_file("test.jpg", std::ios::out | std::ios::binary);
  output_file.write(jpeg.data(), length);
  output_file.close();

  //https://docs.nvidia.com/cuda/nvjpeg/index.html#nvjpeg-encode-examples
  //////////////////////////////////////////////////////////////////////////////

  cudaFree(gpu_buff_CbYCr422);
  err_cu_api = err_cu_api;

  delete[] buff_UYVY;

  return 0;
}
$ ./test
nvjpegCreateSimple : 0
nvjpegEncoderStateCreate : 0
nvjpegEncoderParamsCreate : 0
nvjpegEncodeYUV : 2
nvjpegEncodeRetrieveBitstream : 2
nvjpegEncodeRetrieveBitstream : 2
CC = g++
CFLAGS = -v -Wall -I/usr/local/cuda/include -g
LDFLAGS += -L/usr/local/cuda/lib64
SRCS = main_gpu.cpp
PROG = test

OPENCV = `pkg-config opencv4 --cflags --libs`
LIBS = $(OPENCV) \
       -lcudart \
       -lnppisu \
       -lnpps \
       -lnppc \
       -lnppial \
       -lnppicc \
       -lnppidei \
       -lnppif \
       -lnppig \
       -lnppim \
       -lnppist \
       -lnppitc \
       -lnvjpeg

.PHONY: all clean

all: $(PROG)

$(PROG):$(SRCS)
        $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROG) $(SRCS) $(LIBS)

clean:
        rm -f $(OBJS) $(PROG) *.jpg *.bmp

獲取輸入文件:

git clone https://github.com/jumogehn/Jumogehn.git

uyvy422.raw 是它。

根據我在您的代碼中看到的內容,我猜您的輸入存儲格式是普通的 YUV422

U0 Y0 V0 Y1 U2 Y2 V2 Y3 U4 Y4 V4…

那是一種交錯存儲格式。 但是nvjpegEncodeYUV狀態的文檔:

源參數應填充相應的 YUV平面數據。

因此,您需要將交錯輸入轉換為 Y 平面的平面存儲,然后是 U 平面,然后是 V 平面

結果,您的imgdesc需要更改,因為 U 和 V 平面的間距是 Y 平面的一半:

  nvjpegImage_t imgdesc =
  {
    {
      gpu_buff_CbYCr422,                        // pointer to start of Y plane
      gpu_buff_CbYCr422 + 1920*1080,                 // pointer to start of U plane
      gpu_buff_CbYCr422 + 1920*1080 + 960*1080,  // pointer to start of V plane
      NULL
    },
    {
      1920,                         // pitch of Y plane
      960,                           // pitch of U plane
      960,                          // pitch of V plane
      0
    }
  };

最后, 您似乎需要在參數中設置采樣因子:

$ cat t2017.cpp
#include "nvjpeg.h"

#include "cuda_runtime.h"
#include <iostream>

#define DEFAULT_RAWFILE  "./uyvy422.raw"

int main(int argc, char*argv[])
{
  unsigned char *buff_UYVY =
    new unsigned char[1920 * 1080 * 2];

  cudaError_t err_cu_api;
  unsigned char* gpu_buff_CbYCr422;

  err_cu_api = cudaMalloc((void**)&gpu_buff_CbYCr422,
                          1920*1080*2);
  err_cu_api = cudaMemcpy((void*)gpu_buff_CbYCr422,
                          (const void*)buff_UYVY,
                          1920*1080*2,
                          cudaMemcpyHostToDevice);

  //////////////////////////////////////////////////////////////////////////////
  //https://docs.nvidia.com/cuda/nvjpeg/index.html#nvjpeg-encode-examples

  nvjpegStatus_t status;
  nvjpegHandle_t nv_handle;
  nvjpegEncoderState_t nv_enc_state;
  nvjpegEncoderParams_t nv_enc_params;
  cudaStream_t stream = 0;

  // initialize nvjpeg structures
  status = nvjpegCreateSimple(&nv_handle);
  std::cout << "nvjpegCreateSimple : " << status << std::endl;
  status = nvjpegEncoderStateCreate(nv_handle, &nv_enc_state, stream);
  std::cout << "nvjpegEncoderStateCreate : " << status << std::endl;
  status = nvjpegEncoderParamsCreate(nv_handle, &nv_enc_params, stream);
  std::cout << "nvjpegEncoderParamsCreate : " << status << std::endl;

  nvjpegImage_t imgdesc =
  {
    {
      gpu_buff_CbYCr422,
      gpu_buff_CbYCr422 + 1920*1080,
      gpu_buff_CbYCr422 + 1920*1080 + 960*1080,
      NULL
    },
    {
      1920,
      960,
      960,
      0
    }
  };
  status = nvjpegEncoderParamsSetSamplingFactors(nv_enc_params, NVJPEG_CSS_422, stream);
  std::cout << "nvjpegEncoderParamsSetSamplingFactors: " << status << std::endl;
  // Compress image
  status = nvjpegEncodeYUV(nv_handle, nv_enc_state, nv_enc_params,
                  &imgdesc, NVJPEG_CSS_422, 1920, 1080,
                  stream);
  std::cout << "nvjpegEncodeYUV : " << status << std::endl;
}
$ g++ t2017.cpp -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lnvjpeg -lcudart -o t2017
$ ./t2017
nvjpegCreateSimple : 0
nvjpegEncoderStateCreate : 0
nvjpegEncoderParamsCreate : 0
nvjpegEncoderParamsSetSamplingFactors: 0
nvjpegEncodeYUV : 0
$

我並不是建議這修復代碼中所有可能的錯誤,只是它似乎解決了這個問題:

第一次失敗來自 nvjpegEncodeYUV() 返回的錯誤代碼是 2。這抱怨一些無效的參數。 但我不知道出了什么問題……你能幫我找出問題所在嗎?

暫無
暫無

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

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