NV12格式是yuv420格式的一種,NV12格式的u,v排布順序為交錯排布,假如一幅圖像尺寸為W*H,則先Y分量有W*H個,然后U分量和V分量交錯排布,U分量和V分量各有W*H/4個,U,V加起來總數是Y分量的一半。
NV12內存YUV分量排布如下所示:
下面是CUDA實現的NV12格式到BGR格式的轉換代碼。StepY,StepUV分別為ffmpeg解碼出的源數據中的Y分量一行的寬度和UV分量一行的寬度,比實際的圖像寬度要大。
__global__ void YCrCb2RGBConver(uchar *pYdata, uchar *pUVdata,int stepY, int stepUV, uchar *pImgData, int width, int height, int channels) { const int tidx = blockIdx.x * blockDim.x + threadIdx.x; const int tidy = blockIdx.y * blockDim.y + threadIdx.y; if (tidx < width && tidy < height) { int indexY, indexU, indexV; uchar Y, U, V; indexY = tidy * stepY + tidx; Y = pYdata[indexY]; if (tidx % 2 == 0) { indexU = tidy / 2 * stepUV + tidx; indexV = tidy / 2 * stepUV + tidx + 1; U = pUVdata[indexU]; V = pUVdata[indexV]; } else if (tidx % 2 == 1) { indexV = tidy / 2 * stepUV + tidx; indexU = tidy / 2 * stepUV + tidx - 1; U = pUVdata[indexU]; V = pUVdata[indexV]; } pImgData[(tidy*width + tidx) * channels + 2] = uchar (Y + 1.402 * (V - 128)); pImgData[(tidy*width + tidx) * channels + 1] = uchar (Y - 0.34413 * (U - 128) - 0.71414*(V - 128)); pImgData[(tidy*width + tidx) * channels + 0] = uchar (Y + 1.772*(U - 128)); } }
CPU版本如下:
void YCrCb2RGBConver(uchar *pYdata, uchar *pUVdata, int stepY, int stepUV, uchar *pImgData, int width, int height, int channels) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int indexY, indexU, indexV; uchar Y, U, V; indexY = i * stepY + j; Y = pYdata[indexY]; if (j % 2 == 0) { indexU = i / 2 * stepUV + j; indexV = i / 2 * stepUV + j + 1; U = pUVdata[indexU]; V = pUVdata[indexV]; } else if (j % 2 == 1) { indexV = i / 2 * stepUV + j; indexU = i / 2 * stepUV + j - 1; U = pUVdata[indexU]; V = pUVdata[indexV]; } pImgData[(i*width + j) * channels + 2] = uchar(Y + 1.402 * (V - 128)); pImgData[(i*width + j) * channels + 1] = uchar(Y - 0.34413 * (U - 128) - 0.71414*(V - 128)); pImgData[(i*width + j) * channels + 0] = uchar(Y + 1.772*(U - 128)); } } }