Files
vision-anti-pinch/native/uyvy_converter.cu
T

49 lines
2.0 KiB
Plaintext

#include "uyvy_converter.hpp"
#include "gpu_preprocess.hpp"
#include <cstring>
namespace cms {
__global__ void swapRedBlue(unsigned char* image,int count) {
int i=blockIdx.x*blockDim.x+threadIdx.x;
if(i>=count)return;
unsigned char r=image[3*i];image[3*i]=image[3*i+2];image[3*i+2]=r;
}
struct UyvyConverter::Impl {
int width,height;
cudaStream_t stream{};
unsigned char *uyvy{},*bgr{},*host{};
Impl(int w,int h):width(w),height(h) {
try {
CUDA_CHECK(cudaStreamCreateWithFlags(&stream,cudaStreamNonBlocking));
CUDA_CHECK(cudaMalloc(&uyvy,std::size_t(w)*h*2));
CUDA_CHECK(cudaMalloc(&bgr,std::size_t(w)*h*3));
CUDA_CHECK(cudaMallocHost(&host,std::size_t(w)*h*3));
} catch(...) {release();throw;}
}
~Impl(){release();}
void release() noexcept {
if(stream)cudaStreamSynchronize(stream);
if(uyvy)cudaFree(uyvy);
if(bgr)cudaFree(bgr);
if(host)cudaFreeHost(host);
if(stream)cudaStreamDestroy(stream);
}
};
UyvyConverter::UyvyConverter(int w,int h):impl_(std::make_unique<Impl>(w,h)){}
UyvyConverter::~UyvyConverter()=default;
std::shared_ptr<const BgrImage> UyvyConverter::convert(void const* data,std::size_t stride) {
auto& s=*impl_;
CUDA_CHECK(cudaMemcpy2DAsync(s.uyvy,s.width*2,data,stride,s.width*2,s.height,cudaMemcpyHostToDevice,s.stream));
nppCheck(nppiCbYCr422ToRGB_8u_C2C3R_Ctx(s.uyvy,s.width*2,s.bgr,s.width*3,{s.width,s.height},nppContext(s.stream)));
int pixels=s.width*s.height;
swapRedBlue<<<(pixels+255)/256,256,0,s.stream>>>(s.bgr,pixels);
CUDA_CHECK(cudaGetLastError());
CUDA_CHECK(cudaMemcpyAsync(s.host,s.bgr,std::size_t(pixels)*3,cudaMemcpyDeviceToHost,s.stream));
CUDA_CHECK(cudaStreamSynchronize(s.stream));
auto image=std::make_shared<BgrImage>();
image->width=s.width;image->height=s.height;image->stride=s.width*3;
image->pixels.assign(s.host,s.host+std::size_t(pixels)*3);
return image;
}
}