mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2024-12-01 13:39:17 +08:00
472 lines
17 KiB
C++
472 lines
17 KiB
C++
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <iostream>
|
|
/* Nvidia headers */
|
|
#include "nvmedia_utils/cmdline.h"
|
|
#include "nvmedia_image.h"
|
|
#include "nvmedia_2d.h"
|
|
#include "nvmedia_surface.h"
|
|
#include "nvmedia_utils/image_utils.h"
|
|
#include "nvmedia_image_nvscibuf.h"
|
|
#include "nvmedia_producer.h"
|
|
#include "nvmedia_2d_nvscisync.h"
|
|
#include "nvsci_setup.h"
|
|
|
|
NvMediaImage *NvMediaImageCreateUsingNvScibuf(NvMediaDevice *device,
|
|
NvMediaSurfaceType type,
|
|
const NvMediaSurfAllocAttr *attrs,
|
|
uint32_t numAttrs, uint32_t flags,
|
|
NvSciBufObj &bufobj,
|
|
int cudaDeviceId) {
|
|
NvSciBufModule module = NULL;
|
|
NvSciError err = NvSciError_Success;
|
|
NvMediaStatus status = NVMEDIA_STATUS_OK;
|
|
NvSciBufAttrList attrlist = NULL;
|
|
NvSciBufAttrList conflictlist = NULL;
|
|
NvSciBufAttrValAccessPerm access_perm = NvSciBufAccessPerm_ReadWrite;
|
|
NvSciBufAttrKeyValuePair attr_kvp = {NvSciBufGeneralAttrKey_RequiredPerm,
|
|
&access_perm, sizeof(access_perm)};
|
|
NvSciBufAttrKeyValuePair pairArrayOut[10];
|
|
|
|
NvMediaImage *image = NULL;
|
|
|
|
err = NvSciBufModuleOpen(&module);
|
|
if (err != NvSciError_Success) {
|
|
printf("%s: NvSciBuffModuleOpen failed. Error: %d \n", __func__, err);
|
|
goto fail_cleanup;
|
|
}
|
|
|
|
err = NvSciBufAttrListCreate(module, &attrlist);
|
|
if (err != NvSciError_Success) {
|
|
printf("%s: SciBufAttrListCreate failed. Error: %d \n", __func__, err);
|
|
goto fail_cleanup;
|
|
}
|
|
|
|
err = NvSciBufAttrListSetAttrs(attrlist, &attr_kvp, 1);
|
|
if (err != NvSciError_Success) {
|
|
printf("%s: AccessPermSetAttr failed. Error: %d \n", __func__, err);
|
|
goto fail_cleanup;
|
|
}
|
|
|
|
status =
|
|
NvMediaImageFillNvSciBufAttrs(device, type, attrs, numAttrs, 0, attrlist);
|
|
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: ImageFillSciBufAttrs failed. Error: %d \n", __func__, err);
|
|
goto fail_cleanup;
|
|
}
|
|
|
|
setupNvSciBuf(bufobj, attrlist, cudaDeviceId);
|
|
|
|
status = NvMediaImageCreateFromNvSciBuf(device, bufobj, &image);
|
|
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: ImageCreatefromSciBuf failed. Error: %d \n", __func__, err);
|
|
goto fail_cleanup;
|
|
}
|
|
|
|
NvSciBufAttrListFree(attrlist);
|
|
|
|
if (module != NULL) {
|
|
NvSciBufModuleClose(module);
|
|
}
|
|
|
|
return image;
|
|
|
|
fail_cleanup:
|
|
if (attrlist != NULL) {
|
|
NvSciBufAttrListFree(attrlist);
|
|
}
|
|
if (bufobj != NULL) {
|
|
NvSciBufObjFree(bufobj);
|
|
bufobj = NULL;
|
|
}
|
|
|
|
if (module != NULL) {
|
|
NvSciBufModuleClose(module);
|
|
}
|
|
NvMediaImageDestroy(image);
|
|
return NULL;
|
|
}
|
|
|
|
/* Create NvMediaImage surface based on the input attributes.
|
|
* Returns NVMEDIA_STATUS_OK on success
|
|
*/
|
|
static NvMediaStatus createSurface(Blit2DTest *ctx,
|
|
NvMediaSurfFormatAttr *surfFormatAttrs,
|
|
NvMediaSurfAllocAttr *surfAllocAttrs,
|
|
uint32_t numSurfAllocAttrs,
|
|
NvMediaImage **image, NvSciBufObj &bufObj,
|
|
int cudaDeviceId) {
|
|
NvMediaSurfaceType surfType;
|
|
|
|
/* create source image */
|
|
surfType =
|
|
NvMediaSurfaceFormatGetType(surfFormatAttrs, NVM_SURF_FMT_ATTR_MAX);
|
|
*image = NvMediaImageCreateUsingNvScibuf(ctx->device, /* device */
|
|
surfType, /* surface type */
|
|
surfAllocAttrs, numSurfAllocAttrs, 0,
|
|
bufObj, cudaDeviceId);
|
|
|
|
if (*image == NULL) {
|
|
printf("Unable to create image\n");
|
|
return NVMEDIA_STATUS_ERROR;
|
|
}
|
|
InitImage(*image, surfAllocAttrs[0].value, surfAllocAttrs[1].value);
|
|
|
|
/* printf("%s: NvMediaImageCreate:: Image size: %ux%u Image type: %d\n",
|
|
__func__, surfAllocAttrs[0].value, surfAllocAttrs[1].value,
|
|
surfType);*/
|
|
|
|
return NVMEDIA_STATUS_OK;
|
|
}
|
|
|
|
/* Create NvMediaImage surface based on the input attributes.
|
|
* Returns NVMEDIA_STATUS_OK on success
|
|
*/
|
|
static NvMediaStatus createSurfaceNonNvSCI(
|
|
Blit2DTest *ctx, NvMediaSurfFormatAttr *surfFormatAttrs,
|
|
NvMediaSurfAllocAttr *surfAllocAttrs, uint32_t numSurfAllocAttrs,
|
|
NvMediaImage **image) {
|
|
NvMediaSurfaceType surfType;
|
|
|
|
/* create source image */
|
|
surfType =
|
|
NvMediaSurfaceFormatGetType(surfFormatAttrs, NVM_SURF_FMT_ATTR_MAX);
|
|
|
|
*image = NvMediaImageCreateNew(ctx->device, surfType, surfAllocAttrs,
|
|
numSurfAllocAttrs, 0);
|
|
|
|
if (*image == NULL) {
|
|
printf("Unable to create image\n");
|
|
return NVMEDIA_STATUS_ERROR;
|
|
}
|
|
InitImage(*image, surfAllocAttrs[0].value, surfAllocAttrs[1].value);
|
|
|
|
/* printf("%s: NvMediaImageCreate:: Image size: %ux%u Image type: %d\n",
|
|
__func__, surfAllocAttrs[0].value, surfAllocAttrs[1].value,
|
|
surfType);*/
|
|
|
|
return NVMEDIA_STATUS_OK;
|
|
}
|
|
|
|
static void destroySurface(NvMediaImage *image) { NvMediaImageDestroy(image); }
|
|
|
|
static NvMediaStatus blit2DImage(Blit2DTest *ctx, TestArgs *args,
|
|
NvSciSyncObj &nvMediaSignalerSyncObj,
|
|
NvSciSyncFence *preSyncFence,
|
|
NvSciSyncFence *fence) {
|
|
NvMediaStatus status;
|
|
NvMediaImageSurfaceMap surfaceMap;
|
|
|
|
status = ReadImage(args->inputFileName, /* fileName */
|
|
0, /* frameNum */
|
|
args->srcSurfAllocAttrs[0].value, /* source image width */
|
|
args->srcSurfAllocAttrs[1].value, /* source image height */
|
|
ctx->srcImage, /* srcImage */
|
|
NVMEDIA_TRUE, /* uvOrderFlag */
|
|
1, /* bytesPerPixel */
|
|
MSB_ALIGNED); /* pixelAlignment */
|
|
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: ReadImage failed for input buffer: %d\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
if ((args->srcRect.x1 <= args->srcRect.x0) ||
|
|
(args->srcRect.y1 <= args->srcRect.y0)) {
|
|
ctx->srcRect = NULL;
|
|
} else {
|
|
ctx->srcRect = &(args->srcRect);
|
|
}
|
|
|
|
if ((args->dstRect.x1 <= args->dstRect.x0) ||
|
|
(args->dstRect.y1 <= args->dstRect.y0)) {
|
|
ctx->dstRect = NULL;
|
|
} else {
|
|
ctx->dstRect = &(args->dstRect);
|
|
}
|
|
|
|
static int64_t launch = 0;
|
|
// Start inserting pre-fence from second launch inorder to for NvMedia2Blit to
|
|
// wait
|
|
// for cuda signal on fence.
|
|
if (launch) {
|
|
status = NvMedia2DInsertPreNvSciSyncFence(ctx->i2d, preSyncFence);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMedia2DSetNvSciSyncObjforEOF failed: %d\n", __func__,
|
|
status);
|
|
return status;
|
|
}
|
|
NvSciSyncFenceClear(preSyncFence);
|
|
}
|
|
launch++;
|
|
|
|
status = NvMedia2DSetNvSciSyncObjforEOF(ctx->i2d, nvMediaSignalerSyncObj);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMedia2DSetNvSciSyncObjforEOF failed: %d\n", __func__,
|
|
status);
|
|
return status;
|
|
}
|
|
|
|
/* 2DBlit processing on input image */
|
|
status = NvMedia2DBlitEx(ctx->i2d, /* i2d */
|
|
ctx->dstImage, /* dstSurface */
|
|
ctx->dstRect, /* dstRect */
|
|
ctx->srcImage, /* srcSurface */
|
|
ctx->srcRect, /* srcRect */
|
|
&args->blitParams, /* params */
|
|
NULL); /* paramsOut */
|
|
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMedia2DBlitEx failed: %d\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
status =
|
|
NvMedia2DGetEOFNvSciSyncFence(ctx->i2d, nvMediaSignalerSyncObj, fence);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMedia2DGetEOFNvSciSyncFence failed: %d\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
return NVMEDIA_STATUS_OK;
|
|
}
|
|
|
|
static NvMediaStatus blit2DImageNonNvSCI(Blit2DTest *ctx, TestArgs *args) {
|
|
NvMediaStatus status;
|
|
NvMediaImageSurfaceMap surfaceMap;
|
|
|
|
status = ReadImage(args->inputFileName, /* fileName */
|
|
0, /* frameNum */
|
|
args->srcSurfAllocAttrs[0].value, /* source image width */
|
|
args->srcSurfAllocAttrs[1].value, /* source image height */
|
|
ctx->srcImage, /* srcImage */
|
|
NVMEDIA_TRUE, /* uvOrderFlag */
|
|
1, /* bytesPerPixel */
|
|
MSB_ALIGNED); /* pixelAlignment */
|
|
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: ReadImage failed for input buffer: %d\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
if ((args->srcRect.x1 <= args->srcRect.x0) ||
|
|
(args->srcRect.y1 <= args->srcRect.y0)) {
|
|
ctx->srcRect = NULL;
|
|
} else {
|
|
ctx->srcRect = &(args->srcRect);
|
|
}
|
|
|
|
if ((args->dstRect.x1 <= args->dstRect.x0) ||
|
|
(args->dstRect.y1 <= args->dstRect.y0)) {
|
|
ctx->dstRect = NULL;
|
|
} else {
|
|
ctx->dstRect = &(args->dstRect);
|
|
}
|
|
|
|
/* 2DBlit processing on input image */
|
|
status = NvMedia2DBlitEx(ctx->i2d, /* i2d */
|
|
ctx->dstImage, /* dstSurface */
|
|
ctx->dstRect, /* dstRect */
|
|
ctx->srcImage, /* srcSurface */
|
|
ctx->srcRect, /* srcRect */
|
|
&args->blitParams, /* params */
|
|
NULL); /* paramsOut */
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMedia2DBlitEx failed: %d\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
/* Write output image into buffer */
|
|
ctx->bytesPerPixel = 1;
|
|
WriteImageToAllocatedBuffer(ctx, ctx->dstImage, NVMEDIA_TRUE, NVMEDIA_FALSE,
|
|
ctx->bytesPerPixel);
|
|
|
|
return NVMEDIA_STATUS_OK;
|
|
}
|
|
|
|
static void cleanup(Blit2DTest *ctx, NvMediaStatus status = NVMEDIA_STATUS_OK) {
|
|
if (ctx->srcImage != NULL) {
|
|
NvMedia2DImageUnRegister(ctx->i2d, ctx->srcImage);
|
|
destroySurface(ctx->srcImage);
|
|
}
|
|
if (ctx->dstImage != NULL) {
|
|
NvMedia2DImageUnRegister(ctx->i2d, ctx->dstImage);
|
|
destroySurface(ctx->dstImage);
|
|
}
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void cleanupNvMedia(Blit2DTest *ctx, NvSciSyncObj &syncObj,
|
|
NvSciSyncObj &preSyncObj) {
|
|
NvMediaStatus status;
|
|
cleanup(ctx);
|
|
status = NvMedia2DUnregisterNvSciSyncObj(ctx->i2d, syncObj);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
status = NvMedia2DUnregisterNvSciSyncObj(ctx->i2d, preSyncObj);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
NvMediaImageNvSciBufDeinit();
|
|
}
|
|
|
|
void cleanupNvMedia(Blit2DTest *ctx) {
|
|
cleanup(ctx);
|
|
free(ctx->dstBuffPitches);
|
|
free(ctx->dstBuffer);
|
|
free(ctx->dstBuff);
|
|
}
|
|
|
|
void setupNvMedia(TestArgs *args, Blit2DTest *ctx, NvSciBufObj &srcNvSciBufobj,
|
|
NvSciBufObj &dstNvSciBufobj, NvSciSyncObj &syncObj,
|
|
NvSciSyncObj &preSyncObj, int cudaDeviceId) {
|
|
NvMediaStatus status;
|
|
status = NvMediaImageNvSciBufInit();
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
// Create source surface
|
|
status = createSurface(ctx, args->srcSurfFormatAttrs, args->srcSurfAllocAttrs,
|
|
args->numSurfAllocAttrs, &ctx->srcImage,
|
|
srcNvSciBufobj, cudaDeviceId);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to create buffer pools\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
// Create destination surface
|
|
status = createSurface(ctx, args->dstSurfFormatAttrs, args->dstSurfAllocAttrs,
|
|
args->numSurfAllocAttrs, &ctx->dstImage,
|
|
dstNvSciBufobj, cudaDeviceId);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to create buffer pools\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
// Register source Surface
|
|
status =
|
|
NvMedia2DImageRegister(ctx->i2d, ctx->srcImage, NVMEDIA_ACCESS_MODE_READ);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to register source surface\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
// Register destination Surface
|
|
status = NvMedia2DImageRegister(ctx->i2d, ctx->dstImage,
|
|
NVMEDIA_ACCESS_MODE_READ_WRITE);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to register destination surface\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
status = NvMedia2DRegisterNvSciSyncObj(ctx->i2d, NVMEDIA_EOFSYNCOBJ, syncObj);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to NvMedia2DRegisterNvSciSyncObj\n", __func__);
|
|
}
|
|
|
|
status =
|
|
NvMedia2DRegisterNvSciSyncObj(ctx->i2d, NVMEDIA_PRESYNCOBJ, preSyncObj);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to NvMedia2DRegisterNvSciSyncObj\n", __func__);
|
|
}
|
|
}
|
|
|
|
// Create NvMedia src & dst image without NvSciBuf
|
|
void setupNvMedia(TestArgs *args, Blit2DTest *ctx) {
|
|
NvMediaStatus status;
|
|
|
|
// Create source surface
|
|
status = createSurfaceNonNvSCI(ctx, args->srcSurfFormatAttrs,
|
|
args->srcSurfAllocAttrs,
|
|
args->numSurfAllocAttrs, &ctx->srcImage);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to create buffer pools\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
// Create destination surface
|
|
status = createSurfaceNonNvSCI(ctx, args->dstSurfFormatAttrs,
|
|
args->dstSurfAllocAttrs,
|
|
args->numSurfAllocAttrs, &ctx->dstImage);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to create buffer pools\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
// Register source Surface
|
|
status =
|
|
NvMedia2DImageRegister(ctx->i2d, ctx->srcImage, NVMEDIA_ACCESS_MODE_READ);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to register source surface\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
// Register destination Surface
|
|
status = NvMedia2DImageRegister(ctx->i2d, ctx->dstImage,
|
|
NVMEDIA_ACCESS_MODE_READ_WRITE);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Unable to register destination surface\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
|
|
// Allocate buffer for writing image & set image parameters in Blit2DTest.
|
|
ctx->bytesPerPixel = 1;
|
|
AllocateBufferToWriteImage(ctx, ctx->dstImage, NVMEDIA_TRUE, /* uvOrderFlag */
|
|
NVMEDIA_FALSE); /* appendFlag */
|
|
}
|
|
|
|
void runNvMediaBlit2D(TestArgs *args, Blit2DTest *ctx) {
|
|
// Blit2D function
|
|
NvMediaStatus status = blit2DImageNonNvSCI(ctx, args);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Blit2D failed\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
}
|
|
|
|
void runNvMediaBlit2D(TestArgs *args, Blit2DTest *ctx,
|
|
NvSciSyncObj &nvMediaSignalerSyncObj,
|
|
NvSciSyncFence *preSyncFence, NvSciSyncFence *fence) {
|
|
// Blit2D function
|
|
NvMediaStatus status =
|
|
blit2DImage(ctx, args, nvMediaSignalerSyncObj, preSyncFence, fence);
|
|
if (status != NVMEDIA_STATUS_OK) {
|
|
printf("%s: Blit2D failed\n", __func__);
|
|
cleanup(ctx, status);
|
|
}
|
|
}
|