├── LICENSE ├── Makefile ├── README.md ├── common ├── NvBuffer.cpp ├── NvElement.cpp ├── NvElementProfiler.cpp ├── NvLogging.cpp ├── NvV4l2Element.cpp ├── NvV4l2ElementPlane.cpp ├── NvVideoConverter.cpp ├── NvVideoDecoder.cpp └── NvVideoEncoder.cpp ├── converter ├── cuda_converter.cu ├── cuda_converter.h ├── fd_egl_frame_map.cpp ├── fd_egl_frame_map.h └── vic_onverter.h ├── cuda_utils ├── cudaMappedMemory.h └── cudaUtility.h ├── image ├── imageFormat.h └── imageFormat.inl ├── include ├── NvBuffer.h ├── NvElement.h ├── NvElementProfiler.h ├── NvLogging.h ├── NvV4l2Element.h ├── NvV4l2ElementPlane.h ├── NvVideoConverter.h ├── NvVideoDecoder.h ├── NvVideoEncoder.h ├── libv4l2.h ├── nvbuf_utils.h └── v4l2_nv_extensions.h ├── log ├── logging.cpp └── logging.h ├── nvjmi.h ├── nvjmi_dec.cpp ├── nvjmi_enc.cpp └── utils ├── commandLine.cpp └── commandLine.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 chaof 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #makefile for libnvjmi.so 2 | 3 | CC = gcc 4 | CPP = g++ 5 | AR = ar 6 | RM = rm -f 7 | NVCC := /usr/local/cuda/bin/nvcc 8 | 9 | #Define the resource compiler. 10 | 11 | ## debug flag 12 | DBG_ENABLE := 1 13 | 14 | OS = $(shell uname) 15 | 16 | ## source file path 17 | SRC_PATH := ./ ./common/ ./converter/ ./log/ ./utils/ 18 | SRC_PATH_EXT := 19 | 20 | ## target file name 21 | TARGET := nvjmi 22 | 23 | ############################################# 24 | # Gencode arguments 25 | SMS ?= 60 61 62 70 72 75 26 | 27 | ifeq ($(GENCODE_FLAGS),) 28 | # Generate SASS code for each SM architecture listed in $(SMS) 29 | $(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm))) 30 | 31 | # Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility 32 | HIGHEST_SM := $(lastword $(sort $(SMS))) 33 | ifneq ($(HIGHEST_SM),) 34 | GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM) 35 | endif 36 | endif 37 | 38 | ## get all source files 39 | #$(warning $(SRC_FILES_SHARED)) 40 | SRCS := $(foreach spath, $(SRC_PATH), $(wildcard $(spath)*.c)) $(foreach spath, $(SRC_PATH), $(wildcard $(spath)*.cpp)) $(foreach spath, $(SRC_PATH), $(wildcard $(spath)*.cu)) 41 | #$(warning $(SRCS)) 42 | #$(wildcard $(SRC_PATH)*.c*) $(wildcard $(SRC_PATH)*.c) $(wildcard $(SRC_PATH_EXT)*.cpp) 43 | 44 | ## all .o based on all .c/.cpp 45 | OBJS = $(SRCS:.c=.o) 46 | OBJS := $(OBJS:.cpp=.o) 47 | OBJS := $(OBJS:.cu=.o) 48 | 49 | ## macro define 50 | DEFS := _FILE_OFFSET_BITS=64 $(if $(findstring D,$(ENCYPT)), _USE_ENCYPTION_DONGLE, ) $(if $(findstring T,$(ENCYPT)), _USE_ENCYPTION_TEMP, ) $(if $(findstring S,$(ENCYPT)), _USE_ENCYPTION_SOFT, ) 51 | 52 | #if freeimage is static-linked use this ! 53 | #DEFS += FREEIMAGE_LIB 54 | 55 | ## need libs, add at here 56 | LIBS := v4l2 nvbuf_utils tbb cudart 57 | 58 | ## used headers file path 59 | INCLUDE_PATH := ./ ./include ./converter ./cuda_utils ./image ./log ./utils /usr/local/cuda/include 60 | 61 | #$(warning $(INCLUDE_PATH)) 62 | 63 | ## used include librarys file path 64 | LIBRARY_PATH := /usr/lib/aarch64-linux-gnu/tegra /usr/local/cuda/targets/aarch64-linux/lib 65 | 66 | ## debug for debug info, when use gdb to debug 67 | ifeq (1, ${DBG_ENABLE}) 68 | CFLAGS += -D_DEBUG -g -DDEBUG=1 69 | else 70 | CFLAGS += -O3 -DNDEBUG 71 | endif 72 | 73 | # for ENCYPT flags 74 | 75 | ifeq ($(OS), Linux) 76 | LIBS += dl $(if $(findstring D,$(ENCYPT)), RockeyARM, ) 77 | CFLAGS += -fPIC 78 | BUILDTARGET = lib$(TARGET).so 79 | LIBRARY_PATH += 80 | else 81 | #do nothing 82 | DEFS += _WINDOWS 83 | LIBS += ws2_32 $(if $(findstring D,$(ENCYPT)), Dongle_d, ) 84 | LIBRARY_PATH += ../win_lib 85 | BUILDTARGET = $(TARGET).dll 86 | LDFLAGS += $(WIN32_LDFLAGS) 87 | endif 88 | 89 | CFLAGS += -march=armv8.2-a -pipe $(foreach m, $(DEFS), -D$(m)) 90 | 91 | ## get all include path 92 | CFLAGS += $(foreach dir, $(INCLUDE_PATH), -I$(dir)) 93 | 94 | CXXFLAGS += $(CFLAGS) -std=c++11 95 | 96 | ## get all library path 97 | LDFLAGS += -Wl,--rpath-link=./ -pthread $(foreach lib, $(LIBRARY_PATH), -L$(lib)) 98 | 99 | ## get all librarys 100 | LDFLAGS += $(foreach lib, $(LIBS), -l$(lib)) 101 | 102 | 103 | RCFLAGS ?= -DNDEBUG 104 | 105 | 106 | default: all 107 | 108 | %.o: %.c 109 | $(CC) $(CFLAGS) -c $< -o $@ 110 | 111 | %.o: %.cpp 112 | $(CPP) $(CXXFLAGS) -c $< -o $@ 113 | 114 | %.o: %.cu 115 | $(NVCC) -m64 -std=c++11 $(foreach dir, $(INCLUDE_PATH), -I$(dir)) --default-stream per-thread $(GENCODE_FLAGS) -Xcompiler -fPIC -Xcompiler -O3 -c $< -o $@ 116 | #$(NVCC) -m64 -g -G -std=c++11 $(foreach dir, $(INCLUDE_PATH), -I$(dir)) --default-stream per-thread $(GENCODE_FLAGS) -Xcompiler -fPIC -c $< -o $@ 117 | 118 | 119 | all: $(OBJS) 120 | $(CPP) $(CXXFLAGS) -shared -o $(BUILDTARGET) $(OBJS) $(LDFLAGS) 121 | 122 | clean: 123 | $(RM) $(OBJS) $(BUILDTARGET) 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nvjmi:palm_tree: 2 | ## 1. 简介 3 | 封装Jetson Multimedia API的编解码库,基于 https://github.com/jocover/jetson-ffmpeg 和 https://github.com/dusty-nv/jetson-utils 基础进行的修改,未集成于ffmpeg,可单独使用。功能如下。 4 | 1. 支持H.264解码。 5 | 2. 支持解码后直接硬件完成缩放操作。 6 | 3. 支持解码后直接硬件完成颜色空间转换操作。 7 | 4. 支持Jetpack 4.3、4.4。 8 | 5. 对于Jetpack 4.5需要使用对应的multimedia api,即使用Jetpack 4.5中/usr/src/jetson_multimedia_api更新include/和common/中的文件。 9 | 10 | 当前仅完成解码器的修改,还未完成编码器的修改。 11 | 12 | 关于解码API的使用,详见nvjmi.h接口说明。 13 | 14 | ## 2. 使用说明 15 | 1. 编译 16 | 直接使用make编译nvjmi动态库。 17 | 18 | 2. 示例 19 | nvjmi接口使用示例如下: 20 | ```cpp 21 | if(jmi_ctx_ == nullptr) { 22 | jmi::nvJmiCtxParam jmi_ctx_param{}; 23 | 24 | if(rsz_w > 0 && rsz_h > 0){ 25 | jmi_ctx_param.resize_width = rsz_w; 26 | jmi_ctx_param.resize_height = rsz_h; 27 | } 28 | 29 | if ("H264" == m_pRtspClient->GetCodeName()) { 30 | jmi_ctx_param.coding_type =jmi::NV_VIDEO_CodingH264; 31 | } 32 | else if ("H265" == m_pRtspClient->GetCodeName()) { 33 | jmi_ctx_param.coding_type = jmi::NV_VIDEO_CodingHEVC; 34 | } 35 | string dec_name = "dec-" + session_id(); 36 | jmi_ctx_ = jmi::nvjmi_create_decoder(dec_name.data(), &jmi_ctx_param); 37 | } 38 | 39 | //基于jetson nvdec解码 40 | jmi::nvPacket nvpacket; 41 | 42 | nvpacket.payload_size = dataLen; 43 | nvpacket.payload = data; 44 | 45 | int ret{}; 46 | ret = jmi::nvjmi_decoder_put_packet(jmi_ctx_, &nvpacket); 47 | if(ret == jmi::NVJMI_ERROR_STOP) { 48 | LOG_INFO(VDO_RTSP_LOG, "[{}] frameCallback: nvjmi decode error, frame callback EOF!", m_ip); 49 | } 50 | 51 | while (ret >= 0) { 52 | jmi::nvFrameMeta nvframe_meta; 53 | ret = jmi::nvjmi_decoder_get_frame_meta(jmi_ctx_, &nvframe_meta); 54 | if (ret < 0) break; 55 | 56 | Buffer buf; 57 | buf.allocate(nvframe_meta.width, nvframe_meta.height, 3, nvframe_meta.payload_size / nvframe_meta.height); 58 | jmi::nvjmi_decoder_retrieve_frame_data(jmi_ctx_, &nvframe_meta, (void*)buf.getData()); 59 | } 60 | ``` 61 | ## 3. 常见问题 62 | 1. **Q:** 出现错误nvbuf_utils: Could not get EGL display connection,并且eglGetDisplay(EGL_DEFAULT_DISPLAY)返回NULL? 63 | **A:** 1>在ssh终端输入unset DISPLAY,然后再运行程序即可。 64 | 2>vim /etc/profile,添加unset DISPLAY,然后souce /etc/profile生效,然后重启机器reboot。 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /common/NvBuffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "NvBuffer.h" 30 | #include "NvLogging.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #define CAT_NAME "Buffer" 38 | 39 | #define MAX(a,b) (a > b ? a : b) 40 | 41 | NvBuffer::NvBuffer(enum v4l2_buf_type buf_type, enum v4l2_memory memory_type, 42 | uint32_t n_planes, NvBufferPlaneFormat * fmt, uint32_t index) 43 | :buf_type(buf_type), 44 | memory_type(memory_type), 45 | index(index), 46 | n_planes(n_planes) 47 | { 48 | uint32_t i; 49 | 50 | mapped = false; 51 | allocated = false; 52 | 53 | memset(planes, 0, sizeof(planes)); 54 | for (i = 0; i < n_planes; i++) 55 | { 56 | this->planes[i].fd = -1; 57 | this->planes[i].fmt = fmt[i]; 58 | } 59 | 60 | ref_count = 0; 61 | pthread_mutex_init(&ref_lock, NULL); 62 | shared_buffer = NULL; 63 | } 64 | 65 | NvBuffer::NvBuffer(uint32_t pixfmt, uint32_t width, uint32_t height, 66 | uint32_t index) 67 | :buf_type(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE), 68 | memory_type(V4L2_MEMORY_USERPTR), 69 | index(index) 70 | { 71 | uint32_t i; 72 | NvBuffer::NvBufferPlaneFormat fmt[MAX_PLANES]; 73 | 74 | mapped = false; 75 | allocated = false; 76 | 77 | fill_buffer_plane_format(&n_planes, fmt, width, height, pixfmt); 78 | 79 | for (i = 0; i < MAX_PLANES; i++) 80 | { 81 | this->planes[i].fd = -1; 82 | this->planes[i].data = NULL; 83 | this->planes[i].bytesused = 0; 84 | this->planes[i].mem_offset = 0; 85 | this->planes[i].length = 0; 86 | this->planes[i].fmt = fmt[i]; 87 | this->planes[i].fmt.sizeimage = fmt[i].width * fmt[i].height * 88 | fmt[i].bytesperpixel; 89 | this->planes[i].fmt.stride = fmt[i].width * fmt[i].bytesperpixel; 90 | } 91 | 92 | ref_count = 0; 93 | pthread_mutex_init(&ref_lock, NULL); 94 | shared_buffer = NULL; 95 | } 96 | 97 | NvBuffer::NvBuffer(uint32_t size, uint32_t index) 98 | :buf_type(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE), 99 | memory_type(V4L2_MEMORY_USERPTR), 100 | index(index) 101 | { 102 | uint32_t i; 103 | 104 | mapped = false; 105 | allocated = false; 106 | 107 | n_planes = 1; 108 | for (i = 0; i < n_planes; i++) 109 | { 110 | this->planes[i].fd = -1; 111 | this->planes[i].data = NULL; 112 | this->planes[i].bytesused = 0; 113 | this->planes[i].mem_offset = 0; 114 | this->planes[i].length = 0; 115 | this->planes[i].fmt.sizeimage = size; 116 | } 117 | 118 | ref_count = 0; 119 | pthread_mutex_init(&ref_lock, NULL); 120 | shared_buffer = NULL; 121 | } 122 | 123 | NvBuffer::~NvBuffer() 124 | { 125 | if (mapped) 126 | { 127 | unmap(); 128 | } 129 | if (allocated) 130 | { 131 | deallocateMemory(); 132 | } 133 | 134 | pthread_mutex_destroy(&ref_lock); 135 | } 136 | 137 | int 138 | NvBuffer::map() 139 | { 140 | uint32_t j; 141 | 142 | if (memory_type != V4L2_MEMORY_MMAP) 143 | { 144 | CAT_WARN_MSG("Buffer " << index << "already mapped"); 145 | return -1; 146 | } 147 | 148 | if (mapped) 149 | { 150 | CAT_WARN_MSG("Buffer " << index << "already mapped"); 151 | return 0; 152 | } 153 | 154 | for (j = 0; j < n_planes; j++) 155 | { 156 | if (planes[j].fd == -1) 157 | { 158 | return -1; 159 | } 160 | 161 | planes[j].data = (unsigned char *) mmap(NULL, 162 | planes[j].length, 163 | PROT_READ | PROT_WRITE, 164 | MAP_SHARED, 165 | planes[j].fd, 166 | planes[j].mem_offset); 167 | if (planes[j].data == MAP_FAILED) 168 | { 169 | CAT_ERROR_MSG("Could not map buffer " << index << ", plane " << j); 170 | return -1; 171 | } 172 | else 173 | { 174 | CAT_DEBUG_MSG("Mapped buffer " << index << ", plane " << j << " to " 175 | << planes[j].data); 176 | } 177 | } 178 | mapped = true; 179 | return 0; 180 | } 181 | 182 | void 183 | NvBuffer::unmap() 184 | { 185 | if (memory_type != V4L2_MEMORY_MMAP || !mapped) 186 | { 187 | CAT_WARN_MSG("Cannot Unmap Buffer " << index << 188 | ". Only mapped MMAP buffer can be unmapped"); 189 | return; 190 | } 191 | 192 | for (uint32_t j = 0; j < n_planes; j++) 193 | { 194 | if (planes[j].data) 195 | { 196 | munmap(planes[j].data, planes[j].length); 197 | } 198 | planes[j].data = NULL; 199 | } 200 | mapped = false; 201 | CAT_DEBUG_MSG("Buffer " << index << " unmapped "); 202 | } 203 | 204 | int 205 | NvBuffer::allocateMemory() 206 | { 207 | uint32_t j; 208 | 209 | if (memory_type != V4L2_MEMORY_USERPTR) 210 | { 211 | CAT_ERROR_MSG("Only USERPTR buffers can be allocated"); 212 | return -1; 213 | } 214 | 215 | if (allocated) 216 | { 217 | CAT_WARN_MSG("Buffer " << index << "already allocated memory"); 218 | return 0; 219 | } 220 | 221 | for (j = 0; j < n_planes; j++) 222 | { 223 | if (planes[j].data) 224 | { 225 | ERROR_MSG("Buffer " << index << ", Plane " << j << 226 | " already allocated"); 227 | return -1; 228 | } 229 | 230 | planes[j].length = MAX(planes[j].fmt.sizeimage, 231 | planes[j].fmt.width * 232 | planes[j].fmt.bytesperpixel * 233 | planes[j].fmt.height); 234 | planes[j].data = new unsigned char [planes[j].length]; 235 | 236 | if (planes[j].data == MAP_FAILED) 237 | { 238 | SYS_ERROR_MSG("Error while allocating buffer " << index << 239 | " plane " << j); 240 | return -1; 241 | } 242 | else 243 | { 244 | DEBUG_MSG("Buffer " << index << ", Plane " << j << 245 | " allocated to " << (void *) planes[j].data); 246 | } 247 | } 248 | allocated = true; 249 | return 0; 250 | } 251 | 252 | void 253 | NvBuffer::deallocateMemory() 254 | { 255 | uint32_t j; 256 | 257 | if (memory_type != V4L2_MEMORY_USERPTR || !allocated) 258 | { 259 | ERROR_MSG("Only allocated USERPTR buffers can be deallocated"); 260 | return; 261 | } 262 | 263 | for (j = 0; j < n_planes; j++) 264 | { 265 | if (!planes[j].data) 266 | { 267 | DEBUG_MSG("Buffer " << index << ", Plane " << j << 268 | " not allocated"); 269 | continue; 270 | } 271 | delete[] planes[j].data; 272 | planes[j].data = NULL; 273 | } 274 | allocated = false; 275 | DEBUG_MSG("Buffer " << index << " deallocated"); 276 | } 277 | 278 | int 279 | NvBuffer::ref() 280 | { 281 | int ref_count; 282 | 283 | pthread_mutex_lock(&ref_lock); 284 | ref_count = ++this->ref_count; 285 | pthread_mutex_unlock(&ref_lock); 286 | return ref_count; 287 | } 288 | 289 | int 290 | NvBuffer::unref() 291 | { 292 | int ref_count; 293 | 294 | pthread_mutex_lock(&ref_lock); 295 | if (this->ref_count > 0) 296 | { 297 | --this->ref_count; 298 | } 299 | ref_count = this->ref_count; 300 | pthread_mutex_unlock(&ref_lock); 301 | return ref_count; 302 | } 303 | 304 | int 305 | NvBuffer::fill_buffer_plane_format(uint32_t *num_planes, 306 | NvBuffer::NvBufferPlaneFormat *planefmts, 307 | uint32_t width, uint32_t height, uint32_t raw_pixfmt) 308 | { 309 | switch (raw_pixfmt) 310 | { 311 | case V4L2_PIX_FMT_YUV444M: 312 | *num_planes = 3; 313 | 314 | planefmts[0].width = width; 315 | planefmts[1].width = width; 316 | planefmts[2].width = width; 317 | 318 | planefmts[0].height = height; 319 | planefmts[1].height = height; 320 | planefmts[2].height = height; 321 | 322 | planefmts[0].bytesperpixel = 1; 323 | planefmts[1].bytesperpixel = 1; 324 | planefmts[2].bytesperpixel = 1; 325 | break; 326 | case V4L2_PIX_FMT_YUV422M: 327 | *num_planes = 3; 328 | 329 | planefmts[0].width = width; 330 | planefmts[1].width = width / 2; 331 | planefmts[2].width = width / 2; 332 | 333 | planefmts[0].height = height; 334 | planefmts[1].height = height; 335 | planefmts[2].height = height; 336 | 337 | planefmts[0].bytesperpixel = 1; 338 | planefmts[1].bytesperpixel = 1; 339 | planefmts[2].bytesperpixel = 1; 340 | break; 341 | case V4L2_PIX_FMT_YUV422RM: 342 | *num_planes = 3; 343 | 344 | planefmts[0].width = width; 345 | planefmts[1].width = width; 346 | planefmts[2].width = width; 347 | 348 | planefmts[0].height = height; 349 | planefmts[1].height = height / 2; 350 | planefmts[2].height = height / 2; 351 | 352 | planefmts[0].bytesperpixel = 1; 353 | planefmts[1].bytesperpixel = 1; 354 | planefmts[2].bytesperpixel = 1; 355 | break; 356 | case V4L2_PIX_FMT_YUV420M: 357 | case V4L2_PIX_FMT_YVU420M: 358 | *num_planes = 3; 359 | 360 | planefmts[0].width = width; 361 | planefmts[1].width = width / 2; 362 | planefmts[2].width = width / 2; 363 | 364 | planefmts[0].height = height; 365 | planefmts[1].height = height / 2; 366 | planefmts[2].height = height / 2; 367 | 368 | planefmts[0].bytesperpixel = 1; 369 | planefmts[1].bytesperpixel = 1; 370 | planefmts[2].bytesperpixel = 1; 371 | break; 372 | case V4L2_PIX_FMT_NV12M: 373 | *num_planes = 2; 374 | 375 | planefmts[0].width = width; 376 | planefmts[1].width = width / 2; 377 | 378 | planefmts[0].height = height; 379 | planefmts[1].height = height / 2; 380 | 381 | planefmts[0].bytesperpixel = 1; 382 | planefmts[1].bytesperpixel = 2; 383 | break; 384 | case V4L2_PIX_FMT_GREY: 385 | *num_planes = 1; 386 | 387 | planefmts[0].width = width; 388 | 389 | planefmts[0].height = height; 390 | 391 | planefmts[0].bytesperpixel = 1; 392 | break; 393 | case V4L2_PIX_FMT_YUYV: 394 | case V4L2_PIX_FMT_YVYU: 395 | case V4L2_PIX_FMT_UYVY: 396 | case V4L2_PIX_FMT_VYUY: 397 | *num_planes = 1; 398 | 399 | planefmts[0].width = width; 400 | 401 | planefmts[0].height = height; 402 | 403 | planefmts[0].bytesperpixel = 2; 404 | break; 405 | case V4L2_PIX_FMT_ABGR32: 406 | case V4L2_PIX_FMT_XRGB32: 407 | *num_planes = 1; 408 | 409 | planefmts[0].width = width; 410 | 411 | planefmts[0].height = height; 412 | 413 | planefmts[0].bytesperpixel = 4; 414 | break; 415 | case V4L2_PIX_FMT_P010M: 416 | *num_planes = 2; 417 | 418 | planefmts[0].width = width; 419 | planefmts[1].width = width / 2; 420 | 421 | planefmts[0].height = height; 422 | planefmts[1].height = height / 2; 423 | 424 | planefmts[0].bytesperpixel = 2; 425 | planefmts[1].bytesperpixel = 4; 426 | break; 427 | default: 428 | ERROR_MSG("Unsupported pixel format " << raw_pixfmt); 429 | return -1; 430 | } 431 | return 0; 432 | } 433 | -------------------------------------------------------------------------------- /common/NvElement.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "NvElement.h" 30 | 31 | void NvElement::getProfilingData(NvElementProfiler::NvElementProfilerData &data) 32 | { 33 | profiler.getProfilerData(data); 34 | } 35 | 36 | void NvElement::printProfilingStats(std::ostream &out_stream) 37 | { 38 | out_stream << "----------- Element = " << comp_name << " -----------" << std::endl; 39 | profiler.printProfilerData(out_stream); 40 | out_stream << "-------------------------------------" << std::endl; 41 | } 42 | 43 | void NvElement::enableProfiling() 44 | { 45 | profiler.enableProfiling(true); 46 | } 47 | 48 | bool NvElement::isProfilingEnabled() 49 | { 50 | return profiler.enabled; 51 | } 52 | 53 | NvElement::NvElement(const char *name, NvElementProfiler::ProfilerField fields) 54 | :profiler(fields) 55 | { 56 | is_in_error = 0; 57 | if (!name) 58 | is_in_error = 1; 59 | this->comp_name = name; 60 | } 61 | -------------------------------------------------------------------------------- /common/NvElementProfiler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "NvElementProfiler.h" 34 | 35 | #define LOCK() pthread_mutex_lock(&profiler_lock) 36 | #define UNLOCK() pthread_mutex_unlock(&profiler_lock) 37 | 38 | #define RETURN_IF_DISABLED() \ 39 | if (!enabled) { \ 40 | UNLOCK(); \ 41 | return; \ 42 | } 43 | 44 | #define GET_TIME(timeval) gettimeofday(timeval, NULL); 45 | 46 | #define TIMESPEC_DIFF_USEC(timespec1, timespec2) \ 47 | (((timespec1)->tv_sec - (timespec2)->tv_sec) * 1000000L + \ 48 | (timespec1)->tv_usec - (timespec2)->tv_usec) 49 | 50 | using namespace std; 51 | 52 | NvElementProfiler::NvElementProfiler(ProfilerField fields) 53 | :valid_fields(fields) 54 | { 55 | enabled = false; 56 | unit_id_counter = 0; 57 | 58 | reset(); 59 | 60 | pthread_mutex_init(&profiler_lock, NULL); 61 | } 62 | 63 | NvElementProfiler::~NvElementProfiler() 64 | { 65 | LOCK(); 66 | reset(); 67 | UNLOCK(); 68 | pthread_mutex_destroy(&profiler_lock); 69 | } 70 | void 71 | NvElementProfiler::enableProfiling(bool reset_data) 72 | { 73 | LOCK(); 74 | if (enabled) 75 | { 76 | UNLOCK(); 77 | return; 78 | } 79 | 80 | if(reset_data) 81 | { 82 | reset(); 83 | } 84 | 85 | enabled = true; 86 | UNLOCK(); 87 | } 88 | 89 | void 90 | NvElementProfiler::disableProfiling() 91 | { 92 | LOCK(); 93 | RETURN_IF_DISABLED(); 94 | 95 | data_int.accumulated_time.tv_sec += 96 | (data_int.stop_time.tv_sec - data_int.start_time.tv_sec); 97 | data_int.accumulated_time.tv_usec += 98 | (data_int.stop_time.tv_usec - data_int.start_time.tv_usec); 99 | data_int.start_time.tv_sec = 0; 100 | data_int.start_time.tv_usec = 0; 101 | data_int.stop_time.tv_sec = 0; 102 | data_int.stop_time.tv_usec = 0; 103 | enabled = false; 104 | UNLOCK(); 105 | } 106 | 107 | void NvElementProfiler::getProfilerData(NvElementProfiler::NvElementProfilerData &data) 108 | { 109 | uint64_t total_time; 110 | 111 | LOCK(); 112 | 113 | total_time = data_int.accumulated_time.tv_sec * 1000000L + 114 | data_int.accumulated_time.tv_usec + 115 | TIMESPEC_DIFF_USEC(&data_int.stop_time, &data_int.start_time); 116 | 117 | if (data_int.total_processed_units == 0 || total_time == 0) 118 | { 119 | data.average_fps = 0; 120 | } 121 | else 122 | { 123 | data.average_fps = ((float) (data_int.total_processed_units - 1)) * 124 | 1000000 / total_time; 125 | } 126 | 127 | if (data_int.total_processed_units == 0) 128 | { 129 | data.max_latency_usec = 0; 130 | data.min_latency_usec = 0; 131 | data.average_latency_usec = 0; 132 | } 133 | else 134 | { 135 | data.max_latency_usec = data_int.max_latency_usec; 136 | data.min_latency_usec = data_int.min_latency_usec; 137 | data.average_latency_usec = 138 | data_int.total_latency / data_int.total_processed_units; 139 | } 140 | 141 | data.profiling_time.tv_sec = 142 | data_int.accumulated_time.tv_sec + data_int.stop_time.tv_sec - 143 | data_int.start_time.tv_sec; 144 | 145 | data.profiling_time.tv_usec = 146 | data_int.accumulated_time.tv_usec + data_int.stop_time.tv_usec - 147 | data_int.start_time.tv_usec; 148 | 149 | if (data.profiling_time.tv_usec < 0) 150 | { 151 | data.profiling_time.tv_usec += 1000000; 152 | data.profiling_time.tv_sec--; 153 | } 154 | 155 | if (data.profiling_time.tv_usec > 1000000) 156 | { 157 | data.profiling_time.tv_usec -= 1000000; 158 | data.profiling_time.tv_sec++; 159 | } 160 | 161 | data.total_processed_units = data_int.total_processed_units; 162 | data.num_late_units = data_int.num_late_units; 163 | data.valid_fields = valid_fields; 164 | UNLOCK(); 165 | } 166 | 167 | void NvElementProfiler::printProfilerData(ostream &out_stream) 168 | { 169 | NvElementProfilerData data; 170 | getProfilerData(data); 171 | 172 | if (data.valid_fields & PROFILER_FIELD_FPS) 173 | { 174 | out_stream << "Total Profiling time = " << 175 | (data.profiling_time.tv_sec + 176 | (data.profiling_time.tv_usec / 1000000.0)) << endl; 177 | out_stream << "Average FPS = " << data.average_fps << endl; 178 | } 179 | if (data.valid_fields & PROFILER_FIELD_TOTAL_UNITS) 180 | { 181 | out_stream << "Total units processed = " << 182 | data.total_processed_units << endl; 183 | } 184 | if (data.valid_fields & PROFILER_FIELD_LATE_UNITS) 185 | { 186 | out_stream << "Num. of late units = " << 187 | data.num_late_units << endl; 188 | } 189 | if (data.valid_fields & PROFILER_FIELD_LATENCIES) 190 | { 191 | out_stream << "Average latency(usec) = " << 192 | data.average_latency_usec << endl; 193 | out_stream << "Minimum latency(usec) = " << 194 | data.min_latency_usec << endl; 195 | out_stream << "Maximum latency(usec) = " << 196 | data.max_latency_usec << endl; 197 | } 198 | } 199 | 200 | void 201 | NvElementProfiler::reset() 202 | { 203 | memset(&data_int, 0, sizeof(data_int)); 204 | data_int.min_latency_usec = (uint64_t) -1; 205 | 206 | unit_start_time_queue.clear(); 207 | } 208 | 209 | uint64_t 210 | NvElementProfiler::startProcessing() 211 | { 212 | struct timeval time; 213 | uint64_t ret = 0; 214 | LOCK(); 215 | if (enabled) 216 | { 217 | std::map::iterator it = 218 | unit_start_time_queue.end(); 219 | 220 | unit_id_counter++; 221 | GET_TIME(&time); 222 | 223 | unit_start_time_queue.insert(it, 224 | std::pair(unit_id_counter, time)); 225 | 226 | ret = unit_id_counter; 227 | } 228 | UNLOCK(); 229 | return ret; 230 | } 231 | 232 | void 233 | NvElementProfiler::finishProcessing(uint64_t id, bool is_late) 234 | { 235 | struct timeval unit_start_time; 236 | struct timeval stop_time; 237 | uint64_t latency; 238 | 239 | LOCK(); 240 | RETURN_IF_DISABLED(); 241 | 242 | if ((valid_fields & PROFILER_FIELD_LATENCIES) && 243 | unit_start_time_queue.empty()) 244 | { 245 | UNLOCK(); 246 | return; 247 | } 248 | 249 | GET_TIME(&stop_time); 250 | 251 | if (valid_fields & PROFILER_FIELD_LATENCIES) 252 | { 253 | std::map::iterator it; 254 | if (id) 255 | { 256 | it = unit_start_time_queue.find(id); 257 | } 258 | else 259 | { 260 | it = unit_start_time_queue.begin(); 261 | } 262 | 263 | if (it == unit_start_time_queue.end()) 264 | { 265 | UNLOCK(); 266 | return; 267 | } 268 | unit_start_time = it->second; 269 | unit_start_time_queue.erase(it); 270 | 271 | latency = TIMESPEC_DIFF_USEC(&stop_time, &unit_start_time); 272 | data_int.total_latency += latency; 273 | 274 | if (latency < data_int.min_latency_usec) 275 | { 276 | data_int.min_latency_usec = latency; 277 | } 278 | if(latency > data_int.max_latency_usec) 279 | { 280 | data_int.max_latency_usec = latency; 281 | } 282 | } 283 | 284 | data_int.stop_time = stop_time; 285 | 286 | if (!data_int.start_time.tv_sec && !data_int.start_time.tv_usec) 287 | { 288 | data_int.start_time = data_int.stop_time; 289 | } 290 | 291 | if (is_late) 292 | { 293 | data_int.num_late_units++; 294 | } 295 | data_int.total_processed_units++; 296 | 297 | UNLOCK(); 298 | } 299 | -------------------------------------------------------------------------------- /common/NvLogging.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "NvLogging.h" 30 | 31 | int log_level = DEFAULT_LOG_LEVEL; 32 | 33 | const char *log_level_name[] = {"INFO", "ERROR", "WARN", "DEBUG"}; -------------------------------------------------------------------------------- /common/NvV4l2Element.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "NvV4l2Element.h" 30 | #include "NvLogging.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #define CAT_NAME "V4l2Element" 38 | 39 | using namespace std; 40 | 41 | /*initialization of mutex for NvV4l2Element*/ 42 | pthread_mutex_t initializer_mutex = PTHREAD_MUTEX_INITIALIZER; 43 | 44 | NvV4l2Element::NvV4l2Element(const char *comp_name, const char *dev_node, int flags, NvElementProfiler::ProfilerField fields) 45 | :NvElement(comp_name, fields), 46 | output_plane(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, comp_name, 47 | fd, !(flags & O_NONBLOCK), profiler), 48 | capture_plane(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, comp_name, 49 | fd, !(flags & O_NONBLOCK), profiler) 50 | { 51 | struct v4l2_capability caps; 52 | int ret; 53 | 54 | app_data = NULL; 55 | output_plane_pixfmt = 0; 56 | capture_plane_pixfmt = 0; 57 | 58 | /*Synchronization issue of libv4l2 open source library fixing here,adding lock for that*/ 59 | pthread_mutex_lock(&initializer_mutex); 60 | fd = v4l2_open(dev_node, flags | O_RDWR); 61 | if (fd == -1) 62 | { 63 | COMP_SYS_ERROR_MSG("Could not open device '" << dev_node << "'"); 64 | is_in_error = 1; 65 | pthread_mutex_unlock(&initializer_mutex); 66 | return; 67 | } 68 | pthread_mutex_unlock(&initializer_mutex); 69 | 70 | COMP_DEBUG_MSG("Opened, fd = " << fd); 71 | 72 | ret = v4l2_ioctl(fd, VIDIOC_QUERYCAP, &caps); 73 | if (ret != 0) 74 | { 75 | COMP_SYS_ERROR_MSG("Error in VIDIOC_QUERYCAP"); 76 | is_in_error = 1; 77 | return; 78 | } 79 | if (!(caps.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE)) 80 | { 81 | COMP_ERROR_MSG("Device does not support V4L2_CAP_VIDEO_M2M_MPLANE"); 82 | is_in_error = 1; 83 | return; 84 | } 85 | } 86 | 87 | NvV4l2Element::~NvV4l2Element() 88 | { 89 | output_plane.deinitPlane(); 90 | capture_plane.deinitPlane(); 91 | 92 | if (fd != -1) 93 | { 94 | v4l2_close(fd); 95 | CAT_DEBUG_MSG("Device closed, fd = " << fd); 96 | } 97 | } 98 | 99 | int 100 | NvV4l2Element::dqEvent(struct v4l2_event &ev, uint32_t max_wait_ms) 101 | { 102 | int ret; 103 | 104 | do 105 | { 106 | ret = v4l2_ioctl(fd, VIDIOC_DQEVENT, &ev); 107 | 108 | if (ret == 0) 109 | { 110 | COMP_DEBUG_MSG("DQed event " << hex << ev.type << dec); 111 | } 112 | else if (errno != EAGAIN) 113 | { 114 | COMP_SYS_ERROR_MSG("Error while DQing event"); 115 | break; 116 | } 117 | else if (max_wait_ms-- == 0) 118 | { 119 | COMP_WARN_MSG("Error while DQing event: Resource temporarily unavailable"); 120 | break; 121 | } 122 | else 123 | { 124 | usleep(1000); 125 | } 126 | } 127 | while (ret && (output_plane.getStreamStatus() || capture_plane.getStreamStatus())); 128 | 129 | return ret; 130 | } 131 | 132 | int 133 | NvV4l2Element::setControl(uint32_t id, int32_t value) 134 | { 135 | struct v4l2_control ctl; 136 | int ret; 137 | 138 | ctl.id = id; 139 | ctl.value = value; 140 | 141 | ret = v4l2_ioctl(fd, VIDIOC_S_CTRL, &ctl); 142 | 143 | if (ret < 0) 144 | { 145 | COMP_SYS_ERROR_MSG("Error setting value " << value << " on control " << 146 | id); 147 | } 148 | else 149 | { 150 | COMP_DEBUG_MSG("Set value " << value << " on control " << id); 151 | } 152 | return ret; 153 | } 154 | 155 | int 156 | NvV4l2Element::getControl(uint32_t id, int32_t &value) 157 | { 158 | struct v4l2_control ctl; 159 | int ret; 160 | 161 | ctl.id = id; 162 | 163 | ret = v4l2_ioctl(fd, VIDIOC_G_CTRL, &ctl); 164 | 165 | if (ret < 0) 166 | { 167 | COMP_SYS_ERROR_MSG("Error getting value of control " << id); 168 | } 169 | else 170 | { 171 | COMP_DEBUG_MSG("Got value " << ctl.value << " for control " << id); 172 | value = ctl.value; 173 | } 174 | return ret; 175 | } 176 | 177 | int 178 | NvV4l2Element::setExtControls(v4l2_ext_controls &ctl) 179 | { 180 | int ret; 181 | 182 | ret = v4l2_ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctl); 183 | 184 | if (ret < 0) 185 | { 186 | COMP_SYS_ERROR_MSG("Error setting controls"); 187 | } 188 | else 189 | { 190 | COMP_DEBUG_MSG("Set controls"); 191 | } 192 | return ret; 193 | } 194 | 195 | int 196 | NvV4l2Element::getExtControls(v4l2_ext_controls &ctl) 197 | { 198 | int ret; 199 | 200 | ret = v4l2_ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctl); 201 | 202 | if (ret < 0) 203 | { 204 | COMP_SYS_ERROR_MSG("Error getting value of controls"); 205 | } 206 | else 207 | { 208 | COMP_DEBUG_MSG("Got controls"); 209 | } 210 | return ret; 211 | } 212 | 213 | int 214 | NvV4l2Element::subscribeEvent(uint32_t type, uint32_t id, uint32_t flags) 215 | { 216 | struct v4l2_event_subscription sub; 217 | int ret; 218 | 219 | memset(&sub, 0, sizeof(struct v4l2_event_subscription)); 220 | 221 | sub.type = type; 222 | sub.id = id; 223 | sub.flags = flags; 224 | 225 | ret = v4l2_ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub); 226 | if (ret == 0) 227 | { 228 | COMP_DEBUG_MSG("Successfully subscribed to event " << type); 229 | } 230 | else 231 | { 232 | COMP_SYS_ERROR_MSG 233 | ("Error while subscribing to event " << type); 234 | } 235 | 236 | return ret; 237 | } 238 | 239 | int 240 | NvV4l2Element::abort() 241 | { 242 | int ret = 0; 243 | 244 | ret |= output_plane.setStreamStatus(false); 245 | ret |= capture_plane.setStreamStatus(false); 246 | 247 | return ret; 248 | } 249 | 250 | int 251 | NvV4l2Element::waitForIdle(uint32_t max_wait_ms) 252 | { 253 | COMP_ERROR_MSG("wait_for_idle not implemented"); 254 | return 0; 255 | } 256 | 257 | int 258 | NvV4l2Element::isInError() 259 | { 260 | int error = is_in_error; 261 | error |= capture_plane.isInError(); 262 | error |= output_plane.isInError(); 263 | return error; 264 | } 265 | 266 | void 267 | NvV4l2Element::enableProfiling() 268 | { 269 | if (output_plane_pixfmt || capture_plane_pixfmt) 270 | { 271 | COMP_ERROR_MSG("Profiling must be enabled before setting formats on either plane"); 272 | return; 273 | } 274 | profiler.enableProfiling(true); 275 | } 276 | -------------------------------------------------------------------------------- /common/NvVideoConverter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "NvVideoConverter.h" 30 | #include "NvLogging.h" 31 | 32 | #include 33 | #include 34 | 35 | #define CONVERTER_DEV "/dev/nvhost-vic" 36 | #define CAT_NAME "NVVIDCONV" 37 | 38 | #define CHECK_V4L2_RETURN(ret, str) \ 39 | if (ret < 0) { \ 40 | COMP_SYS_ERROR_MSG(str << ": failed"); \ 41 | return -1; \ 42 | } else { \ 43 | COMP_DEBUG_MSG(str << ": success"); \ 44 | return 0; \ 45 | } 46 | 47 | #define RETURN_ERROR_IF_FORMATS_SET() \ 48 | if (output_plane_pixfmt != 0 || capture_plane_pixfmt != 0) { \ 49 | COMP_ERROR_MSG("Should be called before setting plane formats") \ 50 | return -1; \ 51 | } 52 | 53 | #define RETURN_ERROR_IF_BUFFERS_REQUESTED() \ 54 | if (output_plane.getNumBuffers() != 0 && capture_plane.getNumBuffers() != 0) { \ 55 | COMP_ERROR_MSG("Should be called before requesting buffers on either plane") \ 56 | return -1; \ 57 | } 58 | 59 | #define RETURN_ERROR_IF_FORMATS_NOT_SET() \ 60 | if (output_plane_pixfmt == 0 || capture_plane_pixfmt == 0) { \ 61 | COMP_ERROR_MSG("Should be called after setting plane formats") \ 62 | return -1; \ 63 | } 64 | 65 | using namespace std; 66 | 67 | NvVideoConverter::NvVideoConverter(const char *name, int flags) 68 | :NvV4l2Element(name, CONVERTER_DEV, flags, valid_fields) 69 | { 70 | } 71 | 72 | NvVideoConverter * 73 | NvVideoConverter::createVideoConverter(const char *name, int flags) 74 | { 75 | NvVideoConverter *conv = new NvVideoConverter(name, flags); 76 | if (conv->isInError()) 77 | { 78 | delete conv; 79 | return NULL; 80 | } 81 | return conv; 82 | } 83 | 84 | NvVideoConverter::~NvVideoConverter() 85 | { 86 | } 87 | 88 | int 89 | NvVideoConverter::setCapturePlaneFormat(uint32_t pixfmt, uint32_t width, 90 | uint32_t height, enum v4l2_nv_buffer_layout type) 91 | { 92 | struct v4l2_format format; 93 | uint32_t num_bufferplanes; 94 | NvBuffer::NvBufferPlaneFormat planefmts[MAX_PLANES]; 95 | 96 | if (setCapturePlaneBufferLayout(type) < 0) 97 | { 98 | return -1; 99 | } 100 | 101 | capture_plane_pixfmt = pixfmt; 102 | NvBuffer::fill_buffer_plane_format(&num_bufferplanes, planefmts, width, 103 | height, pixfmt); 104 | capture_plane.setBufferPlaneFormat(num_bufferplanes, planefmts); 105 | 106 | memset(&format, 0, sizeof(struct v4l2_format)); 107 | format.type = capture_plane.getBufType(); 108 | format.fmt.pix_mp.width = width; 109 | format.fmt.pix_mp.height = height; 110 | format.fmt.pix_mp.pixelformat = pixfmt; 111 | format.fmt.pix_mp.num_planes = num_bufferplanes; 112 | 113 | CHECK_V4L2_RETURN(capture_plane.setFormat(format), 114 | "Setting capture plane format"); 115 | } 116 | 117 | int 118 | NvVideoConverter::setOutputPlaneFormat(uint32_t pixfmt, uint32_t width, 119 | uint32_t height, enum v4l2_nv_buffer_layout type) 120 | { 121 | struct v4l2_format format; 122 | uint32_t num_bufferplanes; 123 | NvBuffer::NvBufferPlaneFormat planefmts[MAX_PLANES]; 124 | 125 | if (setOutputPlaneBufferLayout(type) < 0) 126 | { 127 | return -1; 128 | } 129 | 130 | output_plane_pixfmt = pixfmt; 131 | NvBuffer::fill_buffer_plane_format(&num_bufferplanes, planefmts, width, 132 | height, pixfmt); 133 | output_plane.setBufferPlaneFormat(num_bufferplanes, planefmts); 134 | 135 | memset(&format, 0, sizeof(struct v4l2_format)); 136 | format.type = output_plane.getBufType(); 137 | format.fmt.pix_mp.width = width; 138 | format.fmt.pix_mp.height = height; 139 | format.fmt.pix_mp.pixelformat = pixfmt; 140 | format.fmt.pix_mp.num_planes = num_bufferplanes; 141 | 142 | CHECK_V4L2_RETURN(output_plane.setFormat(format), 143 | "Setting output plane format"); 144 | } 145 | 146 | int 147 | NvVideoConverter::waitForIdle(uint32_t max_wait_ms) 148 | { 149 | struct timespec timeToWait; 150 | struct timeval now; 151 | int return_val = 0; 152 | int ret; 153 | 154 | gettimeofday(&now, NULL); 155 | 156 | timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L; 157 | timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 + 158 | timeToWait.tv_nsec / 1000000000L; 159 | timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L; 160 | 161 | pthread_mutex_lock(&capture_plane.plane_lock); 162 | while (output_plane.getTotalQueuedBuffers() > 163 | capture_plane.getTotalDequeuedBuffers()) 164 | { 165 | if (!capture_plane.getStreamStatus()) 166 | { 167 | return_val = -2; 168 | break; 169 | } 170 | ret = pthread_cond_timedwait(&capture_plane.plane_cond, 171 | &capture_plane.plane_lock, &timeToWait); 172 | if (ret == ETIMEDOUT) 173 | { 174 | return_val = -1; 175 | break; 176 | } 177 | } 178 | pthread_mutex_unlock(&capture_plane.plane_lock); 179 | 180 | return return_val; 181 | } 182 | 183 | int 184 | NvVideoConverter::setOutputPlaneBufferLayout(enum v4l2_nv_buffer_layout type) 185 | { 186 | struct v4l2_ext_control ctl; 187 | struct v4l2_ext_controls controls; 188 | 189 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 190 | 191 | memset(&ctl, 0, sizeof(ctl)); 192 | memset(&controls, 0, sizeof(controls)); 193 | 194 | ctl.id = V4L2_CID_VIDEO_CONVERT_OUTPUT_PLANE_LAYOUT; 195 | ctl.value = (uint32_t) type; 196 | controls.controls = &ctl; 197 | controls.count = 1; 198 | 199 | CHECK_V4L2_RETURN(setExtControls(controls), 200 | "Setting output plane buffer layout to " << type); 201 | } 202 | 203 | int 204 | NvVideoConverter::setCapturePlaneBufferLayout(enum v4l2_nv_buffer_layout type) 205 | { 206 | struct v4l2_ext_control ctl; 207 | struct v4l2_ext_controls controls; 208 | 209 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 210 | 211 | memset(&ctl, 0, sizeof(ctl)); 212 | memset(&controls, 0, sizeof(controls)); 213 | 214 | ctl.id = V4L2_CID_VIDEO_CONVERT_CAPTURE_PLANE_LAYOUT; 215 | ctl.value = (uint32_t) type; 216 | controls.controls = &ctl; 217 | controls.count = 1; 218 | 219 | CHECK_V4L2_RETURN(setExtControls(controls), 220 | "Setting capture plane buffer layout to " << type); 221 | } 222 | 223 | int 224 | NvVideoConverter::setInterpolationMethod(enum v4l2_interpolation_method method) 225 | { 226 | struct v4l2_ext_control ctl; 227 | struct v4l2_ext_controls controls; 228 | 229 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 230 | 231 | memset(&ctl, 0, sizeof(ctl)); 232 | memset(&controls, 0, sizeof(controls)); 233 | 234 | ctl.id = V4L2_CID_VIDEO_CONVERT_INTERPOLATION_METHOD; 235 | ctl.value = (uint32_t) method; 236 | controls.controls = &ctl; 237 | controls.count = 1; 238 | 239 | CHECK_V4L2_RETURN(setExtControls(controls), 240 | "Setting interpolation method to " << method); 241 | } 242 | 243 | int 244 | NvVideoConverter::setFlipMethod(enum v4l2_flip_method method) 245 | { 246 | struct v4l2_ext_control ctl; 247 | struct v4l2_ext_controls controls; 248 | 249 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 250 | 251 | memset(&ctl, 0, sizeof(ctl)); 252 | memset(&controls, 0, sizeof(controls)); 253 | 254 | ctl.id = V4L2_CID_VIDEO_CONVERT_FLIP_METHOD; 255 | ctl.value = (uint32_t) method; 256 | controls.controls = &ctl; 257 | controls.count = 1; 258 | 259 | CHECK_V4L2_RETURN(setExtControls(controls), 260 | "Setting flip method to " << method); 261 | } 262 | 263 | int 264 | NvVideoConverter::setTnrAlgorithm(enum v4l2_tnr_algorithm algorithm) 265 | { 266 | struct v4l2_ext_control ctl; 267 | struct v4l2_ext_controls controls; 268 | 269 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 270 | 271 | memset(&ctl, 0, sizeof(ctl)); 272 | memset(&controls, 0, sizeof(controls)); 273 | 274 | ctl.id = V4L2_CID_VIDEO_CONVERT_TNR_ALGORITHM; 275 | ctl.value = (uint32_t) algorithm; 276 | controls.controls = &ctl; 277 | controls.count = 1; 278 | 279 | CHECK_V4L2_RETURN(setExtControls(controls), 280 | "Setting TNR algorithm to " << algorithm); 281 | } 282 | 283 | int 284 | NvVideoConverter::setYUVRescale(enum v4l2_yuv_rescale_method method) 285 | { 286 | struct v4l2_ext_control ctl; 287 | struct v4l2_ext_controls controls; 288 | 289 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 290 | 291 | memset(&ctl, 0, sizeof(ctl)); 292 | memset(&controls, 0, sizeof(controls)); 293 | 294 | ctl.id = V4L2_CID_VIDEO_CONVERT_YUV_RESCALE_METHOD; 295 | ctl.value = (uint32_t) method; 296 | controls.controls = &ctl; 297 | controls.count = 1; 298 | 299 | CHECK_V4L2_RETURN(setExtControls(controls), 300 | "Setting YUV Rescale mothod to " << method); 301 | } 302 | 303 | int 304 | NvVideoConverter::setCropRect(uint32_t left, uint32_t top, uint32_t width, 305 | uint32_t height) 306 | { 307 | struct v4l2_rect rect; 308 | 309 | rect.left = left; 310 | rect.top = top; 311 | rect.width = width; 312 | rect.height = height; 313 | 314 | CHECK_V4L2_RETURN(capture_plane.setSelection(V4L2_SEL_TGT_CROP, 0, rect), 315 | "Setting crop rectangle to left=" << left << ", top=" << top << 316 | ", width=" << width << ", height=" << height); 317 | } 318 | 319 | int 320 | NvVideoConverter::setDestRect(uint32_t left, uint32_t top, uint32_t width, 321 | uint32_t height) 322 | { 323 | struct v4l2_rect rect; 324 | 325 | rect.left = left; 326 | rect.top = top; 327 | rect.width = width; 328 | rect.height = height; 329 | 330 | CHECK_V4L2_RETURN(output_plane.setSelection(V4L2_SEL_TGT_COMPOSE, 0, rect), 331 | "Setting compose rectangle to left=" << left << ", top=" << top << 332 | ", width=" << width << ", height=" << height); 333 | } 334 | -------------------------------------------------------------------------------- /common/NvVideoDecoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "NvVideoDecoder.h" 30 | #include "NvLogging.h" 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #define DECODER_DEV "/dev/nvhost-nvdec" 37 | #define CAT_NAME "NVDEC" 38 | 39 | #define CHECK_V4L2_RETURN(ret, str) \ 40 | if (ret < 0) { \ 41 | COMP_SYS_ERROR_MSG(str << ": failed"); \ 42 | return -1; \ 43 | } else { \ 44 | COMP_DEBUG_MSG(str << ": success"); \ 45 | return 0; \ 46 | } 47 | 48 | #define RETURN_ERROR_IF_FORMATS_SET() \ 49 | if (output_plane_pixfmt != 0) { \ 50 | COMP_ERROR_MSG("Should be called before setting plane formats") \ 51 | return -1; \ 52 | } 53 | 54 | #define RETURN_ERROR_IF_BUFFERS_REQUESTED() \ 55 | if (output_plane.getNumBuffers() != 0 && capture_plane.getNumBuffers() != 0) { \ 56 | COMP_ERROR_MSG("Should be called before requesting buffers on either plane") \ 57 | return -1; \ 58 | } 59 | 60 | #define RETURN_ERROR_IF_FORMATS_NOT_SET() \ 61 | if (output_plane_pixfmt == 0) { \ 62 | COMP_ERROR_MSG("Should be called after setting plane formats") \ 63 | return -1; \ 64 | } 65 | 66 | using namespace std; 67 | 68 | NvVideoDecoder::NvVideoDecoder(const char *name, int flags) 69 | :NvV4l2Element(name, DECODER_DEV, flags, valid_fields) 70 | { 71 | } 72 | 73 | NvVideoDecoder * 74 | NvVideoDecoder::createVideoDecoder(const char *name, int flags) 75 | { 76 | NvVideoDecoder *dec = new NvVideoDecoder(name, flags); 77 | if (dec->isInError()) 78 | { 79 | delete dec; 80 | return NULL; 81 | } 82 | return dec; 83 | } 84 | 85 | NvVideoDecoder::~NvVideoDecoder() 86 | { 87 | } 88 | 89 | int 90 | NvVideoDecoder::setCapturePlaneFormat(uint32_t pixfmt, uint32_t width, 91 | uint32_t height) 92 | { 93 | struct v4l2_format format; 94 | uint32_t num_bufferplanes; 95 | NvBuffer::NvBufferPlaneFormat planefmts[MAX_PLANES]; 96 | 97 | if (! ((pixfmt == V4L2_PIX_FMT_NV12M) || (pixfmt == V4L2_PIX_FMT_P010M))) 98 | { 99 | COMP_ERROR_MSG("Only V4L2_PIX_FMT_NV12M or V4L2_PIX_FMT_P010M is supported"); 100 | return -1; 101 | } 102 | 103 | capture_plane_pixfmt = pixfmt; 104 | NvBuffer::fill_buffer_plane_format(&num_bufferplanes, planefmts, width, 105 | height, pixfmt); 106 | capture_plane.setBufferPlaneFormat(num_bufferplanes, planefmts); 107 | 108 | memset(&format, 0, sizeof(struct v4l2_format)); 109 | format.type = capture_plane.getBufType(); 110 | format.fmt.pix_mp.width = width; 111 | format.fmt.pix_mp.height = height; 112 | format.fmt.pix_mp.pixelformat = pixfmt; 113 | format.fmt.pix_mp.num_planes = num_bufferplanes; 114 | 115 | return capture_plane.setFormat(format); 116 | } 117 | 118 | int 119 | NvVideoDecoder::setOutputPlaneFormat(uint32_t pixfmt, uint32_t sizeimage) 120 | { 121 | struct v4l2_format format; 122 | 123 | memset(&format, 0, sizeof(struct v4l2_format)); 124 | format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 125 | switch (pixfmt) 126 | { 127 | case V4L2_PIX_FMT_H264: 128 | case V4L2_PIX_FMT_H265: 129 | case V4L2_PIX_FMT_VP8: 130 | case V4L2_PIX_FMT_VP9: 131 | case V4L2_PIX_FMT_MPEG2: 132 | case V4L2_PIX_FMT_MPEG4: 133 | output_plane_pixfmt = pixfmt; 134 | break; 135 | default: 136 | COMP_ERROR_MSG("Unsupported pixel format for decoder output plane " 137 | << pixfmt); 138 | return -1; 139 | } 140 | format.fmt.pix_mp.pixelformat = pixfmt; 141 | format.fmt.pix_mp.num_planes = 1; 142 | format.fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage; 143 | 144 | return output_plane.setFormat(format); 145 | } 146 | 147 | int 148 | NvVideoDecoder::disableDPB() 149 | { 150 | struct v4l2_ext_control control; 151 | struct v4l2_ext_controls ctrls; 152 | 153 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 154 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 155 | 156 | memset(&control, 0, sizeof(control)); 157 | memset(&ctrls, 0, sizeof(ctrls)); 158 | 159 | ctrls.count = 1; 160 | ctrls.controls = &control; 161 | 162 | control.id = V4L2_CID_MPEG_VIDEO_DISABLE_DPB; 163 | 164 | CHECK_V4L2_RETURN(setExtControls(ctrls), 165 | "Disabling decoder DPB"); 166 | } 167 | 168 | int 169 | NvVideoDecoder::disableCompleteFrameInputBuffer() 170 | { 171 | struct v4l2_ext_control control; 172 | struct v4l2_ext_controls ctrls; 173 | 174 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 175 | 176 | memset(&control, 0, sizeof(control)); 177 | memset(&ctrls, 0, sizeof(ctrls)); 178 | 179 | ctrls.count = 1; 180 | ctrls.controls = &control; 181 | 182 | control.id = V4L2_CID_MPEG_VIDEO_DISABLE_COMPLETE_FRAME_INPUT; 183 | control.value = 1; 184 | 185 | CHECK_V4L2_RETURN(setExtControls(ctrls), 186 | "Disabling decoder complete frame input buffer"); 187 | } 188 | 189 | int 190 | NvVideoDecoder::setFrameInputMode(unsigned int ctrl_value) 191 | { 192 | struct v4l2_ext_control control; 193 | struct v4l2_ext_controls ctrls; 194 | 195 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 196 | 197 | memset(&control, 0, sizeof(control)); 198 | memset(&ctrls, 0, sizeof(ctrls)); 199 | 200 | ctrls.count = 1; 201 | ctrls.controls = &control; 202 | 203 | control.id = V4L2_CID_MPEG_VIDEO_DISABLE_COMPLETE_FRAME_INPUT; 204 | control.value = ctrl_value; 205 | 206 | CHECK_V4L2_RETURN(setExtControls(ctrls), 207 | "Setting decoder frame input mode to " << ctrl_value); 208 | } 209 | 210 | 211 | int 212 | NvVideoDecoder::getMinimumCapturePlaneBuffers(int &num) 213 | { 214 | CHECK_V4L2_RETURN(getControl(V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, num), 215 | "Getting decoder minimum capture plane buffers (" << num << ")"); 216 | } 217 | 218 | int 219 | NvVideoDecoder::setSkipFrames(enum v4l2_skip_frames_type skip_frames) 220 | { 221 | struct v4l2_ext_control control; 222 | struct v4l2_ext_controls ctrls; 223 | 224 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 225 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 226 | 227 | memset(&control, 0, sizeof(control)); 228 | memset(&ctrls, 0, sizeof(ctrls)); 229 | 230 | ctrls.count = 1; 231 | ctrls.controls = &control; 232 | 233 | control.id = V4L2_CID_MPEG_VIDEO_SKIP_FRAMES; 234 | control.value = skip_frames; 235 | 236 | CHECK_V4L2_RETURN(setExtControls(ctrls), 237 | "Setting decoder skip frames to " << skip_frames); 238 | } 239 | 240 | int 241 | NvVideoDecoder::setMaxPerfMode(int flag) 242 | { 243 | struct v4l2_ext_control control; 244 | struct v4l2_ext_controls ctrls; 245 | 246 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 247 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 248 | 249 | memset(&control, 0, sizeof(control)); 250 | memset(&ctrls, 0, sizeof(ctrls)); 251 | 252 | ctrls.count = 1; 253 | ctrls.controls = &control; 254 | 255 | control.id = V4L2_CID_MPEG_VIDEO_MAX_PERFORMANCE; 256 | control.value = flag; 257 | 258 | CHECK_V4L2_RETURN(setExtControls(ctrls), 259 | "Enabling Maximum Performance "); 260 | } 261 | 262 | int 263 | NvVideoDecoder::enableMetadataReporting() 264 | { 265 | struct v4l2_ext_control control; 266 | struct v4l2_ext_controls ctrls; 267 | 268 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 269 | RETURN_ERROR_IF_BUFFERS_REQUESTED(); 270 | 271 | memset(&control, 0, sizeof(control)); 272 | memset(&ctrls, 0, sizeof(ctrls)); 273 | 274 | ctrls.count = 1; 275 | ctrls.controls = &control; 276 | 277 | control.id = V4L2_CID_MPEG_VIDEO_ERROR_REPORTING; 278 | 279 | CHECK_V4L2_RETURN(setExtControls(ctrls), 280 | "Enabling decoder output metadata reporting"); 281 | } 282 | 283 | int 284 | NvVideoDecoder::getMetadata(uint32_t buffer_index, 285 | v4l2_ctrl_videodec_outputbuf_metadata &dec_metadata) 286 | { 287 | v4l2_ctrl_video_metadata metadata; 288 | struct v4l2_ext_control control; 289 | struct v4l2_ext_controls ctrls; 290 | 291 | ctrls.count = 1; 292 | ctrls.controls = &control; 293 | 294 | metadata.buffer_index = buffer_index; 295 | metadata.VideoDecMetadata = &dec_metadata; 296 | 297 | control.id = V4L2_CID_MPEG_VIDEODEC_METADATA; 298 | control.string = (char *)&metadata; 299 | 300 | CHECK_V4L2_RETURN(getExtControls(ctrls), 301 | "Getting decoder output metadata for buffer " << buffer_index); 302 | } 303 | 304 | int 305 | NvVideoDecoder::getInputMetadata(uint32_t buffer_index, 306 | v4l2_ctrl_videodec_inputbuf_metadata &dec_input_metadata) 307 | { 308 | v4l2_ctrl_video_metadata metadata; 309 | struct v4l2_ext_control control; 310 | struct v4l2_ext_controls ctrls; 311 | 312 | ctrls.count = 1; 313 | ctrls.controls = &control; 314 | 315 | metadata.buffer_index = buffer_index; 316 | metadata.VideoDecHeaderErrorMetadata = &dec_input_metadata; 317 | 318 | control.id = V4L2_CID_MPEG_VIDEODEC_INPUT_METADATA; 319 | control.string = (char *)&metadata; 320 | 321 | CHECK_V4L2_RETURN(getExtControls(ctrls), 322 | "Getting decoder input metadata for buffer " << buffer_index); 323 | } 324 | 325 | int 326 | NvVideoDecoder::checkifMasteringDisplayDataPresent(v4l2_ctrl_video_displaydata 327 | &displaydata) 328 | { 329 | struct v4l2_ext_control control; 330 | struct v4l2_ext_controls ctrls; 331 | 332 | ctrls.count = 1; 333 | ctrls.controls = &control; 334 | 335 | control.id = V4L2_CID_VIDEODEC_DISPLAYDATA_PRESENT; 336 | control.string = (char *)&displaydata; 337 | 338 | CHECK_V4L2_RETURN(getExtControls(ctrls), 339 | "Getting decoder output displaydata for buffer "); 340 | } 341 | 342 | int 343 | NvVideoDecoder::MasteringDisplayData(v4l2_ctrl_video_hdrmasteringdisplaydata 344 | *hdrmasteringdisplaydata) 345 | { 346 | struct v4l2_ext_control control; 347 | struct v4l2_ext_controls ctrls; 348 | 349 | ctrls.count = 1; 350 | ctrls.controls = &control; 351 | 352 | control.id = V4L2_CID_VIDEODEC_HDR_MASTERING_DISPLAY_DATA; 353 | control.string = (char *)hdrmasteringdisplaydata; 354 | 355 | CHECK_V4L2_RETURN(getExtControls(ctrls), 356 | "Getting decoder output hdrdisplaydata for buffer "); 357 | } 358 | 359 | int 360 | NvVideoDecoder::DevicePoll(v4l2_ctrl_video_device_poll *devicepoll) 361 | { 362 | struct v4l2_ext_control control; 363 | struct v4l2_ext_controls ctrls; 364 | 365 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 366 | 367 | memset(&control, 0, sizeof(control)); 368 | memset(&ctrls, 0, sizeof(ctrls)); 369 | 370 | ctrls.count = 1; 371 | ctrls.controls = &control; 372 | 373 | control.id = V4L2_CID_MPEG_VIDEO_DEVICE_POLL; 374 | control.string = (char *)devicepoll; 375 | 376 | CHECK_V4L2_RETURN(setExtControls(ctrls), 377 | "Done calling video device poll "); 378 | } 379 | 380 | int 381 | NvVideoDecoder::SetPollInterrupt() 382 | { 383 | struct v4l2_ext_control control; 384 | struct v4l2_ext_controls ctrls; 385 | 386 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 387 | 388 | memset(&control, 0, sizeof(control)); 389 | memset(&ctrls, 0, sizeof(ctrls)); 390 | 391 | ctrls.count = 1; 392 | ctrls.controls = &control; 393 | 394 | control.id = V4L2_CID_MPEG_SET_POLL_INTERRUPT; 395 | control.value = 1; 396 | 397 | CHECK_V4L2_RETURN(setExtControls(ctrls), 398 | "Setting decoder poll interrupt to 1 "); 399 | } 400 | 401 | int 402 | NvVideoDecoder::ClearPollInterrupt() 403 | { 404 | struct v4l2_ext_control control; 405 | struct v4l2_ext_controls ctrls; 406 | 407 | RETURN_ERROR_IF_FORMATS_NOT_SET(); 408 | 409 | memset(&control, 0, sizeof(control)); 410 | memset(&ctrls, 0, sizeof(ctrls)); 411 | 412 | ctrls.count = 1; 413 | ctrls.controls = &control; 414 | 415 | control.id = V4L2_CID_MPEG_SET_POLL_INTERRUPT; 416 | control.value = 0; 417 | 418 | CHECK_V4L2_RETURN(setExtControls(ctrls), 419 | "Setting decoder poll interrupt to 0 "); 420 | } 421 | 422 | -------------------------------------------------------------------------------- /converter/cuda_converter.cu: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1993-2019 NVIDIA Corporation. All rights reserved. 3 | * 4 | * NOTICE TO LICENSEE: 5 | * 6 | * This source code and/or documentation ("Licensed Deliverables") are 7 | * subject to NVIDIA intellectual property rights under U.S. and 8 | * international Copyright laws. 9 | * 10 | * These Licensed Deliverables contained herein is PROPRIETARY and 11 | * CONFIDENTIAL to NVIDIA and is being provided under the terms and 12 | * conditions of a form of NVIDIA software license agreement by and 13 | * between NVIDIA and Licensee ("License Agreement") or electronically 14 | * accepted by Licensee. Notwithstanding any terms or conditions to 15 | * the contrary in the License Agreement, reproduction or disclosure 16 | * of the Licensed Deliverables to any third party without the express 17 | * written consent of NVIDIA is prohibited. 18 | * 19 | * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE 20 | * LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE 21 | * SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE. IT IS 22 | * PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. 23 | * NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED 24 | * DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, 25 | * NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. 26 | * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE 27 | * LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY 28 | * SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY 29 | * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 30 | * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 31 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 32 | * OF THESE LICENSED DELIVERABLES. 33 | * 34 | * U.S. Government End Users. These Licensed Deliverables are a 35 | * "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT 36 | * 1995), consisting of "commercial computer software" and "commercial 37 | * computer software documentation" as such terms are used in 48 38 | * C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government 39 | * only as a commercial end item. Consistent with 48 C.F.R.12.212 and 40 | * 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all 41 | * U.S. Government End Users acquire the Licensed Deliverables with 42 | * only those rights set forth herein. 43 | * 44 | * Any use of the Licensed Deliverables in individual and commercial 45 | * software must include, in the user documentation and internal 46 | * comments to the code, the above Disclaimer and U.S. Government End 47 | * Users Notice. 48 | */ 49 | 50 | #include "cuda_converter.h" 51 | #include "cudaUtility.h" 52 | 53 | #include 54 | #include 55 | 56 | #include 57 | 58 | static __global__ void convertIntRGBAPackedToFloatBGRPlanar(void *pDevPtr 59 | , int width 60 | , int height 61 | , void* cudaBuf 62 | , int pitch 63 | , void* meanDataInfer 64 | , void* scalesInfer) { 65 | float *pData = (float *)cudaBuf; 66 | char *pSrcData = (char *)pDevPtr; 67 | int *meanData = (int *)meanDataInfer; 68 | float *scales = (float *)scalesInfer; 69 | int row = blockIdx.y * blockDim.y + threadIdx.y; 70 | int col = blockIdx.x * blockDim.x + threadIdx.x; 71 | 72 | if (col < width && row < height) { 73 | // For V4L2_PIX_FMT_ABGR32 --> RGBA-8-8-8-8 74 | for (int k = 0; k < 3; k++) { 75 | pData[width * height * k + row * width + col] = 76 | (float)(*(pSrcData + row * pitch + col * 4 + (3 - 1 - k)) - meanData[k]) * scales[k]; 77 | } 78 | } 79 | } 80 | 81 | static __global__ void convertIntRGBAPackedToFloatRGBPlanar(void *pDevPtr 82 | , int width 83 | , int height 84 | , void* cudaBuf 85 | , int pitch 86 | , void* meanDataInfer 87 | , void* scalesInfer) { 88 | float *pData = (float *)cudaBuf; 89 | char *pSrcData = (char *)pDevPtr; 90 | int *meanData = (int *)meanDataInfer; 91 | float *scales = (float *)scalesInfer; 92 | int row = blockIdx.y * blockDim.y + threadIdx.y; 93 | int col = blockIdx.x * blockDim.x + threadIdx.x; 94 | 95 | if (col < width && row < height) { 96 | // For V4L2_PIX_FMT_ABGR32 --> RGBA-8-8-8-8 97 | for (int k = 0; k < 3; k++) { 98 | pData[width * height * k + row * width + col] = 99 | (float)(*(pSrcData + row * pitch + col * 4 + k) - meanData[k]) * scales[k]; 100 | } 101 | } 102 | } 103 | 104 | static int convertIntPackedToFloatPlanar(void *pDevPtr, 105 | int width, 106 | int height, 107 | int pitch, 108 | RGBColorFormat colorFormat, 109 | void* meanData, 110 | void* scales, 111 | void* cudaBuf, void* pStream) { 112 | dim3 threadsPerBlock(16, 16); 113 | dim3 blocks(width / threadsPerBlock.x, height / threadsPerBlock.y); 114 | cudaStream_t stream; 115 | 116 | if (pStream != nullptr) { 117 | stream = *(cudaStream_t*)pStream; 118 | } 119 | else { 120 | fprintf(stderr, "better not to run on default CUDA stream!\n"); 121 | stream = 0; 122 | } 123 | 124 | if (colorFormat == COLOR_FORMAT_RGB) { 125 | convertIntRGBAPackedToFloatRGBPlanar << > >(pDevPtr, width, 126 | height, cudaBuf, pitch, meanData, scales); 127 | } 128 | else if (colorFormat == COLOR_FORMAT_BGR) { 129 | convertIntRGBAPackedToFloatBGRPlanar << > >(pDevPtr, width, 130 | height, cudaBuf, pitch, meanData, scales); 131 | } 132 | 133 | return 0; 134 | } 135 | 136 | //conver RGBA to BGR uchar 137 | static __global__ void convertIntBGRAPackedToBGRPlanar(void *pDevPtr 138 | , int width 139 | , int height 140 | , void* cudaBuf 141 | , int pitch) { 142 | 143 | unsigned char *pData = (unsigned char *)cudaBuf; 144 | char *pSrcData = (char *)pDevPtr; 145 | 146 | const int x = blockIdx.x * blockDim.x + threadIdx.x; 147 | const int y = blockIdx.y * blockDim.y + threadIdx.y; 148 | 149 | if (x >= width || y >= height) 150 | return; 151 | 152 | // For V4L2_PIX_FMT_ABGR32 --> RGBA-8-8-8-8 153 | for (int k = 0; k < 3; ++k){ 154 | pData[y*width * 3 + x * 3 + k] = pSrcData[y * pitch + x * 4 + (3 - 1 - k)]; 155 | } 156 | } 157 | 158 | //conver RGBA to RGB uchar 159 | static __global__ void convertIntBGRAPackedToRGBPlanar(void *pDevPtr 160 | , int width 161 | , int height 162 | , void* cudaBuf 163 | , int pitch) { 164 | 165 | unsigned char *pData = (unsigned char *)cudaBuf; 166 | char *pSrcData = (char *)pDevPtr; 167 | 168 | const int x = blockIdx.x * blockDim.x + threadIdx.x; 169 | const int y = blockIdx.y * blockDim.y + threadIdx.y; 170 | 171 | if (x >= width || y >= height) 172 | return; 173 | 174 | // For V4L2_PIX_FMT_ABGR32 --> RGBA-8-8-8-8 175 | for (int k = 0; k < 3; ++k){ 176 | pData[y*width * 3 + x * 3 + k] = pSrcData[y * pitch + x * 4 + k]; 177 | } 178 | } 179 | 180 | static int convertIntPackedToPlanar(void *pDevPtr, 181 | int width, 182 | int height, 183 | int pitch, 184 | RGBColorFormat colorFormat, 185 | void* cudaBuf, void* pStream) { 186 | 187 | // launch kernel 188 | const dim3 blockDim(16, 16); 189 | const dim3 gridDim(iDivUp(width, blockDim.x), iDivUp(height, blockDim.y)); 190 | 191 | cudaStream_t stream; 192 | 193 | if (pStream != nullptr) { 194 | stream = *(cudaStream_t*)pStream; 195 | } 196 | else { 197 | fprintf(stderr, "better not to run on default CUDA stream!\n"); 198 | stream = 0; 199 | } 200 | 201 | if (colorFormat == COLOR_FORMAT_RGB) { 202 | convertIntBGRAPackedToRGBPlanar << > >(pDevPtr, width, 203 | height, cudaBuf, pitch); 204 | } 205 | else if (colorFormat == COLOR_FORMAT_BGR) { 206 | convertIntBGRAPackedToBGRPlanar << > >(pDevPtr, width, 207 | height, cudaBuf, pitch); 208 | } 209 | 210 | return 0; 211 | } 212 | 213 | 214 | //! 215 | //! \details call the CUDA kernel to convert one BGRA packed frame to 216 | //! RGB or BGR planar frame 217 | //! 218 | //! \param eglFrame eglImage that is mapping to the BGRA packed frame 219 | //! 220 | //! \param width width of the frame 221 | //! 222 | //! \param height height of the frame 223 | //! 224 | //! \param colorFormat format of output frame, i.e. RGB or BGR 225 | //! 226 | //! \param cudaBuf CUDA buffer for the output frame 227 | //! 228 | //! \param offsets mean value from inference 229 | //! 230 | //! \param scales scale the float for following inference 231 | //! 232 | void CUDAConverter::convert(cudaEglFrame eglFrame 233 | , int width 234 | , int height 235 | , RGBColorFormat colorFormat 236 | , void* cudaBuf 237 | , void* meanData 238 | , void* scales 239 | , cudaStream_t stream) { 240 | if (eglFrame.frameType == cudaEglFrameTypePitch) { 241 | convertIntPackedToFloatPlanar((void *)eglFrame.frame.pPitch[0].ptr, 242 | width, 243 | height, 244 | eglFrame.frame.pPitch[0].pitch, 245 | colorFormat, 246 | meanData, 247 | scales, 248 | cudaBuf, 249 | &stream); 250 | } 251 | } 252 | 253 | void CUDAConverter::convert(cudaEglFrame eglFrame 254 | , int width 255 | , int height 256 | , RGBColorFormat colorFormat 257 | , void* cudaBuf 258 | , cudaStream_t stream) { 259 | if (eglFrame.frameType == cudaEglFrameTypePitch) { 260 | convertIntPackedToPlanar((void *)eglFrame.frame.pPitch[0].ptr, 261 | width, 262 | height, 263 | eglFrame.frame.pPitch[0].pitch, 264 | colorFormat, 265 | cudaBuf, 266 | &stream); 267 | } 268 | } -------------------------------------------------------------------------------- /converter/cuda_converter.h: -------------------------------------------------------------------------------- 1 | #ifndef __CUDA_CONVERTER_H__ 2 | #define __CUDA_CONVERTER_H__ 3 | 4 | #include 5 | #include "cuda_egl_interop.h" 6 | 7 | enum RGBColorFormat { 8 | COLOR_FORMAT_RGB, 9 | COLOR_FORMAT_BGR, 10 | }; 11 | 12 | //! 13 | //! \brief Class CUDAConverter uses CUDA to do ABGR32 packed(int) to BGR/RGB planar(float) conversion. 14 | //! 15 | class CUDAConverter { 16 | public: 17 | void convert(cudaEglFrame eglFrame 18 | , int width 19 | , int height 20 | , RGBColorFormat colorFormat 21 | , void* cudaBuf 22 | , void* offsets 23 | , void* scales 24 | , cudaStream_t stream); 25 | 26 | void convert(cudaEglFrame eglFrame 27 | , int width 28 | , int height 29 | , RGBColorFormat colorFormat 30 | , void* cudaBuf 31 | , cudaStream_t stream); 32 | }; 33 | 34 | #endif // !__CUDA_CONVERTER_H__ -------------------------------------------------------------------------------- /converter/fd_egl_frame_map.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1993-2019 NVIDIA Corporation. All rights reserved. 3 | * 4 | * NOTICE TO LICENSEE: 5 | * 6 | * This source code and/or documentation ("Licensed Deliverables") are 7 | * subject to NVIDIA intellectual property rights under U.S. and 8 | * international Copyright laws. 9 | * 10 | * These Licensed Deliverables contained herein is PROPRIETARY and 11 | * CONFIDENTIAL to NVIDIA and is being provided under the terms and 12 | * conditions of a form of NVIDIA software license agreement by and 13 | * between NVIDIA and Licensee ("License Agreement") or electronically 14 | * accepted by Licensee. Notwithstanding any terms or conditions to 15 | * the contrary in the License Agreement, reproduction or disclosure 16 | * of the Licensed Deliverables to any third party without the express 17 | * written consent of NVIDIA is prohibited. 18 | * 19 | * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE 20 | * LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE 21 | * SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE. IT IS 22 | * PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. 23 | * NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED 24 | * DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, 25 | * NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. 26 | * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE 27 | * LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY 28 | * SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY 29 | * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 30 | * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 31 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 32 | * OF THESE LICENSED DELIVERABLES. 33 | * 34 | * U.S. Government End Users. These Licensed Deliverables are a 35 | * "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT 36 | * 1995), consisting of "commercial computer software" and "commercial 37 | * computer software documentation" as such terms are used in 48 38 | * C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government 39 | * only as a commercial end item. Consistent with 48 C.F.R.12.212 and 40 | * 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all 41 | * U.S. Government End Users acquire the Licensed Deliverables with 42 | * only those rights set forth herein. 43 | * 44 | * Any use of the Licensed Deliverables in individual and commercial 45 | * software must include, in the user documentation and internal 46 | * comments to the code, the above Disclaimer and U.S. Government End 47 | * Users Notice. 48 | */ 49 | 50 | #include "fd_egl_frame_map.h" 51 | 52 | #include "cudaEGL.h" 53 | #include "nvbuf_utils.h" 54 | 55 | #include 56 | 57 | using namespace std; 58 | 59 | int FdEglFrameMap::init() { 60 | mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 61 | if (mEglDisplay == EGL_NO_DISPLAY) { 62 | cerr << "Error while get EGL display connection" << std::endl; 63 | return false; 64 | } 65 | 66 | if (!eglInitialize(mEglDisplay, nullptr, nullptr)) { 67 | cerr << "Erro while initialize EGL display connection" << std::endl; 68 | return false; 69 | } 70 | return true; 71 | } 72 | 73 | cudaEglFrame FdEglFrameMap::get(int fd) { 74 | auto iter = mEglFrameMap.find(fd); 75 | 76 | if (iter == mEglFrameMap.end()) { 77 | return createMap(fd); 78 | } 79 | return iter->second; 80 | } 81 | 82 | cudaEglFrame FdEglFrameMap::createMap(int fd) { 83 | cudaEglFrame eglFrame; 84 | EGLImageKHR eglImage; 85 | cudaGraphicsResource_t resource; 86 | cudaError_t status; 87 | 88 | eglImage = NvEGLImageFromFd(nullptr, fd); 89 | if (eglImage == nullptr) { 90 | cerr << "Error while mapping dmabuf fd (" << fd << ") to EGLImage" << endl; 91 | return eglFrame; 92 | } 93 | 94 | status = cudaGraphicsEGLRegisterImage(&resource, eglImage, 95 | cudaGraphicsRegisterFlagsNone); 96 | if (status != cudaSuccess) { 97 | cerr << "cuGraphicsEGLRegisterImage failed: " << status 98 | << " cuda process stop" << endl; 99 | return eglFrame; 100 | } 101 | 102 | status = cudaGraphicsResourceGetMappedEglFrame(&eglFrame, resource, 0, 0); 103 | if (status != cudaSuccess) { 104 | cerr << "cuGraphicsSubResourceGetMappedArray failed" << endl; 105 | return eglFrame; 106 | } 107 | mEglFrameMap.insert(make_pair(fd, eglFrame)); 108 | mEglImageKHRVector.push_back(eglImage); 109 | mCudaGraphicsResourceVector.push_back(resource); 110 | 111 | return eglFrame; 112 | } 113 | 114 | void FdEglFrameMap::exit() { 115 | cudaError_t status; 116 | 117 | for (auto &eglImage : mEglImageKHRVector) { 118 | NvDestroyEGLImage(mEglDisplay, eglImage); 119 | } 120 | for (auto &resource : mCudaGraphicsResourceVector) { 121 | status = cudaGraphicsUnregisterResource(resource); 122 | if (status != cudaSuccess) { 123 | cerr << "cuGraphicsEGLUnRegisterResource failed: " << status << endl; 124 | } 125 | } 126 | if (mEglDisplay) { 127 | if (!eglTerminate(mEglDisplay)) { 128 | cerr << "Error while terminate EGL display connection" << endl; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /converter/fd_egl_frame_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1993-2019 NVIDIA Corporation. All rights reserved. 3 | * 4 | * NOTICE TO LICENSEE: 5 | * 6 | * This source code and/or documentation ("Licensed Deliverables") are 7 | * subject to NVIDIA intellectual property rights under U.S. and 8 | * international Copyright laws. 9 | * 10 | * These Licensed Deliverables contained herein is PROPRIETARY and 11 | * CONFIDENTIAL to NVIDIA and is being provided under the terms and 12 | * conditions of a form of NVIDIA software license agreement by and 13 | * between NVIDIA and Licensee ("License Agreement") or electronically 14 | * accepted by Licensee. Notwithstanding any terms or conditions to 15 | * the contrary in the License Agreement, reproduction or disclosure 16 | * of the Licensed Deliverables to any third party without the express 17 | * written consent of NVIDIA is prohibited. 18 | * 19 | * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE 20 | * LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE 21 | * SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE. IT IS 22 | * PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. 23 | * NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED 24 | * DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, 25 | * NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. 26 | * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE 27 | * LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY 28 | * SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY 29 | * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 30 | * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 31 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 32 | * OF THESE LICENSED DELIVERABLES. 33 | * 34 | * U.S. Government End Users. These Licensed Deliverables are a 35 | * "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT 36 | * 1995), consisting of "commercial computer software" and "commercial 37 | * computer software documentation" as such terms are used in 48 38 | * C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government 39 | * only as a commercial end item. Consistent with 48 C.F.R.12.212 and 40 | * 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all 41 | * U.S. Government End Users acquire the Licensed Deliverables with 42 | * only those rights set forth herein. 43 | * 44 | * Any use of the Licensed Deliverables in individual and commercial 45 | * software must include, in the user documentation and internal 46 | * comments to the code, the above Disclaimer and U.S. Government End 47 | * Users Notice. 48 | */ 49 | 50 | #ifndef __FD_EGL_FRAME_MAP_H__ 51 | #define __FD_EGL_FRAME_MAP_H__ 52 | 53 | #include "cudaEGL.h" 54 | #include "cuda_egl_interop.h" 55 | 56 | #include 57 | #include 58 | 59 | //! 60 | //! \brief Class FdEglFrameMap maps DMA buffer fd to cudaEglFrame. 61 | //! 62 | class FdEglFrameMap { 63 | public: 64 | int init(); 65 | void exit(); 66 | 67 | cudaEglFrame get(int fd); 68 | 69 | private: 70 | cudaEglFrame createMap(int fd); 71 | 72 | private: 73 | std::map mEglFrameMap; 74 | std::vector mCudaGraphicsResourceVector; 75 | std::vector mEglImageKHRVector; 76 | EGLDisplay mEglDisplay{}; 77 | }; 78 | #endif // !__FD_EGL_FRAME_MAP_H__ 79 | -------------------------------------------------------------------------------- /converter/vic_onverter.h: -------------------------------------------------------------------------------- 1 | //! 2 | //! \brief Class VICConverter uses VIC to do YUV to target resolution ABGR32 packed conversion. 3 | //! 4 | 5 | #ifndef __VIC_CONVERTER_H__ 6 | #define __VIC_CONVERTER_H__ 7 | 8 | #include "nvbuf_utils.h" 9 | #include 10 | 11 | class VICConverter { 12 | public: 13 | void init(NvBufferRect srcRect, NvBufferRect destRect) { 14 | memset(&mConvertParams, 0, sizeof(mConvertParams)); 15 | mConvertParams.transform_flag = NVBUFFER_TRANSFORM_FILTER; 16 | mConvertParams.transform_flip = NvBufferTransform_None; 17 | mConvertParams.transform_filter = NvBufferTransform_Filter_Smart; 18 | mConvertParams.src_rect = srcRect; 19 | mConvertParams.dst_rect = destRect; 20 | } 21 | void exit() {} 22 | int convert(int inFd, int outFd) { 23 | return NvBufferTransform(inFd, outFd, &mConvertParams); 24 | } 25 | 26 | private: 27 | NvBufferTransformParams mConvertParams; 28 | }; 29 | 30 | #endif // !__VIC_CONVERTER_H__ 31 | 32 | -------------------------------------------------------------------------------- /cuda_utils/cudaMappedMemory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __CUDA_MAPPED_MEMORY_H_ 24 | #define __CUDA_MAPPED_MEMORY_H_ 25 | 26 | 27 | #include "cudaUtility.h" 28 | #include "imageFormat.h" 29 | #include "logging.h" 30 | 31 | 32 | /** 33 | * Allocate ZeroCopy mapped memory, shared between CUDA and CPU. 34 | * 35 | * @note although two pointers are returned, one for CPU and GPU, they both resolve to the same physical memory. 36 | * 37 | * @param[out] cpuPtr Returned CPU pointer to the shared memory. 38 | * @param[out] gpuPtr Returned GPU pointer to the shared memory. 39 | * @param[in] size Size (in bytes) of the shared memory to allocate. 40 | * 41 | * @returns `true` if the allocation succeeded, `false` otherwise. 42 | * @ingroup cudaMemory 43 | */ 44 | inline bool cudaAllocMapped( void** cpuPtr, void** gpuPtr, size_t size ) 45 | { 46 | if( !cpuPtr || !gpuPtr || size == 0 ) 47 | return false; 48 | 49 | //CUDA(cudaSetDeviceFlags(cudaDeviceMapHost)); 50 | 51 | if( CUDA_FAILED(cudaHostAlloc(cpuPtr, size, cudaHostAllocMapped)) ) 52 | return false; 53 | 54 | if( CUDA_FAILED(cudaHostGetDevicePointer(gpuPtr, *cpuPtr, 0)) ) 55 | return false; 56 | 57 | memset(*cpuPtr, 0, size); 58 | LogDebug(LOG_CUDA "cudaAllocMapped %zu bytes, CPU %p GPU %p\n", size, *cpuPtr, *gpuPtr); 59 | return true; 60 | } 61 | 62 | 63 | /** 64 | * Allocate ZeroCopy mapped memory, shared between CUDA and CPU. 65 | * 66 | * @note this overload of cudaAllocMapped returns one pointer, assumes that the 67 | * CPU and GPU addresses will match (as is the case with any recent CUDA version). 68 | * 69 | * @param[out] ptr Returned pointer to the shared CPU/GPU memory. 70 | * @param[in] size Size (in bytes) of the shared memory to allocate. 71 | * 72 | * @returns `true` if the allocation succeeded, `false` otherwise. 73 | * @ingroup cudaMemory 74 | */ 75 | inline bool cudaAllocMapped( void** ptr, size_t size ) 76 | { 77 | void* cpuPtr = NULL; 78 | void* gpuPtr = NULL; 79 | 80 | if( !ptr || size == 0 ) 81 | return false; 82 | 83 | if( !cudaAllocMapped(&cpuPtr, &gpuPtr, size) ) 84 | return false; 85 | 86 | if( cpuPtr != gpuPtr ) 87 | { 88 | LogError(LOG_CUDA "cudaAllocMapped() - addresses of CPU and GPU pointers don't match\n"); 89 | return false; 90 | } 91 | 92 | *ptr = gpuPtr; 93 | return true; 94 | } 95 | 96 | /** 97 | * Allocate ZeroCopy mapped memory, shared between CUDA and CPU. 98 | * 99 | * This overload is for allocating images from an imageFormat type 100 | * and the image dimensions. The overall size of the allocation 101 | * will be calculated with the imageFormatSize() function. 102 | * 103 | * @param[out] ptr Returned pointer to the shared CPU/GPU memory. 104 | * @param[in] width Width (in pixels) to allocate. 105 | * @param[in] height Height (in pixels) to allocate. 106 | * @param[in] format Format of the image. 107 | * 108 | * @returns `true` if the allocation succeeded, `false` otherwise. 109 | * @ingroup cudaMemory 110 | */ 111 | inline bool cudaAllocMapped( void** ptr, size_t width, size_t height, imageFormat format ) 112 | { 113 | return cudaAllocMapped(ptr, imageFormatSize(format, width, height)); 114 | } 115 | 116 | 117 | /** 118 | * Allocate ZeroCopy mapped memory, shared between CUDA and CPU. 119 | * 120 | * This overload is for allocating images from an imageFormat type 121 | * and the image dimensions. The overall size of the allocation 122 | * will be calculated with the imageFormatSize() function. 123 | * 124 | * @param[out] ptr Returned pointer to the shared CPU/GPU memory. 125 | * @param[in] dims `int2` vector where `width=dims.x` and `height=dims.y` 126 | * @param[in] format Format of the image. 127 | * 128 | * @returns `true` if the allocation succeeded, `false` otherwise. 129 | * @ingroup cudaMemory 130 | */ 131 | inline bool cudaAllocMapped( void** ptr, const int2& dims, imageFormat format ) 132 | { 133 | return cudaAllocMapped(ptr, imageFormatSize(format, dims.x, dims.y)); 134 | } 135 | 136 | 137 | /** 138 | * Allocate ZeroCopy mapped memory, shared between CUDA and CPU. 139 | * 140 | * This is a templated version for allocating images from vector types 141 | * like uchar3, uchar4, float3, float4, ect. The overall size of the 142 | * allocation will be calculated as `width * height * sizeof(T)`. 143 | * 144 | * @param[out] ptr Returned pointer to the shared CPU/GPU memory. 145 | * @param[in] width Width (in pixels) to allocate. 146 | * @param[in] height Height (in pixels) to allocate. 147 | * 148 | * @returns `true` if the allocation succeeded, `false` otherwise. 149 | * @ingroup cudaMemory 150 | */ 151 | template inline bool cudaAllocMapped( T** ptr, size_t width, size_t height ) 152 | { 153 | return cudaAllocMapped((void**)ptr, width * height * sizeof(T)); 154 | } 155 | 156 | 157 | /** 158 | * Allocate ZeroCopy mapped memory, shared between CUDA and CPU. 159 | * 160 | * This is a templated version for allocating images from vector types 161 | * like uchar3, uchar4, float3, float4, ect. The overall size of the 162 | * allocation will be calculated as `dims.x * dims.y * sizeof(T)`. 163 | * 164 | * @param[out] ptr Returned pointer to the shared CPU/GPU memory. 165 | * @param[in] dims `int2` vector where `width=dims.x` and `height=dims.y` 166 | * 167 | * @returns `true` if the allocation succeeded, `false` otherwise. 168 | * @ingroup cudaMemory 169 | */ 170 | template inline bool cudaAllocMapped( T** ptr, const int2& dims ) 171 | { 172 | return cudaAllocMapped((void**)ptr, dims.x * dims.y * sizeof(T)); 173 | } 174 | 175 | 176 | #endif 177 | -------------------------------------------------------------------------------- /cuda_utils/cudaUtility.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __CUDA_UTILITY_H_ 24 | #define __CUDA_UTILITY_H_ 25 | 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "logging.h" 34 | 35 | 36 | /** 37 | * Execute a CUDA call and print out any errors 38 | * @return the original cudaError_t result 39 | * @ingroup cudaError 40 | */ 41 | #define CUDA(x) cudaCheckError((x), #x, __FILE__, __LINE__) 42 | 43 | /** 44 | * Evaluates to true on success 45 | * @ingroup cudaError 46 | */ 47 | #define CUDA_SUCCESS(x) (CUDA(x) == cudaSuccess) 48 | 49 | /** 50 | * Evaluates to true on failure 51 | * @ingroup cudaError 52 | */ 53 | #define CUDA_FAILED(x) (CUDA(x) != cudaSuccess) 54 | 55 | /** 56 | * Return from the boolean function if CUDA call fails 57 | * @ingroup cudaError 58 | */ 59 | #define CUDA_VERIFY(x) if(CUDA_FAILED(x)) return false; 60 | 61 | /** 62 | * LOG_CUDA string. 63 | * @ingroup cudaError 64 | */ 65 | #define LOG_CUDA "[cuda] " 66 | 67 | /* 68 | * define this if you want all cuda calls to be printed 69 | * @ingroup cudaError 70 | */ 71 | //#define CUDA_TRACE 72 | 73 | 74 | 75 | /** 76 | * cudaCheckError 77 | * @ingroup cudaError 78 | */ 79 | inline cudaError_t cudaCheckError(cudaError_t retval, const char* txt, const char* file, int line ) 80 | { 81 | #if !defined(CUDA_TRACE) 82 | if( retval == cudaSuccess) 83 | return cudaSuccess; 84 | #endif 85 | 86 | //int activeDevice = -1; 87 | //cudaGetDevice(&activeDevice); 88 | 89 | //Log("[cuda] device %i - %s\n", activeDevice, txt); 90 | 91 | if( retval == cudaSuccess ) 92 | LogDebug(LOG_CUDA "%s\n", txt); 93 | else 94 | LogError(LOG_CUDA "%s\n", txt); 95 | 96 | if( retval != cudaSuccess ) 97 | { 98 | LogError(LOG_CUDA " %s (error %u) (hex 0x%02X)\n", cudaGetErrorString(retval), retval, retval); 99 | LogError(LOG_CUDA " %s:%i\n", file, line); 100 | } 101 | 102 | return retval; 103 | } 104 | 105 | 106 | /** 107 | * Check for non-NULL pointer before freeing it, and then set the pointer to NULL. 108 | * @ingroup cudaError 109 | */ 110 | #define CUDA_FREE(x) if(x != NULL) { cudaFree(x); x = NULL; } 111 | 112 | /** 113 | * Check for non-NULL pointer before freeing it, and then set the pointer to NULL. 114 | * @ingroup cudaError 115 | */ 116 | #define CUDA_FREE_HOST(x) if(x != NULL) { cudaFreeHost(x); x = NULL; } 117 | 118 | /** 119 | * Check for non-NULL pointer before deleting it, and then set the pointer to NULL. 120 | * @ingroup util 121 | */ 122 | #define SAFE_DELETE(x) if(x != NULL) { delete x; x = NULL; } 123 | 124 | 125 | /** 126 | * If a / b has a remainder, round up. This function is commonly using when launching 127 | * CUDA kernels, to compute a grid size inclusive of the entire dataset if it's dimensions 128 | * aren't evenly divisible by the block size. 129 | * 130 | * For example: 131 | * 132 | * const dim3 blockDim(8,8); 133 | * const dim3 gridDim(iDivUp(imgWidth,blockDim.x), iDivUp(imgHeight,blockDim.y)); 134 | * 135 | * Then inside the CUDA kernel, there is typically a check that thread index is in-bounds. 136 | * 137 | * Without the use of iDivUp(), if the data dimensions weren't evenly divisible by the 138 | * block size, parts of the data wouldn't be covered by the grid and not processed. 139 | * 140 | * @ingroup cuda 141 | */ 142 | inline __device__ __host__ int iDivUp( int a, int b ) { return (a % b != 0) ? (a / b + 1) : (a / b); } 143 | 144 | 145 | #endif 146 | 147 | -------------------------------------------------------------------------------- /image/imageFormat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __IMAGE_FORMAT_H_ 24 | #define __IMAGE_FORMAT_H_ 25 | 26 | 27 | // include vector types (float4, float3, uchar4, uchar3, ect.) 28 | #include "cudaUtility.h" 29 | 30 | 31 | /** 32 | * The imageFormat enum is used to identify the pixel format and colorspace 33 | * of an image. Supported data types are based on `uint8` and `float`, with 34 | * colorspaces including RGB/RGBA, BGR/BGRA, grayscale, YUV, and Bayer. 35 | * 36 | * There are also a variety of helper functions available that provide info about 37 | * each format at runtime - for example, the pixel bit depth (imageFormatDepth()) 38 | * the number of image channels (imageFormatChannels()), and computing the size of 39 | * an image from it's dimensions (@see imageFormatSize()). To convert between 40 | * image formats using the GPU, there is also the cudaConvertColor() function. 41 | * 42 | * In addition to the enums below, each format can also be identified by a string. 43 | * The string corresponding to each format is included in the documentation below. 44 | * These strings are more commonly used from Python, but can also be used from C++ 45 | * with the imageFormatFromStr() and imageFormatToStr() functions. 46 | * 47 | * @ingroup imageFormat 48 | */ 49 | enum imageFormat 50 | { 51 | // RGB 52 | IMAGE_RGB8=0, /**< uchar3 RGB8 (`'rgb8'`) */ 53 | IMAGE_RGBA8, /**< uchar4 RGBA8 (`'rgba8'`) */ 54 | IMAGE_RGB32F, /**< float3 RGB32F (`'rgb32f'`) */ 55 | IMAGE_RGBA32F, /**< float4 RGBA32F (`'rgba32f'`) */ 56 | 57 | // BGR 58 | IMAGE_BGR8, /**< uchar3 BGR8 (`'bgr8'`) */ 59 | IMAGE_BGRA8, /**< uchar4 BGRA8 (`'bgra8'`) */ 60 | IMAGE_BGR32F, /**< float3 BGR32F (`'bgr32f'`) */ 61 | IMAGE_BGRA32F, /**< float4 BGRA32F (`'bgra32f'`) */ 62 | 63 | // YUV 64 | IMAGE_YUYV, /**< YUV YUYV 4:2:2 packed (`'yuyv'`) */ 65 | IMAGE_YUY2=IMAGE_YUYV, /**< Duplicate of YUYV (`'yuy2'`) */ 66 | IMAGE_YVYU, /**< YUV YVYU 4:2:2 packed (`'yvyu'`) */ 67 | IMAGE_UYVY, /**< YUV UYVY 4:2:2 packed (`'uyvy'`) */ 68 | IMAGE_I420, /**< YUV I420 4:2:0 planar (`'i420'`) */ 69 | IMAGE_YV12, /**< YUV YV12 4:2:0 planar (`'yv12'`) */ 70 | IMAGE_NV12, /**< YUV NV12 4:2:0 planar (`'nv12'`) */ 71 | 72 | // Bayer 73 | IMAGE_BAYER_BGGR, /**< 8-bit Bayer BGGR (`'bayer-bggr'`) */ 74 | IMAGE_BAYER_GBRG, /**< 8-bit Bayer GBRG (`'bayer-gbrg'`) */ 75 | IMAGE_BAYER_GRBG, /**< 8-bit Bayer GRBG (`'bayer-grbg'`) */ 76 | IMAGE_BAYER_RGGB, /**< 8-bit Bayer RGGB (`'bayer-rggb'`) */ 77 | 78 | // grayscale 79 | IMAGE_GRAY8, /**< uint8 grayscale (`'gray8'`) */ 80 | IMAGE_GRAY32F, /**< float grayscale (`'gray32f'`) */ 81 | 82 | // extras 83 | IMAGE_COUNT, /**< The number of image formats */ 84 | IMAGE_UNKNOWN=999, /**< Unknown/undefined format */ 85 | IMAGE_DEFAULT=IMAGE_RGBA32F /**< Default format (IMAGE_RGBA32F) */ 86 | }; 87 | 88 | /** 89 | * The imageBaseType enum is used to identify the base data type of an 90 | * imageFormat - either uint8 or float. For example, the IMAGE_RGB8 91 | * format has a base type of uint8, while IMAGE_RGB32F is float. 92 | * 93 | * You can retrieve the base type of each format with imageFormatBaseType() 94 | * 95 | * @ingroup imageFormat 96 | */ 97 | enum imageBaseType 98 | { 99 | IMAGE_UINT8, 100 | IMAGE_FLOAT 101 | }; 102 | 103 | /** 104 | * Get the base type of an image format (uint8 or float). 105 | * @see imageBaseType 106 | * @ingroup imageFormat 107 | */ 108 | inline imageBaseType imageFormatBaseType( imageFormat format ); 109 | 110 | /** 111 | * Convert an imageFormat enum to a string. 112 | * @see imageFormat for the strings that correspond to each format. 113 | * @ingroup imageFormat 114 | */ 115 | inline const char* imageFormatToStr( imageFormat format ); 116 | 117 | /** 118 | * Parse an imageFormat enum from a string. 119 | * @see imageFormat for the strings that correspond to each format. 120 | * @returns the imageFormat, or IMAGE_UNKNOWN on an unrecognized string. 121 | * @ingroup imageFormat 122 | */ 123 | inline imageFormat imageFormatFromStr( const char* str ); 124 | 125 | /** 126 | * Get the number of image channels in each format. 127 | * For example, IMAGE_RGB8 has 3 channels, while IMAGE_RGBA8 has 4. 128 | * @ingroup imageFormat 129 | */ 130 | inline size_t imageFormatChannels( imageFormat format ); 131 | 132 | /** 133 | * Get the pixel bit depth (in bits, not bytes). 134 | * 135 | * The bit depth is the size in bits of each pixel in the image. For example, 136 | * IMAGE_RGB8 has a bit depth of 24. This function returns bits instead of bytes, 137 | * because some formats have a bit depth that's not evenly divisible by 8 (a byte). 138 | * YUV 4:2:0 formats like I420, YV12, and NV12 have a depth of 12 bits. 139 | * 140 | * If you are calculating the overall size of an image, it's recommended to use 141 | * the imageFormatSize() function instead. It will automatically convert to bytes. 142 | * 143 | * @ingroup imageFormat 144 | */ 145 | inline size_t imageFormatDepth( imageFormat format ); 146 | 147 | /** 148 | * Compute the size of an image (in bytes) 149 | * @ingroup imageFormat 150 | */ 151 | inline size_t imageFormatSize( imageFormat format, size_t width, size_t height ); 152 | 153 | /** 154 | * Check if an image format is one of the RGB/RGBA formats. 155 | * 156 | * @returns true if the imageFormat is a RGB/RGBA format 157 | * (IMAGE_RGB8, IMAGE_RGBA8, IMAGE_RGB32F, IMAGE_RGBA32F) 158 | * otherwise, returns false. 159 | * @ingroup imageFormat 160 | */ 161 | inline bool imageFormatIsRGB( imageFormat format ); 162 | 163 | /** 164 | * Check if an image format is one of the BGR/BGRA formats. 165 | * 166 | * @returns true if the imageFormat is a BGR/BGRA format 167 | * (IMAGE_BGR8, IMAGE_BGRA8, IMAGE_BGR32F, IMAGE_BGRA32F) 168 | * otherwise, returns false. 169 | * @ingroup imageFormat 170 | */ 171 | inline bool imageFormatIsBGR( imageFormat format ); 172 | 173 | /** 174 | * Check if an image format is one of the YUV formats. 175 | * 176 | * @returns true if the imageFormat is a YUV format 177 | * (IMAGE_YUYV, IMAGE_YVYU, IMAGE_UYVY, IMAGE_I420, IMAGE_YV12, IMAGE_NV12) 178 | * otherwise, returns false. 179 | * @ingroup imageFormat 180 | */ 181 | inline bool imageFormatIsYUV( imageFormat format ); 182 | 183 | /** 184 | * Check if an image format is one of the grayscale formats. 185 | * 186 | * @returns true if the imageFormat is grayscale (IMAGE_GRAY8, IMAGE_GRAY32) 187 | * otherwise, returns false. 188 | * @ingroup imageFormat 189 | */ 190 | inline bool imageFormatIsGray( imageFormat format ); 191 | 192 | /** 193 | * Check if an image format is one of the Bayer formats. 194 | * 195 | * @returns true if the imageFormat is a Bayer format 196 | * (IMAGE_BAYER_BGGR, IMAGE_BAYER_GBRG, IMAGE_BAYER_GRBG, IMAGE_BAYER_RGGB) 197 | * otherwise, returns false. 198 | * @ingroup imageFormat 199 | */ 200 | inline bool imageFormatIsBayer( imageFormat format ); 201 | 202 | 203 | ////////////////////////////////////////////////////////////////////////////////// 204 | /// @name Internal Type Templates 205 | /// @internal 206 | /// @ingroup imageFormat 207 | ////////////////////////////////////////////////////////////////////////////////// 208 | 209 | ///@{ 210 | 211 | // get the IMAGE_RGB* formats from uchar3/uchar4/float3/float4 212 | template inline imageFormat imageFormatFromType(); 213 | 214 | template<> inline imageFormat imageFormatFromType(); 215 | template<> inline imageFormat imageFormatFromType(); 216 | template<> inline imageFormat imageFormatFromType(); 217 | template<> inline imageFormat imageFormatFromType(); 218 | 219 | // templated version of base type / vector type 220 | template struct imageFormatType; 221 | 222 | template<> struct imageFormatType { typedef uint8_t Base; typedef uchar3 Vector; }; 223 | template<> struct imageFormatType { typedef uint8_t Base; typedef uchar4 Vector; }; 224 | 225 | template<> struct imageFormatType { typedef float Base; typedef float3 Vector; }; 226 | template<> struct imageFormatType { typedef float Base; typedef float4 Vector; }; 227 | 228 | ///@} 229 | 230 | // inline implementations 231 | #include "imageFormat.inl" 232 | 233 | 234 | #endif 235 | 236 | -------------------------------------------------------------------------------- /image/imageFormat.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __IMAGE_FORMAT_INLINE_H_ 24 | #define __IMAGE_FORMAT_INLINE_H_ 25 | 26 | #include 27 | #include 28 | 29 | 30 | // imageFormatToStr 31 | inline const char* imageFormatToStr( imageFormat format ) 32 | { 33 | switch(format) 34 | { 35 | case IMAGE_RGB8: return "rgb8"; 36 | case IMAGE_RGBA8: return "rgba8"; 37 | case IMAGE_RGB32F: return "rgb32f"; 38 | case IMAGE_RGBA32F: return "rgba32f"; 39 | case IMAGE_BGR8: return "bgr8"; 40 | case IMAGE_BGRA8: return "bgra8"; 41 | case IMAGE_BGR32F: return "bgr32f"; 42 | case IMAGE_BGRA32F: return "bgra32f"; 43 | case IMAGE_I420: return "i420"; 44 | case IMAGE_YV12: return "yv12"; 45 | case IMAGE_NV12: return "nv12"; 46 | case IMAGE_UYVY: return "uyvy"; 47 | case IMAGE_YUYV: return "yuyv"; 48 | case IMAGE_YVYU: return "yvyu"; 49 | case IMAGE_BAYER_BGGR: return "bayer-bggr"; 50 | case IMAGE_BAYER_GBRG: return "bayer-gbrg"; 51 | case IMAGE_BAYER_GRBG: return "bayer-grbg"; 52 | case IMAGE_BAYER_RGGB: return "bayer-rggb"; 53 | case IMAGE_GRAY8: return "gray8"; 54 | case IMAGE_GRAY32F: return "gray32f"; 55 | case IMAGE_UNKNOWN: return "unknown"; 56 | }; 57 | 58 | return "unknown"; 59 | } 60 | 61 | // imageFormatIsRGB 62 | inline bool imageFormatIsRGB( imageFormat format ) 63 | { 64 | //if( format == IMAGE_RGB8 || format == IMAGE_RGBA8 || format == IMAGE_RGB32F || format == IMAGE_RGBA32F ) 65 | // return true; 66 | if( format >= IMAGE_RGB8 && format <= IMAGE_RGBA32F ) 67 | return true; 68 | 69 | return false; 70 | } 71 | 72 | // imageFormatIsBGR 73 | inline bool imageFormatIsBGR( imageFormat format ) 74 | { 75 | if( format >= IMAGE_BGR8 && format <= IMAGE_BGRA32F ) 76 | return true; 77 | 78 | return false; 79 | } 80 | 81 | // imageFormatIsYUV 82 | inline bool imageFormatIsYUV( imageFormat format ) 83 | { 84 | if( format >= IMAGE_YUYV && format <= IMAGE_NV12 ) 85 | return true; 86 | 87 | return false; 88 | } 89 | 90 | // imageFormatIsGray 91 | inline bool imageFormatIsGray( imageFormat format ) 92 | { 93 | if( format == IMAGE_GRAY8 || format == IMAGE_GRAY32F ) 94 | return true; 95 | 96 | return false; 97 | } 98 | 99 | // imageFormatIsBayer 100 | inline bool imageFormatIsBayer( imageFormat format ) 101 | { 102 | //if( format == IMAGE_BAYER_BGGR || format == IMAGE_BAYER_GBRG || format == IMAGE_BAYER_GRBG || format == IMAGE_BAYER_RGGB ) 103 | // return true; 104 | if( format >= IMAGE_BAYER_BGGR && format <= IMAGE_BAYER_RGGB ) 105 | return true; 106 | 107 | return false; 108 | } 109 | 110 | // imageFormatFromStr 111 | inline imageFormat imageFormatFromStr( const char* str ) 112 | { 113 | if( !str ) 114 | return IMAGE_UNKNOWN; 115 | 116 | for( uint32_t n=0; n < IMAGE_COUNT; n++ ) 117 | { 118 | const imageFormat fmt = (imageFormat)n; 119 | 120 | if( strcasecmp(str, imageFormatToStr(fmt)) == 0 ) 121 | return fmt; 122 | } 123 | 124 | if( strcasecmp(str, "yuy2") == 0 ) 125 | return IMAGE_YUY2; 126 | else if( strcasecmp(str, "rgb32") == 0 ) 127 | return IMAGE_RGB32F; 128 | else if( strcasecmp(str, "rgba32") == 0 ) 129 | return IMAGE_RGBA32F; 130 | else if( strcasecmp(str, "grey8") == 0 ) 131 | return IMAGE_GRAY8; 132 | else if( strcasecmp(str, "grey32f") == 0 ) 133 | return IMAGE_GRAY32F; 134 | 135 | return IMAGE_UNKNOWN; 136 | } 137 | 138 | 139 | // imageFormatBaseType 140 | inline imageBaseType imageFormatBaseType( imageFormat format ) 141 | { 142 | switch(format) 143 | { 144 | case IMAGE_GRAY32F: 145 | case IMAGE_RGB32F: 146 | case IMAGE_BGR32F: 147 | case IMAGE_RGBA32F: 148 | case IMAGE_BGRA32F: return IMAGE_FLOAT; 149 | } 150 | 151 | return IMAGE_UINT8; 152 | } 153 | 154 | 155 | // imageFormatChannels 156 | inline size_t imageFormatChannels( imageFormat format ) 157 | { 158 | switch(format) 159 | { 160 | case IMAGE_RGB8: 161 | case IMAGE_RGB32F: 162 | case IMAGE_BGR8: 163 | case IMAGE_BGR32F: return 3; 164 | case IMAGE_RGBA8: 165 | case IMAGE_RGBA32F: 166 | case IMAGE_BGRA8: 167 | case IMAGE_BGRA32F: return 4; 168 | case IMAGE_GRAY8: 169 | case IMAGE_GRAY32F: return 1; 170 | case IMAGE_I420: 171 | case IMAGE_YV12: 172 | case IMAGE_NV12: 173 | case IMAGE_UYVY: 174 | case IMAGE_YUYV: 175 | case IMAGE_YVYU: return 3; 176 | case IMAGE_BAYER_BGGR: 177 | case IMAGE_BAYER_GBRG: 178 | case IMAGE_BAYER_GRBG: 179 | case IMAGE_BAYER_RGGB: return 1; 180 | } 181 | 182 | return 0; 183 | } 184 | 185 | 186 | // imageFormatDepth 187 | inline size_t imageFormatDepth( imageFormat format ) 188 | { 189 | switch(format) 190 | { 191 | case IMAGE_RGB8: 192 | case IMAGE_BGR8: return sizeof(uchar3) * 8; 193 | case IMAGE_RGBA8: 194 | case IMAGE_BGRA8: return sizeof(uchar4) * 8; 195 | case IMAGE_RGB32F: 196 | case IMAGE_BGR32F: return sizeof(float3) * 8; 197 | case IMAGE_RGBA32F: 198 | case IMAGE_BGRA32F: return sizeof(float4) * 8; 199 | case IMAGE_GRAY8: return sizeof(unsigned char) * 8; 200 | case IMAGE_GRAY32F: return sizeof(float) * 8; 201 | case IMAGE_I420: 202 | case IMAGE_YV12: 203 | case IMAGE_NV12: return 12; 204 | case IMAGE_UYVY: 205 | case IMAGE_YUYV: 206 | case IMAGE_YVYU: return 16; 207 | case IMAGE_BAYER_BGGR: 208 | case IMAGE_BAYER_GBRG: 209 | case IMAGE_BAYER_GRBG: 210 | case IMAGE_BAYER_RGGB: return sizeof(unsigned char) * 8; 211 | } 212 | 213 | return 0; 214 | } 215 | 216 | 217 | // imageFormatSize 218 | inline size_t imageFormatSize( imageFormat format, size_t width, size_t height ) 219 | { 220 | return (width * height * imageFormatDepth(format)) / 8; 221 | } 222 | 223 | 224 | /** 225 | * @ingroup image 226 | * @internal 227 | */ 228 | template struct __image_format_assert_false : std::false_type { }; 229 | 230 | 231 | // imageFormatFromType 232 | template inline imageFormat imageFormatFromType() 233 | { 234 | static_assert(__image_format_assert_false::value, "invalid image format type - supported types are uchar3, uchar4, float3, float4"); 235 | } 236 | 237 | template<> inline imageFormat imageFormatFromType() { return IMAGE_RGB8; } 238 | template<> inline imageFormat imageFormatFromType() { return IMAGE_RGBA8; } 239 | template<> inline imageFormat imageFormatFromType() { return IMAGE_RGB32F; } 240 | template<> inline imageFormat imageFormatFromType() { return IMAGE_RGBA32F; } 241 | 242 | 243 | #endif 244 | 245 | -------------------------------------------------------------------------------- /include/NvBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions, and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /** 30 | * @file 31 | * NVIDIA Multimedia API: Buffer API 32 | * 33 | * @b Description: This file declares the NvBuffer APIs. 34 | */ 35 | 36 | #ifndef __NV_BUFFER_H__ 37 | #define __NV_BUFFER_H__ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include "v4l2_nv_extensions.h" 44 | 45 | /** 46 | * 47 | * @defgroup l4t_mm_nvbuffer_group Buffer API 48 | * 49 | * The @c %NvBuffer API provides buffer functionality, including reference 50 | * count functionality and convenience methods. 51 | * @ingroup aa_framework_api_group 52 | * @{ 53 | */ 54 | 55 | /** 56 | * Specifies the maximum number of planes a buffer can contain. 57 | */ 58 | #define MAX_PLANES 3 59 | 60 | /** 61 | * @brief Class representing a buffer. 62 | * 63 | * The NvBuffer class is modeled on the basis of the @c v4l2_buffer 64 | * structure. The buffer has @c buf_type @c v4l2_buf_type, @c 65 | * memory_type @c v4l2_memory, and an index. It contains an 66 | * NvBufferPlane array similar to the array of @c v4l2_plane 67 | * structures in @c v4l2_buffer.m.planes. It also contains a 68 | * corresponding NvBufferPlaneFormat array that describes the 69 | * format of each of the planes. 70 | * 71 | * Even though @c %NvBuffer closely resembles v4l2 structures, it can 72 | * be easily used with other non-v4l2 components. @c %NvBuffer 73 | * contains data pointers, buffer length, file descriptor (FD) of 74 | * buffer planes, buffer format (height, width, stride, etc.), and 75 | * other members that are required by such components. 76 | * 77 | * This class also provides buffer reference count functionality. This 78 | * is useful when the same buffer is being used by multiple elements. 79 | * 80 | * In the case of a V4L2 MMAP, this class provides convenience methods 81 | * for mapping or unmapping the contents of the buffer to or from 82 | * memory, allocating or deallocating software memory depending on its 83 | * format. 84 | */ 85 | class NvBuffer 86 | { 87 | public: 88 | /** 89 | * Holds the buffer plane format. 90 | */ 91 | typedef struct 92 | { 93 | uint32_t width; /**< Holds the width of the plane in pixels. */ 94 | uint32_t height; /**< Holds the height of the plane in pixels. */ 95 | 96 | uint32_t bytesperpixel; /**< Holds the bytes used to represent one 97 | pixel in the plane. */ 98 | uint32_t stride; /**< Holds the stride of the plane in bytes. */ 99 | uint32_t sizeimage; /**< Holds the size of the plane in bytes. */ 100 | } NvBufferPlaneFormat; 101 | 102 | /** 103 | * Holds the buffer plane parameters. 104 | */ 105 | typedef struct 106 | { 107 | NvBufferPlaneFormat fmt; /**< Holds the format of the plane. */ 108 | 109 | unsigned char *data; /**< Holds a pointer to the plane memory. */ 110 | uint32_t bytesused; /**< Holds the number of valid bytes in the plane. */ 111 | 112 | int fd; /**< Holds the file descriptor (FD) of the plane of the 113 | exported buffer, in the case of V4L2 MMAP buffers. */ 114 | uint32_t mem_offset; /**< Holds the offset of the first valid byte 115 | from the data pointer. */ 116 | uint32_t length; /**< Holds the size of the buffer in bytes. */ 117 | } NvBufferPlane; 118 | 119 | /** 120 | * Creates a new NvBuffer object. 121 | * 122 | * This convenience method for V4L2 elements creates a new buffer 123 | * with the planes array memset to zero and the refcount 124 | * initialized to zero. 125 | * 126 | 127 | * @param[in] buf_type Type of buffer, enumerated as @c 128 | * v4l2_buf_type. 129 | * @param[in] memory_type @c %NvBuffer memory, enumerated as an 130 | * @c v4l2_memory enum. 131 | * @param[in] n_planes Number of planes in the buffer. 132 | * @param[in] fmt Specifies a pointer to the array of buffer plane formats. 133 | * Should contain at least @a n_planes elements. 134 | * @param[in] index Index of the buffer in the plane. 135 | */ 136 | NvBuffer(enum v4l2_buf_type buf_type, enum v4l2_memory memory_type, 137 | uint32_t n_planes, NvBufferPlaneFormat *fmt, uint32_t index); 138 | 139 | /** 140 | * Creates a new NvBuffer for raw pixel formats. 141 | * 142 | * This convenience method for V4L2 elements is an @c %NvBuffer 143 | * constructor for raw pixel formats only. It requires width, 144 | * height, and pixel format to be specified. 145 | * 146 | * The planes array is memset to zero and the refcount is 147 | * initialized to zero. 148 | * 149 | * @attention The memory must be allocated by the application 150 | * by calling NvBuffer::allocateMemory. 151 | * 152 | * @param[in] pixfmt Pixel format of the buffer. 153 | * @param[in] width Width of the buffer in pixels. 154 | * @param[in] height Height of the buffer in pixels. 155 | * @param[in] index Index/ID of the buffer. 156 | */ 157 | NvBuffer(uint32_t pixfmt, uint32_t width, uint32_t height, uint32_t index); 158 | 159 | /** 160 | * Creates a new NvBuffer object for non-raw pixel formats. 161 | * 162 | * This convenience method for V4L2 elements is an @c %NvBuffer 163 | * constructor for non raw pixel formats. It requires size of the 164 | * buffer to be supplied. 165 | * 166 | * The planes array is memset to zero and refcount initialized to 167 | * zero. 168 | * 169 | * @attention The memory needs to be allocated by the application 170 | * by calling NvBuffer::allocateMemory. 171 | * 172 | * @param[in] size Size of the buffer in bytes. 173 | * @param[in] index Index/ID of the buffer. 174 | */ 175 | NvBuffer(uint32_t size, uint32_t index); 176 | 177 | /** 178 | * Destroys an NvBuffer object. 179 | * 180 | * This method cleans up class instances, unmapping any mapped 181 | * planes. 182 | */ 183 | ~NvBuffer(); 184 | 185 | /** 186 | * Maps the contents of the buffer to memory. 187 | * 188 | * This method maps the file descriptor (FD) of the planes to 189 | * a data pointer of @c planes. (MMAP buffers only.) 190 | * 191 | * @return 0 on success, -1 otherwise. 192 | */ 193 | int map(); 194 | /** 195 | * Unmaps the contents of the buffer from memory. (MMAP buffers only.) 196 | * 197 | */ 198 | void unmap(); 199 | 200 | /** 201 | * Allocates software memory for the buffer. 202 | * 203 | * @warning This method works only for @c V4L2_MEMORY_USERPTR memory. 204 | * 205 | * This method allocates memory on the basis of the buffer format: 206 | * @a height, @a width, @a bytesperpixel, and @a sizeimage. 207 | * 208 | * @return 0 for success, -1 otherwise. 209 | */ 210 | int allocateMemory(); 211 | /** 212 | * Deallocates buffer memory. 213 | * 214 | * @warning This method works only for @c V4L2_MEMORY_USERPTR memory and if 215 | * the memory was previously allocated using NvBuffer::allocateMemory. 216 | */ 217 | void deallocateMemory(); 218 | 219 | /** 220 | * Increases the reference count of the buffer. 221 | * 222 | * This method is thread safe. 223 | * 224 | * @return Reference count of the buffer after the operation. 225 | */ 226 | int ref(); 227 | /** 228 | * Decreases the reference count of the buffer. 229 | * 230 | * This thread-safe method decreases the buffer reference count if the 231 | * buffer reference count is above 0. 232 | * 233 | * @return Reference count of the buffer after the operation. 234 | */ 235 | int unref(); 236 | 237 | const enum v4l2_buf_type buf_type; /**< Type of the buffer. */ 238 | const enum v4l2_memory memory_type; /**< Type of memory associated 239 | with the buffer. */ 240 | 241 | const uint32_t index; /**< Holds the buffer index. */ 242 | 243 | uint32_t n_planes; /**< Holds the number of planes in the buffer. */ 244 | NvBufferPlane planes[MAX_PLANES]; /**< Holds the data pointer, plane file 245 | descriptor (FD), plane format, etc. */ 246 | 247 | /** 248 | * Fills the NvBuffer::NvBufferPlaneFormat array. 249 | * 250 | * This convenience method populates the 251 | * @c %NvBuffer::NvBufferPlaneFormat array on the basis of @a width, 252 | * @a height and pixel format (@a raw_pixfmt). It also returns the number of planes 253 | * required for the pixel format in @a num_planes. 254 | * 255 | * 256 | * @param[out] num_planes The number of planes. Must not be NULL. 257 | * @param[in,out] planefmts Array of %NvBuffer::NvBufferPlaneFormat to 258 | * fill. Must be at least \a num_planes in length. For best 259 | * results, pass an array of length #MAX_PLANES. 260 | * @param[in] width Width of the buffer in pixels. 261 | * @param[in] height Height of the buffer in pixels. 262 | * @param[in] raw_pixfmt Raw V4L2 pixel formats. 263 | * @return 0 for success, -1 for an unsupported pixel format. 264 | */ 265 | static int fill_buffer_plane_format(uint32_t *num_planes, 266 | NvBuffer::NvBufferPlaneFormat *planefmts, 267 | uint32_t width, uint32_t height, uint32_t raw_pixfmt); 268 | private: 269 | uint32_t ref_count; /**< Holds the reference count of the buffer. */ 270 | pthread_mutex_t ref_lock; /**< Mutex to synchronize increment/ 271 | decrement operations of @c ref_count. */ 272 | 273 | bool mapped; /**< Indicates if the buffer is mapped to 274 | memory. */ 275 | bool allocated; /**< Indicates if the buffer is allocated 276 | memory. */ 277 | NvBuffer *shared_buffer; /**< If this is a DMABUF buffer, @c shared_buffer 278 | points to the MMAP @c NvBuffer whose FD was 279 | sent when this buffer was queued. */ 280 | 281 | /** 282 | * Disallows copy constructor. 283 | */ 284 | NvBuffer(const NvBuffer& that); 285 | /** 286 | * Disallows assignment. 287 | */ 288 | void operator=(NvBuffer const&); 289 | 290 | friend class NvV4l2ElementPlane; 291 | }; 292 | /** @} */ 293 | #endif 294 | -------------------------------------------------------------------------------- /include/NvElement.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /** 30 | * @file 31 | * NVIDIA Multimedia API: %NvElement Base Class 32 | * 33 | * @b This file declares the NvElement base class. 34 | */ 35 | 36 | #ifndef __NV_ELEMENT_H__ 37 | #define __NV_ELEMENT_H__ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "NvElementProfiler.h" 45 | 46 | /** 47 | * 48 | * @defgroup l4t_mm_nvelement_base_group NvElement Base Class 49 | * @ingroup l4t_mm_nvelement_group 50 | * 51 | * This class is the class from which both V4L2 and non-V4L2 52 | * components are derived. 53 | * 54 | * @{ 55 | */ 56 | /** 57 | * Every element has a unique name that can be used for identifying 58 | * the element in debug logs. 59 | * 60 | * @c %NvElement also provides other common functionality, such as keeping 61 | * track of errors. 62 | */ 63 | class NvElement 64 | { 65 | public: 66 | /** 67 | * Indicates whether the element encountered an error during its operation. 68 | * 69 | * @return 0 if no error was encountered, a non-zero value if an 70 | * error was encountered. 71 | */ 72 | virtual int isInError() 73 | { 74 | return is_in_error; 75 | } 76 | virtual ~NvElement() 77 | { 78 | } 79 | 80 | /** 81 | * Gets profiling data for the element. 82 | * 83 | * @return A constant reference to the element's profiling data. 84 | */ 85 | void getProfilingData(NvElementProfiler::NvElementProfilerData &data); 86 | 87 | /** 88 | * Prints profiling data for the element to an output stream. 89 | * 90 | * @param[in] out_stream Output stream of type std::ostream to print the 91 | * data to. It takes the default value std::cout if not specified. 92 | */ 93 | void printProfilingStats(std::ostream &out_stream = std::cout); 94 | 95 | /** 96 | * Enables profiling for the element. 97 | */ 98 | virtual void enableProfiling(); 99 | 100 | /** 101 | * Checks whether profiling is enabled for the element. 102 | * 103 | * @return Boolean value indicating if profiling is enabled. 104 | */ 105 | bool isProfilingEnabled(); 106 | 107 | protected: 108 | 109 | /** 110 | * Creates a new NvElement object with name @a name. 111 | * 112 | * If the @a name parameter is NULL, this method sets the internal 113 | * error variable. 114 | * 115 | * @param[in] name If non-NULL, a pointer to the name of the 116 | * element. 117 | */ 118 | NvElement(const char *name, NvElementProfiler::ProfilerField = NvElementProfiler::PROFILER_FIELD_NONE); 119 | 120 | int is_in_error; /**< Indicates if an error was encountered during 121 | the operation of the element. */ 122 | const char *comp_name; /**< Specifies the name of the component, 123 | for debugging. */ 124 | NvElementProfiler profiler; /**< Profiler for the element. */ 125 | 126 | /** 127 | * Disallows copy constructor. 128 | */ 129 | NvElement(const NvElement& that); 130 | /** 131 | * Disallows assignment. 132 | */ 133 | void operator=(NvElement const&); 134 | 135 | }; 136 | /** @} */ 137 | #endif 138 | -------------------------------------------------------------------------------- /include/NvElementProfiler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef __NV_ELEMENT_PROFILER_H__ 30 | #define __NV_ELEMENT_PROFILER_H__ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | /** 39 | * @file 40 | * NVIDIA Multimedia API: Element Profiler API 41 | * 42 | * @b Description: This file profiles the performance of individual elements. 43 | */ 44 | 45 | 46 | /** 47 | * 48 | * Helper class for profiling the performance of individual elements. 49 | * 50 | * NvElementProfiler currently measures processing latencies, average processing rate, and 51 | * the number of units that arrived late at the element. Components should use this 52 | * information internally. 53 | * 54 | * If you require latency measurements, 55 | * you must call startProcessing() to indicate that a unit has been submitted 56 | * for processing and finishProcessing() to indicate that a unit has finished processing. 57 | * If you require only averaging processing rate or the number of units that 58 | * arrived late need not call startProcessing(). 59 | * 60 | * You can get data from NvElementProfiler using getProfilerData(). This function 61 | * fills the [NvElementProfilerData](@ref NvElementProfiler::NvElementProfilerData) 62 | * structure. Components that do not support all 63 | * the fields available in the structure must use the variable 64 | * [valid_fields](@ref NvElementProfiler::NvElementProfilerData::valid_fields) of 65 | * type [ProfilerField](@ref NvElementProfiler::ProfilerField), which is also 66 | * included in the structure. 67 | * 68 | * @defgroup l4t_mm_nvelementprofiler_group Element Profiler API 69 | * @ingroup aa_framework_api_group 70 | * @{ 71 | */ 72 | class NvElementProfiler { 73 | public: 74 | /** 75 | * @defgroup Defines @c valid_field values for the #NvElementProfilerData structure. 76 | * @ingroup l4t_mm_nvelementprofiler_group 77 | * @{ 78 | */ 79 | typedef int ProfilerField; 80 | static const ProfilerField PROFILER_FIELD_NONE = 0; 81 | static const ProfilerField PROFILER_FIELD_TOTAL_UNITS = 1; 82 | static const ProfilerField PROFILER_FIELD_LATE_UNITS = 2; 83 | static const ProfilerField PROFILER_FIELD_LATENCIES = 4; 84 | static const ProfilerField PROFILER_FIELD_FPS = 8; 85 | static const ProfilerField PROFILER_FIELD_ALL = (PROFILER_FIELD_FPS << 1) - 1; 86 | /** @} */ 87 | 88 | /** 89 | * Holds profiling data for the element. 90 | * 91 | * Some elements may not support all the fields in the structure. User must check 92 | * the @a valid_fields flag to determine which fields are valid. 93 | */ 94 | typedef struct { 95 | /** Valid Fields which are supported by the element. */ 96 | ProfilerField valid_fields; 97 | 98 | /** Average latency of all processed units, in microseconds. */ 99 | uint64_t average_latency_usec; 100 | /** Minimum of latencies for each processed units, in microseconds. */ 101 | uint64_t min_latency_usec; 102 | /** Maximum of latencies for each processed units, in microseconds. */ 103 | uint64_t max_latency_usec; 104 | 105 | /** Total units processed. */ 106 | uint64_t total_processed_units; 107 | /** Number of units which arrived late at the element. */ 108 | uint64_t num_late_units; 109 | 110 | /** Average rate at which the units were processed. */ 111 | float average_fps; 112 | 113 | /** Total profiling time. */ 114 | struct timeval profiling_time; 115 | } NvElementProfilerData; 116 | 117 | /** 118 | * Gets the profiling data for the element. 119 | * 120 | * @param[out] data Reference to the NvElementProfilerData structure which should be filled. 121 | */ 122 | void getProfilerData(NvElementProfilerData &data); 123 | 124 | /** 125 | * Prints the element's profiling data to an output stream. 126 | * 127 | * @param[in] out_stream Reference to a std::ostream. 128 | */ 129 | void printProfilerData(std::ostream &out_stream = std::cout); 130 | 131 | /** 132 | * Informs the profiler that processing has started. 133 | * 134 | * Has no effect if profiler is disabled. 135 | * 136 | * @return ID of the unit, to be supplied with finishProcessing();. 137 | */ 138 | uint64_t startProcessing(); 139 | 140 | /** 141 | * Informs the profiler that processing has finished. 142 | * 143 | * Has no effect if profiler is disabled. 144 | * 145 | * @param[in] id ID of the unit whose processing is finished, 146 | * 0 if the first unit in the profiler's queue should be picked. 147 | * @param[in] is_late Should be true if the frame arrived late at the element. 148 | */ 149 | void finishProcessing(uint64_t id, bool is_late); 150 | 151 | /** 152 | * Enables the profiler. 153 | * 154 | * startProcessing() and finishProcessing() are ineffective until the profiler is enabled. 155 | * 156 | * @param[in] reset_data Reset the profiled data. 157 | */ 158 | void enableProfiling(bool reset_data); 159 | 160 | /** 161 | * Disables the profiler. 162 | */ 163 | void disableProfiling(); 164 | private: 165 | /** 166 | * Resets the profiler data. 167 | */ 168 | void reset(); 169 | 170 | pthread_mutex_t profiler_lock; /**< Mutex to synchronize multithreaded access to profiler data. */ 171 | 172 | bool enabled; /**< Flag indicating if profiler is enabled. */ 173 | 174 | const ProfilerField valid_fields; /**< Valid fields for the element. */ 175 | 176 | struct NvElementProfilerDataInternal : NvElementProfilerData { 177 | /** Wall-clock time at which the first unit was processed. */ 178 | struct timeval start_time; 179 | 180 | /** Wall-clock time at which the latest unit was processed. */ 181 | struct timeval stop_time; 182 | 183 | /** Total accumulated time. 184 | * When performance measurement is restarted @a start_time and @a stop_time 185 | * are reset. This field is used to accumulate time before 186 | * resetting. */ 187 | struct timeval accumulated_time; 188 | 189 | /** Total accumulated latency for all units, in microseconds. */ 190 | uint64_t total_latency; 191 | } data_int; 192 | 193 | /** Queue used to maintain the timestamps of when the unit 194 | * processing started. Required to calculate latency. */ 195 | std::map unit_start_time_queue; 196 | 197 | uint64_t unit_id_counter; /**< Unique ID of the last unit. */ 198 | 199 | /** 200 | * Constructor for NvElementProfiler. 201 | * 202 | * Initializes internal data structures. The profiler is disabled by default. 203 | * @param fields 204 | */ 205 | NvElementProfiler(ProfilerField fields); 206 | 207 | /** 208 | * Disallow copy constructor. 209 | */ 210 | NvElementProfiler(const NvElementProfiler& that); 211 | /** 212 | * Disallow assignment. 213 | */ 214 | void operator=(NvElementProfiler const&); 215 | 216 | ~NvElementProfiler(); 217 | 218 | friend class NvElement; 219 | }; 220 | 221 | /** @} */ 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /include/NvLogging.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /** 30 | * @file 31 | * NVIDIA Multimedia API: Logging API 32 | * 33 | * @brief Description: This file defines macros for logging messages. 34 | */ 35 | 36 | #ifndef __NV_LOGGING_H_ 37 | #define __NV_LOGGING_H_ 38 | 39 | #include 40 | #include 41 | 42 | /** 43 | * 44 | * @defgroup l4t_mm_nvlogging_group Logging API 45 | * 46 | * This file defines macros that provide message logging 47 | * functionality. 48 | * 49 | * @ingroup aa_framework_api_group 50 | * @{ 51 | */ 52 | 53 | 54 | /** 55 | * Specifies the log level for Information messages. 56 | */ 57 | #define LOG_LEVEL_INFO 0 58 | /** 59 | * Specifies the log level for Error messages. 60 | */ 61 | #define LOG_LEVEL_ERROR 1 62 | /** 63 | * Specifies the log level for Warning messages. 64 | */ 65 | #define LOG_LEVEL_WARN 2 66 | /** 67 | * Specifies the log level for Debug messages. 68 | */ 69 | #define LOG_LEVEL_DEBUG 3 70 | 71 | /** 72 | * Holds the current log level at runtime by assignment of one of the 73 | * @c LOG_LEVEL_* values. 74 | */ 75 | extern int log_level; 76 | 77 | /** 78 | * Specifies the default log level. 79 | */ 80 | #define DEFAULT_LOG_LEVEL LOG_LEVEL_ERROR 81 | 82 | /** 83 | * @cond 84 | */ 85 | #define stringify(s) #s 86 | #define xstringify(s) stringify(s) 87 | #define __LINE_NUM_STR__ xstringify(__LINE__) 88 | 89 | extern const char *log_level_name[]; 90 | /** 91 | * @endcond 92 | */ 93 | 94 | /** 95 | * 96 | * Prints log messages. 97 | * 98 | * Prints a log message only if the current log_level is greater 99 | * than or equal to the level of the message. 100 | * 101 | * Messages are in the following form: 102 | * [LEVEL] (FILE: LINE_NUM) Message 103 | * 104 | * @param[in] level The Log level of the message. 105 | * @param[in] str1 The NULL-terminated char array to print. 106 | */ 107 | #define PRINT_MSG(level, str1) if(level <= log_level) { \ 108 | std::ostringstream ostr; \ 109 | ostr << "[" << log_level_name[level] << "] (" << \ 110 | __FILE__ << ":" __LINE_NUM_STR__ ") " << \ 111 | str1 << std::endl; \ 112 | std::cerr << ostr.str(); \ 113 | } 114 | 115 | /** 116 | * Prints a log message of level LOG_LEVEL_INFO. 117 | */ 118 | #define INFO_MSG(str) PRINT_MSG(LOG_LEVEL_INFO, str) 119 | /** 120 | * Prints a component-specific log message of level LOG_LEVEL_INFO. 121 | * This is used by the components internally and should not be used by 122 | * the application. 123 | * 124 | * Messages are in the following form: 125 | * [LEVEL] (FILE: LINE_NUM) 126 | */ 127 | #define COMP_INFO_MSG(str) INFO_MSG("<" << comp_name << "> " << str) 128 | /** 129 | * Prints a category-specific (Component type) system error log 130 | * message of level LOG_LEVEL_INFO. This is used by the components 131 | * internally and should not be used by the application. 132 | * 133 | * Messages are in the following form: 134 | * [LEVEL] (FILE: LINE_NUM) 135 | */ 136 | #define CAT_INFO_MSG(str) INFO_MSG("<" CAT_NAME "> " << str) 137 | 138 | /** 139 | * Prints a log message of level LOG_LEVEL_ERROR. 140 | */ 141 | #define ERROR_MSG(str) PRINT_MSG(LOG_LEVEL_ERROR, str) 142 | /** 143 | * Prints a component-specific log message of level 144 | * LOG_LEVEL_ERROR. This is used by the components internally 145 | * and should not be used by the application. 146 | * 147 | * Messages are in the following form: 148 | * [LEVEL] (FILE:LINE_NUM) 149 | */ 150 | #define COMP_ERROR_MSG(str) ERROR_MSG("<" << comp_name << "> " << str) 151 | /** 152 | * Prints a category-specific (Component type) log message of level 153 | * LOG_LEVEL_ERROR. This is used by the components internally and 154 | * should not be used by the application. 155 | * 156 | * Messages are in the following form: 157 | * [LEVEL] (FILE:LINE_NUM) 158 | */ 159 | #define CAT_ERROR_MSG(str) ERROR_MSG("<" CAT_NAME "> " << str) 160 | 161 | /** 162 | * Prints a system error log message of level LOG_LEVEL_ERROR with 163 | * the string description of the errno value appended. 164 | */ 165 | #define SYS_ERROR_MSG(str) ERROR_MSG(str << ": " << strerror(errno)) 166 | /** 167 | * Prints a component-specific system error log message of level 168 | * LOG_LEVEL_ERROR. This is used by the components internally and 169 | * should not be used by the application. 170 | * 171 | * Messages are in the following form: 172 | * [LEVEL] (FILE:LINE_NUM) 173 | */ 174 | #define COMP_SYS_ERROR_MSG(str) SYS_ERROR_MSG("<" << comp_name << "> " << str) 175 | /** 176 | * Prints a category-specific (Component type) system error log 177 | * message of level LOG_LEVEL_ERROR. This is used by the components 178 | * internally and should not be used by the application. 179 | * 180 | * Messages are in the following form: 181 | * [LEVEL] (FILE:LINE_NUM) 182 | */ 183 | #define CAT_SYS_ERROR_MSG(str) SYS_ERROR_MSG("<" CAT_NAME "> " << str) 184 | 185 | /** 186 | * Prints a log message of level LOG_LEVEL_WARN. 187 | */ 188 | #define WARN_MSG(str) PRINT_MSG(LOG_LEVEL_WARN, str) 189 | /** 190 | * Prints a component-specific log message of level LOG_LEVEL_WARN. 191 | * This is used by the components internally and should not be used by 192 | * the application. 193 | * 194 | * Messages are in the following form: 195 | * [LEVEL] (FILE:LINE_NUM) 196 | */ 197 | #define COMP_WARN_MSG(str) WARN_MSG("<" << comp_name << "> :" << str) 198 | /** 199 | * Print a category-specific (Component type) log message of level 200 | * LOG_LEVEL_WARN. 201 | * This is used by the components internally and should not be used by the 202 | * application. 203 | * 204 | * Messages are in the following form: 205 | * [LEVEL] (FILE:LINE_NUM) 206 | */ 207 | #define CAT_WARN_MSG(str) WARN_MSG("<" CAT_NAME "> " << str) 208 | 209 | /** 210 | * Prints a log message of level LOG_LEVEL_DEBUG. 211 | */ 212 | #define DEBUG_MSG(str) PRINT_MSG(LOG_LEVEL_DEBUG, str) 213 | /** 214 | * Prints a component-specific log message of level LOG_LEVEL_DEBUG. 215 | * This is used by the components internally and should not be used by the 216 | * application. 217 | * 218 | * Messages are in the following form: 219 | * [LEVEL] (FILE:LINE_NUM) 220 | */ 221 | #define COMP_DEBUG_MSG(str) DEBUG_MSG("<" << comp_name << "> :" << str) 222 | /** 223 | * Prints a category-specific (Component type) log message of level 224 | * LOG_LEVEL_DEBUG. This is used by the components internally and 225 | * should not be used by the application. 226 | * 227 | * Messages are in the following form: 228 | * [LEVEL] (FILE:LINE_NUM) 229 | */ 230 | #define CAT_DEBUG_MSG(str) DEBUG_MSG("<" CAT_NAME "> " << str) 231 | 232 | #endif 233 | /** @} */ 234 | -------------------------------------------------------------------------------- /include/NvV4l2Element.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /** 30 | * @file 31 | * NVIDIA Multimedia API: V4L2 Helper Class 32 | * 33 | * @b Description: This file declares a helper class for V4L2-based components. 34 | */ 35 | 36 | /** 37 | * @defgroup l4t_mm_nvv4l2element_group V4L2 Element Class 38 | * @ingroup l4t_mm_nvelement_group 39 | * 40 | * Helper class that provides common functionality for V4L2-based components, 41 | * such as encoder and decoder. Objects instantiated from this class create 42 | * new V4L2 elements, subscribes to V4L2 events, dequeues an event from 43 | * an element, and sets/gets control values. 44 | * @{ 45 | */ 46 | #ifndef __NV_V4L2_ELEMENT_H__ 47 | #define __NV_V4L2_ELEMENT_H__ 48 | 49 | #include "NvElement.h" 50 | #include "NvV4l2ElementPlane.h" 51 | 52 | #include "v4l2_nv_extensions.h" 53 | 54 | /** 55 | * Defines a helper class for V4L2 based components. 56 | * 57 | * This derived class provides common functionality for V4L2 components. V4L2-based 58 | * components such as encoder/decoder extend from this class. 59 | * 60 | * This class is modeled on V4L2 M2M devices. It includes the file descriptor (FD) of the device 61 | * opened using %v4l2_open, two planes (NvV4l2ElementPlane), output plane, 62 | * capture plane, and other helper methods, such as setting/getting controls, 63 | * subscribing/dequeueing events, etc. 64 | */ 65 | class NvV4l2Element:public NvElement 66 | { 67 | public: 68 | virtual ~NvV4l2Element(); 69 | 70 | /** 71 | * Subscribes to an V4L2 event. 72 | * 73 | * Calls \c VIDIOC_SUBSCRIBE_EVENT IOCTL internally. 74 | * 75 | * @param[in] type Type of the event. 76 | * @param[in] id ID of the event source. 77 | * @param[in] flags Event flags. 78 | * @return 0 for success, -1 otherwise. 79 | */ 80 | int subscribeEvent(uint32_t type, uint32_t id, uint32_t flags); 81 | /** 82 | * Dequeues an event from the element. 83 | * 84 | * Calls \c VIDIOC_DQEVENT IOCTL internally. The caller can specify the maximum time 85 | * to wait for dequeuing the event. The call blocks until an event is 86 | * dequeued successfully or timeout is reached. 87 | * 88 | * @param[in,out] event A reference to the \c v4l2_event structure to fill. 89 | * @param[in] max_wait_ms Specifies the max wait time for dequeuing an event, 90 | * in milliseconds. 91 | * @return 0 for success, -1 otherwise. 92 | */ 93 | int dqEvent(struct v4l2_event &event, uint32_t max_wait_ms); 94 | 95 | /** 96 | * Sets the value of a control. 97 | * 98 | * Calls \c VIDIOC_S_CTRL IOCTL internally. 99 | * 100 | * @param[in] id ID of the control to be set. 101 | * @param[in] value Value to be set on the control. 102 | * @return 0 for success, -1 otherwise. 103 | */ 104 | int setControl(uint32_t id, int32_t value); 105 | /** 106 | * Gets the value of a control. 107 | * 108 | * Calls \c VIDIOC_G_CTRL IOCTL internally. 109 | * 110 | * @param[in] id ID of the control to get. 111 | * @param[out] value A reference to the variable into which the control value 112 | is read. 113 | * @return 0 for success, -1 otherwise. 114 | */ 115 | int getControl(uint32_t id, int32_t &value); 116 | 117 | /** 118 | * Sets the value of several controls. 119 | * 120 | * Calls \c VIDIOC_S_EXT_CTRLS IOCTL internally. 121 | * 122 | * @param[in] ctl A pointer to the controls to set. 123 | * @return 0 for success, -1 otherwise. 124 | */ 125 | int setExtControls(struct v4l2_ext_controls &ctl); 126 | /** 127 | * Gets the value of several controls. 128 | * 129 | * Calls \c VIDIOC_G_EXT_CTRLS IOCTL internally. 130 | * 131 | * @param[in,out] ctl A pointer to the controls to get. 132 | * @return 0 for success, -1 otherwise. 133 | */ 134 | int getExtControls(struct v4l2_ext_controls &ctl); 135 | 136 | virtual int isInError(); 137 | 138 | /** 139 | * Sets the output plane. 140 | */ 141 | NvV4l2ElementPlane output_plane; /**< Output plane of the element */ 142 | /** 143 | * Sets the capture plane. 144 | */ 145 | NvV4l2ElementPlane capture_plane; /**< Capture plane of the element */ 146 | 147 | /** 148 | * 149 | * Terminates processing of queued buffers immediately. All the buffers are 150 | * returned to the application. 151 | * 152 | * Calls VIDIOC_STREAMOFF IOCTL on both of the planes internally. 153 | * 154 | * @return 0 for success, -1 otherwise. 155 | */ 156 | int abort(); 157 | 158 | /** 159 | * Waits until the element processes all the output plane buffers. 160 | * 161 | * Objects extending @c V4l2Element must implement this because the idle 162 | * condition is component-specific. 163 | * 164 | * @param[in] max_wait_ms Max time to wait in milliseconds. 165 | * @return 0 for success, -1 otherwise. 166 | */ 167 | virtual int waitForIdle(uint32_t max_wait_ms); 168 | 169 | void *app_data; /**< A pointer to the application-specific data. */ 170 | 171 | /** 172 | * Enables profiling for the V4l2Element. 173 | * 174 | * Must be called before setting either plane formats. 175 | */ 176 | void enableProfiling(); 177 | 178 | protected: 179 | int fd; /**< Specifies the FD of the device opened using \c v4l2_open. */ 180 | 181 | uint32_t output_plane_pixfmt; /**< Pixel format of output plane buffers */ 182 | uint32_t capture_plane_pixfmt; /**< Pixel format of capture plane buffers */ 183 | 184 | /** 185 | * Creates a new V4l2Element named \a name. 186 | * 187 | * This constructor calls v4l2_open on the \a dev_node. It sets an error if 188 | * v4l2_open fails. 189 | * 190 | * This function also checks if the device supports V4L2_CAP_VIDEO_M2M_MPLANE 191 | * capability. 192 | * 193 | * @param[in] comp_name A pointer to the unique name to identity the element instance. 194 | * @param[in] dev_node A pointer to /dev/ * node of the device. 195 | * @param[in] flags Flags with which to open the device. 196 | * @param[in] fields Profiler fields that are valid for the element. 197 | */ 198 | NvV4l2Element(const char *comp_name, const char *dev_node, int flags, NvElementProfiler::ProfilerField fields); 199 | }; 200 | /** @} */ 201 | #endif 202 | -------------------------------------------------------------------------------- /include/NvVideoConverter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /** 30 | * @file 31 | * NVIDIA Multimedia API: Video Converter 32 | * 33 | * @b Description: This file declares a helper class for V4L2 Video Converter. 34 | */ 35 | 36 | /** 37 | * @defgroup l4t_mm_nvvideoconverter_group Video Converter 38 | * @ingroup l4t_mm_nvvideo_group 39 | * 40 | * Helper class that creates new V4L2 41 | * video converters, and it sets converter capture and output plane 42 | * formats. 43 | * @{ 44 | */ 45 | 46 | #ifndef __NV_VIDEO_CONVERTER_H__ 47 | #define __NV_VIDEO_CONVERTER_H__ 48 | 49 | #include "NvV4l2Element.h" 50 | 51 | /** 52 | * @brief Defines a helper class for V4L2 Video Converter. 53 | * 54 | * Use video converter for color space conversion, scaling, and 55 | * conversion between hardware buffer memory (V4L2_MEMORY_MMAP/ 56 | * V4L2_MEMORY_DMABUF) and software buffer memory (\c V4L2_MEMORY_USERPTR). 57 | * 58 | * The video converter device node is \c "/dev/nvhost-vic". The category name 59 | * for the converter is \c "NVVIDCONV". 60 | * 61 | * Refer to [V4L2 Video Converter](group__V4L2Conv.html) for more information on the converter. 62 | */ 63 | 64 | class NvVideoConverter:public NvV4l2Element 65 | { 66 | public: 67 | 68 | /** 69 | * Creates a new V4L2 Video Converter object named \a name. 70 | * 71 | * This method internally calls \c v4l2_open on the converter dev node 72 | * \c "/dev/nvhost-vic" and checks for \c V4L2_CAP_VIDEO_M2M_MPLANE 73 | * capability on the device. This method allows the caller to specify 74 | * additional flags with which the device should be opened. 75 | * 76 | * The device is opened in blocking mode, which can be modified by passing 77 | * the O_NONBLOCK flag to this method. 78 | * 79 | * @returns Reference to the newly created converter object, else \a NULL in 80 | * case of failure during initialization. 81 | */ 82 | static NvVideoConverter *createVideoConverter(const char *name, int flags = 0); 83 | 84 | ~NvVideoConverter(); 85 | /** 86 | * Sets the format on the converter output plane. 87 | * 88 | * Calls \c VIDIOC_S_FMT IOCTL internally on the capture plane. 89 | * 90 | * @param[in] pixfmt One of the raw V4L2 pixel formats. 91 | * @param[in] width Width of the output buffers in pixels. 92 | * @param[in] height Height of the output buffers in pixels. 93 | * @param[in] type Layout of the buffers in plane, one of 94 | * enum v4l2_nv_buffer_layout. 95 | * @return 0 for success, -1 otherwise. 96 | */ 97 | int setCapturePlaneFormat(uint32_t pixfmt, uint32_t width, uint32_t height, 98 | enum v4l2_nv_buffer_layout type); 99 | /** 100 | * Sets the format on the converter output plane. 101 | * 102 | * Calls \c VIDIOC_S_FMT IOCTL internally on the output plane. 103 | * 104 | * @param[in] pixfmt One of the raw V4L2 pixel formats. 105 | * @param[in] width Width of the output buffers in pixels. 106 | * @param[in] height Height of the output buffers in pixels. 107 | * @param[in] type Layout of the buffers in plane, one of 108 | * enum v4l2_nv_buffer_layout. 109 | * @return 0 for success, -1 otherwise. 110 | */ 111 | int setOutputPlaneFormat(uint32_t pixfmt, uint32_t width, uint32_t height, 112 | enum v4l2_nv_buffer_layout type); 113 | 114 | /** 115 | * Sets the buffer layout of the output plane buffers. 116 | * 117 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with control ID 118 | * #V4L2_CID_VIDEO_CONVERT_OUTPUT_PLANE_LAYOUT. Must be called before 119 | * setFormat() on any of the planes. 120 | * 121 | * @param[in] type Type of layout, one of enum v4l2_nv_buffer_layout. 122 | * 123 | * @return 0 for success, -1 otherwise. 124 | */ 125 | int setOutputPlaneBufferLayout(enum v4l2_nv_buffer_layout type); 126 | 127 | /** 128 | * Sets the buffer layout of the capture plane buffers. 129 | * 130 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 131 | * #V4L2_CID_VIDEO_CONVERT_CAPTURE_PLANE_LAYOUT. Must be called before 132 | * setFormat() on any of the planes. 133 | * 134 | * @param[in] type Type of layout, one of enum v4l2_nv_buffer_layout. 135 | * 136 | * @return 0 for success, -1 otherwise. 137 | */ 138 | int setCapturePlaneBufferLayout(enum v4l2_nv_buffer_layout type); 139 | 140 | /** 141 | * Sets the interpolation(filter) method used for scaling. 142 | * 143 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 144 | * #V4L2_CID_VIDEO_CONVERT_INTERPOLATION_METHOD. Must be called before 145 | * setFormat() on any of the planes. 146 | * 147 | * @param[in] method Type of interpolation method, one of enum 148 | * v4l2_interpolation_method. 149 | * 150 | * @return 0 for success, -1 otherwise. 151 | */ 152 | int setInterpolationMethod(enum v4l2_interpolation_method method); 153 | 154 | /** 155 | * Sets the flip method. 156 | * 157 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 158 | * #V4L2_CID_VIDEO_CONVERT_FLIP_METHOD. Must be called before 159 | * setFormat() on any of the planes. 160 | * 161 | * @param[in] method Type of flip method, one of enum v4l2_flip_method. 162 | * 163 | * @return 0 for success, -1 otherwise. 164 | */ 165 | int setFlipMethod(enum v4l2_flip_method method); 166 | 167 | /** 168 | * Sets the TNR(Temporal Noise Reduction) algorithm to use. 169 | * 170 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 171 | * #V4L2_CID_VIDEO_CONVERT_TNR_ALGORITHM. Must be called before 172 | * setForma() on any of the planes. 173 | * 174 | * @param[in] algorithm Type of TNR algorithm to use, one of enum 175 | * v4l2_tnr_algorithm. 176 | * 177 | * @return 0 for success, -1 otherwise. 178 | */ 179 | int setTnrAlgorithm(enum v4l2_tnr_algorithm algorithm); 180 | 181 | /** 182 | * Sets the YUV Rescale method to use. 183 | * 184 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 185 | * #V4L2_CID_VIDEO_CONVERT_YUV_RESCALE_METHOD. Must be called before 186 | * setFormat() on any of the planes. 187 | * 188 | * @param[in] method Type of YUV Rescale method to use, one of enum 189 | * v4l2_yuv_rescale_method. 190 | * 191 | * @return 0 for success, -1 otherwise. 192 | */ 193 | int setYUVRescale(enum v4l2_yuv_rescale_method method); 194 | 195 | /** 196 | * Set the cropping rectangle for the converter 197 | * 198 | * Calls the VIDIOC_S_SELECTION internally on the capture plane. Must be called 199 | * before setFormat() on any of the planes. 200 | * 201 | * @param[in] left Horizontal offset of the rectangle, in pixels. 202 | * @param[in] top Verticaal offset of the rectangle, in pixels. 203 | * @param[in] width Width of the rectangle, in pixels. 204 | * @param[in] height Height of the rectangle, in pixels. 205 | * 206 | * @returns 0 for success, -1 for failure 207 | */ 208 | int setCropRect(uint32_t left, uint32_t top, uint32_t width, 209 | uint32_t height); 210 | 211 | /** 212 | * Sets the destnation rectangle for the converter. 213 | * 214 | * Calls the VIDIOC_S_SELECTION internally on output plane. Must be called 215 | * before setFormat() on any of the planes. 216 | * 217 | * @param[in] left Horizontal offset of the rectangle, in pixels 218 | * @param[in] top Verticaal offset of the rectangle, in pixels 219 | * @param[in] width Width of the rectangle, in pixels 220 | * @param[in] height Height of the rectangle, in pixels 221 | * 222 | * @returns 0 for success, -1 for failure 223 | */ 224 | int setDestRect(uint32_t left, uint32_t top, uint32_t width, 225 | uint32_t height); 226 | 227 | /** 228 | * Waits until all buffers queued on the output plane are converted and 229 | * dequeued from the capture plane. This is a blocking call. 230 | * 231 | * @param[in] max_wait_ms Maximum time to wait in milliseconds 232 | * @returns 0 for success, -1 for timeout. 233 | */ 234 | int waitForIdle(uint32_t max_wait_ms); 235 | 236 | private: 237 | /** 238 | * Constructor used by #createVideoConverter. 239 | */ 240 | NvVideoConverter(const char *name, int flags); 241 | 242 | static const NvElementProfiler::ProfilerField valid_fields = 243 | NvElementProfiler::PROFILER_FIELD_TOTAL_UNITS | 244 | NvElementProfiler::PROFILER_FIELD_LATENCIES | 245 | NvElementProfiler::PROFILER_FIELD_FPS; 246 | }; 247 | /** @} */ 248 | #endif 249 | -------------------------------------------------------------------------------- /include/NvVideoDecoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of NVIDIA CORPORATION nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /** 30 | * @file 31 | * NVIDIA Multimedia API: Video Decode API 32 | * 33 | */ 34 | 35 | /** 36 | * @defgroup l4t_mm_nvvideodecoder_group Video Decoder 37 | * @ingroup l4t_mm_nvvideo_group 38 | * 39 | * Helper class that creates new V4L2 40 | * video decoders, and it sets decoder capture and output plane 41 | * formats. 42 | * @{ 43 | */ 44 | 45 | #ifndef __NV_VIDEO_DECODER_H__ 46 | #define __NV_VIDEO_DECODER_H__ 47 | 48 | #include "NvV4l2Element.h" 49 | 50 | /** 51 | * @brief Defines a helper class for V4L2 Video Decoder. 52 | * 53 | * The video decoder device node is `/dev/nvhost-nvdec`. The category name 54 | * for the decoder is \c "NVDEC". 55 | * 56 | * Refer to [V4L2 Video Decoder](group__V4L2Dec.html) for more information on the decoder. 57 | */ 58 | class NvVideoDecoder:public NvV4l2Element 59 | { 60 | public: 61 | /** 62 | * Creates a new V4L2 Video Decoder object named \a name. 63 | * 64 | * This method internally calls \c v4l2_open on the decoder dev node 65 | * \c "/dev/nvhost-nvdec" and checks for \c V4L2_CAP_VIDEO_M2M_MPLANE 66 | * capability on the device. This method allows the caller to specify 67 | * additional flags with which the device should be opened. 68 | * 69 | * The device is opened in blocking mode, which can be modified by passing 70 | * the @a O_NONBLOCK flag to this method. 71 | * 72 | * @returns Reference to the newly created decoder object else \a NULL in 73 | * case of failure during initialization. 74 | */ 75 | static NvVideoDecoder *createVideoDecoder(const char *name, int flags = 0); 76 | 77 | ~NvVideoDecoder(); 78 | /** 79 | * Sets the format on the decoder output plane. 80 | * 81 | * Calls \c VIDIOC_S_FMT IOCTL internally on the capture plane. 82 | * 83 | * @param[in] pixfmt One of the raw V4L2 pixel formats. 84 | * @param[in] width Width of the output buffers in pixels. 85 | * @param[in] height Height of the output buffers in pixels. 86 | * @return 0 for success, -1 otherwise. 87 | */ 88 | int setCapturePlaneFormat(uint32_t pixfmt, uint32_t width, uint32_t height); 89 | /** 90 | * Sets the format on the decoder output plane. 91 | * 92 | * Calls the \c VIDIOC_S_FMT IOCTL internally on the output plane. 93 | * 94 | * @param[in] pixfmt One of the coded V4L2 pixel formats. 95 | * @param[in] sizeimage Maximum size of the buffers on the output plane. 96 | containing encoded data in bytes. 97 | * @return 0 for success, -1 otherwise. 98 | */ 99 | int setOutputPlaneFormat(uint32_t pixfmt, uint32_t sizeimage); 100 | 101 | /** 102 | * Informs the decoder that input buffers may not contain complete frames. 103 | * Deprecated interface, Use setFrameInputMode instead. 104 | * 105 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 106 | * V4L2_CID_MPEG_VIDEO_DISABLE_COMPLETE_FRAME_INPUT. 107 | * 108 | * @return 0 for success, -1 otherwise. 109 | */ 110 | int disableCompleteFrameInputBuffer(); 111 | 112 | /** 113 | * Informs the decoder that input buffers may not contain complete frames. 114 | * 115 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 116 | * V4L2_CID_MPEG_VIDEO_DISABLE_COMPLETE_FRAME_INPUT. 117 | * 118 | * @param[in] ctrl_value control value to disable 119 | * complete frame input buffer. 120 | * @return 0 for success, -1 otherwise. 121 | */ 122 | int setFrameInputMode(unsigned int ctrl_value); 123 | 124 | /** 125 | * Disables the display picture buffer. 126 | * 127 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 128 | * V4L2_CID_MPEG_VIDEO_DISABLE_DPB. Must be called after setFormat on both 129 | * the planes and before requestBuffers on any of the planes. 130 | * 131 | * @return 0 for success, -1 otherwise. 132 | */ 133 | int disableDPB(); 134 | 135 | /** 136 | * Gets the minimum number of buffers to be requested on the decoder capture plane. 137 | * 138 | * Calls the VIDIOC_G_CTRL IOCTL internally with Control ID 139 | * V4L2_CID_MIN_BUFFERS_FOR_CAPTURE. It is valid after the first 140 | * V4L2_RESOLUTION_CHANGE_EVENT and may change after each subsequent 141 | * event. 142 | * 143 | * @param[out] num A reference to the integer to return the number of buffers. 144 | * 145 | * @return 0 for success, -1 otherwise. 146 | */ 147 | int getMinimumCapturePlaneBuffers(int & num); 148 | 149 | /** 150 | * Sets the skip-frames parameter of the decoder. 151 | * 152 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 153 | * V4L2_CID_MPEG_VIDEO_SKIP_FRAMES. Must be called after setFormat on both 154 | * the planes and before requestBuffers on any of the planes. 155 | * 156 | * @param[in] skip_frames Type of frames to skip decoding, one of 157 | * enum v4l2_skip_frames_type. 158 | * 159 | * @return 0 for success, -1 otherwise. 160 | */ 161 | int setSkipFrames(enum v4l2_skip_frames_type skip_frames); 162 | 163 | /** 164 | * Sets the decoder for maximum performance. 165 | * 166 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 167 | * V4L2_CID_MPEG_VIDEO_MAX_PERFORMANCE. Must be called after setFormat on both 168 | * the planes and before requestBuffers on any of the planes. 169 | * 170 | * @param[in] flag Integer variable to indicate whether max performance is to be 171 | * enabled/disabled. 172 | * 173 | * @return 0 for success, -1 otherwise. 174 | */ 175 | int setMaxPerfMode(int flag); 176 | 177 | /** 178 | * Enables video decoder output metadata reporting. 179 | * 180 | * Calls the VIDIOC_S_EXT_CTRLS IOCTL internally with Control ID 181 | * V4L2_CID_MPEG_VIDEO_ERROR_REPORTING. Must be called after setFormat on 182 | * both the planes and before requestBuffers on any of the planes. 183 | * 184 | * @return 0 for success, -1 otherwise. 185 | */ 186 | int enableMetadataReporting(); 187 | 188 | int checkifMasteringDisplayDataPresent(v4l2_ctrl_video_displaydata &displaydata); 189 | int MasteringDisplayData(v4l2_ctrl_video_hdrmasteringdisplaydata *hdrmasteringdisplaydata); 190 | 191 | /** 192 | * Gets metadata for the decoded capture plane buffer. 193 | * 194 | * Calls the VIDIOC_G_EXT_CTRLS IOCTL internally with Control ID 195 | * V4L2_CID_MPEG_VIDEODEC_METADATA. Must be called for a buffer that has 196 | * been dequeued from the capture plane. The returned metadata corresponds 197 | * to the last dequeued buffer with index @a buffer_index. 198 | * 199 | * @param[in] buffer_index Index of the capture plane buffer whose metadata 200 | * is required. 201 | * @param[in,out] metadata Reference to the metadata structure 202 | * v4l2_ctrl_videodec_outputbuf_metadata to be filled. 203 | * 204 | * @return 0 for success, -1 otherwise. 205 | */ 206 | int getMetadata(uint32_t buffer_index, 207 | v4l2_ctrl_videodec_outputbuf_metadata &metadata); 208 | 209 | /** 210 | * Gets metadata for the decoder output plane buffer. 211 | * 212 | * Calls the VIDIOC_G_EXT_CTRLS IOCTL internally with Control ID 213 | * V4L2_CID_MPEG_VIDEODEC_INPUT_METADATA. Must be called for a buffer that has 214 | * been dequeued from the output plane. The returned metadata corresponds 215 | * to the last dequeued buffer with index @a buffer_index. 216 | * 217 | * @param[in] buffer_index Index of the output plane buffer whose metadata 218 | * is required. 219 | * @param[in,out] input_metadata Reference to the metadata structure 220 | * v4l2_ctrl_videodec_inputbuf_metadata to be filled. 221 | * 222 | * @return 0 for success, -1 otherwise. 223 | */ 224 | int getInputMetadata(uint32_t buffer_index, 225 | v4l2_ctrl_videodec_inputbuf_metadata &input_metadata); 226 | 227 | /** 228 | * Issues Poll on the device which blocks until : 229 | * a) Either there is something to dequeue from capture or output plane or any events. 230 | * b) Poll was interrupted by a call to the device using V4L2_CID_SET_POLL_INTERRUPT 231 | * c) Application has already interrupted polling by V4L2_CID_SET_POLL_INTERRUPT 232 | */ 233 | int DevicePoll(v4l2_ctrl_video_device_poll *devicepoll); 234 | 235 | /** 236 | * Sets the polling interrupt, now if the application calls Poll, the device should 237 | * not block, in other words polling is disabled. 238 | */ 239 | int SetPollInterrupt(); 240 | 241 | /** 242 | * Clears the polling interrupt, now if the application calls Poll, the device should 243 | * block until the event is triggered, in other words polling is enabled. 244 | */ 245 | int ClearPollInterrupt(); 246 | 247 | private: 248 | /** 249 | * Constructor used by #createVideoDecoder. 250 | */ 251 | NvVideoDecoder(const char *name, int flags); 252 | 253 | static const NvElementProfiler::ProfilerField valid_fields = 254 | NvElementProfiler::PROFILER_FIELD_TOTAL_UNITS | 255 | NvElementProfiler::PROFILER_FIELD_FPS; 256 | }; 257 | /** @} */ 258 | #endif 259 | -------------------------------------------------------------------------------- /include/libv4l2.h: -------------------------------------------------------------------------------- 1 | /* 2 | # (C) 2008 Hans de Goede 3 | 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation; either version 2.1 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 17 | */ 18 | 19 | #ifndef __LIBV4L2_H 20 | #define __LIBV4L2_H 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif /* __cplusplus */ 29 | 30 | #if HAVE_VISIBILITY 31 | #define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) 32 | #else 33 | #define LIBV4L_PUBLIC 34 | #endif 35 | 36 | /* Point this to a FILE opened for writing when you want to log error and 37 | status messages to a file, when NULL errors will get send to stderr */ 38 | LIBV4L_PUBLIC extern FILE *v4l2_log_file; 39 | 40 | /* Just like your regular open/close/etc, except that format conversion is 41 | done if necessary when capturing. That is if you (try to) set a capture 42 | format which is not supported by the cam, but is supported by libv4lconvert, 43 | then the try_fmt / set_fmt will succeed as if the cam supports the format 44 | and on dqbuf / read the data will be converted for you and returned in 45 | the request format. enum_fmt will also report support for the formats to 46 | which conversion is possible. 47 | 48 | Another difference is that you can make v4l2_read() calls even on devices 49 | which do not support the regular read() method. 50 | 51 | Note the device name passed to v4l2_open must be of a video4linux2 device, 52 | if it is anything else (including a video4linux1 device), v4l2_open will 53 | fail. 54 | 55 | Note that the argument to v4l2_ioctl after the request must be a valid 56 | memory address of structure of the appropriate type for the request (for 57 | v4l2 requests which expect a structure address). Passing in NULL or an 58 | invalid memory address will not lead to failure with errno being EFAULT, 59 | as it would with a real ioctl, but will cause libv4l2 to break, and you 60 | get to keep both pieces. 61 | */ 62 | 63 | LIBV4L_PUBLIC int v4l2_open(const char *file, int oflag, ...); 64 | LIBV4L_PUBLIC int v4l2_close(int fd); 65 | LIBV4L_PUBLIC int v4l2_dup(int fd); 66 | LIBV4L_PUBLIC int v4l2_ioctl(int fd, unsigned long int request, ...); 67 | LIBV4L_PUBLIC ssize_t v4l2_read(int fd, void *buffer, size_t n); 68 | LIBV4L_PUBLIC ssize_t v4l2_write(int fd, const void *buffer, size_t n); 69 | LIBV4L_PUBLIC void *v4l2_mmap(void *start, size_t length, int prot, int flags, 70 | int fd, int64_t offset); 71 | LIBV4L_PUBLIC int v4l2_munmap(void *_start, size_t length); 72 | 73 | 74 | /* Misc utility functions */ 75 | 76 | /* This function takes a value of 0 - 65535, and then scales that range to 77 | the actual range of the given v4l control id, and then if the cid exists 78 | and is not locked sets the cid to the scaled value. 79 | 80 | Normally returns 0, even if the cid did not exist or was locked, returns 81 | non 0 when an other error occurred. */ 82 | LIBV4L_PUBLIC int v4l2_set_control(int fd, int cid, int value); 83 | 84 | /* This function returns a value of 0 - 65535, scaled to from the actual range 85 | of the given v4l control id. When the cid does not exist, or could not be 86 | accessed -1 is returned. */ 87 | LIBV4L_PUBLIC int v4l2_get_control(int fd, int cid); 88 | 89 | 90 | /* "low level" access functions, these functions allow somewhat lower level 91 | access to libv4l2 (currently there only is v4l2_fd_open here) */ 92 | 93 | /* Flags for v4l2_fd_open's v4l2_flags argument */ 94 | 95 | /* Disable all format conversion done by libv4l2, this includes the software 96 | whitebalance, gamma correction, flipping, etc. libv4lconvert does. Use this 97 | if you want raw frame data, but still want the additional error checks and 98 | the read() emulation libv4l2 offers. */ 99 | #define V4L2_DISABLE_CONVERSION 0x01 100 | /* This flag is *OBSOLETE*, since version 0.5.98 libv4l *always* reports 101 | emulated formats to ENUM_FMT, except when conversion is disabled. */ 102 | #define V4L2_ENABLE_ENUM_FMT_EMULATION 0x02 103 | 104 | /* v4l2_fd_open: open an already opened fd for further use through 105 | v4l2lib and possibly modify libv4l2's default behavior through the 106 | v4l2_flags argument. 107 | 108 | Returns fd on success, -1 if the fd is not suitable for use through libv4l2 109 | (note the fd is left open in this case). */ 110 | LIBV4L_PUBLIC int v4l2_fd_open(int fd, int v4l2_flags); 111 | 112 | #ifdef __cplusplus 113 | } 114 | #endif /* __cplusplus */ 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /log/logging.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "logging.h" 24 | #include 25 | 26 | 27 | // set default logging options 28 | Log::Level Log::mLevel = Log::LOG_DEFAULT; 29 | FILE* Log::mFile = stdout; 30 | std::string Log::mFilename = "stdout"; 31 | 32 | 33 | // ParseCmdLine 34 | void Log::ParseCmdLine( const int argc, char** argv ) 35 | { 36 | ParseCmdLine(commandLine(argc, argv)); 37 | } 38 | 39 | 40 | // ParseCmdLine 41 | void Log::ParseCmdLine( const commandLine& cmdLine ) 42 | { 43 | const char* levelStr = cmdLine.GetString("log-level"); 44 | 45 | if( levelStr != NULL ) 46 | { 47 | SetLevel(LevelFromStr(levelStr)); 48 | } 49 | else 50 | { 51 | if( cmdLine.GetFlag("verbose") ) 52 | SetLevel(LOG_VERBOSE); 53 | 54 | if( cmdLine.GetFlag("debug") ) 55 | SetLevel(LOG_DEBUG); 56 | } 57 | 58 | SetFile(cmdLine.GetString("log-file")); 59 | } 60 | 61 | 62 | // SetFile 63 | void Log::SetFile( FILE* file ) 64 | { 65 | if( !file || mFile == file ) 66 | return; 67 | 68 | mFile = file; 69 | 70 | if( mFile == stdout ) 71 | mFilename = "stdout"; 72 | else if( mFile == stderr ) 73 | mFilename = "stderr"; 74 | } 75 | 76 | 77 | // SetFilename 78 | void Log::SetFile( const char* filename ) 79 | { 80 | if( !filename ) 81 | return; 82 | 83 | if( strcasecmp(filename, "stdout") == 0 ) 84 | SetFile(stdout); 85 | else if( strcasecmp(filename, "stderr") == 0 ) 86 | SetFile(stderr); 87 | else 88 | { 89 | if( strcasecmp(filename, mFilename.c_str()) == 0 ) 90 | return; 91 | 92 | FILE* file = fopen(filename, "w"); 93 | 94 | if( file != NULL ) 95 | { 96 | SetFile(file); 97 | mFilename = filename; 98 | } 99 | else 100 | { 101 | LogError("failed to open '%s' for logging\n", filename); 102 | return; 103 | } 104 | } 105 | } 106 | 107 | // LevelToStr 108 | const char* Log::LevelToStr( Log::Level level ) 109 | { 110 | switch(level) 111 | { 112 | case LOG_SILENT: return "silent"; 113 | case LOG_ERROR: return "error"; 114 | case LOG_WARNING: return "warning"; 115 | case LOG_SUCCESS: return "success"; 116 | case LOG_INFO: return "info"; 117 | case LOG_VERBOSE: return "verbose"; 118 | case LOG_DEBUG: return "debug"; 119 | } 120 | 121 | return "default"; 122 | } 123 | 124 | 125 | // LevelFromStr 126 | Log::Level Log::LevelFromStr( const char* str ) 127 | { 128 | if( !str ) 129 | return LOG_DEFAULT; 130 | 131 | for (int n = 0; n <= LOG_DEBUG; n++) 132 | { 133 | const Level level = (Level)n; 134 | 135 | if( strcasecmp(str, LevelToStr(level)) == 0 ) 136 | return level; 137 | } 138 | 139 | if( strcasecmp(str, "disable") == 0 || strcasecmp(str, "disabled") == 0 || strcasecmp(str, "none") == 0 ) 140 | return LOG_SILENT; 141 | 142 | return LOG_DEFAULT; 143 | } 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /log/logging.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __LOGGING_UTILS_H_ 24 | #define __LOGGING_UTILS_H_ 25 | 26 | #include "commandLine.h" 27 | 28 | #include 29 | #include 30 | 31 | 32 | /** 33 | * Standard command-line options able to be passed to videoOutput::Create() 34 | * @ingroup log 35 | */ 36 | #define LOG_USAGE_STRING "logging arguments: \n" \ 37 | " --log-file=FILE output destination file (default is stdout)\n" \ 38 | " --log-level=LEVEL message output threshold, one of the following:\n" \ 39 | " * silent\n" \ 40 | " * error\n" \ 41 | " * warning\n" \ 42 | " * success\n" \ 43 | " * info\n" \ 44 | " * verbose (default)\n" \ 45 | " * debug\n" \ 46 | " --verbose enable verbose logging (same as --log-level=verbose)\n" \ 47 | " --debug enable debug logging (same as --log-level=debug)\n" 48 | 49 | 50 | /** 51 | * Message logging with a variable level of output and destinations. 52 | * @ingroup log 53 | */ 54 | class Log 55 | { 56 | public: 57 | /** 58 | * Defines the logging level of a message, and the threshold 59 | * used by the logger to either drop or output messages. 60 | */ 61 | enum Level 62 | { 63 | LOG_SILENT=0, /**< No messages are output. */ 64 | LOG_ERROR, /**< Major errors that may impact application execution. */ 65 | LOG_WARNING, /**< Warning conditions where the application may be able to proceed in some capacity. */ 66 | LOG_SUCCESS, /**< Successful events (e.g. the loading or creation of a resource) */ 67 | LOG_INFO, /**< Informational messages that are more important than VERBOSE messages */ 68 | LOG_VERBOSE, /**< Verbose details about program execution */ 69 | LOG_DEBUG, /**< Low-level debugging (disabled by default) */ 70 | LOG_DEFAULT = LOG_VERBOSE /**< The default level is `VERBOSE` */ 71 | }; 72 | 73 | /** 74 | * Get the current logging level. 75 | */ 76 | static inline Level GetLevel() { return mLevel; } 77 | 78 | /** 79 | * Set the current logging level. 80 | */ 81 | static inline void SetLevel( Level level ) { mLevel = level; } 82 | 83 | /** 84 | * Get the current log output. 85 | */ 86 | static inline FILE* GetFile() { return mFile; } 87 | 88 | /** 89 | * Get the filename of the log output. 90 | * This may also return `"stdout"` or `"stderror"`. 91 | */ 92 | static inline const char* GetFilename() { return mFilename.c_str(); } 93 | 94 | /** 95 | * Set the logging output. 96 | * This can be a built-in file, like `stdout` or `stderr`, 97 | * or a file that has been opened by the user. 98 | */ 99 | static void SetFile( FILE* file ); 100 | 101 | /** 102 | * Set the logging output. 103 | * Can be `"stdout"`, `"stderr"`, `"log.txt"`, ect. 104 | */ 105 | static void SetFile( const char* filename ); 106 | 107 | /** 108 | * Usage string for command line arguments to Create() 109 | */ 110 | static inline const char* Usage() { return LOG_USAGE_STRING; } 111 | 112 | /** 113 | * Parse command line options (see Usage() above) 114 | */ 115 | static void ParseCmdLine( const int argc, char** argv ); 116 | 117 | /** 118 | * Parse command line options (see Usage() above) 119 | */ 120 | static void ParseCmdLine( const commandLine& cmdLine ); 121 | 122 | /** 123 | * Convert a logging level to string. 124 | */ 125 | static const char* LevelToStr( Level level ); 126 | 127 | /** 128 | * Parse a logging level from a string. 129 | */ 130 | static Level LevelFromStr( const char* str ); 131 | 132 | protected: 133 | static Level mLevel; 134 | static FILE* mFile; 135 | static std::string mFilename; 136 | }; 137 | 138 | 139 | /** 140 | * Log a printf-style message with the provided level. 141 | * @ingroup log 142 | * @internal 143 | */ 144 | #define LogMessage(level, format, args...) if( level <= Log::GetLevel() ) fprintf(Log::GetFile(), format, ## args) 145 | 146 | /** 147 | * Log a printf-style error message (Log::ERROR) 148 | * @ingroup log 149 | */ 150 | #define LogError(format, args...) LogMessage(Log::LOG_ERROR, LOG_COLOR_RED LOG_LEVEL_PREFIX_ERROR format LOG_COLOR_RESET, ## args) 151 | 152 | /** 153 | * Log a printf-style warning message (Log::WARNING) 154 | * @ingroup log 155 | */ 156 | #define LogWarning(format, args...) LogMessage(Log::LOG_WARNING, LOG_COLOR_YELLOW LOG_LEVEL_PREFIX_WARNING format LOG_COLOR_RESET, ## args) 157 | 158 | /** 159 | * Log a printf-style success message (Log::SUCCESS) 160 | * @ingroup log 161 | */ 162 | #define LogSuccess(format, args...) LogMessage(Log::LOG_SUCCESS, LOG_COLOR_GREEN LOG_LEVEL_PREFIX_SUCCESS format LOG_COLOR_RESET, ## args) 163 | 164 | /** 165 | * Log a printf-style info message (Log::INFO) 166 | * @ingroup log 167 | */ 168 | #define LogInfo(format, args...) LogMessage(Log::LOG_INFO, LOG_LEVEL_PREFIX_INFO format, ## args) 169 | 170 | /** 171 | * Log a printf-style verbose message (Log::VERBOSE) 172 | * @ingroup log 173 | */ 174 | #define LogVerbose(format, args...) LogMessage(Log::LOG_VERBOSE, LOG_LEVEL_PREFIX_VERBOSE format, ## args) 175 | 176 | /** 177 | * Log a printf-style debug message (Log::DEBUG) 178 | * @ingroup log 179 | */ 180 | #define LogDebug(format, args...) LogMessage(Log::LOG_DEBUG, LOG_LEVEL_PREFIX_DEBUG format, ## args) 181 | 182 | 183 | /////////////////////////////////////////////////////////////////// 184 | /// @name Logging Internals 185 | /// @internal 186 | /// @ingroup log 187 | /////////////////////////////////////////////////////////////////// 188 | 189 | ///@{ 190 | 191 | #ifdef LOG_DISABLE_COLORS 192 | #define LOG_COLOR_RESET "" 193 | #define LOG_COLOR_RED "" 194 | #define LOG_COLOR_GREEN "" 195 | #define LOG_COLOR_YELLOW "" 196 | #define LOG_COLOR_BLUE "" 197 | #define LOG_COLOR_MAGENTA "" 198 | #define LOG_COLOR_CYAN "" 199 | #define LOG_COLOR_LIGHT_GRAY "" 200 | #define LOG_COLOR_DARK_GRAY "" 201 | #else 202 | // https://misc.flogisoft.com/bash/tip_colors_and_formatting 203 | #define LOG_COLOR_RESET "\033[0m" 204 | #define LOG_COLOR_RED "\033[0;31m" 205 | #define LOG_COLOR_GREEN "\033[0;32m" 206 | #define LOG_COLOR_YELLOW "\033[0;33m" 207 | #define LOG_COLOR_BLUE "\033[0;34m" 208 | #define LOG_COLOR_MAGENTA "\033[0;35m" 209 | #define LOG_COLOR_CYAN "\033[0;36m" 210 | #define LOG_COLOR_LIGHT_GRAY "\033[0;37m" 211 | #define LOG_COLOR_DARK_GRAY "\033[0;90m" 212 | #endif 213 | 214 | #ifdef LOG_ENABLE_LEVEL_PREFIX 215 | #define LOG_LEVEL_PREFIX_ERROR "[E]" 216 | #define LOG_LEVEL_PREFIX_WARNING "[W]" 217 | #define LOG_LEVEL_PREFIX_SUCCESS "[S]" 218 | #define LOG_LEVEL_PREFIX_INFO "[I]" 219 | #define LOG_LEVEL_PREFIX_VERBOSE "[V]" 220 | #define LOG_LEVEL_PREFIX_DEBUG "[D]" 221 | #else 222 | #define LOG_LEVEL_PREFIX_ERROR "" 223 | #define LOG_LEVEL_PREFIX_WARNING "" 224 | #define LOG_LEVEL_PREFIX_SUCCESS "" 225 | #define LOG_LEVEL_PREFIX_INFO "" 226 | #define LOG_LEVEL_PREFIX_VERBOSE "" 227 | #define LOG_LEVEL_PREFIX_DEBUG "" 228 | #endif 229 | 230 | ///@} 231 | 232 | #endif 233 | 234 | -------------------------------------------------------------------------------- /nvjmi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * NVIDIA jetson multimedia wrapper interface for video decoding and encoding 4 | * 5 | */ 6 | 7 | #ifndef __NVJMI_H__ 8 | #define __NVJMI_H__ 9 | 10 | #ifdef __GNUC__ 11 | #define JMI_API extern 12 | #endif 13 | 14 | #include 15 | #include 16 | 17 | namespace jmi { 18 | typedef struct nvJmiCtx nvJmiCtx; 19 | 20 | typedef enum{ 21 | NVJMI_OK = 0, 22 | NVJMI_ERROR_UNKNOWN = -1, 23 | NVJMI_ERROR_EOS = -2, 24 | NVJMI_ERROR_STOP = -3, 25 | NVJMI_ERROR_DEC_INTERNAL = -4, 26 | NVJMI_ERROR_GET_FRAME_META = -5, 27 | NVJMI_ERROR_FRAMES_EMPTY = -6, 28 | NVJMI_ERROR_OUTPUT_PLANE_STOP = -10, 29 | NVJMI_ERROR_OUTPUT_PLANE_DQBUF = -11, 30 | NVJMI_ERROR_OUTPUT_PLANE_QBUF = -12, 31 | NVJMI_ERROR_CAPTURE_PLANE_DQEVENT = -13, 32 | NVJMI_ERROR_CAPTURE_PLANE_STOP = -20, 33 | } nvErrorCode; 34 | 35 | typedef enum { 36 | NV_PIX_NV12 = 0, 37 | NV_PIX_YUV420, 38 | NV_PIX_ABGR32 39 | } nvPixFormat; 40 | 41 | typedef struct _NVENCPARAM{ 42 | unsigned int width; 43 | unsigned int height; 44 | unsigned int profile; 45 | unsigned int level; 46 | unsigned int bitrate; 47 | unsigned int peak_bitrate; 48 | char enableLossless; 49 | char mode_vbr; 50 | char insert_spspps_idr; 51 | unsigned int iframe_interval; 52 | unsigned int idr_interval; 53 | unsigned int fps_n; 54 | unsigned int fps_d; 55 | int capture_num; 56 | unsigned int max_b_frames; 57 | unsigned int refs; 58 | unsigned int qmax; 59 | unsigned int qmin; 60 | unsigned int hw_preset_type; 61 | } nvEncParam; 62 | 63 | typedef struct _NVPACKET { 64 | unsigned long flags; 65 | unsigned long payload_size; 66 | unsigned char *payload; 67 | unsigned long pts; 68 | } nvPacket; 69 | 70 | typedef struct _NVFRAME { 71 | unsigned long flags; 72 | unsigned long payload_size[3]; 73 | unsigned char *payload[3]; 74 | unsigned int linesize[3]; 75 | nvPixFormat type; 76 | unsigned int width; 77 | unsigned int height; 78 | time_t timestamp; 79 | } nvFrame; 80 | 81 | typedef struct _NVFRAMEMETA { 82 | unsigned long payload_size; 83 | unsigned int coded_width; 84 | unsigned int coded_height; 85 | unsigned int width; 86 | unsigned int height; 87 | time_t timestamp; 88 | int frame_index; 89 | char got_data; 90 | } nvFrameMeta; 91 | 92 | typedef enum { 93 | NV_VIDEO_CodingUnused, 94 | NV_VIDEO_CodingH264, /**< H.264 */ 95 | NV_VIDEO_CodingMPEG4, /**< MPEG-4 */ 96 | NV_VIDEO_CodingMPEG2, /**< MPEG-2 */ 97 | NV_VIDEO_CodingVP8, /**< VP8 */ 98 | NV_VIDEO_CodingVP9, /**< VP9 */ 99 | NV_VIDEO_CodingHEVC, /**< H.265/HEVC */ 100 | } nvCodingType; 101 | 102 | typedef struct NVJMICTXPARAM { 103 | nvCodingType coding_type; //帧编码类型 104 | int resize_width; //缩放后的frame width 105 | int resize_height; //缩放后的frame_height 106 | } nvJmiCtxParam; 107 | 108 | /* 109 | * Decoder functions 110 | */ 111 | 112 | /** 113 | * 创建nvjmi解码器 114 | * 115 | * @使用nvhost-nvdec硬件解码. 116 | * 117 | * @参数[输入] dec_name 解码器名称,任意字符串 118 | * @参数[输入] param 创建nvjmi上下文所需要的参数. 119 | * 120 | * @返回 nvJmiCtx* 指针, 如果创建成功, 指针非空; 否则为空指针 121 | * @ingroup nvjmi 122 | */ 123 | JMI_API nvJmiCtx* nvjmi_create_decoder(char const* dec_name, nvJmiCtxParam* param); 124 | 125 | /** 126 | * 关闭vjmi解码器 127 | * 128 | * @用于关闭之前创建的nvjmi解码器. 129 | * 130 | * @参数[输入] nvJmiCtx* nvjmi解码器上下文指针 131 | * 132 | * @返回 int , 如果关闭成功返回0; 失败返回非0 133 | * @ingroup nvjmi 134 | */ 135 | JMI_API int nvjmi_decoder_close(nvJmiCtx* ctx); 136 | 137 | /** 138 | * 释放解码器资源 139 | * 140 | * @用于释放解码器绑定的资源. 141 | * 142 | * @参数[输入] nvJmiCtx** nvjmi解码器上下文指针地址 143 | * 144 | * @返回 int , 如果释放成功返回0; 失败返回非0 145 | * @ingroup nvjmi 146 | */ 147 | JMI_API int nvjmi_decoder_free_context(nvJmiCtx** ctx); 148 | 149 | /** 150 | * 解码图像数据帧 151 | * 152 | * @将待解码的帧数据包出入nvjmi解码器, 等待解码. 153 | * 154 | * @参数[输入] nvJmiCtx* nvjmi解码器上下文指针 155 | * @参数[输入] nvPacket* 待解码的帧数据包 156 | * 157 | * @返回 int , 如果传入成功返回0; 失败返回非0 158 | * @ingroup nvjmi 159 | */ 160 | JMI_API int nvjmi_decoder_put_packet(nvJmiCtx* ctx, nvPacket* packet); 161 | 162 | /** 163 | * 解码图像数据帧 - 获得帧元数据 164 | * 165 | * @获取nvjmi解码器成功解码的帧元数据 166 | * @note 此API仅获取解码后帧的元数据, 不包含具体的帧图像数据 167 | * @帧数据使用AP Invjmi_decoder_retrieve_frame_data提取 168 | * 169 | * @参数[输入] nvJmiCtx* nvjmi解码器上下文指针 170 | * @参数[输出] frame_meta* 一帧解码后的帧元数据 171 | * 172 | * @返回 int , 如果传入成功返回0; 失败返回非0 173 | * @ingroup nvjmi 174 | */ 175 | JMI_API int nvjmi_decoder_get_frame_meta(nvJmiCtx* ctx, nvFrameMeta* frame_meta); 176 | 177 | /** 178 | * 解码图像数据帧 - 提取帧图像数据 179 | * 180 | * @获取nvjmi解码器成功解码的帧元数据 181 | * @note 此API仅当前nvjmi_decoder_get_frame_meta返回成功时调用 182 | * 183 | * @参数[输入] nvJmiCtx* nvjmi解码器上下文指针 184 | * @参数[输入] frame_meta* 要提取的帧图像数据的帧元数据 185 | * @参数[输出] frame_data* 提取的帧元数据 186 | * 187 | * @返回 int , 如果传入成功返回0; 失败返回非0 188 | * @ingroup nvjmi 189 | */ 190 | JMI_API int nvjmi_decoder_retrieve_frame_data(nvJmiCtx* ctx, nvFrameMeta* frame_meta, void* frame_data); 191 | 192 | /* 193 | * Encoder functions 194 | */ 195 | JMI_API nvJmiCtx* nvjmi_create_encoder(nvCodingType coding_type, nvEncParam* param); 196 | JMI_API int nvjmi_encoder_close(nvJmiCtx* ctx); 197 | JMI_API int nvjmi_endocder_free_context(nvJmiCtx** ctx); 198 | 199 | JMI_API int nvjmi_encoder_put_frame(nvJmiCtx* ctx, nvFrame* frame); 200 | JMI_API int nvjmi_encoder_get_packet(nvJmiCtx* ctx, nvPacket* packet); 201 | } 202 | #endif // !__NVJMI_H__ 203 | -------------------------------------------------------------------------------- /utils/commandLine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "commandLine.h" 24 | #include "logging.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #define ARGC_START 0 32 | 33 | 34 | // search for the end of a leading character in a string (e.g. '--foo') 35 | static inline int strFindDelimiter( char delimiter, const char* string ) 36 | { 37 | int string_start = 0; 38 | 39 | while( string[string_start] == delimiter ) 40 | string_start++; 41 | 42 | if( string_start >= (int)strlen(string)-1 ) 43 | return 0; 44 | 45 | return string_start; 46 | } 47 | 48 | 49 | // replace hyphens for underscores and vice-versa (returns NULL if no changes) 50 | static inline char* strSwapDelimiter( const char* string ) 51 | { 52 | if( !string ) 53 | return NULL; 54 | 55 | // determine if the original char is in the string 56 | bool found = false; 57 | const int str_length = strlen(string); 58 | 59 | for( int n=0; n < str_length; n++ ) 60 | { 61 | if( string[n] == '-' || string[n] == '_' ) 62 | { 63 | found = true; 64 | break; 65 | } 66 | } 67 | 68 | if( !found ) 69 | return NULL; 70 | 71 | // allocate a new string to modify 72 | char* new_str = (char*)malloc(str_length); 73 | 74 | if( !new_str ) 75 | return NULL; 76 | 77 | strcpy(new_str, string); 78 | 79 | // replace instances of the old char 80 | for( int n=0; n < str_length; n++ ) 81 | { 82 | if( new_str[n] == '-' ) 83 | new_str[n] = '_'; 84 | else if( new_str[n] == '_' ) 85 | new_str[n] = '-'; 86 | } 87 | 88 | return new_str; 89 | } 90 | 91 | 92 | // constructor 93 | commandLine::commandLine( const int pArgc, char** pArgv, const char* extraFlag ) 94 | { 95 | argc = pArgc; 96 | argv = pArgv; 97 | 98 | AddFlag(extraFlag); 99 | 100 | Log::ParseCmdLine(*this); 101 | } 102 | 103 | 104 | // constructor 105 | commandLine::commandLine( const int pArgc, char** pArgv, const char** extraArgs ) 106 | { 107 | argc = pArgc; 108 | argv = pArgv; 109 | 110 | AddArgs(extraArgs); 111 | 112 | Log::ParseCmdLine(*this); 113 | } 114 | 115 | 116 | // GetInt 117 | int commandLine::GetInt( const char* string_ref, int default_value, bool allowOtherDelimiters ) const 118 | { 119 | if( argc < 1 ) 120 | return 0; 121 | 122 | bool bFound = false; 123 | int value = -1; 124 | 125 | for( int i=ARGC_START; i < argc; i++ ) 126 | { 127 | const int string_start = strFindDelimiter('-', argv[i]); 128 | 129 | if( string_start == 0 ) 130 | continue; 131 | 132 | const char* string_argv = &argv[i][string_start]; 133 | const int length = (int)strlen(string_ref); 134 | 135 | if (!strncasecmp(string_argv, string_ref, length)) 136 | { 137 | if (length+1 <= (int)strlen(string_argv)) 138 | { 139 | int auto_inc = (string_argv[length] == '=') ? 1 : 0; 140 | value = atoi(&string_argv[length + auto_inc]); 141 | } 142 | else 143 | { 144 | value = 0; 145 | } 146 | 147 | bFound = true; 148 | continue; 149 | } 150 | } 151 | 152 | 153 | if( bFound ) 154 | return value; 155 | 156 | if( !allowOtherDelimiters ) 157 | return default_value; 158 | 159 | // try looking for the argument with delimiters swapped 160 | char* swapped_ref = strSwapDelimiter(string_ref); 161 | 162 | if( !swapped_ref ) 163 | return default_value; 164 | 165 | value = GetInt(swapped_ref, default_value, false); 166 | free(swapped_ref); 167 | return value; 168 | } 169 | 170 | 171 | // GetUnsignedInt 172 | uint32_t commandLine::GetUnsignedInt( const char* argName, uint32_t defaultValue, bool allowOtherDelimiters ) const 173 | { 174 | const int val = GetInt(argName, (int)defaultValue, allowOtherDelimiters); 175 | 176 | if( val < 0 ) 177 | return defaultValue; 178 | 179 | return val; 180 | } 181 | 182 | 183 | // GetFloat 184 | float commandLine::GetFloat( const char* string_ref, float default_value, bool allowOtherDelimiters ) const 185 | { 186 | if( argc < 1 ) 187 | return 0; 188 | 189 | bool bFound = false; 190 | float value = -1; 191 | 192 | for (int i=ARGC_START; i < argc; i++) 193 | { 194 | const int string_start = strFindDelimiter('-', argv[i]); 195 | 196 | if( string_start == 0 ) 197 | continue; 198 | 199 | const char* string_argv = &argv[i][string_start]; 200 | const int length = (int)strlen(string_ref); 201 | 202 | if (!strncasecmp(string_argv, string_ref, length)) 203 | { 204 | if (length+1 <= (int)strlen(string_argv)) 205 | { 206 | int auto_inc = (string_argv[length] == '=') ? 1 : 0; 207 | value = (float)atof(&string_argv[length + auto_inc]); 208 | } 209 | else 210 | { 211 | value = 0.f; 212 | } 213 | 214 | bFound = true; 215 | continue; 216 | } 217 | } 218 | 219 | if( bFound ) 220 | return value; 221 | 222 | if( !allowOtherDelimiters ) 223 | return default_value; 224 | 225 | // try looking for the argument with delimiters swapped 226 | char* swapped_ref = strSwapDelimiter(string_ref); 227 | 228 | if( !swapped_ref ) 229 | return default_value; 230 | 231 | value = GetFloat(swapped_ref, default_value, false); 232 | free(swapped_ref); 233 | return value; 234 | } 235 | 236 | 237 | // GetFlag 238 | bool commandLine::GetFlag( const char* string_ref, bool allowOtherDelimiters ) const 239 | { 240 | if( argc < 1 ) 241 | return false; 242 | 243 | for (int i=ARGC_START; i < argc; i++) 244 | { 245 | const int string_start = strFindDelimiter('-', argv[i]); 246 | 247 | if( string_start == 0 ) 248 | continue; 249 | 250 | const char* string_argv = &argv[i][string_start]; 251 | const char* equal_pos = strchr(string_argv, '='); 252 | 253 | const int argv_length = (int)(equal_pos == 0 ? strlen(string_argv) : equal_pos - string_argv); 254 | const int length = (int)strlen(string_ref); 255 | 256 | if( length == argv_length && !strncasecmp(string_argv, string_ref, length) ) 257 | return true; 258 | } 259 | 260 | if( !allowOtherDelimiters ) 261 | return false; 262 | 263 | // try looking for the argument with delimiters swapped 264 | char* swapped_ref = strSwapDelimiter(string_ref); 265 | 266 | if( !swapped_ref ) 267 | return false; 268 | 269 | const bool value = GetFlag(swapped_ref, false); 270 | free(swapped_ref); 271 | return value; 272 | } 273 | 274 | 275 | // GetString 276 | const char* commandLine::GetString( const char* string_ref, const char* default_value, bool allowOtherDelimiters ) const 277 | { 278 | if( argc < 1 ) 279 | return 0; 280 | 281 | for (int i=ARGC_START; i < argc; i++) 282 | { 283 | const int string_start = strFindDelimiter('-', argv[i]); 284 | 285 | if( string_start == 0 ) 286 | continue; 287 | 288 | char* string_argv = (char*)&argv[i][string_start]; 289 | const int length = (int)strlen(string_ref); 290 | 291 | if (!strncasecmp(string_argv, string_ref, length)) 292 | return (string_argv + length + 1); 293 | //*string_retval = &string_argv[length+1]; 294 | } 295 | 296 | if( !allowOtherDelimiters ) 297 | return default_value; 298 | 299 | // try looking for the argument with delimiters swapped 300 | char* swapped_ref = strSwapDelimiter(string_ref); 301 | 302 | if( !swapped_ref ) 303 | return default_value; 304 | 305 | const char* value = GetString(swapped_ref, default_value, false); 306 | free(swapped_ref); 307 | return value; 308 | } 309 | 310 | 311 | // GetPosition 312 | const char* commandLine::GetPosition( unsigned int position, const char* default_value ) const 313 | { 314 | if( argc < 1 ) 315 | return 0; 316 | 317 | unsigned int position_count = 0; 318 | 319 | for (int i=1/*ARGC_START*/; i < argc; i++) 320 | { 321 | const int string_start = strFindDelimiter('-', argv[i]); 322 | 323 | if( string_start != 0 ) 324 | continue; 325 | 326 | if( position == position_count ) 327 | return argv[i]; 328 | 329 | position_count++; 330 | } 331 | 332 | return default_value; 333 | } 334 | 335 | 336 | // GetPositionArgs 337 | unsigned int commandLine::GetPositionArgs() const 338 | { 339 | unsigned int position_count = 0; 340 | 341 | for (int i=1/*ARGC_START*/; i < argc; i++) 342 | { 343 | const int string_start = strFindDelimiter('-', argv[i]); 344 | 345 | if( string_start != 0 ) 346 | continue; 347 | 348 | position_count++; 349 | } 350 | 351 | return position_count; 352 | } 353 | 354 | 355 | // AddArg 356 | void commandLine::AddArg( const char* arg ) 357 | { 358 | if( !arg ) 359 | return; 360 | 361 | const size_t arg_length = strlen(arg); 362 | 363 | if( arg_length == 0 ) 364 | return; 365 | 366 | const int new_argc = argc + 1; 367 | char** new_argv = (char**)malloc(sizeof(char*) * new_argc); 368 | 369 | if( !new_argv ) 370 | return; 371 | 372 | for( int n=0; n < argc; n++ ) 373 | new_argv[n] = argv[n]; 374 | 375 | new_argv[argc] = (char*)malloc(arg_length + 1); 376 | 377 | if( !new_argv[argc] ) 378 | return; 379 | 380 | strcpy(new_argv[argc], arg); 381 | 382 | argc = new_argc; 383 | argv = new_argv; 384 | } 385 | 386 | 387 | // AddArgs 388 | void commandLine::AddArgs( const char** args ) 389 | { 390 | if( !args ) 391 | return; 392 | 393 | int arg_count = 0; 394 | 395 | while(true) 396 | { 397 | if( !args[arg_count] ) 398 | return; 399 | 400 | AddArg(args[arg_count]); 401 | arg_count++; 402 | } 403 | } 404 | 405 | 406 | // AddFlag 407 | void commandLine::AddFlag( const char* flag ) 408 | { 409 | if( !flag || strlen(flag) == 0 ) 410 | return; 411 | 412 | if( GetFlag(flag) ) 413 | return; 414 | 415 | const std::string arg = std::string("--") + flag; 416 | AddArg(arg.c_str()); 417 | } 418 | 419 | 420 | // Print 421 | void commandLine::Print() const 422 | { 423 | for( int n=0; n < argc; n++ ) 424 | printf("%s ", argv[n]); 425 | 426 | printf("\n"); 427 | } 428 | 429 | 430 | 431 | 432 | -------------------------------------------------------------------------------- /utils/commandLine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __COMMAND_LINE_H_ 24 | #define __COMMAND_LINE_H_ 25 | 26 | 27 | #include 28 | #include 29 | 30 | 31 | /** 32 | * Command line parser for extracting flags, values, and strings. 33 | * @ingroup commandLine 34 | */ 35 | class commandLine 36 | { 37 | public: 38 | /** 39 | * Constructor, takes the command line from `main()` 40 | */ 41 | commandLine( const int argc, char** argv, const char* extraFlag=NULL ); 42 | 43 | /** 44 | * Constructor, takes the command line from `main()` 45 | */ 46 | commandLine( const int argc, char** argv, const char** extraArgs ); 47 | 48 | /** 49 | * Checks to see whether the specified flag was included on the 50 | * command line. For example, if argv contained `--foo`, then 51 | * `GetFlag("foo")` would return `true` 52 | * 53 | * @param allowOtherDelimiters if true (default), the argName will be 54 | * matched against occurances containing either `-` or `_`. 55 | * For example, `--foo-bar` and `--foo_bar` would be the same. 56 | * 57 | * @returns `true`, if the flag with argName was found 58 | * `false`, if the flag with argName was not found 59 | */ 60 | bool GetFlag( const char* argName, bool allowOtherDelimiters=true ) const; 61 | 62 | /** 63 | * Get float argument. For example if argv contained `--foo=3.14159`, 64 | * then `GetInt("foo")` would return `3.14159f` 65 | * 66 | * @param allowOtherDelimiters if true (default), the argName will be 67 | * matched against occurances containing either `-` or `_`. 68 | * For example, `--foo-bar` and `--foo_bar` would be the same. 69 | * 70 | * @returns `defaultValue` if the argument couldn't be found. (`0.0` by default). 71 | * Otherwise, returns the value of the argument. 72 | */ 73 | float GetFloat( const char* argName, float defaultValue=0.0f, bool allowOtherDelimiters=true ) const; 74 | 75 | /** 76 | * Get integer argument. For example if argv contained `--foo=100`, 77 | * then `GetInt("foo")` would return `100` 78 | * 79 | * @param allowOtherDelimiters if true (default), the argName will be 80 | * matched against occurances containing either `-` or `_`. 81 | * For example, `--foo-bar` and `--foo_bar` would be the same. 82 | * 83 | * @returns `defaultValue` if the argument couldn't be found (`0` by default). 84 | * Otherwise, returns the value of the argument. 85 | */ 86 | int GetInt( const char* argName, int defaultValue=0, bool allowOtherDelimiters=true ) const; 87 | 88 | /** 89 | * Get unsigned integer argument. For example if argv contained `--foo=100`, 90 | * then `GetUnsignedInt("foo")` would return `100` 91 | * 92 | * @param allowOtherDelimiters if true (default), the argName will be 93 | * matched against occurances containing either `-` or `_`. 94 | * For example, `--foo-bar` and `--foo_bar` would be the same. 95 | * 96 | * @returns `defaultValue` if the argument couldn't be found, or if the value 97 | * was negative (`0` by default). Otherwise, returns the parsed value. 98 | */ 99 | uint32_t GetUnsignedInt( const char* argName, uint32_t defaultValue=0, bool allowOtherDelimiters=true ) const; 100 | 101 | /** 102 | * Get string argument. For example if argv contained `--foo=bar`, 103 | * then `GetString("foo")` would return `"bar"` 104 | * 105 | * @param allowOtherDelimiters if true (default), the argName will be 106 | * matched against occurances containing either `-` or `_`. 107 | * For example, `--foo-bar` and `--foo_bar` would be the same. 108 | * 109 | * @returns `defaultValue` if the argument couldn't be found (`NULL` by default). 110 | * Otherwise, returns a pointer to the argument value string 111 | * from the `argv` array. 112 | */ 113 | const char* GetString( const char* argName, const char* defaultValue=NULL, bool allowOtherDelimiters=true ) const; 114 | 115 | /** 116 | * Get positional string argument. Positional arguments aren't named, but rather 117 | * referenced by their index in the list. For example if the command line contained 118 | * `my-program --foo=bar /path/to/my_file.txt`, then `GetString(0)` would return 119 | * `"/path/to/my_file.txt" 120 | * 121 | * @returns `defaultValue` if the argument couldn't be found (`NULL` by default). 122 | * Otherwise, returns a pointer to the argument value string 123 | * from the `argv` array. 124 | */ 125 | const char* GetPosition( unsigned int position, const char* defaultValue=NULL ) const; 126 | 127 | /** 128 | * Get the number of positional arguments in the command line. 129 | * Positional arguments are those that don't have a name. 130 | */ 131 | unsigned int GetPositionArgs() const; 132 | 133 | /** 134 | * Add an argument to the command line. 135 | */ 136 | void AddArg( const char* arg ); 137 | 138 | /** 139 | * Add arguments to the command line. 140 | */ 141 | void AddArgs( const char** args ); 142 | 143 | /** 144 | * Add a flag to the command line. 145 | */ 146 | void AddFlag( const char* flag ); 147 | 148 | /** 149 | * Print out the command line for reference. 150 | */ 151 | void Print() const; 152 | 153 | /** 154 | * The argument count that the object was created with from main() 155 | */ 156 | int argc; 157 | 158 | /** 159 | * The argument strings that the object was created with from main() 160 | */ 161 | char** argv; 162 | }; 163 | 164 | 165 | /** 166 | * Specify a positional argument index. 167 | * @ingroup commandLine 168 | */ 169 | #define ARG_POSITION(x) x 170 | 171 | 172 | #endif 173 | 174 | --------------------------------------------------------------------------------