cuda-samples/Samples/4_CUDA_Libraries/cudaNvSciNvMedia/nvmedia_producer.cpp
2022-01-13 11:35:24 +05:30

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);
}
}