Commit 2af51c1c authored by xulei's avatar xulei

driveos_demos

parent 9dc25fc2
# Copyright (c) 2013-2019, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
SUBDIRS := ext_dev_prgm/img_dev \
eglstream img_cap img_cc img_isp \
img_enc img_usbcap ipp_raw ipp_yuv \
misc_util vid_cap vid_enc \
vid_play nvsipl
.PHONY: all clean $(SUBDIRS)
all clean: $(SUBDIRS)
$(SUBDIRS):
test ! -r $@/Makefile || make -C $@ ${MAKECMDGOALS}
# Copyright (c) 2013-2019, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
NV_WINSYS = egldevice
include ../../../../make/nvdefs.mk
TARGETS = nvm_egldgpu
CFLAGS := $(NV_PLATFORM_OPT) $(NV_PLATFORM_CFLAGS) -I. -I../../utils -Iwinintf
CPPFLAGS := $(NV_PLATFORM_SDK_INC) $(NV_PLATFORM_CPPFLAGS)
LDFLAGS := $(NV_PLATFORM_SDK_LIB) $(NV_PLATFORM_TARGET_LIB) $(NV_PLATFORM_LDFLAGS)
OBJS += cmdline.o
OBJS += cuda_consumer.o
OBJS += eglstrm_setup.o
OBJS += img_producer.o
OBJS += main.o
OBJS += ../../utils/image_utils.o
OBJS += ../../utils/log_utils.o
OBJS += ../../utils/misc_utils.o
OBJS += ../../utils/thread_utils.o
OBJS += winintf/egl_utils.o
OBJS += winintf/egl_utilsdGPU.o
OBJS += winintf/win_egldevice.o
LDLIBS := -L ../../utils
LDLIBS := -lnvmedia
LDLIBS += -lEGL
LDLIBS += -lGLESv2
LDLIBS += -lcuda
CFLAGS += -D_FILE_OFFSET_BITS=64
ifeq ($(NV_PLATFORM_OS), QNX)
CFLAGS += -DNVMEDIA_QNX
endif
ifeq ($(NV_PLATFORM_OS), Linux)
LDLIBS += -pthread
LDLIBS += -ldl
LDLIBS += -lrt
else
LDLIBS += -lsocket
endif
$(TARGETS): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
clean clobber:
rm -rf $(OBJS) $(TARGETS)
/*
* Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#include <stdlib.h>
#include <string.h>
#include <cmdline.h>
#include <misc_utils.h>
#include <log_utils.h>
void PrintUsage(void)
{
LOG_MSG("nvm_egldgpu:\n");
LOG_MSG("-h \tPrint this usage\n");
LOG_MSG("-v [level] \tVerbose, diagnostics prints\n");
LOG_MSG("-f [file name] \tInput File Name(should be in YUV420p or RAW)\n");
LOG_MSG("-fr [WxH] \tInput file resolution\n");
LOG_MSG("-st [type] \tType: 420p/raw (Default type: 420p)\n");
LOG_MSG("-bl \tProducer uses blocklinear surface. Default is pitch linear\n");
LOG_MSG(" \tBlocklinear is supported only for iGPU\n");
LOG_MSG(" \tdGPU works with pitch linear only\n");
LOG_MSG("-n [frame count] \tNo. of frames to produce(Default: all frames in file)\n");
LOG_MSG("--fifo \tSet FIFO mode for EGL stream. Default is Mailbox mode\n");
LOG_MSG("--crossproc \tSet cross process for producer & consumer: prod/con\n");
LOG_MSG("-s [file name] \tSave to file for consumer \n");
LOG_MSG("--dgpu [1/0] \t 1- Consumer is running on dGPU.\n");
LOG_MSG(" \t 0 - Consumer is on Tegra.(Default is 1)\n");
LOG_MSG("--useblit \t Use blit before posting the surfaces to eglstream\n");
LOG_MSG("Examples: \n");
LOG_MSG(" 1.To test image producer and cuda consumer from a single process\n");
LOG_MSG(" ./nvm_egldgpu -f test.yuv -s cuda.yuv --fifo -fr 1920x1080\n");
LOG_MSG(" 2.To test image producer and cuda consumer from 2 different processes\n");
LOG_MSG(" First run consumer \n");
LOG_MSG(" ./nvm_egldgpu --crossproc con -s cuda.yuv --fifo \n");
LOG_MSG(" Then run producer \n");
LOG_MSG(" ./nvm_egldgpu --crossproc prod -f test1.yuv -fr 1920x1080 --fifo \n");
}
int MainParseArgs(int argc, char **argv, TestArgs *args)
{
int bLastArg = 0;
int bDataAvailable = 0;
int i;
//default params
args->imagetype = IMAGE_TYPE_YUV420;
args->isConsumerondGPU = true;
args->producer = EGLSTREAM_NVMEDIA_IMAGE;
args->consumer = EGLSTREAM_CUDA;
args->pitchLinearOutput = true;
for (i = 1; i < argc; i++) {
// check if this is the last argument
bLastArg = ((argc - i) == 1);
// check if there is data available to be parsed following the option
bDataAvailable = (!bLastArg) && !(argv[i+1][0] == '-');
if (argv[i][0] == '-') {
if (strcmp(&argv[i][1], "h") == 0) {
PrintUsage();
return 1;
} else if (strcmp(&argv[i][1], "-fifo") == 0) {
args->fifoMode = true;
} else if (strcmp(&argv[i][1], "-useblit") == 0) {
args->useblitpath = true;
} else if (strcmp(&argv[i][1], "v") == 0) {
int logLevel = LEVEL_DBG;
if(bDataAvailable) {
logLevel = atoi(argv[++i]);
if(logLevel < LEVEL_ERR || logLevel > LEVEL_DBG) {
LOG_INFO("MainParseArgs: Invalid logging level chosen (%d). ", logLevel);
LOG_INFO(" Setting logging level to LEVEL_ERR (0)\n");
logLevel = LEVEL_ERR;
}
}
SetLogLevel(logLevel);
args->logLevel = logLevel;
} else if (strcmp(&argv[i][1], "-crossproc") == 0 ) {
if(bDataAvailable) {
++i;
if(!strcasecmp(argv[i], "prod")) {
args->isProdCrossProc = true;
} else if(!strcasecmp(argv[i], "con")) {
args->isConsCrossProc = true;
} else {
LOG_ERR("ERR: ParseArgs: --crossproc must be followed by prod or con\n");
return 1;
}
} else {
args->isCrossProc = true;
}
} else if (strcmp(&argv[i][1], "-dgpu") == 0 ) {
if(bDataAvailable) {
++i;
if(!strcasecmp(argv[i], "1")) {
args->isConsumerondGPU = true;
} else if(!strcasecmp(argv[i], "0")) {
args->isConsumerondGPU = false;
} else {
LOG_ERR("ERR: ParseArgs: --dgpu must be followed by 1 or 0\n");
return 1;
}
} else {
args->isConsumerondGPU = true;
}
} else if(strcmp(&argv[i][1], "f") == 0) {
// Input file name
if(bDataAvailable) {
args->inpFileName = argv[++i];
} else {
LOG_ERR("ParseArgs: -f must be followed by input file name\n");
return 1;
}
} else if(strcmp(&argv[i][1], "fr") == 0) {
if(bDataAvailable) {
if((sscanf(argv[++i], "%ux%u", &args->width, &args->height) != 2)) {
LOG_ERR("ParseArgs: Bad output resolution: %s\n", argv[i]);
return 1;
}
} else {
LOG_ERR("ParseArgs: -fr must be followed by resolution\n");
return 1;
}
} else if(strcmp(&argv[i][1], "bl") == 0) {
args->pitchLinearOutput = false;
} else if (strcmp(&argv[i][1], "st") == 0 ) {
if(bDataAvailable) {
++i;
if(!strcasecmp(argv[i], "420p")) {
args->imagetype = IMAGE_TYPE_YUV420;
} else if(!strcasecmp(argv[i], "rgba")) {
args->imagetype = IMAGE_TYPE_RGBA;
} else if(!strcasecmp(argv[i], "raw")) {
args->imagetype = IMAGE_TYPE_RAW;
} else {
LOG_ERR("ParseArgs: -st must be 420p or rgba or raw. Setting to 420p\n");
args->imagetype = IMAGE_TYPE_YUV420;
}
} else {
LOG_ERR("ERR: ParseArgs: -st must be followed by surface type\n");
return 1;
}
} else if(strcmp(&argv[i][1], "s") == 0) {
// Output file name
if(bDataAvailable) {
args->outFileName = argv[++i];
} else {
LOG_ERR("ParseArgs: -s must be followed by output file name\n");
return 1;
}
} else if (strcmp(&argv[i][1], "n") == 0) {
if (bDataAvailable) {
int frameCount;
if (sscanf(argv[++i], "%d", &frameCount)) {
args->frameCount = frameCount;
} else {
LOG_DBG("ERR: -n must be followed by frame count.\n");
}
} else {
LOG_DBG("ERR: -n must be followed by frame count.\n");
return 1;
}
}
else {
LOG_ERR("Invalid command line option -- %s\n", &argv[i][1]);
return 1;
}
}
}
//check validity of the Args
if (!args->isConsCrossProc) {
if (!args->inpFileName || !args->width || !args->height) {
goto fail;
}
}
if((args->isCrossProc)) {
/*Cross-process creation of producer */
char argsProducer[1024];
char str[256];
/*Append flag -crossproc and prod used to internally indicate crossproc producer*/
strcpy(argsProducer,"./nvm_egldgpu --crossproc prod ");
if(args->inpFileName) {
sprintf(str,"-f %s ",args->inpFileName);
strcat(argsProducer,str);
}
if((args->width) & (args->height)) {
sprintf(str,"-fr %ux%u ",args->width,args->height);
strcat(argsProducer,str);
}
if(args->imagetype == IMAGE_TYPE_RGBA) {
strcat(argsProducer,"-st rgba ");
}else if(args->imagetype == IMAGE_TYPE_RAW) {
strcat(argsProducer,"-st raw ");
}else {
strcat(argsProducer,"-st 420p ");
}
if(args->fifoMode) {
strcat(argsProducer,"--fifo ");
}
if(args->frameCount) {
sprintf(str,"-n %d ",args->frameCount);
strcat(argsProducer,str);
}
if(args->logLevel == LEVEL_DBG) {
strcat(argsProducer,"-v ");
}
/*Make the process run in bg*/
strcat (argsProducer,"& ");
LOG_DBG("\n Crossproc Producer command: %s \n",argsProducer);
/*Create crossproc Producer*/
system(argsProducer);
/*Enable crossproc Consumer in the same process */
args->isConsCrossProc = true;
}
return 0;
fail:
LOG_ERR("Invalid command\n");
return 1;
}
/*
* Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#ifndef _CMDLINE_H_
#define _CMDLINE_H_
#include <stdbool.h>
#include "nvmedia_core.h"
#include "nvmedia_surface.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define FILE_PATH_LENGTH_MAX 256
typedef enum
{
EGLSTREAM_NVMEDIA_VIDEO = 0,
EGLSTREAM_NVMEDIA_IMAGE = 1,
EGLSTREAM_GL = 2,
EGLSTREAM_CUDA = 3,
} ProdConsType;
typedef enum
{
IMAGE_TYPE_YUV420 = 0,
IMAGE_TYPE_RGBA = 1,
IMAGE_TYPE_RAW = 2,
}ImageType;
typedef struct _TestArgs {
uint32_t width;
uint32_t height;
uint32_t frameCount;
ImageType imagetype;
ProdConsType producer;
ProdConsType consumer;
char *inpFileName;
char *outFileName;
int logLevel;
bool fifoMode;
/*Cross proc*/
bool isCrossProc;
bool isProdCrossProc;
bool isConsCrossProc;
bool pitchLinearOutput;
bool isConsumerondGPU;
bool useblitpath;
} TestArgs;
void PrintUsage(void);
int MainParseArgs(int argc, char **argv, TestArgs *args);
#endif
This diff is collapsed.
/*
* Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#ifndef _CUDA_CONSUMER_H_
#define _CUDA_CONSUMER_H_
#include "cudaEGL.h"
#include "log_utils.h"
#include "misc_utils.h"
#include "image_utils.h"
#include "egl_utils.h"
#include "eglstrm_setup.h"
#include "cmdline.h"
#include <pthread.h>
typedef struct _CudaConsumerCtx
{
CUcontext context;
CUeglStreamConnection cudaConn;
EGLStreamKHR eglStream;
EGLDisplay display;
/* Params */
char *outFileName;
unsigned int frameCount;
/* Thread */
pthread_t procThread;
bool procThreadExited;
bool quit;
volatile bool *consumerDone;
bool isConsumerondGPU;
} CudaConsumerCtx;
#if defined(EGL_KHR_stream)
int CudaConsumerInit (volatile bool *consumerDone,
CudaConsumerCtx *cudaConsumer,
EglStreamClient *streamClient,
TestArgs *args);
#endif
void CudaConsumerFini (CudaConsumerCtx *cudaConsumer);
#endif
This diff is collapsed.
/*
* Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#ifndef _EGLSTRM_SETUP_H_
#define _EGLSTRM_SETUP_H_
#include "egl_utils.h"
#define SOCK_PATH "/tmp/nvmedia_egl_socket"
/* struct to give client params of the connection */
/* struct members are read-only to client */
typedef struct _EglStreamClient {
EGLDisplay display;
EGLStreamKHR eglStream;
bool fifoMode;
EGLDisplay display_dGPU;
EGLStreamKHR eglStream_dGPU;
} EglStreamClient;
void EGLStreamPrintStateInfo(EGLint streamState);
EglStreamClient *EGLStreamSingleProcInit(EGLDisplay display,
bool fifoMode,
EGLDisplay display_dGPU,
bool consumerondGPU);
EglStreamClient *EGLStreamProducerProcInit(EGLDisplay display,
bool fifoMode);
EglStreamClient *EGLStreamConsumerProcInit(EGLDisplay display,
bool fifoMode);
void EGLStreamFini(EglStreamClient *client, bool consumerondGPU);
#endif /* _EGLSTRM_SETUP_H_ */
This diff is collapsed.
/*
* Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#ifndef __IMG_PRODUCER_H__
#define __IMG_PRODUCER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <pthread.h>
#include "image_utils.h"
#include "log_utils.h"
#include "misc_utils.h"
#include "thread_utils.h"
#include "cmdline.h"
#include "eglstrm_setup.h"
#include "nvmedia_core.h"
#include "nvmedia_surface.h"
#include "nvmedia_image.h"
#include "nvmedia_2d.h"
#include <nvmedia_eglstream.h>
#define IMAGE_BUFFERS_POOL_SIZE 6
#define ENQUEUE_TIMEOUT 100
typedef struct {
NvMediaDevice *device;
NvMediaEGLStreamProducer *producer;
NvQueue *inputQueue;
EGLStreamKHR eglStream;
EGLDisplay display;
/* Params */
char *inpFileName;
uint32_t width;
uint32_t height;
uint32_t frameCount;
NvMediaSurfaceType surfaceType;
/* Threads */
pthread_t procThread;
volatile bool *producerDone;
NvMediaImage *fileimage;
bool useblitpath;
NvMedia2D *blitter;
} ImageProducerCtx;
#if defined(EGL_KHR_stream)
int ImageProducerInit(volatile bool *prodFinished,
ImageProducerCtx *imgProducer,
EglStreamClient *streamClient,
TestArgs *args);
#endif
void ImageProducerFini(ImageProducerCtx *imgProducer);
void ImageProducerStop(ImageProducerCtx *imgProducer);
void ImageProducerFlush(ImageProducerCtx *imgProducer);
#ifdef __cplusplus
}
#endif
#endif // __IMG_PRODUCER_H__
/*
* Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "egl_utils.h"
#include "eglstrm_setup.h"
#include "img_producer.h"
#include "cuda_consumer.h"
#include "cmdline.h"
#include "log_utils.h"
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
volatile bool signal_stop = 0;
static void
sig_handler(int sig)
{
signal_stop = true;
LOG_DBG("Signal: %d\n", sig);
}
int main(int argc, char **argv)
{
TestArgs args;
EglUtilState *eglUtil = NULL;
EglStreamClient *streamClient = NULL;
volatile bool producerDone = 0;
volatile bool consumerDone = 0;
ImageProducerCtx imgProducer;
CudaConsumerCtx cudaConsumer;
EglUtilOptions options;
int res = 1;
/* Hook up Ctrl-C handler */
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
memset(&args, 0, sizeof(TestArgs));
if (MainParseArgs(argc, argv, &args)) {
return res;
}
memset(&options, 0, sizeof(EglUtilOptions));
options.windowInitDisable = 1;
LOG_DBG("eglutil init\n");
eglUtil = EGLUtilInit(&options);
if (!eglUtil) {
LOG_ERR("failed to initialize egl \n");
return 1;
}
if(EGLUtilInit_dGPU(eglUtil)){
LOG_ERR("Failed in EGLUtilInit_dGPU \n");
return 1;
}
/* Setting single proc/cross proc */
if (args.isProdCrossProc) {
streamClient = EGLStreamProducerProcInit(eglUtil->display,
args.fifoMode);
if (!streamClient) {
LOG_ERR("%s: failed to init EGLStream client in producer process\n", __func__);
goto fail;
}
} else if (args.isConsCrossProc) {
streamClient = EGLStreamConsumerProcInit(args.isConsumerondGPU ? eglUtil->display_dGPU : eglUtil->display,
args.fifoMode);
if (!streamClient) {
LOG_ERR("%s: failed to init EGLStream client in consumer process\n", __func__);
goto fail;
}
} else {
streamClient = EGLStreamSingleProcInit(eglUtil->display,
args.fifoMode,
eglUtil->display_dGPU,
args.isConsumerondGPU);
if (!streamClient) {
LOG_ERR("%s: failed to init EGLStream client\n", __func__);
goto fail;
}
}
/* Init Consumer */
if (args.isConsCrossProc || !args.isProdCrossProc) {
switch(args.consumer) {
case EGLSTREAM_CUDA:
if(CudaConsumerInit(&consumerDone,
&cudaConsumer,
streamClient,
&args)) {
LOG_ERR("%s: CudaConsumerInit failed\n", __func__);
goto fail;
}
break;
default:
break;
}
}
/* Init Producer */
if (args.isProdCrossProc || !args.isConsCrossProc) {
EGLint streamState = 0;
/*Wait till consumer is connected*/
while(!signal_stop && streamState != EGL_STREAM_STATE_CONNECTING_KHR) {
if(!eglQueryStreamKHR(streamClient->display,
streamClient->eglStream,
EGL_STREAM_STATE_KHR,
&streamState)) {
LOG_ERR("main: EGLStream failed to connect \n");
goto fail;
}
}
switch(args.producer) {
case EGLSTREAM_NVMEDIA_IMAGE:
if (ImageProducerInit(&producerDone,
&imgProducer,
streamClient,
&args)) {
LOG_ERR("%s: ImageProducerInit failed\n", __func__);
goto fail;
}
break;
default:
break;
}
}
/* wait for signal_stop or producer/consumer done */
while(!signal_stop && !producerDone && !consumerDone) {
usleep(1000);
}
/* Stop Producer */
if (args.isProdCrossProc || !args.isConsCrossProc) {
LOG_DBG("%s - stop producer thread \n", __func__);
switch(args.producer) {
case EGLSTREAM_NVMEDIA_IMAGE:
ImageProducerStop(&imgProducer);
break;
default:
break;
}
}
/* Flush producer */
if (args.isProdCrossProc || !args.isConsCrossProc) {
LOG_DBG("%s - flush producer \n", __func__);
switch(args.producer) {
case EGLSTREAM_NVMEDIA_IMAGE:
ImageProducerFlush(&imgProducer);
break;
default:
break;
}
}
LOG_DBG("%s - program end, clean up start\n", __func__);
res = 0;
fail:
/* Fini Producer */
if (args.isProdCrossProc || !args.isConsCrossProc) {
switch(args.producer) {
case EGLSTREAM_NVMEDIA_IMAGE:
ImageProducerFini(&imgProducer);
break;
default:
break;
}
}
/* Fini Consumer */
if (args.isConsCrossProc || !args.isProdCrossProc){
switch(args.consumer){
case EGLSTREAM_CUDA:
{
CudaConsumerFini(&cudaConsumer);
break;
}
default:
break;
}
}
EGLStreamFini(streamClient, args.isConsumerondGPU);
LOG_DBG("%s: EGLUtil shut down\n", __func__);
EGLUtilDeinit(eglUtil);
return res;
}
/*
* egl_utils.c
*
* Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "egl_utils.h"
#include "log_utils.h"
#define MAX_ATTRIB 31
EXTENSION_LIST(EXTLST_DECL)
typedef void (*extlst_fnptr_t)(void);
static struct {
extlst_fnptr_t *fnptr;
char const *name;
} extensionList[] = { EXTENSION_LIST(EXTLST_ENTRY) };
/* Get the required extension function addresses */
static int EGLUtilSetupExtensions(void)
{
unsigned int i;
for (i = 0; i < (sizeof(extensionList) / sizeof(*extensionList)); i++) {
*extensionList[i].fnptr = eglGetProcAddress(extensionList[i].name);
if (*extensionList[i].fnptr == NULL) {
#ifdef NVMEDIA_QNX
if(!strcmp(extensionList[i].name, "eglGetOutputLayersEXT"))
continue;
if(!strcmp(extensionList[i].name, "eglStreamConsumerOutputEXT"))
continue;
#endif
#ifdef NVMEDIA_GHSI
if (!strcmp(extensionList[i].name, "eglGetStreamFileDescriptorKHR")) {
continue;
}
if (!strcmp(extensionList[i].name, "eglCreateStreamFromFileDescriptorKHR")) {
continue;
}
#endif
LOG_ERR("Couldn't get address of %s()\n", extensionList[i].name);
return -1;
}
}
return 0;
}
int EGLUtilCreateContext(EglUtilState *state)
{
int glversion = 2;
EGLint ctxAttrs[2*MAX_ATTRIB+1], ctxAttrIndex=0;
EGLBoolean eglStatus;
ctxAttrs[ctxAttrIndex++] = EGL_CONTEXT_CLIENT_VERSION;
ctxAttrs[ctxAttrIndex++] = glversion;
ctxAttrs[ctxAttrIndex++] = EGL_NONE;
// Create an EGL context
state->context =
eglCreateContext(state->display,
state->config,
NULL,
ctxAttrs);
if (!state->context) {
LOG_ERR("EGL couldn't create context.\n");
return 0;
}
// Make the context and surface current for rendering
eglStatus = eglMakeCurrent(state->display,
state->surface, state->surface,
state->context);
if (!eglStatus) {
LOG_ERR("EGL couldn't make context/surface current.\n");
return 0;
}
return 1;
}
EGLDisplay EGLUtilDefaultDisplayInit(void)
{
EGLBoolean eglStatus;
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLDeviceEXT devices[16];
EGLint num_devices = 0;
LOG_DBG("%s: Enter\n", __func__);
if (EGLUtilSetupExtensions()) {
LOG_ERR("%s: failed to setup egl extensions\n", __func__);
return EGL_NO_DISPLAY;
}
eglQueryDevicesEXT(5, devices, &num_devices);
if (num_devices == 0) {
LOG_ERR("%s: eglQueryDevicesEXT returned 0 devices\n", __func__);
return EGL_NO_DISPLAY;
}
eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
(void*)devices[0], NULL);
if (EGL_NO_DISPLAY == eglDisplay) {
LOG_ERR("%s: failed to get default display\n", __func__);
return EGL_NO_DISPLAY;
}
// Initialize EGL
eglStatus = eglInitialize(eglDisplay, 0, 0);
if (!eglStatus) {
LOG_ERR("EGL failed to initialize.\n");
return EGL_NO_DISPLAY;
}
LOG_DBG("%s: Exit\n", __func__);
return eglDisplay;
}
EglUtilState *EGLUtilInit(EglUtilOptions *options)
{
EGLBoolean eglStatus;
EglUtilState *state = NULL;
if (EGLUtilSetupExtensions()) {
LOG_ERR("%s: failed to setup egl extensions\n", __func__);
return NULL;
}
state = malloc(sizeof(EglUtilState));
if (!state) {
return NULL;
}
memset(state, 0, sizeof(EglUtilState));
state->display = EGL_NO_DISPLAY;
state->surface = EGL_NO_SURFACE;
/*Initialize with options if passed*/
if(options) {
if(options->windowSize[0])
state->width = options->windowSize[0];
if(options->windowSize[1])
state->height = options->windowSize[1];
state->xoffset = options->windowOffset[0];
state->yoffset = options->windowOffset[1];
state->displayId = options->displayId;
state->windowId = options->windowId;
state->vidConsumer = options->vidConsumer;
state->windowInitDisable = options->windowInitDisable;
}
if(!WindowSystemInit(state)) { // get state->display
free(state);
return NULL;
}
// Initialize EGL
eglStatus = eglInitialize(state->display, 0, 0);
if (!eglStatus) {
LOG_ERR("EGL failed to initialize.\n");
goto eglInit_failed;
}
if(!state->windowInitDisable) {
if(!WindowSystemWindowInit(state)) {
goto windowInit_failed;
}
if(!WindowSystemEglSurfaceCreate(state)) {
LOG_ERR("Couldn't obtain surface \n");
goto surfaceCreate_failed;
}
// Query the EGL surface width and height
eglStatus = eglQuerySurface(state->display, state->surface,
EGL_WIDTH, &state->width)
&& eglQuerySurface(state->display, state->surface,
EGL_HEIGHT, &state->height);
if (!eglStatus) {
LOG_ERR("EGL couldn't get window width/height.\n");
goto querySurface_failed;
}
}
return state;
querySurface_failed:
// Destroy the EGL surface
if(!state->windowInitDisable) {
WindowSystemEglSurfaceDestroy(state);
}
surfaceCreate_failed:
// Close the window
if(!state->windowInitDisable) {
WindowSystemWindowTerminate(state);
}
windowInit_failed:
// Terminate EGL
if (state->display != EGL_NO_DISPLAY) {
eglStatus = eglTerminate(state->display);
if (!eglStatus)
LOG_ERR("Error terminating EGL.\n");
state->display = EGL_NO_DISPLAY;
}
// Release EGL thread
eglStatus = eglReleaseThread();
if (!eglStatus) {
LOG_ERR("Error releasing EGL thread.\n");
}
eglInit_failed:
WindowSystemTerminate();
free(state);
return NULL;
}
// DestroyContext,destroying egl context.
void EGLUtilDestroyContext(EglUtilState *state)
{
EGLBoolean eglStatus;
if(!state) {
LOG_ERR("Bad parameter: Error destroying EGL Context.\n");
return;
}
// Clear rendering context
// Note that we need to bind the API to unbind... yick
if (state->display != EGL_NO_DISPLAY) {
eglBindAPI(EGL_OPENGL_ES_API);
eglStatus = eglMakeCurrent(state->display,
EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
if (!eglStatus)
LOG_ERR("Error clearing current surfaces/context.\n");
}
// Destroy the EGL context
if (state->context != EGL_NO_CONTEXT) {
eglStatus = eglDestroyContext(state->display, state->context);
if (!eglStatus)
LOG_ERR("Error destroying EGL context.\n");
state->context = EGL_NO_CONTEXT;
}
if (state->context_dGPU != EGL_NO_CONTEXT && state->display_dGPU != EGL_NO_DISPLAY) {
eglStatus = eglDestroyContext(state->display_dGPU, state->context_dGPU);
if (!eglStatus)
LOG_ERR("Error destroying EGL context.\n");
state->context_dGPU = EGL_NO_CONTEXT;
}
}
//Deinit, terminate EGL
void EGLUtilDefaultDisplayDeinit(EGLDisplay eglDisplay)
{
EGLBoolean eglStatus;
if (EGL_NO_DISPLAY == eglDisplay) {
return;
}
eglStatus = eglTerminate(eglDisplay);
if (EGL_TRUE != eglStatus) {
LOG_ERR("%s: Error terminating EGL\n, __func__");
}
LOG_DBG("%s: EGL terminated\n", __func__);
}
//Deinit, destroying egl surface and native window system resources
void EGLUtilDeinit(EglUtilState *state)
{
EGLBoolean eglStatus;
if(!state) {
LOG_ERR("Bad parameter: Error destroying EGL Surface.\n");
return;
}
if(!state->windowInitDisable) {
// Destroy the EGL surface
WindowSystemEglSurfaceDestroy(state);
// Close the window
WindowSystemWindowTerminate(state);
}
// Terminate EGL
if (state->display != EGL_NO_DISPLAY) {
eglStatus = eglTerminate(state->display);
if (!eglStatus)
LOG_ERR("Error terminating EGL.\n");
state->display = EGL_NO_DISPLAY;
}
// Release EGL thread
eglStatus = eglReleaseThread();
if (!eglStatus)
LOG_ERR("Error releasing EGL thread.\n");
// Terminate display access
WindowSystemTerminate();
free(state);
}
/*
* egl_utils.h
*
* Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#ifndef _TEST_EGL_SETUP_H
#define _TEST_EGL_SETUP_H
#include <stdbool.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2ext_nv.h>
#include "nvmedia_core.h"
#include "nvmedia_surface.h"
/* ----- Extension pointers ---------*/
#define EXTENSION_LIST(T) \
T( PFNEGLQUERYDEVICESEXTPROC, eglQueryDevicesEXT ) \
T( PFNEGLQUERYDEVICESTRINGEXTPROC, eglQueryDeviceStringEXT ) \
T( PFNEGLGETPLATFORMDISPLAYEXTPROC, eglGetPlatformDisplayEXT ) \
T( PFNEGLGETOUTPUTLAYERSEXTPROC, eglGetOutputLayersEXT ) \
T( PFNEGLSTREAMCONSUMEROUTPUTEXTPROC, eglStreamConsumerOutputEXT) \
T( PFNEGLCREATESTREAMKHRPROC, eglCreateStreamKHR ) \
T( PFNEGLDESTROYSTREAMKHRPROC, eglDestroyStreamKHR ) \
T( PFNEGLQUERYSTREAMKHRPROC, eglQueryStreamKHR ) \
T( PFNEGLQUERYSTREAMU64KHRPROC, eglQueryStreamu64KHR ) \
T( PFNEGLQUERYSTREAMTIMEKHRPROC, eglQueryStreamTimeKHR ) \
T( PFNEGLSTREAMATTRIBKHRPROC, eglStreamAttribKHR ) \
T( PFNEGLCREATESTREAMSYNCNVPROC, eglCreateStreamSyncNV ) \
T( PFNEGLCLIENTWAITSYNCKHRPROC, eglClientWaitSyncKHR ) \
T( PFNEGLSIGNALSYNCKHRPROC, eglSignalSyncKHR ) \
T( PFNEGLSTREAMCONSUMERACQUIREKHRPROC, eglStreamConsumerAcquireKHR ) \
T( PFNEGLSTREAMCONSUMERRELEASEKHRPROC, eglStreamConsumerReleaseKHR ) \
T( PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC, \
eglStreamConsumerGLTextureExternalKHR ) \
T( PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC, eglGetStreamFileDescriptorKHR) \
T( PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC, eglCreateStreamFromFileDescriptorKHR) \
T( PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC, eglCreateStreamProducerSurfaceKHR ) \
T( PFNEGLQUERYSTREAMMETADATANVPROC, eglQueryStreamMetadataNV ) \
T( PFNEGLSETSTREAMMETADATANVPROC, eglSetStreamMetadataNV ) \
T( PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC, eglStreamConsumerAcquireAttribEXT ) \
T( PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALATTRIBSNVPROC, \
eglStreamConsumerGLTextureExternalAttribsNV )
#define EXTLST_DECL(tx, x) tx x = NULL;
#define EXTLST_EXTERN(tx, x) extern tx x;
#define EXTLST_ENTRY(tx, x) { (extlst_fnptr_t *)&x, #x },
typedef struct {
int windowSize[2]; // Window size
int windowOffset[2]; // Window offset
int displayId;
int windowId;
bool vidConsumer;
bool windowInitDisable;
} EglUtilOptions;
typedef struct _EglUtilState {
EGLDisplay display;
EGLSurface surface;
EGLConfig config;
EGLContext context;
EGLint width;
EGLint height;
EGLint xoffset;
EGLint yoffset;
EGLint displayId;
EGLint windowId;
bool vidConsumer;
EGLDisplay display_dGPU;
EGLContext context_dGPU;
bool windowInitDisable;
} EglUtilState;
int EGLUtilCreateContext(EglUtilState *state);
EGLDisplay EGLUtilDefaultDisplayInit(void);
EglUtilState *EGLUtilInit(EglUtilOptions *);
void EGLUtilDefaultDisplayDeinit(EGLDisplay eglDisplay);
void EGLUtilDeinit(EglUtilState *state);
void EGLUtilDestroyContext(EglUtilState *state);
int EGLUtilInit_dGPU(EglUtilState *state);
int EGLUtilCreateContext_dGPU(EglUtilState *state);
bool WindowSystemInit(EglUtilState *state);
void WindowSystemTerminate(void);
int WindowSystemWindowInit(EglUtilState *state);
void WindowSystemWindowTerminate(EglUtilState *state);
bool WindowSystemEglSurfaceCreate(EglUtilState *state);
void WindowSystemEglSurfaceDestroy(EglUtilState *state);
bool WindowSystemInit_dGPU(EglUtilState *state);
void WindowSystemTerminate_dGPU(void);
#endif /* _TEST_EGL_SETUP_H */
/*
* egl_utilsdGPU.c
*
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "egl_utils.h"
#include "log_utils.h"
#define MAX_ATTRIB (31)
int EGLUtilCreateContext_dGPU(EglUtilState *state)
{
int glversion = 2;
EGLint ctxAttrs[2*MAX_ATTRIB+1], ctxAttrIndex=0;
EGLBoolean eglStatus;
EGLint configAttrs[] = {
EGL_SURFACE_TYPE, EGL_STREAM_BIT_KHR,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_ALPHA_SIZE, 1,
EGL_NONE
};
EGLint ncfg = 0;
EGLConfig cfg;
if (!eglChooseConfig(state->display_dGPU, configAttrs, &cfg, 1, &ncfg))
LOG_ERR("Could not find EGL config for dGPU in %s\n", __FUNCTION__);
if (ncfg == 0)
LOG_ERR("No EGL config found for dGPU in %s\n", __FUNCTION__);
ctxAttrs[ctxAttrIndex++] = EGL_CONTEXT_CLIENT_VERSION;
ctxAttrs[ctxAttrIndex++] = glversion;
ctxAttrs[ctxAttrIndex++] = EGL_NONE;
// Create an EGL context
state->context_dGPU =
eglCreateContext(state->display_dGPU,
cfg,
NULL,
ctxAttrs);
if (!state->context_dGPU) {
LOG_ERR("EGL couldn't create context for dGPU.\n");
LOG_ERR("eglerror is %x \n", eglGetError());
return 0;
}
// Make the context and surface current for rendering
eglStatus = eglMakeCurrent(state->display_dGPU,
EGL_NO_SURFACE, EGL_NO_SURFACE,
state->context_dGPU);
if (!eglStatus) {
LOG_ERR("EGL couldn't make context/surface current.\n");
return 0;
}
return 1;
}
int EGLUtilInit_dGPU(EglUtilState *state)
{
EGLBoolean eglStatus;
if(!state){
LOG_ERR("EglUtilState is NULL\n");
return 1;
}
if(!WindowSystemInit_dGPU(state)) { // get state->display
LOG_ERR("WindowSystemInit_dGPU Failed\n");
return 1;
}
// Initialize EGL
LOG_INFO("dGPU display %d.\n", state->display_dGPU);
eglStatus = eglInitialize(state->display_dGPU, 0, 0);
if (!eglStatus) {
LOG_ERR("eglInitialize failed for dGPU display.\n");
goto fail;
}
return 0;
fail:
WindowSystemTerminate_dGPU();
return 1;
}
This diff is collapsed.
# Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
include ../../../make/nvdefs.mk
TARGETS = nvm_dlaSample
CFLAGS := $(NV_PLATFORM_OPT) $(NV_PLATFORM_CFLAGS)
CPPFLAGS := $(NV_PLATFORM_CPPFLAGS) $(NV_PLATFORM_SDK_INC) -DWIN_INTERFACE_CUSTOM -D_POSIX_C_SOURCE=200112L -I. -I./dla -I./logging -I./tensor -I./scisync -I./utils -I./cmdline
CPPFLAGS += -std=c++11 -fexceptions -frtti -fPIC
LDFLAGS := $(NV_PLATFORM_SDK_LIB) $(NV_PLATFORM_TARGET_LIB) $(NV_PLATFORM_LDFLAGS)
OBJS := cmdline/cmdParser.o
OBJS += dla/dla.o
OBJS += logging/cLogger.o
OBJS += tensor/tensor.o
OBJS += scisync/sciSync.o
OBJS += utils/utils.o
OBJS += main.o
OBJS += testRuntime.o
OBJS += testSciSync.o
LDLIBS += -lnvscisync
LDLIBS += -lnvscibuf
LDLIBS += -lnvmedia_dla
LDLIBS += -lnvmedia_tensor
ifeq ($(NV_PLATFORM_SAFETY), 1)
LDLIBS += -lnvmedia_core
else
LDLIBS += -lnvmedia
endif
ifeq ($(NV_PLATFORM_OS), Linux)
LDLIBS += -lpthread
LDLIBS += -ldl
LDLIBS += -lrt
LDLIBS += -lstdc++
else
LDLIBS += -lsocket
LDLIBS += -lc++
endif
.PHONY: default
default: $(TARGETS)
$(TARGETS): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
clean clobber:
rm -rf $(OBJS) $(TARGETS)
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#include "cmdParser.h"
void CmdParser::ShowUsage(void)
{
LOG_MSG("\nExecute runtime test -\n");
LOG_MSG("-h Usage of the test app\n");
LOG_MSG("-v Enable verbose\n");
LOG_MSG("--mode runtime/scisync/ping.\n");
LOG_MSG("-d Specify the dla instance. Avaiable values are 0, 1\n");
LOG_MSG("-n Specify the number of tasks.");
LOG_MSG(" Availabe values are in range of (0, maximum_number_of_outstanding_tasks].");
LOG_MSG(" maximum_number_of_outstanding_tasks can be got from API NvMediaDlaGetMaxOutstandingTasks\n");
LOG_MSG("--profile Specify path to the profile file\n");
LOG_MSG("Sample command line to run a ping test:\n");
LOG_MSG("nvm_dlaSample --mode ping -d dlaId\n");
LOG_MSG("Sample command line to run a runtime test:\n");
LOG_MSG("nvm_dlaSample --mode runtime -d dlaId -n numTasks --loadable <PathToLoadableFile>]\n");
LOG_MSG("Sample command line to run a scisync test:\n");
LOG_MSG("nvm_dlaSample --mode scisync -d dlaId -n numTasks --loadable <PathToLoadableFile>]\n");
return;
}
int CmdParser::Parse(int argc, char* argv[])
{
const char* const short_options = "hm:d:n:p:v";
const struct option long_options[] =
{
{ "help", no_argument, 0, 'h' },
{ "mode", required_argument, 0, 'm' },
{ "instance", required_argument, 0, 'd' },
{ "numTasks", required_argument, 0, 'n' },
{ "loadable", required_argument, 0, 'l' },
{ "verbose", no_argument, 0, 'v' },
{ 0, 0, 0, 0 }
};
int index = 0;
auto bShowHelp = false;
SET_LOG_LEVEL(CLogger::LogLevel::LEVEL_INFORMATION);
while (1) {
const auto getopt_ret = getopt_long(argc, argv, short_options , &long_options[0], &index);
if (getopt_ret == -1) {
// Done parsing all arguments.
break;
}
switch (getopt_ret) {
default: /* Unrecognized option */
case '?': /* Unrecognized option */
LOG_ERR("Invalid or Unrecognized command line option\n");
bShowHelp = true;
break;
case 'h': /* -h or --help */
bShowHelp = true;
break;
case 'v':
verboseLevel = CLogger::LogLevel::LEVEL_DEBUG;
SET_LOG_LEVEL((CLogger::LogLevel)verboseLevel);
break;
case 'm':
if (std::string(optarg) == "runtime") {
testRuntime = true;
} else if (std::string(optarg) == "scisync") {
testSciSync = true;
} else if (std::string(optarg) == "ping") {
testPing = true;
} else {
LOG_ERR("Unknown mode\n");
goto fail;
}
break;
case 'd':
dlaId = atoi(optarg);
break;
case 'n':
numTasks = atoi(optarg);
break;
case 'l':
loadableName = std::string(optarg);
break;
}
}
// Bad arguments
if (bShowHelp) {
goto fail;
}
// Verify command line argument
if (testPing) {
if (testRuntime || testSciSync) {
LOG_ERR("Only one of Runtime / SciSync / Ping test should be enabled \n");
goto fail;
}
}
if (testRuntime) {
if (testPing || testSciSync) {
LOG_ERR("Only one of Runtime / SciSync / Ping test should be enabled \n");
goto fail;
}
if (!loadableName.size()) {
LOG_ERR("loadableName need to be set\n");
goto fail;
}
if (!numTasks) {
LOG_ERR("numTasks need to be set\n");
goto fail;
}
}
if (testSciSync) {
if (testRuntime || testPing) {
LOG_ERR("Only one of Runtime / SciSync / Ping test should be enabled \n");
goto fail;
}
if (!loadableName.size()) {
LOG_ERR("loadableName need to be set\n");
goto fail;
}
if (!numTasks) {
LOG_ERR("numTasks need to be set\n");
goto fail;
}
}
return 0;
fail:
return -1;
}
void CmdParser::PrintArgs() const
{
LOG_INFO("Test runtime = %d \n", testRuntime);
LOG_INFO("Test scisync = %d \n", testSciSync);
LOG_INFO("Test ping = %d \n", testPing);
LOG_INFO("loadable name = %s \n", loadableName.c_str());
LOG_INFO("dlaId = %d \n", dlaId);
LOG_INFO("numTasks = %d \n", numTasks);
LOG_INFO("verbose level = %d \n", verboseLevel);
}
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#ifndef _CMDPARSER_H_
#define _CMDPARSER_H_
/* STL Headers */
#include <unistd.h>
#include <cstdbool>
#include <cstring>
#include <iostream>
#include <getopt.h>
#include <vector>
#include <iomanip>
#include "utils.h"
//! Command line parser class
//! Parse command line options
class CmdParser
{
public:
bool testRuntime = false;
bool testSciSync = false;
bool testPing = false;
std::string loadableName = std::string();
uint32_t dlaId = 0;
uint32_t numTasks = 0;
uint32_t verboseLevel;
static void ShowUsage(void);
int Parse(int argc, char* argv[]);
void PrintArgs() const;
};
#endif // _CMDPARSER_H_
This diff is collapsed.
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. All
* information contained herein is proprietary and confidential to NVIDIA
* Corporation. Any use, reproduction, or disclosure without the written
* permission of NVIDIA Corporation is prohibited.
*/
#ifndef _DLA_H_
#define _DLA_H_
#include <memory>
#include <vector>
#include <array>
#include "nvscisync.h"
#include "nvmedia_dla.h"
#include "nvmedia_dla_nvscisync.h"
#include "nvmedia_core.h"
#include "tensor.h"
#include <limits>
//! Dla class
//! Dla class abstract NvMediaDla APIs and provide functions to load loadable and
//! execute loadable with provided input data.
class Dla final
{
public:
static const uint32_t INVALID_LOADABLEINDEX = std::numeric_limits<uint32_t>::max();
static NvMediaStatus GetDlaVersion(NvMediaVersion *version);
static NvMediaStatus PingById(const uint32_t dlaId);
static std::unique_ptr<Dla> Create();
~Dla();
NvMediaStatus Init(uint32_t dlaId, uint32_t numTasks);
//! One Dla class can hold only one loadable.
NvMediaStatus AddLoadable(std::string profileName, uint32_t &loadableIndex);
NvMediaStatus GetDesc(
uint32_t loadableIndex,
std::vector<NvMediaDlaTensorDescriptor> &vInputTensorDesc,
std::vector<NvMediaDlaTensorDescriptor> &vOutputTensorDesc
);
NvMediaStatus DataRegister(
uint32_t loadableIndex,
Tensor *tensor
);
NvMediaStatus DataUnregister(
uint32_t loadableIndex,
Tensor *tensor
);
NvMediaStatus RemoveLoadable(uint32_t loadableIndex);
NvMediaStatus Submit(
uint32_t loadableIndex,
std::vector<Tensor*> &vpInputTensor,
std::vector<Tensor*> &vpOutputTensor
);
//SciSync related api
NvMediaStatus GetAttrList(
NvSciSyncModule module,
NvSciSyncAttrList &attrList,
NvMediaNvSciSyncClientType syncType);
NvMediaStatus RegisterSyncObj(
NvMediaNvSciSyncObjType syncObjType,
NvSciSyncObj syncObj);
NvMediaStatus UnRegisterSyncObj(
NvSciSyncObj syncObj);
NvMediaStatus SetEOFSyncObj(
NvSciSyncObj syncObj);
NvMediaStatus InsertPreSciFences(NvSciSyncFence *EOFfence);
NvMediaStatus GetEOFSciFences(
NvSciSyncObj eofSyncObj,
NvSciSyncFence *EOFfence);
protected:
NvMediaStatus PrintTensorDesc(NvMediaDlaTensorDescriptor *tensorDesc);
private:
Dla(NvMediaDla *m_pDla);
NvMediaDla *m_pDla;
std::vector<NvMediaDlaLoadable*> m_vLoadables;
static const std::size_t MAX_NUM_OF_DLA_DATA = 40;
std::array<NvMediaDlaData, MAX_NUM_OF_DLA_DATA> m_aInputDlaData;
std::array<NvMediaDlaData, MAX_NUM_OF_DLA_DATA> m_aOutputDlaData;
};
#endif // END OF _DLA_H_
/*
* Copyright (c) 2019 NVIDIA Corporation. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property
* and proprietary rights in and to this software and related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA Corporation is strictly prohibited.
*/
#include "cLogger.h"
#include <cstring>
using namespace std;
CLogger::CLogger() :
m_level(LEVEL_ERR),
m_style(LOG_STYLE_NORMAL),
m_logFile(stdout)
{
}
CLogger::~CLogger()
{
}
CLogger& CLogger::GetInstance()
{
static CLogger instance;
return instance;
}
void CLogger::SetLogLevel(LogLevel level)
{
m_level = (level > LEVEL_DBG) ? LEVEL_DBG : level;
}
void CLogger::SetLogStyle(LogStyle style)
{
m_style = (style > LOG_STYLE_FUNCTION_LINE) ? LOG_STYLE_FUNCTION_LINE
: style;
}
void CLogger::SetLogFile(FILE *logFilePtr)
{
if (logFilePtr) {
m_logFile = logFilePtr;
}
}
void CLogger::LogLevelMessageVa(LogLevel level, const char *functionName,
uint32_t lineNumber, const char *format,
va_list ap)
{
char str[256] = {'\0',};
if (level > m_level) {
return;
}
strcpy(str, "NvMTest: ");
switch (level) {
case LEVEL_NONE:
break;
case LEVEL_ERR:
strcat(str, "ERROR: ");
break;
case LEVEL_WARN:
strcat(str, "WARNING: ");
break;
case LEVEL_INFO:
break;
case LEVEL_DBG:
// Empty
break;
}
vsnprintf(str + strlen(str), sizeof(str) - strlen(str), format, ap);
if (m_style == LOG_STYLE_NORMAL) {
if (strlen(str) != 0 && str[strlen(str) - 1] == '\n') {
strcat(str, "\n");
}
} else if (m_style == LOG_STYLE_FUNCTION_LINE) {
if (strlen(str) != 0 && str[strlen(str) - 1] == '\n') {
str[strlen(str) - 1] = 0;
}
snprintf(str + strlen(str), sizeof(str) - strlen(str), " at %s():%d\n",
functionName, lineNumber);
}
fprintf(m_logFile, "%s", str);
}
void CLogger::LogLevelMessage(LogLevel level, const char *functionName,
uint32_t lineNumber, const char *format, ...)
{
va_list ap;
va_start(ap, format);
LogLevelMessageVa(level, functionName, lineNumber, format, ap);
va_end(ap);
}
void CLogger::LogLevelMessage(LogLevel level, std::string functionName,
uint32_t lineNumber, std::string format, ...)
{
va_list ap;
va_start(ap, format);
LogLevelMessageVa(level, functionName.c_str(), lineNumber,
format.c_str(), ap);
va_end(ap);
}
void CLogger::LogMessageVa(const char *format, va_list ap)
{
char str[128] = {'\0',};
vsnprintf(str, sizeof(str), format, ap);
fprintf(m_logFile, "%s", str);
}
void CLogger::LogMessage(const char *format, ...)
{
va_list ap;
va_start(ap, format);
LogMessageVa(format, ap);
va_end(ap);
}
void CLogger::LogMessage(std::string format, ...)
{
va_list ap;
va_start(ap, format);
LogMessageVa(format.c_str(), ap);
va_end(ap);
}
/*
* Copyright (c) 2019 NVIDIA Corporation. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property
* and proprietary rights in and to this software and related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA Corporation is strictly prohibited.
*/
#ifndef _CLOGGER_H_
#define _CLOGGER_H_
#include <stdint.h>
#include <cstdarg>
#include <cstdio>
#include <string>
//! Set log level
#define SET_LOG_LEVEL(level) \
CLogger::GetInstance().SetLogLevel(level)
#define LINE_INFO __FUNCTION__, __LINE__
//! Quick-log a message at debugging level
#define LOG_DBG(...) \
CLogger::GetInstance().LogLevelMessage(LEVEL_DBG, LINE_INFO, __VA_ARGS__)
//! Quick-log a message at info level
#define LOG_INFO(...) \
CLogger::GetInstance().LogLevelMessage(LEVEL_INFO, LINE_INFO, __VA_ARGS__)
//! Quick-log a message at warning level
#define LOG_WARN(...) \
CLogger::GetInstance().LogLevelMessage(LEVEL_WARN, LINE_INFO, __VA_ARGS__)
//! Quick-log a message at error level
#define LOG_ERR(...) \
CLogger::GetInstance().LogLevelMessage(LEVEL_ERR, LINE_INFO, __VA_ARGS__)
//! Quick-log a message at preset level
#define LOG_MSG(...) \
CLogger::GetInstance().LogMessage(__VA_ARGS__)
#define LEVEL_NONE CLogger::LogLevel::LEVEL_NO_LOG
#define LEVEL_ERR CLogger::LogLevel::LEVEL_ERROR
#define LEVEL_WARN CLogger::LogLevel::LEVEL_WARNING
#define LEVEL_INFO CLogger::LogLevel::LEVEL_INFORMATION
#define LEVEL_DBG CLogger::LogLevel::LEVEL_DEBUG
//! \brief Logger utility class
//! This is a singleton class - at most one instance can exist at all times.
class CLogger{
public:
//! enum describing the different levels for logging
enum LogLevel {
/** no log */
LEVEL_NO_LOG = 0,
/** error level */
LEVEL_ERROR,
/** warning level */
LEVEL_WARNING,
/** info level */
LEVEL_INFORMATION,
/** debug level */
LEVEL_DEBUG
};
//! enum describing the different styles for logging
enum LogStyle {
LOG_STYLE_NORMAL = 0,
LOG_STYLE_FUNCTION_LINE = 1
};
//! Get the logging instance.
//! \return Reference to the Logger object.
static CLogger& GetInstance();
//! Destructor of the Logger class
virtual ~CLogger();
//! Set the level for logging.
//! \param[in] eLevel The logging level.
void SetLogLevel(LogLevel eLevel);
//! Set the style for logging.
//! \param[in] eStyle The logging style.
void SetLogStyle(LogStyle eStyle);
//! Set the logging file (C-style).
//! \param[in] hLogFilePtr Handle of the file to be used for logging.
void SetLogFile(FILE *hLogFilePtr);
//! Log a message (cstring).
//! \param[in] eLevel The logging level,
//! \param[in] pszunctionName Name of the function as a cstring.
//! \param[in] sLineNumber Line number,
//! \param[in] pszFormat Format string as a cstring.
void LogLevelMessage(LogLevel eLevel, const char *pszFunctionName,
uint32_t sLineNumber, const char *pszFormat, ...);
//! Log a message (C++ string).
//! \param[in] eLevel The logging level,
//! \param[in] sFunctionName Name of the function as a C++ string.
//! \param[in] sLineNumber Line number,
//! \param[in] sFormat Format string as a C++ string.
void LogLevelMessage(LogLevel eLevel, std::string sFunctionName,
uint32_t sLineNumber, std::string sFormat, ...);
//! Log a message (cstring) at preset level.
//! \param[in] pszFormat Format string as a cstring.
void LogMessage(const char *pszFormat, ...);
//! Log a message (C++ string) at preset level.
//! \param[in] sFormat Format string as a C++ string.
void LogMessage(std::string sFormat, ...);
private:
//! Need private constructor because this is a singleton.
CLogger();
LogLevel m_level;
LogStyle m_style;
FILE *m_logFile;
void LogLevelMessageVa(LogLevel eLevel, const char *pszFunctionName,
uint32_t sLineNumber, const char *pszFormat, va_list ap);
void LogMessageVa(const char *pszFormat, va_list ap);
}; // CLogger class
#endif // _CLOGGER_H_
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. All
* information contained herein is proprietary and confidential to NVIDIA
* Corporation. Any use, reproduction, or disclosure without the written
* permission of NVIDIA Corporation is prohibited.
*/
#include "testRuntime.h"
#include "testSciSync.h"
#include "cmdParser.h"
#include "utils.h"
#include <chrono>
#include <thread>
int main(int argc, char *argv[])
{
CmdParser cmdline {};
NvMediaStatus status = NVMEDIA_STATUS_OK;
int ret = 0;
ret = cmdline.Parse(argc, argv);
if (ret != 0) {
CmdParser::ShowUsage();
return ret;
}
LOG_INFO(">>>>>>>>>>>>>>>>>>>> Test Begin >>>>>>>>>>>>>>>>>>>> \n");
LOG_INFO("List of input arguments: \n");
cmdline.PrintArgs();
if (cmdline.testRuntime || cmdline.testPing) {
LOG_INFO("Runtime test with dlaId = %d numTasks = %d profile name %s PingTest %d\n",\
cmdline.dlaId, cmdline.numTasks, cmdline.loadableName.c_str(), cmdline.testPing);
// Runtime test
TestRuntime test(cmdline.dlaId, cmdline.numTasks, cmdline.loadableName, cmdline.testPing);
status = test.SetUp();
if (status != NVMEDIA_STATUS_OK) {
LOG_ERR("Test setup fails \n");
ret = -1;
goto fail;
}
status = test.RunTest();
if (status != NVMEDIA_STATUS_OK) {
LOG_ERR("Test setup fails \n");
ret = -1;
goto fail;
}
} else if (cmdline.testSciSync) {
LOG_INFO("Scisync test with dlaId = %d numTasks = %d profile name %s PingTest %d\n",\
cmdline.dlaId, cmdline.numTasks, cmdline.loadableName.c_str(), cmdline.testPing);
// SciSync Test
TestSciSync test(cmdline.dlaId, cmdline.numTasks, cmdline.loadableName);
status = test.SetUp();
if (status != NVMEDIA_STATUS_OK) {
LOG_ERR("Test setup fails \n");
ret = -1;
goto fail;
}
status = test.RunTest();
if (status != NVMEDIA_STATUS_OK) {
LOG_ERR("Test setup fails \n");
ret = -1;
goto fail;
}
}
fail:
if (ret != 0) {
LOG_INFO(">>>>>>>>>>>>>>>>>>>> Test Fail >>>>>>>>>>>>>>>>>>>> \n");
} else {
LOG_INFO(">>>>>>>>>>>>>>>>>>>> Test Pass >>>>>>>>>>>>>>>>>>>> \n");
}
LOG_INFO("<<<<<<<<<<<<<<<<<<<< Test End <<<<<<<<<<<<<<<<<<<<< \n");
return ret;
}
This diff is collapsed.
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. All
* information contained herein is proprietary and confidential to NVIDIA
* Corporation. Any use, reproduction, or disclosure without the written
* permission of NVIDIA Corporation is prohibited.
*/
#ifndef _SCISYNC_H_
#define _SCISYNC_H_
#include <mutex>
#include <condition_variable>
#include <thread>
#include <vector>
#include "nvmedia_core.h"
#include "nvscisync.h"
#include "nvmedia_dla.h"
#include "nvmedia_dla_nvscisync.h"
#include "testRuntime.h"
#include "utils.h"
//! Semaphore class.
class Semaphore final
{
public:
//! Construct a semaphore.
//! \param uInitCount The initial semaphore count.
//! \param uMaxCount The maximum semaphore count.
Semaphore(uint32_t uInitCount,
uint32_t uMaxCount);
//! Disallow default constructor
Semaphore() = delete;
//! Dtor.
~Semaphore();
//! Increment the semaphore count.
void Increment();
//! Decrement the semaphore count.
//! \param timeoutMs Maximum amount of time to wait (in milliseconds).
//! -1 means infinite wait;
//! \retval false The semaphore wasn't decremented.
//! \retval true The sempahore was decremented.
bool Decrement(int32_t timeoutMs);
private:
std::condition_variable m_condition;
std::mutex m_mutex;
uint32_t m_maxCount = 0U;
uint32_t m_count = 0U;
};
//! Buffer objects shared between different thread
class ShareBuf final
{
public:
ShareBuf(int32_t numOfBuffers) :
BufferSize(numOfBuffers),
sema_cpu2nvm(new Semaphore(0, 1)),
sema_nvm2cpu(new Semaphore(0, 1)),
sema_cpu2cpu(new Semaphore(0, 1)),
syncObj_cpu2nvm(nullptr),
syncObj_nvm2cpu(nullptr)
{
for (auto i = 0; i < BufferSize; i++) {
NvSciSyncFence fence {};
fence_cpu2nvm.push_back(fence);
fence_nvm2cpu.push_back(fence);
}
}
~ShareBuf() {
for (auto &item : fence_cpu2nvm) {
NvSciSyncFenceClear(&item);
}
for (auto &item : fence_nvm2cpu) {
NvSciSyncFenceClear(&item);
}
if (syncObj_cpu2nvm) {
NvSciSyncObjFree(syncObj_cpu2nvm);
syncObj_cpu2nvm = nullptr;
}
if (syncObj_nvm2cpu) {
NvSciSyncObjFree(syncObj_nvm2cpu);
syncObj_nvm2cpu = nullptr;
}
}
int32_t BufferSize;
std::shared_ptr<Semaphore> sema_cpu2nvm;
std::shared_ptr<Semaphore> sema_nvm2cpu;
std::shared_ptr<Semaphore> sema_cpu2cpu;
std::vector<NvSciSyncFence> fence_cpu2nvm;
std::vector<NvSciSyncFence> fence_nvm2cpu;
NvSciSyncObj syncObj_cpu2nvm;
NvSciSyncObj syncObj_nvm2cpu;
};
//! Base class for a thread
class Worker
{
public:
Worker(
std::string name);
NvMediaStatus Start();
void Stop();
virtual ~Worker() = default;
protected:
virtual bool InitWork() = 0;
virtual bool DoWork() = 0;
virtual bool DeinitWork() = 0;
private:
static void* m_FuncStatic(void* vpParam);
void* m_Func();
std::string m_name;
std::unique_ptr<std::thread> m_thread;
Semaphore m_threadStartFlag;
bool m_bQuit;
};
//! Class for CPU waiter thread
class CPUWaiter : public Worker
{
public:
CPUWaiter(
std::string name,
NvSciSyncCpuWaitContext cpuWaitContext,
ShareBuf* shareBuf);
NvMediaStatus GetAttrList(NvSciSyncModule module, NvSciSyncAttrList &attrList);
~CPUWaiter() = default;
protected:
NvMediaStatus FenceWait();
virtual bool InitWork() override;
virtual bool DoWork() override;
virtual bool DeinitWork() override;
private:
NvSciSyncCpuWaitContext m_cpuWaitContext;
ShareBuf* m_shareBuf = nullptr;
};
//! Class for CPU signaler thread
class CPUSignaler : public Worker
{
public:
CPUSignaler(
std::string name,
ShareBuf* shareBuf);
NvMediaStatus GetAttrList(NvSciSyncModule module, NvSciSyncAttrList &attrList);
~CPUSignaler() = default;
protected:
NvMediaStatus GenerateFences();
NvMediaStatus SignalFences();
virtual bool InitWork() override;
virtual bool DoWork() override;
virtual bool DeinitWork() override;
private:
ShareBuf* m_shareBuf = nullptr;
};
//! Class for Dla operation thread
class DlaWorker : public Worker
{
public:
DlaWorker(
uint32_t dlaId,
uint32_t numTasks,
std::string profileName,
std::string name,
ShareBuf* shareBuf);
NvMediaStatus CreateDla();
NvMediaStatus GetAttrList(
NvSciSyncModule module,
NvSciSyncAttrList &attrList,
NvMediaNvSciSyncClientType syncType);
NvMediaStatus RegisterSyncObj(NvMediaNvSciSyncObjType syncObjType, NvSciSyncObj syncObj);
NvMediaStatus UnRegisterSyncObj(NvSciSyncObj syncObj);
NvMediaStatus SetEOFSyncObj(NvSciSyncObj syncObj);
~DlaWorker() = default;
protected:
NvMediaStatus WaitAndSignal();
virtual bool InitWork() override;
virtual bool DoWork() override;
virtual bool DeinitWork() override;
private:
ShareBuf* m_shareBuf = nullptr;
TestRuntime m_rtDla;
};
#endif // _SCISYNC_H_
This diff is collapsed.
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. All
* information contained herein is proprietary and confidential to NVIDIA
* Corporation. Any use, reproduction, or disclosure without the written
* permission of NVIDIA Corporation is prohibited.
*/
#ifndef _TENSOR_H_
#define _TENSOR_H_
#include <string>
#include "nvmedia_core.h"
#include "nvmedia_tensor.h"
#include "nvmedia_tensor_nvscibuf.h"
//! Class for create and destroy NvMedia Tensor from NvSciBuf
class Tensor
{
public:
static NvMediaStatus FillNvSciBufTensorAttrs(
NvMediaDevice *device,
NvMediaTensorAttr tensorAttrs[],
uint32_t numAttrs,
NvSciBufAttrList attr_h);
Tensor(NvMediaDevice *device);
NvMediaStatus Create(NvSciBufObj bufObj);
// Fill tensor with single value
NvMediaStatus SetData(uint8_t value);
//! Fill tensor with data from buffer
NvMediaStatus FillDataIntoTensor(uint32_t size, void *p);
// Fill tensor with data from pgm image file
virtual NvMediaStatus FillDataIntoTensor(std::string pgmImageFileName) {
return NVMEDIA_STATUS_NOT_SUPPORTED;
}
NvMediaTensor *GetPtr() const;
NvMediaStatus GetStatus();
NvMediaStatus CompareWithRef(uint32_t size, void *p);
virtual ~Tensor();
protected:
NvMediaDevice *m_pDevice;
NvMediaTensor *m_pTensor;
};
#endif // end of _TENSOR_H_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#
# Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA Corporation and its licensors retain all intellectual property
# and proprietary rights in and to this software and related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA Corporation is strictly prohibited.
#
# Default Sensor Module Specific Parameters
############ REF_AR0231 RCCB Module PASS1 ##############################
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment