mirror of
git://nv-tegra.nvidia.com/tegra/gst-src/gst-nvvideo4linux2.git
synced 2025-12-25 03:35:31 +03:00
Compare commits
3 Commits
l4t/l4t-r3
...
l4t/l4t-r3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ace13fff7 | ||
|
|
addfd10d83 | ||
|
|
3f221c626f |
@@ -1,43 +1,45 @@
|
||||
Updating prebuilts and/or headers
|
||||
|
||||
da5475c4506f0f70011e5723f4f3e1e7368a0554 - nvbufsurface.h
|
||||
d53a1ccd9593f927408e1c19b0c0f98260b3c7cf - v4l2_nv_extensions.h
|
||||
44b0e909f18f7e2f457ba501fc47d80ecedd150b - nvbufsurface.h
|
||||
2c5c20979e5fca5ed70b425187c3d09b39c03171 - v4l2_nv_extensions.h
|
||||
d27a433ddeaefb9f42d0312c23472514b0cd6a45 - gst-nvcustomevent.h
|
||||
98d803db7a9d6076b0e0281dd98dfac09aa7e662 - gst-v4l2/gstv4l2object.h
|
||||
778ea5a8ef47b1d761bc1c0fbf94b5eda2927c43 - gst-v4l2/gstv4l2h264enc.c
|
||||
870a72e5038dba9f4df37f900d53a059beee9bbc - gst-v4l2/gstv4l2h26xparser.h
|
||||
a002edef13a3bbbdc41e42a7fca40e574ad1bb3e - gst-v4l2/v4l2-utils.c
|
||||
5948d70c07e87f9b1dc403789dcbed6acfa47ad9 - gst-v4l2/gstv4l2av1enc.c
|
||||
4e79cf75c4fa29791e1f5141318dc8aec13a7835 - gst-v4l2/nalutils.h
|
||||
9f726e4439379bb399f29c68736242f21dab3dd0 - gst-v4l2/gstv4l2allocator.c
|
||||
49a66f0ce02abc71f33e096a65645ddedf5c7f46 - gst-v4l2/gstv4l2bufferpool.c
|
||||
b827fd6cb1e3b8ecebd6a07f8556e846e26cba17 - gst-v4l2/gstv4l2allocator.h
|
||||
dd0804801357dc06664d7c2862d5d76bde28121c - gst-v4l2/gstv4l2h265enc.c
|
||||
110bd46e7f8753e4471cc9a1836c6ff7bded5ce6 - gst-v4l2/Makefile
|
||||
c81eacb7d88c4fb839506dd70055e30d7a9feeec - gst-v4l2/v4l2-utils.h
|
||||
39fcb2f599e6906ab0fd7ab9a46fef3ea58a8cab - gst-v4l2/gstv4l2vp8enc.h
|
||||
d89a680415f6ff5acec2571cde0fce9054d8e81f - gst-v4l2/gstv4l2vp9enc.h
|
||||
bb104683f5e4f7402e3f765a891e149edc794e02 - gst-v4l2/gstv4l2h264enc.h
|
||||
71be284b547ee68fb0e2cd14b0aeb14734a915a1 - gst-v4l2/gstv4l2bufferpool.h
|
||||
e9519308cbf7b36481da7665e3b74d36569cc3d1 - gst-v4l2/gstv4l2.c
|
||||
ba87c2bc0bea986ef461e1bc2ab3ded89700a986 - gst-v4l2/gstv4l2h264enc.c
|
||||
93eaaa0797c1f1dc21c20fbad1885dc109ccffd3 - gst-v4l2/gstv4l2bufferpool.c
|
||||
9ff38f38c224577c4aaadc4ac4d808429f37ca69 - gst-v4l2/gstv4l2allocator.c
|
||||
3d06f0b9ae8e465e8aecd7ef101e652ff62268c4 - gst-v4l2/Makefile
|
||||
02d142337f4b96fcb0c9f2405a3cbe90c5917cca - gst-v4l2/gstv4l2vp9enc.c
|
||||
4e483adcc7b66b228ee8546981a3fa15ae9ad3b4 - gst-v4l2/v4l2_calls.c
|
||||
b1cd923335aa60985ff9866fba91a2068e8671c7 - gst-v4l2/LICENSE.gst-nvvideo4linux2
|
||||
1efde38d61491d533f93f31ad52d4fab3595eaf0 - gst-v4l2/gstv4l2videodec.c
|
||||
cbc84dccd2506afa4c8f03849c95bb28c83ef4a3 - gst-v4l2/gstv4l2av1enc.h
|
||||
6e63f8b6431493365ed1915ca57670216589159c - gst-v4l2/gstv4l2.c
|
||||
9027f628c33b67f04782255a9833766b772d5f15 - gst-v4l2/gstv4l2videoenc.h
|
||||
34adbcb7d5cf5a360d28432429b735710bfe49c5 - gst-v4l2/wsl_utils.h
|
||||
afc982d855f80b1e21ce1831930a9f327c41832b - gst-v4l2/gstv4l2h265enc.c
|
||||
55a2c81ab3ffd72e07fc680369683d9635a3665c - gst-v4l2/gstv4l2h265enc.h
|
||||
5ecd059e5ef9be4014eface37e5e2f7598960f4e - gst-v4l2/nalutils.c
|
||||
807bc9859585a540b0f85e98f147756aab24e1bd - gst-v4l2/gstv4l2vp8enc.c
|
||||
99d65d620807b5ba1ca29a838e032940c9b019cc - gst-v4l2/sei_parse.c
|
||||
c81eacb7d88c4fb839506dd70055e30d7a9feeec - gst-v4l2/v4l2-utils.h
|
||||
b1cd923335aa60985ff9866fba91a2068e8671c7 - gst-v4l2/LICENSE.gst-nvvideo4linux2
|
||||
aa816d369be13e7cb2f6f5283c74bb00f7f1c76e - gst-v4l2/v4l2_calls.c
|
||||
d89a680415f6ff5acec2571cde0fce9054d8e81f - gst-v4l2/gstv4l2vp9enc.h
|
||||
da6c40e84b3b99e443b76c72cbb433541bdc9bcf - gst-v4l2/gstv4l2videodec.c
|
||||
0d69b17838c57184dace9bfa1d30bbe8f2f83848 - gst-v4l2/gstv4l2object.h
|
||||
c3ac3836a2d29d813c3c274cde82d2a59dd45a5a - gst-v4l2/gstv4l2videodec.h
|
||||
4b70823ac5f9a70cce0c909e284c73aed4bccbd6 - gst-v4l2/gstv4l2h26xparser.c
|
||||
d5952b0286c34bf13fbf5e09fe552ced0da49368 - gst-v4l2/gstv4l2videodec.h
|
||||
2259dd5971ec37757e0659b564fdf802de72c757 - gst-v4l2/gstv4l2videoenc.c
|
||||
6c06eb12b6e1fc0c6f17d37861ee003ebaeaeb30 - gst-v4l2/gstv4l2object.c
|
||||
e864ee6647f3572b144403d799f68152e9900da1 - gst-v4l2/gst/gettext.h
|
||||
39fcb2f599e6906ab0fd7ab9a46fef3ea58a8cab - gst-v4l2/gstv4l2vp8enc.h
|
||||
08d68910b07d04e1429763ad1e6dbbeb41c5277d - gst-v4l2/gstv4l2av1enc.h
|
||||
a002edef13a3bbbdc41e42a7fca40e574ad1bb3e - gst-v4l2/v4l2-utils.c
|
||||
870a72e5038dba9f4df37f900d53a059beee9bbc - gst-v4l2/gstv4l2h26xparser.h
|
||||
fac36b61500cf8d1b5f2513d6d2319ef73aa870e - gst-v4l2/sei_parse.c
|
||||
b827fd6cb1e3b8ecebd6a07f8556e846e26cba17 - gst-v4l2/gstv4l2allocator.h
|
||||
e18e54d84e643676bfc88fd559d834f26f5b4d4d - gst-v4l2/wsl_utils.c
|
||||
d0af17fd51ec44b79ef54c1279b631a46cf31f49 - gst-v4l2/gstv4l2videoenc.h
|
||||
4e79cf75c4fa29791e1f5141318dc8aec13a7835 - gst-v4l2/nalutils.h
|
||||
add535643bbb5c58b7eb98b45496204e4d63ebb1 - gst-v4l2/gstv4l2bufferpool.h
|
||||
5ecd059e5ef9be4014eface37e5e2f7598960f4e - gst-v4l2/nalutils.c
|
||||
719c8569e894b0146a6e027550187df5aaf5adc1 - gst-v4l2/gstv4l2av1enc.c
|
||||
bb104683f5e4f7402e3f765a891e149edc794e02 - gst-v4l2/gstv4l2h264enc.h
|
||||
eb5134c907dd4b25097491e4273591db6ac386fc - gst-v4l2/gstv4l2videoenc.c
|
||||
807bc9859585a540b0f85e98f147756aab24e1bd - gst-v4l2/gstv4l2vp8enc.c
|
||||
9c3d135576125a6620cc8fa0b249ac73c070110b - gst-v4l2/gstv4l2object.c
|
||||
20c4f7c0cb89c83256650bc3353ed82154cf3a9d - gst-v4l2/gst/gst-i18n-plugin.h
|
||||
e864ee6647f3572b144403d799f68152e9900da1 - gst-v4l2/gst/gettext.h
|
||||
499a9feb17ceabf1f1443923dffa1e0180bf5972 - gst-v4l2/gst/glib-compat-private.h
|
||||
fe847595bb202501a56702a7c602f0514d23c328 - gst-v4l2/ext/v4l2-common.h
|
||||
583075e89482f1faa08be7f7b278336bf7756def - gst-v4l2/ext/v4l2-controls.h
|
||||
72a34a694337f8f6da3bb94c9faced6730cbd2fc - gst-v4l2/ext/types-compat.h
|
||||
583075e89482f1faa08be7f7b278336bf7756def - gst-v4l2/ext/v4l2-controls.h
|
||||
fe847595bb202501a56702a7c602f0514d23c328 - gst-v4l2/ext/v4l2-common.h
|
||||
2253e5f55e37aace35af706d5662ef017f17e877 - gst-v4l2/ext/videodev2.h
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright (c) 2018-2025, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# NVIDIA Corporation and its licensors retain all intellectual property
|
||||
# and proprietary rights in and to this software, related documentation
|
||||
@@ -14,7 +14,7 @@ SO_NAME := libgstnvvideo4linux2.so
|
||||
|
||||
TARGET_DEVICE = $(shell gcc -dumpmachine | cut -f1 -d -)
|
||||
|
||||
NVDS_VERSION:=6.0
|
||||
NVDS_VERSION:=8.0
|
||||
|
||||
ifeq ($(TARGET_DEVICE),aarch64)
|
||||
GST_INSTALL_DIR?=/usr/lib/aarch64-linux-gnu/gstreamer-1.0/
|
||||
@@ -30,7 +30,7 @@ endif
|
||||
LIBS:= -lnvbufsurface -lnvbufsurftransform -lgstnvdsseimeta -lgstnvcustomhelper
|
||||
SRCS := $(wildcard *.c)
|
||||
|
||||
INCLUDES += -I./ -I../
|
||||
INCLUDES += -I./ -I../ -I/opt/nvidia/deepstream/deepstream-$(NVDS_VERSION)/sources/includes/
|
||||
|
||||
PKGS := gstreamer-1.0 \
|
||||
gstreamer-base-1.0 \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright (c) 2018-2025, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# NVIDIA Corporation and its licensors retain all intellectual property
|
||||
# and proprietary rights in and to this software, related documentation
|
||||
@@ -34,4 +34,4 @@ Steps to compile the "gst-nvvideo4linux2" sources natively:
|
||||
Note: For Jetson, "make install" will copy library "libgstnvvideo4linux2.so"
|
||||
into "/usr/lib/aarch64-linux-gnu/gstreamer-1.0" directory. For x86 platforms,
|
||||
make install will copy the library "libgstnvvideo4linux2.so" into
|
||||
/opt/nvidia/deepstream/deepstream-4.0/lib/gst-plugins
|
||||
/opt/nvidia/deepstream/deepstream/lib/gst-plugins
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* 2006 Edgard Lima <edgard.lima@gmail.com>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* gstv4l2.c: plugin for v4l2 elements
|
||||
*
|
||||
@@ -339,31 +340,32 @@ gst_v4l2_is_v4l2_nvenc_present(void)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
int fd = -1;
|
||||
long len = -1;
|
||||
struct stat statbuf;
|
||||
char info[128];
|
||||
|
||||
if (access (V4L2_DEVICE_PATH_TEGRA_INFO, F_OK) == 0) {
|
||||
stat(V4L2_DEVICE_PATH_TEGRA_INFO, &statbuf);
|
||||
if (access(V4L2_DEVICE_INFO_SOM_EEPROM, F_OK) == 0)
|
||||
{
|
||||
stat(V4L2_DEVICE_INFO_SOM_EEPROM, &statbuf);
|
||||
if (statbuf.st_size > 0 && statbuf.st_size < 128)
|
||||
{
|
||||
fd = open(V4L2_DEVICE_PATH_TEGRA_INFO, O_RDONLY);
|
||||
fd = open(V4L2_DEVICE_INFO_SOM_EEPROM, O_RDONLY);
|
||||
read(fd, info, statbuf.st_size);
|
||||
len = statbuf.st_size - 10;
|
||||
for (int i = 0; i < len; i ++)
|
||||
for (int i = 0; i <= (statbuf.st_size - 9); i++)
|
||||
{
|
||||
if (strncmp(&info[i], "p3767", 5) == 0)
|
||||
if (strncmp(&info[i], "3767", 4) == 0)
|
||||
{
|
||||
/*
|
||||
Jetson Orin Nano 8GB (P3767-0003) Commercial module
|
||||
Jetson Orin Nano 4GB (P3767-0004) Commercial module
|
||||
Jetson Orin Nano 8GB with SD card slot (P3767-0005) For the Developer Kit only
|
||||
* Jetson Orin Nano 8GB (P3767-0003) Commercial module
|
||||
* Jetson Orin Nano 4GB (P3767-0004) Commercial module
|
||||
* Jetson Orin Nano 8GB with SD card slot (P3767-0005) For the Developer Kit only
|
||||
*/
|
||||
if (strncmp(&info[i + 6], "0003", 4) == 0 ||
|
||||
strncmp(&info[i + 6], "0004", 4) == 0 ||
|
||||
strncmp(&info[i + 6], "0005", 4) == 0)
|
||||
if (strncmp(&info[i + 5], "0003", 4) == 0 ||
|
||||
strncmp(&info[i + 5], "0004", 4) == 0 ||
|
||||
strncmp(&info[i + 5], "0005", 4) == 0)
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
@@ -382,15 +384,13 @@ plugin_init (GstPlugin * plugin)
|
||||
GST_DEBUG_CATEGORY_INIT (v4l2_debug, "v4l2", 0, "V4L2 API calls");
|
||||
|
||||
#ifndef USE_V4L2_TARGET_NV_X86
|
||||
int igpu = -1, dgpu = -1;
|
||||
igpu = system("lsmod | grep 'nvgpu' > /dev/null");
|
||||
dgpu = system("modprobe -D -q nvidia | grep 'dkms' > /dev/null");
|
||||
if (igpu == -1 || dgpu == -1)
|
||||
return FALSE;
|
||||
else if (dgpu == 0)
|
||||
is_cuvid = TRUE;
|
||||
else
|
||||
int result = -1;
|
||||
result = (gboolean)system("lsmod | grep 'nvgpu' > /dev/null");
|
||||
|
||||
if (result == 0)
|
||||
is_cuvid = FALSE;
|
||||
else
|
||||
is_cuvid = TRUE;
|
||||
|
||||
if (getenv("AARCH64_DGPU"))
|
||||
is_cuvid = TRUE;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Collabora Ltd.
|
||||
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -1186,7 +1188,7 @@ gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator,
|
||||
|
||||
for (i = 0; i < group->n_mem; i++) {
|
||||
gint dmafd;
|
||||
gsize size, offset, maxsize;
|
||||
gsize size, offset = 0, maxsize = 0;
|
||||
|
||||
if (!gst_is_dmabuf_memory (dma_mem[i]))
|
||||
goto not_dmabuf;
|
||||
@@ -1367,13 +1369,19 @@ gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator,
|
||||
if (obj->is_encode) {
|
||||
if ((is_cuvid == true) && (obj->sei_payload != NULL)) {
|
||||
gint ret;
|
||||
struct v4l2_ext_control ctl;
|
||||
struct v4l2_ext_control ctls[2];
|
||||
struct v4l2_ext_controls ctrls;
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_DS_SEI_DATA;
|
||||
ctl.ptr = obj->sei_payload;
|
||||
ctl.size = obj->sei_payload_size;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
|
||||
ctls[0].id = V4L2_CID_MPEG_VIDEOENC_DS_SEI_DATA;
|
||||
ctls[0].ptr = obj->sei_payload;
|
||||
ctls[0].size = obj->sei_payload_size;
|
||||
|
||||
ctls[1].id = V4L2_CID_MPEG_VIDEOENC_DS_SEI_UUID;
|
||||
ctls[1].string = obj->sei_uuid;
|
||||
ctls[1].size = 16;
|
||||
|
||||
ctrls.count = 2;
|
||||
ctrls.controls = ctls;
|
||||
ret = obj->ioctl (obj->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -56,6 +57,7 @@ enum
|
||||
PROP_ENABLE_TILE_CONFIG,
|
||||
PROP_DISABLE_CDF,
|
||||
PROP_ENABLE_SSIMRDO,
|
||||
PROP_INSERT_SEQ_HDR,
|
||||
PROP_NUM_REFERENCE_FRAMES,
|
||||
};
|
||||
|
||||
@@ -88,6 +90,9 @@ gst_v4l2_av1_enc_set_property (GObject * object,
|
||||
case PROP_ENABLE_SSIMRDO:
|
||||
self->EnableSsimRdo = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_INSERT_SEQ_HDR:
|
||||
self->insert_sps_pps = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_NUM_REFERENCE_FRAMES:
|
||||
self->nRefFrames = g_value_get_uint (value);
|
||||
break;
|
||||
@@ -115,6 +120,9 @@ gst_v4l2_av1_enc_get_property (GObject * object,
|
||||
case PROP_ENABLE_SSIMRDO:
|
||||
g_value_set_boolean (value, self->EnableSsimRdo);
|
||||
break;
|
||||
case PROP_INSERT_SEQ_HDR:
|
||||
g_value_set_boolean (value, self->insert_sps_pps);
|
||||
break;
|
||||
case PROP_NUM_REFERENCE_FRAMES:
|
||||
g_value_set_uint (value, self->nRefFrames);
|
||||
break;
|
||||
@@ -215,23 +223,34 @@ set_v4l2_av1_encoder_properties (GstVideoEncoder * encoder)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->EnableTileConfig) {
|
||||
if (!gst_v4l2_av1_enc_tile_configuration (video_enc->v4l2output,
|
||||
self->EnableTileConfig, self->Log2TileRows, self->Log2TileCols)) {
|
||||
g_print ("S_EXT_CTRLS for Tile Configuration failed\n");
|
||||
if (is_cuvid == FALSE) {
|
||||
|
||||
if (self->EnableTileConfig) {
|
||||
if (!gst_v4l2_av1_enc_tile_configuration (video_enc->v4l2output,
|
||||
self->EnableTileConfig, self->Log2TileRows, self->Log2TileCols)) {
|
||||
g_print ("S_EXT_CTRLS for Tile Configuration failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_AV1_DISABLE_CDF_UPDATE, self->DisableCDFUpdate)) {
|
||||
g_print ("S_EXT_CTRLS for DisableCDF Update failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->EnableSsimRdo) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_AV1_ENABLE_SSIMRDO, self->EnableSsimRdo)) {
|
||||
g_print ("S_EXT_CTRLS for SSIM RDO failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_AV1_DISABLE_CDF_UPDATE, self->DisableCDFUpdate)) {
|
||||
g_print ("S_EXT_CTRLS for DisableCDF Update failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->EnableSsimRdo) {
|
||||
if (self->insert_sps_pps) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_AV1_ENABLE_SSIMRDO, self->EnableSsimRdo)) {
|
||||
V4L2_CID_MPEG_VIDEOENC_INSERT_SPS_PPS_AT_IDR, self->insert_sps_pps)) {
|
||||
g_print ("S_EXT_CTRLS for SSIM RDO failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -255,6 +274,7 @@ gst_v4l2_av1_enc_init (GstV4l2Av1Enc * self)
|
||||
self->EnableTileConfig = FALSE;
|
||||
self->DisableCDFUpdate = TRUE;
|
||||
self->EnableSsimRdo = FALSE;
|
||||
self->insert_sps_pps = FALSE;
|
||||
self->Log2TileRows= 0;
|
||||
self->Log2TileCols= 0;
|
||||
}
|
||||
@@ -291,6 +311,8 @@ gst_v4l2_av1_enc_class_init (GstV4l2Av1EncClass * klass)
|
||||
"Enable AV1 file and frame headers, if enabled, dump elementary stream",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
g_object_class_install_property (gobject_class, PROP_ENABLE_TILE_CONFIG,
|
||||
g_param_spec_string ("tiles", "AV1 Log2 Tile Configuration",
|
||||
"Use string with values of Tile Configuration"
|
||||
@@ -307,6 +329,12 @@ gst_v4l2_av1_enc_class_init (GstV4l2Av1EncClass * klass)
|
||||
"Enable SSIM RDO",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
#endif
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_SEQ_HDR,
|
||||
g_param_spec_boolean ("insert-seq-hdr", "Insert sequence header",
|
||||
"Insert sequence header at every IDR frame",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
g_object_class_install_property (gobject_class, PROP_NUM_REFERENCE_FRAMES,
|
||||
g_param_spec_uint ("num-Ref-Frames",
|
||||
"Sets the number of reference frames for encoder",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -45,6 +46,7 @@ struct _GstV4l2Av1Enc
|
||||
gboolean EnableTileConfig;
|
||||
gboolean DisableCDFUpdate;
|
||||
gboolean EnableSsimRdo;
|
||||
gboolean insert_sps_pps;
|
||||
guint32 Log2TileRows;
|
||||
guint32 Log2TileCols;
|
||||
guint32 nRefFrames;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* 2006 Edgard Lima <edgard.lima@gmail.com>
|
||||
* 2009 Texas Instruments, Inc - http://www.ti.com/
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* gstv4l2bufferpool.c V4L2 buffer pool class
|
||||
*
|
||||
@@ -80,6 +82,8 @@ report_metadata (GstV4l2Object * obj, guint32 buffer_index,
|
||||
static void
|
||||
v4l2_video_dec_get_enable_frame_type_reporting (GstV4l2Object * obj,
|
||||
guint32 buffer_index, v4l2_ctrl_videodec_outputbuf_metadata * dec_metadata);
|
||||
static void
|
||||
v4l2_video_dec_clear_poll_interrupt (GstV4l2Object * obj);
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
@@ -140,11 +144,7 @@ static NvBufSurfTransform_Error CopySurfTransform(NvBufSurface* src, NvBufSurfac
|
||||
NvBufSurfTransformParams transformParams;
|
||||
NvBufSurfTransformRect srcRect;
|
||||
NvBufSurfTransformRect destRect;
|
||||
status = NvBufSurfTransformSetDefaultSession();
|
||||
if (status != NvBufSurfTransformError_Success)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
srcRect.top = srcRect.left = 0;
|
||||
destRect.top = destRect.left = 0;
|
||||
srcRect.width = src->surfaceList[0].width;
|
||||
@@ -415,16 +415,10 @@ gst_v4l2_buffer_pool_import_userptr (GstV4l2BufferPool * pool,
|
||||
for (i = 0; i < GST_VIDEO_FORMAT_INFO_N_PLANES (finfo); i++) {
|
||||
if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) {
|
||||
gint tinfo = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i);
|
||||
gint pstride;
|
||||
guint pheight;
|
||||
size[i] = GST_VIDEO_TILE_X_TILES (tinfo) *
|
||||
GST_VIDEO_TILE_Y_TILES (tinfo) *
|
||||
GST_VIDEO_FORMAT_INFO_TILE_SIZE (finfo, i);
|
||||
|
||||
pstride = GST_VIDEO_TILE_X_TILES (tinfo) <<
|
||||
GST_VIDEO_FORMAT_INFO_TILE_WS (finfo);
|
||||
|
||||
pheight = GST_VIDEO_TILE_Y_TILES (tinfo) <<
|
||||
GST_VIDEO_FORMAT_INFO_TILE_HS (finfo);
|
||||
|
||||
size[i] = pstride * pheight;
|
||||
} else {
|
||||
size[i] = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i) *
|
||||
GST_VIDEO_FRAME_COMP_HEIGHT (&data->frame, i);
|
||||
@@ -728,6 +722,20 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
|
||||
|
||||
for (i = 0; i < group->n_mem; i++)
|
||||
gst_buffer_append_memory (newbuf, group->mem[i]);
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
if (!V4L2_TYPE_IS_OUTPUT(obj->type) && is_cuvid == FALSE) {
|
||||
GstMapInfo map = GST_MAP_INFO_INIT;
|
||||
NvBufSurface *nvbuf_surf = NULL;
|
||||
gst_buffer_map (newbuf, &map, GST_MAP_READ);
|
||||
nvbuf_surf = (NvBufSurface *) map.data;
|
||||
if (g_queue_find(pool->allocated_surfaces_queue, nvbuf_surf) == NULL)
|
||||
{
|
||||
g_queue_push_tail (pool->allocated_surfaces_queue, nvbuf_surf);
|
||||
}
|
||||
gst_buffer_unmap (newbuf, &map);
|
||||
}
|
||||
#endif
|
||||
} else if (newbuf == NULL) {
|
||||
goto allocation_failed;
|
||||
}
|
||||
@@ -757,13 +765,14 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
|
||||
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||
GstV4l2Object *obj = pool->obj;
|
||||
GstCaps *caps;
|
||||
guint size, min_buffers, max_buffers;
|
||||
GstAllocator *allocator;
|
||||
GstAllocationParams params;
|
||||
guint size, min_buffers = 0, max_buffers = 0;
|
||||
GstAllocator *allocator = NULL;
|
||||
GstAllocationParams params = { 0, };
|
||||
gboolean can_allocate = FALSE;
|
||||
gboolean updated = FALSE;
|
||||
gboolean ret;
|
||||
|
||||
gst_allocation_params_init (¶ms);
|
||||
pool->add_videometa =
|
||||
gst_buffer_pool_config_has_option (config,
|
||||
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
@@ -870,7 +879,9 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
|
||||
/* Always update the config to ensure the configured size matches */
|
||||
if ((!strcmp (obj->videodev, V4L2_DEVICE_PATH_NVENC) || !strcmp (obj->videodev, V4L2_DEVICE_PATH_NVENC_ALT)) &&
|
||||
(obj->mode == GST_V4L2_IO_DMABUF_IMPORT)) {
|
||||
gst_buffer_pool_config_set_params (config, caps, sizeof (NvBufSurface), min_buffers,
|
||||
/*For DMABUF Import, queue size should be kept to max to avoid frame drops coming from decoder*/
|
||||
min_buffers = max_buffers = 24; /* NvMM Encoder has MAX Q size as 24*/
|
||||
gst_buffer_pool_config_set_params(config, caps, sizeof(NvBufSurface), min_buffers,
|
||||
max_buffers);
|
||||
}
|
||||
else
|
||||
@@ -995,11 +1006,13 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
|
||||
#endif
|
||||
gint i;
|
||||
|
||||
if (!pool->streaming)
|
||||
return;
|
||||
|
||||
GST_OBJECT_LOCK (pool);
|
||||
|
||||
if (!pool->streaming) {
|
||||
GST_OBJECT_UNLOCK (pool);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (obj->mode) {
|
||||
case GST_V4L2_IO_MMAP:
|
||||
case GST_V4L2_IO_USERPTR:
|
||||
@@ -1060,7 +1073,7 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
|
||||
GstV4l2Object *obj = pool->obj;
|
||||
GstStructure *config;
|
||||
GstCaps *caps;
|
||||
guint size, min_buffers, max_buffers;
|
||||
guint size = 0, min_buffers = 0, max_buffers = 0;
|
||||
guint max_latency, min_latency, copy_threshold = 0;
|
||||
gboolean can_allocate = FALSE, ret = TRUE;
|
||||
|
||||
@@ -1241,6 +1254,32 @@ gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
|
||||
|
||||
GST_DEBUG_OBJECT (pool, "stopping pool");
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
/*
|
||||
* On EOS, video_fd becomes -1, this makes VIDIOC_REQBUFS API fail which
|
||||
* internally releases hardware buffers causing memory leak.
|
||||
* In below code NvBufSurfaces are destroyed explicitly.
|
||||
*/
|
||||
if (pool->vallocator) {
|
||||
if (pool->vallocator->obj->video_fd == -1 &&
|
||||
!V4L2_TYPE_IS_OUTPUT (pool->vallocator->obj->type) &&
|
||||
is_cuvid == FALSE) {
|
||||
while(g_queue_get_length(pool->allocated_surfaces_queue) > 0) {
|
||||
int retval = 0;
|
||||
NvBufSurface* allocated_surface = NULL;
|
||||
allocated_surface = g_queue_pop_head (pool->allocated_surfaces_queue);
|
||||
if (allocated_surface) {
|
||||
retval = NvBufSurfaceDestroy(allocated_surface);
|
||||
if(retval < 0) {
|
||||
GST_ERROR_OBJECT (pool, "failed to destroy nvbufsurface");
|
||||
return GST_V4L2_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pool->group_released_handler > 0) {
|
||||
g_signal_handler_disconnect (pool->vallocator,
|
||||
pool->group_released_handler);
|
||||
@@ -1294,6 +1333,11 @@ gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
|
||||
|
||||
#ifndef USE_V4L2_TARGET_NV
|
||||
gst_poll_set_flushing (pool->poll, TRUE);
|
||||
#else
|
||||
if (is_cuvid == TRUE)
|
||||
{
|
||||
v4l2_video_dec_clear_poll_interrupt (pool->obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
GST_OBJECT_LOCK (pool);
|
||||
@@ -1303,6 +1347,8 @@ gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
|
||||
|
||||
if (pool->other_pool)
|
||||
gst_buffer_pool_set_flushing (pool->other_pool, TRUE);
|
||||
|
||||
GST_DEBUG_OBJECT (pool, "End flushing");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1884,7 +1930,9 @@ gst_v4l2_buffer_pool_finalize (GObject * object)
|
||||
if (pool->video_fd >= 0)
|
||||
pool->obj->close (pool->video_fd);
|
||||
|
||||
#ifndef USE_V4L2_TARGET_NV
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
g_queue_free(pool->allocated_surfaces_queue);
|
||||
#else
|
||||
gst_poll_free (pool->poll);
|
||||
#endif
|
||||
|
||||
@@ -1908,6 +1956,10 @@ gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
|
||||
#endif
|
||||
g_cond_init (&pool->empty_cond);
|
||||
pool->empty = TRUE;
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
pool->allocated_surfaces_queue = g_queue_new();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2032,7 +2084,7 @@ gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
|
||||
GstFlowReturn res;
|
||||
GstV4l2Object *obj = pool->obj;
|
||||
gint amount;
|
||||
GstMapInfo map;
|
||||
GstMapInfo map = GST_MAP_INFO_INIT;
|
||||
gint toread;
|
||||
|
||||
toread = obj->info.size;
|
||||
@@ -2561,5 +2613,25 @@ v4l2_video_dec_get_enable_frame_type_reporting (GstV4l2Object * obj,
|
||||
if (ret < 0)
|
||||
g_print ("Error while getting report metadata\n");
|
||||
}
|
||||
|
||||
static void
|
||||
v4l2_video_dec_clear_poll_interrupt (GstV4l2Object * obj)
|
||||
{
|
||||
struct v4l2_ext_control control;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
gint ret = -1;
|
||||
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &control;
|
||||
ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
|
||||
|
||||
control.id = V4L2_CID_MPEG_SET_POLL_INTERRUPT;
|
||||
control.value = 0;
|
||||
|
||||
ret = obj->ioctl (obj->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret < 0)
|
||||
g_print ("Error while clearing poll interrupt\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* 2006 Edgard Lima <edgard.lima@gmail.com>
|
||||
* 2009 Texas Instruments, Inc - http://www.ti.com/
|
||||
* Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* gstv4l2bufferpool.h V4L2 buffer pool class
|
||||
*
|
||||
@@ -93,6 +95,7 @@ struct _GstV4l2BufferPool
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
GstBuffer *buffers[NV_VIDEO_MAX_FRAME];
|
||||
GQueue *allocated_surfaces_queue;
|
||||
#else
|
||||
GstBuffer *buffers[VIDEO_MAX_FRAME];
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2014 SUMOMO Computer Association
|
||||
* Author: ayaka <ayaka@soulik.info>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -49,6 +50,8 @@ gst_v4l2_videnc_profile_get_type (void);
|
||||
gboolean gst_v4l2_h264_enc_slice_header_spacing (GstV4l2Object * v4l2object,
|
||||
guint32 slice_header_spacing, enum v4l2_enc_slice_length_type slice_length_type);
|
||||
gboolean set_v4l2_h264_encoder_properties (GstVideoEncoder * encoder);
|
||||
gboolean gst_v4l2_h264_enc_slice_intrarefresh (GstV4l2Object * v4l2object,
|
||||
guint32 slice_count, guint32 slice_interval);
|
||||
#endif
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
@@ -115,7 +118,7 @@ enum
|
||||
#define MAX_NUM_REFERENCE_FRAMES 8
|
||||
#define DEFAULT_BIT_PACKETIZATION FALSE
|
||||
#define DEFAULT_SLICE_HEADER_SPACING 0
|
||||
#define DEFAULT_INTRA_REFRESH_FRAME_INTERVAL 60
|
||||
#define DEFAULT_INTRA_REFRESH_FRAME_INTERVAL 0
|
||||
#define DEFAULT_PIC_ORDER_CNT_TYPE 0
|
||||
#endif
|
||||
|
||||
@@ -302,6 +305,8 @@ v4l2_profile_from_string (const gchar * profile)
|
||||
v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH;
|
||||
} else if (g_str_equal (profile, "multiview-high")) {
|
||||
v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH;
|
||||
} else if (g_str_equal (profile, "constrained-high")) {
|
||||
v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH;
|
||||
} else {
|
||||
GST_WARNING ("Unsupported profile string '%s'", profile);
|
||||
}
|
||||
@@ -347,6 +352,8 @@ v4l2_profile_to_string (gint v4l2_profile)
|
||||
return "stereo-high";
|
||||
case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
|
||||
return "multiview-high";
|
||||
case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
|
||||
return "constrained-high";
|
||||
default:
|
||||
GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
|
||||
break;
|
||||
@@ -449,14 +456,20 @@ gst_v4l2_h264_enc_init (GstV4l2H264Enc * self)
|
||||
self->profile = DEFAULT_PROFILE;
|
||||
self->insert_sps_pps = FALSE;
|
||||
self->insert_aud = FALSE;
|
||||
self->insert_vui = FALSE;
|
||||
self->enableLossless = FALSE;
|
||||
|
||||
self->nRefFrames = 1;
|
||||
if (is_cuvid == TRUE)
|
||||
{
|
||||
self->extended_colorformat = FALSE;
|
||||
self->nRefFrames = 0;
|
||||
self->insert_vui = TRUE;
|
||||
}
|
||||
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
self->insert_vui = FALSE;
|
||||
#endif
|
||||
|
||||
self->nBFrames = 0;
|
||||
self->nRefFrames = 1;
|
||||
self->bit_packetization = DEFAULT_BIT_PACKETIZATION;
|
||||
self->slice_header_spacing = DEFAULT_SLICE_HEADER_SPACING;
|
||||
self->poc_type = DEFAULT_PIC_ORDER_CNT_TYPE;
|
||||
@@ -497,26 +510,16 @@ gst_v4l2_h264_enc_class_init (GstV4l2H264EncClass * klass)
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
g_object_class_install_property (gobject_class, PROP_EXTENDED_COLORFORMAT,
|
||||
g_param_spec_boolean ("extended-colorformat",
|
||||
"Set Extended ColorFormat",
|
||||
"Set Extended ColorFormat pixel values 0 to 255 in VUI Info",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
} else if (is_cuvid == FALSE) {
|
||||
g_object_class_install_property (gobject_class, PROP_PIC_ORDER_CNT_TYPE,
|
||||
g_param_spec_uint ("poc-type",
|
||||
"Picture Order Count type",
|
||||
"Set Picture Order Count type value",
|
||||
0, 2, DEFAULT_PIC_ORDER_CNT_TYPE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_VUI,
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_VUI,
|
||||
g_param_spec_boolean ("insert-vui",
|
||||
"Insert H.264 VUI",
|
||||
"Insert H.264 VUI(Video Usability Information) in SPS",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
FALSE,
|
||||
#else
|
||||
TRUE,
|
||||
#endif
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_SPS_PPS,
|
||||
g_param_spec_boolean ("insert-sps-pps",
|
||||
@@ -558,33 +561,11 @@ gst_v4l2_h264_enc_class_init (GstV4l2H264EncClass * klass)
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_ENABLE_MV_META,
|
||||
g_param_spec_boolean ("EnableMVBufferMeta",
|
||||
"Enable Motion Vector Meta data",
|
||||
"Enable Motion Vector Meta data for encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SLICE_INTRA_REFRESH_INTERVAL,
|
||||
g_param_spec_uint ("SliceIntraRefreshInterval",
|
||||
"SliceIntraRefreshInterval", "Set SliceIntraRefreshInterval", 0,
|
||||
G_MAXUINT, DEFAULT_INTRA_REFRESH_FRAME_INTERVAL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_TWO_PASS_CBR,
|
||||
g_param_spec_boolean ("EnableTwopassCBR",
|
||||
"Enable Two pass CBR",
|
||||
"Enable two pass CBR while encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_NUM_REFERENCE_FRAMES,
|
||||
g_param_spec_uint ("num-Ref-Frames",
|
||||
"Sets the number of reference frames for encoder",
|
||||
"Number of Reference Frames for encoder",
|
||||
0, MAX_NUM_REFERENCE_FRAMES, DEFAULT_NUM_REFERENCE_FRAMES,
|
||||
0, MAX_NUM_REFERENCE_FRAMES, (is_cuvid == TRUE) ? 0 : DEFAULT_NUM_REFERENCE_FRAMES,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
@@ -594,6 +575,42 @@ gst_v4l2_h264_enc_class_init (GstV4l2H264EncClass * klass)
|
||||
"Enable lossless encoding for YUV444",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_SLICE_INTRA_REFRESH_INTERVAL,
|
||||
g_param_spec_uint ("SliceIntraRefreshInterval",
|
||||
"SliceIntraRefreshInterval", "Set SliceIntraRefreshInterval", 0,
|
||||
G_MAXUINT, DEFAULT_INTRA_REFRESH_FRAME_INTERVAL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
g_object_class_install_property (gobject_class, PROP_EXTENDED_COLORFORMAT,
|
||||
g_param_spec_boolean ("extended-colorformat",
|
||||
"Set Extended ColorFormat",
|
||||
"Set Extended ColorFormat pixel values 0 to 255 in VUI Info",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
} else if (is_cuvid == FALSE) {
|
||||
g_object_class_install_property (gobject_class, PROP_PIC_ORDER_CNT_TYPE,
|
||||
g_param_spec_uint ("poc-type",
|
||||
"Picture Order Count type",
|
||||
"Set Picture Order Count type value",
|
||||
0, 2, DEFAULT_PIC_ORDER_CNT_TYPE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_ENABLE_MV_META,
|
||||
g_param_spec_boolean ("EnableMVBufferMeta",
|
||||
"Enable Motion Vector Meta data",
|
||||
"Enable Motion Vector Meta data for encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_TWO_PASS_CBR,
|
||||
g_param_spec_boolean ("EnableTwopassCBR",
|
||||
"Enable Two pass CBR",
|
||||
"Enable two pass CBR while encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
}
|
||||
#endif
|
||||
baseclass->codec_name = "H264";
|
||||
@@ -634,11 +651,16 @@ gst_v4l2_videnc_profile_get_type (void)
|
||||
{V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
|
||||
"GST_V4L2_H264_VIDENC_BASELINE_PROFILE",
|
||||
"Baseline"},
|
||||
{V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE,
|
||||
"GST_V4L2_H264_VIDENC_CONSTRAINED_BASELINE_PROFILE",
|
||||
"Constrained-Baseline"},
|
||||
{V4L2_MPEG_VIDEO_H264_PROFILE_MAIN, "GST_V4L2_H264_VIDENC_MAIN_PROFILE",
|
||||
"Main"},
|
||||
{V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, "GST_V4L2_H264_VIDENC_HIGH_PROFILE",
|
||||
"High"},
|
||||
{V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE, "GST_V4L2_H264_VIDENC_HIGH_444_PREDICTIVE",
|
||||
{V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, "GST_V4L2_H264_VIDENC_CONSTRAINED_HIGH_PROFILE",
|
||||
"Constrained-High"},
|
||||
{V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE, "GST_V4L2_H264_VIDENC_HIGH_444_PREDICTIVE_PROFILE",
|
||||
"High444"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
@@ -702,6 +724,41 @@ gst_v4l2_h264_enc_slice_header_spacing (GstV4l2Object * v4l2object,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_v4l2_h264_enc_slice_intrarefresh (GstV4l2Object * v4l2object,
|
||||
guint32 slice_count, guint32 slice_interval)
|
||||
{
|
||||
struct v4l2_ext_control control;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
gint ret;
|
||||
|
||||
v4l2_ctrl_intra_refresh cuvid_param = {1, slice_interval, slice_count};
|
||||
v4l2_enc_slice_intrarefresh_param param = {slice_count};
|
||||
|
||||
memset (&control, 0, sizeof (control));
|
||||
memset (&ctrls, 0, sizeof (ctrls));
|
||||
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &control;
|
||||
ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
|
||||
|
||||
control.id = V4L2_CID_MPEG_VIDEOENC_SLICE_INTRAREFRESH_PARAM;
|
||||
|
||||
if (is_cuvid)
|
||||
control.string = (gchar *)&cuvid_param;
|
||||
else
|
||||
control.string = (gchar *)¶m;
|
||||
|
||||
ret = v4l2object->ioctl(v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret < 0)
|
||||
{
|
||||
g_print("Error while setting slice intrarefresh params\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
set_v4l2_h264_encoder_properties (GstVideoEncoder * encoder)
|
||||
{
|
||||
@@ -731,12 +788,10 @@ set_v4l2_h264_encoder_properties (GstVideoEncoder * encoder)
|
||||
}
|
||||
}
|
||||
|
||||
if (self->insert_vui) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_INSERT_VUI, 1)) {
|
||||
g_print ("S_EXT_CTRLS for INSERT_VUI failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_INSERT_VUI, self->insert_vui)) {
|
||||
g_print ("S_EXT_CTRLS for INSERT_VUI failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
@@ -796,9 +851,9 @@ set_v4l2_h264_encoder_properties (GstVideoEncoder * encoder)
|
||||
}
|
||||
|
||||
if (self->SliceIntraRefreshInterval) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_SLICE_INTRAREFRESH_PARAM,
|
||||
self->SliceIntraRefreshInterval)) {
|
||||
if (!gst_v4l2_h264_enc_slice_intrarefresh (video_enc->v4l2output,
|
||||
self->SliceIntraRefreshInterval,
|
||||
video_enc->idrinterval)) {
|
||||
g_print ("S_EXT_CTRLS for SLICE_INTRAREFRESH_PARAM failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -53,7 +54,8 @@ gboolean gst_v4l2_h265_enc_slice_header_spacing (GstV4l2Object * v4l2object,
|
||||
guint32 slice_header_spacing, enum v4l2_enc_slice_length_type slice_length_type);
|
||||
void set_h265_video_enc_property (GstV4l2Object * v4l2object, guint label,
|
||||
gint param);
|
||||
|
||||
gboolean gst_v4l2_h265_enc_slice_intrarefresh (GstV4l2Object * v4l2object,
|
||||
guint32 slice_count, guint32 slice_interval);
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
@@ -76,7 +78,7 @@ enum
|
||||
#define DEFAULT_PROFILE V4L2_MPEG_VIDEO_H265_PROFILE_MAIN
|
||||
#define DEFAULT_BIT_PACKETIZATION FALSE
|
||||
#define DEFAULT_SLICE_HEADER_SPACING 0
|
||||
#define DEFAULT_INTRA_REFRESH_FRAME_INTERVAL 60
|
||||
#define DEFAULT_INTRA_REFRESH_FRAME_INTERVAL 0
|
||||
#define DEFAULT_NUM_B_FRAMES 0
|
||||
#define MAX_NUM_B_FRAMES 2
|
||||
#define DEFAULT_NUM_REFERENCE_FRAMES 1
|
||||
@@ -246,65 +248,62 @@ v4l2_level_from_string (const gchar * level)
|
||||
{
|
||||
gint v4l2_level = -1;
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
if (is_cuvid == FALSE) {
|
||||
if (g_str_equal(level, "main1.0")) {
|
||||
if (g_str_equal(level, "main_1.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_1_0_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high1.0")) {
|
||||
} else if (g_str_equal(level, "high_1.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_1_0_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main2.0")) {
|
||||
} else if (g_str_equal(level, "main_2.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_2_0_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high2.0")) {
|
||||
} else if (g_str_equal(level, "high_2.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_2_0_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main2.1")) {
|
||||
} else if (g_str_equal(level, "main_2.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_2_1_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high2.1")) {
|
||||
} else if (g_str_equal(level, "high_2.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_2_1_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main3.0")) {
|
||||
} else if (g_str_equal(level, "main_3.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_3_0_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high3.0")) {
|
||||
} else if (g_str_equal(level, "high_3.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_3_0_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main3.1")) {
|
||||
} else if (g_str_equal(level, "main_3.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_3_1_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high3.1")) {
|
||||
} else if (g_str_equal(level, "high_3.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_3_1_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main4.0")) {
|
||||
} else if (g_str_equal(level, "main_4.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_4_0_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high4.0")) {
|
||||
} else if (g_str_equal(level, "high_4.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_4_0_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main4.1")) {
|
||||
} else if (g_str_equal(level, "main_4.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_4_1_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high4.1")) {
|
||||
} else if (g_str_equal(level, "high_4.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_4_1_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main5.0")) {
|
||||
} else if (g_str_equal(level, "main_5.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_5_0_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high5.0")) {
|
||||
} else if (g_str_equal(level, "high_5.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_5_0_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main5.1")) {
|
||||
} else if (g_str_equal(level, "main_5.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_5_1_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high5.1")) {
|
||||
} else if (g_str_equal(level, "high_5.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_5_1_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main5.2")) {
|
||||
} else if (g_str_equal(level, "main_5.2")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_5_2_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high5.2")) {
|
||||
} else if (g_str_equal(level, "high_5.2")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_5_2_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main6.0")) {
|
||||
} else if (g_str_equal(level, "main_6.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_6_0_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high6.0")) {
|
||||
} else if (g_str_equal(level, "high_6.0")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_6_0_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main6.1")) {
|
||||
} else if (g_str_equal(level, "main_6.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_6_1_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high6.1")) {
|
||||
} else if (g_str_equal(level, "high_6.1")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_6_1_HIGH_TIER;
|
||||
} else if (g_str_equal(level, "main6.2")) {
|
||||
} else if (g_str_equal(level, "main_6.2")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_6_2_MAIN_TIER;
|
||||
} else if (g_str_equal(level, "high6.2")) {
|
||||
} else if (g_str_equal(level, "high_6.2")) {
|
||||
v4l2_level = V4L2_MPEG_VIDEO_H265_LEVEL_6_2_HIGH_TIER;
|
||||
} else
|
||||
{
|
||||
GST_WARNING("Unsupported level string '%s'", level);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return v4l2_level;
|
||||
@@ -315,54 +314,64 @@ v4l2_level_to_string (gint v4l2_level)
|
||||
{
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
|
||||
if (is_cuvid == FALSE)
|
||||
{
|
||||
switch (v4l2_level)
|
||||
{
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_1_0_MAIN_TIER:
|
||||
return "main_1.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_1_0_HIGH_TIER:
|
||||
return "1.0";
|
||||
return "high_1.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_2_0_MAIN_TIER:
|
||||
return "main_2.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_2_0_HIGH_TIER:
|
||||
return "2.0";
|
||||
return "high_2.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_2_1_MAIN_TIER:
|
||||
return "main_2.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_2_1_HIGH_TIER:
|
||||
return "2.1";
|
||||
return "high_2.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_3_0_MAIN_TIER:
|
||||
return "main_3.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_3_0_HIGH_TIER:
|
||||
return "3.0";
|
||||
return "high_3.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_3_1_MAIN_TIER:
|
||||
return "main_3.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_3_1_HIGH_TIER:
|
||||
return "3.1";
|
||||
return "high_3.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_4_0_MAIN_TIER:
|
||||
return "main_4.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_4_0_HIGH_TIER:
|
||||
return "4.0";
|
||||
return "high_4.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_4_1_MAIN_TIER:
|
||||
return "main_4.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_4_1_HIGH_TIER:
|
||||
return "4.1";
|
||||
return "high_4.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_5_0_MAIN_TIER:
|
||||
return "main_5.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_5_0_HIGH_TIER:
|
||||
return "5.0";
|
||||
return "high_5.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_5_1_MAIN_TIER:
|
||||
return "main_5.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_5_1_HIGH_TIER:
|
||||
return "5.1";
|
||||
return "high_5.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_5_2_MAIN_TIER:
|
||||
return "main_5.2";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_5_2_HIGH_TIER:
|
||||
return "5.2";
|
||||
return "high_5.2";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_6_0_MAIN_TIER:
|
||||
return "main_6.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_6_0_HIGH_TIER:
|
||||
return "6.0";
|
||||
return "high_6.0";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_6_1_MAIN_TIER:
|
||||
return "main_6.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_6_1_HIGH_TIER:
|
||||
return "6.1";
|
||||
return "high_6.1";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_6_2_MAIN_TIER:
|
||||
return "main_6.2";
|
||||
case V4L2_MPEG_VIDEO_H265_LEVEL_6_2_HIGH_TIER:
|
||||
return "6.2";
|
||||
return "high_6.2";
|
||||
default:
|
||||
GST_WARNING("Unsupported V4L2 level %i", v4l2_level);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
@@ -374,13 +383,22 @@ gst_v4l2_h265_enc_init (GstV4l2H265Enc * self)
|
||||
self->insert_sps_pps = FALSE;
|
||||
self->profile = DEFAULT_PROFILE;
|
||||
self->insert_aud = FALSE;
|
||||
self->insert_vui = FALSE;
|
||||
self->extended_colorformat = FALSE;
|
||||
self->bit_packetization = DEFAULT_BIT_PACKETIZATION;
|
||||
self->slice_header_spacing = DEFAULT_SLICE_HEADER_SPACING;
|
||||
self->nRefFrames = 1;
|
||||
self->nBFrames = 0;
|
||||
self->enableLossless = FALSE;
|
||||
if (is_cuvid == TRUE)
|
||||
{
|
||||
self->extended_colorformat = FALSE;
|
||||
self->nRefFrames = 0;
|
||||
self->insert_vui = TRUE;
|
||||
}
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
self->insert_vui = FALSE;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -418,24 +436,17 @@ gst_v4l2_h265_enc_class_init (GstV4l2H265EncClass * klass)
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
g_object_class_install_property (gobject_class, PROP_EXTENDED_COLORFORMAT,
|
||||
g_param_spec_boolean ("extended-colorformat",
|
||||
"Set Extended ColorFormat",
|
||||
"Set Extended ColorFormat pixel values 0 to 255 in VUI info",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
} else if (is_cuvid == FALSE) {
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_SPS_PPS,
|
||||
g_param_spec_boolean ("insert-sps-pps",
|
||||
"Insert H.265 SPS, PPS",
|
||||
"Insert H.265 SPS, PPS at every IDR frame",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_SPS_PPS,
|
||||
g_param_spec_boolean ("insert-sps-pps",
|
||||
"Insert H.265 SPS, PPS",
|
||||
"Insert H.265 SPS, PPS at every IDR frame",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_VUI,
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_VUI,
|
||||
g_param_spec_boolean ("insert-vui",
|
||||
"Insert H.265 VUI",
|
||||
"Insert H.265 VUI(Video Usability Information) in SPS",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
(is_cuvid == TRUE) ? TRUE : FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_INSERT_AUD,
|
||||
g_param_spec_boolean ("insert-aud",
|
||||
@@ -457,28 +468,6 @@ gst_v4l2_h265_enc_class_init (GstV4l2H265EncClass * klass)
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_ENABLE_MV_META,
|
||||
g_param_spec_boolean ("EnableMVBufferMeta",
|
||||
"Enable Motion Vector Meta data",
|
||||
"Enable Motion Vector Meta data for encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SLICE_INTRA_REFRESH_INTERVAL,
|
||||
g_param_spec_uint ("SliceIntraRefreshInterval",
|
||||
"SliceIntraRefreshInterval", "Set SliceIntraRefreshInterval", 0,
|
||||
G_MAXUINT, DEFAULT_INTRA_REFRESH_FRAME_INTERVAL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_TWO_PASS_CBR,
|
||||
g_param_spec_boolean ("EnableTwopassCBR",
|
||||
"Enable Two pass CBR",
|
||||
"Enable two pass CBR while encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_NUM_BFRAMES,
|
||||
g_param_spec_uint ("num-B-Frames",
|
||||
"B Frames between two reference frames",
|
||||
@@ -491,7 +480,7 @@ gst_v4l2_h265_enc_class_init (GstV4l2H265EncClass * klass)
|
||||
g_param_spec_uint ("num-Ref-Frames",
|
||||
"Sets the number of reference frames for encoder",
|
||||
"Number of Reference Frames for encoder",
|
||||
0, MAX_NUM_REFERENCE_FRAMES, DEFAULT_NUM_REFERENCE_FRAMES,
|
||||
0, MAX_NUM_REFERENCE_FRAMES, (is_cuvid == TRUE) ? 0 : DEFAULT_NUM_REFERENCE_FRAMES,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
@@ -501,6 +490,34 @@ gst_v4l2_h265_enc_class_init (GstV4l2H265EncClass * klass)
|
||||
"Enable lossless encoding for YUV444",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_SLICE_INTRA_REFRESH_INTERVAL,
|
||||
g_param_spec_uint ("SliceIntraRefreshInterval",
|
||||
"SliceIntraRefreshInterval", "Set SliceIntraRefreshInterval", 0,
|
||||
G_MAXUINT, DEFAULT_INTRA_REFRESH_FRAME_INTERVAL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
g_object_class_install_property (gobject_class, PROP_EXTENDED_COLORFORMAT,
|
||||
g_param_spec_boolean ("extended-colorformat",
|
||||
"Set Extended ColorFormat",
|
||||
"Set Extended ColorFormat pixel values 0 to 255 in VUI info",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
} else if (is_cuvid == FALSE) {
|
||||
g_object_class_install_property (gobject_class, PROP_ENABLE_MV_META,
|
||||
g_param_spec_boolean ("EnableMVBufferMeta",
|
||||
"Enable Motion Vector Meta data",
|
||||
"Enable Motion Vector Meta data for encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_TWO_PASS_CBR,
|
||||
g_param_spec_boolean ("EnableTwopassCBR",
|
||||
"Enable Two pass CBR",
|
||||
"Enable two pass CBR while encoding",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -581,6 +598,41 @@ gst_v4l2_h265_enc_slice_header_spacing (GstV4l2Object * v4l2object,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_v4l2_h265_enc_slice_intrarefresh(GstV4l2Object *v4l2object,
|
||||
guint32 slice_count, guint32 slice_interval)
|
||||
{
|
||||
struct v4l2_ext_control control;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
gint ret;
|
||||
|
||||
v4l2_ctrl_intra_refresh cuvid_param = {1, slice_interval, slice_count};
|
||||
v4l2_enc_slice_intrarefresh_param param = {slice_count};
|
||||
|
||||
memset(&control, 0, sizeof(control));
|
||||
memset(&ctrls, 0, sizeof(ctrls));
|
||||
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &control;
|
||||
ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
|
||||
|
||||
control.id = V4L2_CID_MPEG_VIDEOENC_SLICE_INTRAREFRESH_PARAM;
|
||||
|
||||
if (is_cuvid)
|
||||
control.string = (gchar *)&cuvid_param;
|
||||
else
|
||||
control.string = (gchar *)¶m;
|
||||
|
||||
ret = v4l2object->ioctl(v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret < 0)
|
||||
{
|
||||
g_print("Error while setting slice intrarefresh params\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
set_v4l2_h265_encoder_properties (GstVideoEncoder * encoder)
|
||||
{
|
||||
@@ -608,12 +660,10 @@ set_v4l2_h265_encoder_properties (GstVideoEncoder * encoder)
|
||||
}
|
||||
}
|
||||
|
||||
if (self->insert_vui) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_INSERT_VUI, 1)) {
|
||||
g_print ("S_EXT_CTRLS for INSERT_VUI failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_INSERT_VUI, self->insert_vui)) {
|
||||
g_print ("S_EXT_CTRLS for INSERT_VUI failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->extended_colorformat) {
|
||||
@@ -654,9 +704,9 @@ set_v4l2_h265_encoder_properties (GstVideoEncoder * encoder)
|
||||
}
|
||||
|
||||
if (self->SliceIntraRefreshInterval) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_SLICE_INTRAREFRESH_PARAM,
|
||||
self->SliceIntraRefreshInterval)) {
|
||||
if (!gst_v4l2_h265_enc_slice_intrarefresh (video_enc->v4l2output,
|
||||
self->SliceIntraRefreshInterval,
|
||||
video_enc->idrinterval)) {
|
||||
g_print ("S_EXT_CTRLS for SLICE_INTRAREFRESH_PARAM failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -2,21 +2,26 @@
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* 2006 Edgard Lima <edgard.lima@gmail.com>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* gstv4l2object.c: base class for V4L2 elements
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version. This library is distributed in the hope
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Library General Public License for more details.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@@ -180,6 +185,7 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
|
||||
{V4L2_PIX_FMT_NV24M, TRUE, GST_V4L2_RAW},
|
||||
{V4L2_PIX_FMT_YUV444_10LE, TRUE, GST_V4L2_RAW},
|
||||
{V4L2_PIX_FMT_YUV444_12LE, TRUE, GST_V4L2_RAW},
|
||||
{V4L2_PIX_FMT_P216M, TRUE, GST_V4L2_RAW},
|
||||
#endif
|
||||
/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
|
||||
{V4L2_PIX_FMT_SBGGR8, TRUE, GST_V4L2_CODEC},
|
||||
@@ -1149,6 +1155,7 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
|
||||
case V4L2_PIX_FMT_NV24M:
|
||||
case V4L2_PIX_FMT_YUV444_10LE:
|
||||
case V4L2_PIX_FMT_YUV444_12LE:
|
||||
case V4L2_PIX_FMT_P216M:
|
||||
#endif
|
||||
case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
|
||||
case V4L2_PIX_FMT_NV21M: /* Same as NV21 */
|
||||
@@ -1190,6 +1197,9 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
|
||||
case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
|
||||
rank = YUV_BASE_RANK + 4;
|
||||
break;
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
case V4L2_PIX_FMT_YUV422M:
|
||||
#endif
|
||||
case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
|
||||
rank = YUV_BASE_RANK + 8;
|
||||
break;
|
||||
@@ -1439,6 +1449,11 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
|
||||
case V4L2_PIX_FMT_YUV444_12LE:
|
||||
format = GST_VIDEO_FORMAT_Y444_12LE;
|
||||
break;
|
||||
case V4L2_PIX_FMT_P216M:
|
||||
/* NOTE: Gstreamer does not support P216 video format (16bit NV16) yet.
|
||||
Hence, as a WAR it is mapped to GST_VIDEO_FORMAT_NV16_10LE32 for now. */
|
||||
format = GST_VIDEO_FORMAT_NV16_10LE32;
|
||||
break;
|
||||
#endif
|
||||
case V4L2_PIX_FMT_NV12MT:
|
||||
format = GST_VIDEO_FORMAT_NV12_64Z32;
|
||||
@@ -1636,6 +1651,7 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
|
||||
case V4L2_PIX_FMT_YUV444:
|
||||
case V4L2_PIX_FMT_YUV444_10LE:
|
||||
case V4L2_PIX_FMT_YUV444_12LE:
|
||||
case V4L2_PIX_FMT_P216M:
|
||||
#endif
|
||||
case V4L2_PIX_FMT_NV24: /* 24 Y/CrCb 4:4:4 */
|
||||
case V4L2_PIX_FMT_YVU410:
|
||||
@@ -1891,6 +1907,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_Y42B:
|
||||
fourcc = V4L2_PIX_FMT_YUV422P;
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
fourcc_nc = V4L2_PIX_FMT_YUV422M;
|
||||
#endif
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
fourcc = V4L2_PIX_FMT_NV12;
|
||||
@@ -1911,6 +1930,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
case GST_VIDEO_FORMAT_Y444_12LE:
|
||||
fourcc_nc = V4L2_PIX_FMT_YUV444_12LE;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_NV16_10LE32:
|
||||
fourcc = V4L2_PIX_FMT_P216M;
|
||||
break;
|
||||
#endif
|
||||
case GST_VIDEO_FORMAT_NV12_64Z32:
|
||||
fourcc_nc = V4L2_PIX_FMT_NV12MT;
|
||||
@@ -1989,7 +2011,7 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
} else if (g_str_equal (mimetype, "image/jpeg")) {
|
||||
fourcc = V4L2_PIX_FMT_JPEG;
|
||||
} else if (g_str_equal (mimetype, "video/mpeg")) {
|
||||
gint version;
|
||||
gint version = 0;
|
||||
if (gst_structure_get_int (structure, "mpegversion", &version)) {
|
||||
switch (version) {
|
||||
case 1:
|
||||
@@ -2297,8 +2319,10 @@ gst_v4l2_object_get_colorspace (struct v4l2_format *fmt,
|
||||
|
||||
switch (transfer) {
|
||||
case V4L2_XFER_FUNC_709:
|
||||
if (fmt->fmt.pix.height >= 2160)
|
||||
if (colorspace == V4L2_COLORSPACE_BT2020 && fmt->fmt.pix.height >= 2160)
|
||||
cinfo->transfer = GST_VIDEO_TRANSFER_BT2020_12;
|
||||
else if (colorspace == V4L2_COLORSPACE_SMPTE170M)
|
||||
cinfo->transfer = GST_VIDEO_TRANSFER_BT601;
|
||||
else
|
||||
cinfo->transfer = GST_VIDEO_TRANSFER_BT709;
|
||||
break;
|
||||
@@ -2314,6 +2338,9 @@ gst_v4l2_object_get_colorspace (struct v4l2_format *fmt,
|
||||
case V4L2_XFER_FUNC_NONE:
|
||||
cinfo->transfer = GST_VIDEO_TRANSFER_GAMMA10;
|
||||
break;
|
||||
case V4L2_XFER_FUNC_SMPTE2084:
|
||||
cinfo->transfer = GST_VIDEO_TRANSFER_SMPTE2084;
|
||||
break;
|
||||
case V4L2_XFER_FUNC_DEFAULT:
|
||||
/* nothing, just use defaults for colorspace */
|
||||
break;
|
||||
@@ -2739,7 +2766,7 @@ unknown_type:
|
||||
static gint
|
||||
sort_by_frame_size (GstStructure * s1, GstStructure * s2)
|
||||
{
|
||||
int w1, h1, w2, h2;
|
||||
int w1 = 0, h1 = 0, w2 = 0, h2 = 0;
|
||||
|
||||
gst_structure_get_int (s1, "width", &w1);
|
||||
gst_structure_get_int (s1, "height", &h1);
|
||||
@@ -3161,12 +3188,7 @@ gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps)
|
||||
|| !strcmp (v4l2object->videodev, V4L2_DEVICE_PATH_NVENC_ALT))) {
|
||||
/* Currently, DMABUF_IMPORT io mode is used on encoder
|
||||
output plane, when default mode V4L2_IO_AUTO is set */
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
mode = GST_V4L2_IO_MMAP; //TODO make this default to dmabuf_import
|
||||
} else if (is_cuvid == FALSE) {
|
||||
mode = GST_V4L2_IO_DMABUF_IMPORT;
|
||||
}
|
||||
mode = GST_V4L2_IO_DMABUF_IMPORT;
|
||||
} else {
|
||||
if (is_cuvid == TRUE){
|
||||
mode = GST_V4L2_IO_MMAP;
|
||||
@@ -3258,19 +3280,15 @@ gst_v4l2_object_set_stride (GstVideoInfo * info, GstVideoAlignment * align,
|
||||
const GstVideoFormatInfo *finfo = info->finfo;
|
||||
|
||||
if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) {
|
||||
gint x_tiles, y_tiles, ws, hs, tile_height, padded_height;
|
||||
gint x_tiles, y_tiles, tile_height, padded_height;
|
||||
|
||||
|
||||
ws = GST_VIDEO_FORMAT_INFO_TILE_WS (finfo);
|
||||
hs = GST_VIDEO_FORMAT_INFO_TILE_HS (finfo);
|
||||
tile_height = 1 << hs;
|
||||
tile_height = GST_VIDEO_FORMAT_INFO_TILE_HEIGHT (finfo, plane);
|
||||
|
||||
padded_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, plane,
|
||||
info->height + align->padding_top + align->padding_bottom);
|
||||
padded_height = GST_ROUND_UP_N (padded_height, tile_height);
|
||||
|
||||
x_tiles = stride >> ws;
|
||||
y_tiles = padded_height >> hs;
|
||||
x_tiles = stride / GST_VIDEO_FORMAT_INFO_TILE_STRIDE (finfo, plane);
|
||||
y_tiles = (padded_height + tile_height - 1) / tile_height;
|
||||
info->stride[plane] = GST_VIDEO_TILE_MAKE_STRIDE (x_tiles, y_tiles);
|
||||
} else {
|
||||
info->stride[plane] = stride;
|
||||
@@ -3364,12 +3382,10 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
|
||||
padded_height = format->fmt.pix.height;
|
||||
|
||||
if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) {
|
||||
guint hs, tile_height;
|
||||
|
||||
hs = GST_VIDEO_FORMAT_INFO_TILE_HS (finfo);
|
||||
tile_height = 1 << hs;
|
||||
|
||||
padded_height = GST_ROUND_UP_N (padded_height, tile_height);
|
||||
guint tile_height;
|
||||
tile_height = GST_VIDEO_FORMAT_INFO_TILE_HEIGHT (finfo,0);
|
||||
/* Round-up to tile_height as drivers are not forced to do so */
|
||||
padded_height = (padded_height + tile_height - 1) / tile_height * tile_height;
|
||||
}
|
||||
|
||||
align->padding_bottom = padded_height - info->height - align->padding_top;
|
||||
@@ -3481,9 +3497,10 @@ gst_v4l2_object_extrapolate_stride (const GstVideoFormatInfo * finfo,
|
||||
case GST_VIDEO_FORMAT_NV16:
|
||||
case GST_VIDEO_FORMAT_NV61:
|
||||
case GST_VIDEO_FORMAT_NV24:
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
case GST_VIDEO_FORMAT_P010_10LE:
|
||||
case GST_VIDEO_FORMAT_I420_12LE:
|
||||
case GST_VIDEO_FORMAT_NV16_10LE32:
|
||||
#endif
|
||||
estride = (plane == 0 ? 1 : 2) *
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, plane, stride);
|
||||
@@ -3496,6 +3513,17 @@ gst_v4l2_object_extrapolate_stride (const GstVideoFormatInfo * finfo,
|
||||
return estride;
|
||||
}
|
||||
|
||||
void post_error_to_bus(GstElement *element, const gchar *error_message)
|
||||
{
|
||||
GError *error =
|
||||
g_error_new_literal(GST_CORE_ERROR, GST_CORE_ERROR_FAILED, error_message);
|
||||
gst_element_post_message
|
||||
(GST_ELEMENT(element), gst_message_new_error(GST_OBJECT(element),
|
||||
error, NULL));
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
gboolean try_only, GstV4l2Error * error)
|
||||
@@ -3506,8 +3534,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
enum v4l2_field field;
|
||||
guint32 pixelformat;
|
||||
struct v4l2_fmtdesc *fmtdesc;
|
||||
GstVideoInfo info;
|
||||
GstVideoAlignment align;
|
||||
GstVideoInfo info = { 0, };
|
||||
GstVideoAlignment align = { 0, };
|
||||
#ifndef USE_V4L2_TARGET_NV
|
||||
gint width, height, fps_n, fps_d;
|
||||
#else
|
||||
@@ -3517,6 +3545,9 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
guint width, height, fps_n, fps_d;
|
||||
GstV4l2VideoEnc *videoenc = NULL;
|
||||
GstV4l2VideoDec *videodec = NULL;
|
||||
|
||||
gst_video_info_init (&info);
|
||||
gst_video_alignment_reset (&align);
|
||||
if (!strcmp (v4l2object->videodev, V4L2_DEVICE_PATH_NVENC)
|
||||
|| !strcmp (v4l2object->videodev, V4L2_DEVICE_PATH_NVENC_ALT)) {
|
||||
videoenc = GST_V4L2_VIDEO_ENC (v4l2object->element);
|
||||
@@ -3525,7 +3556,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
videodec = GST_V4L2_VIDEO_DEC (v4l2object->element);
|
||||
}
|
||||
GstV4l2VideoEncClass *klass = NULL;
|
||||
if (is_cuvid == FALSE) {
|
||||
{
|
||||
if (!strcmp (v4l2object->videodev, V4L2_DEVICE_PATH_NVENC)
|
||||
|| !strcmp (v4l2object->videodev, V4L2_DEVICE_PATH_NVENC_ALT)) {
|
||||
klass = GST_V4L2_VIDEO_ENC_GET_CLASS (v4l2object->element);
|
||||
@@ -3732,8 +3763,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, i);
|
||||
|
||||
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.finfo))
|
||||
stride = GST_VIDEO_TILE_X_TILES (stride) <<
|
||||
GST_VIDEO_FORMAT_INFO_TILE_WS (info.finfo);
|
||||
stride = GST_VIDEO_TILE_X_TILES (stride) *
|
||||
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.finfo, i);
|
||||
|
||||
format.fmt.pix_mp.plane_fmt[i].bytesperline = stride;
|
||||
}
|
||||
@@ -3751,8 +3782,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
format.fmt.pix.field = field;
|
||||
|
||||
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.finfo))
|
||||
stride = GST_VIDEO_TILE_X_TILES (stride) <<
|
||||
GST_VIDEO_FORMAT_INFO_TILE_WS (info.finfo);
|
||||
stride = GST_VIDEO_TILE_X_TILES (stride) *
|
||||
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.finfo, i);
|
||||
|
||||
/* try to ask our prefered stride */
|
||||
format.fmt.pix.bytesperline = stride;
|
||||
@@ -3866,23 +3897,128 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
if (ret < 0)
|
||||
goto invalid_ctrl;
|
||||
|
||||
if (is_cuvid == FALSE) {
|
||||
if (videoenc) {
|
||||
if (V4L2_TYPE_IS_OUTPUT (v4l2object->type)) {
|
||||
if (strcmp (klass->codec_name, "H264") == 0
|
||||
|| strcmp (klass->codec_name, "H265") == 0
|
||||
|| strcmp (klass->codec_name, "AV1") == 0) {
|
||||
if (!klass->set_encoder_properties (&videoenc->parent)) {
|
||||
g_print ("set_encoder_properties failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!klass->set_video_encoder_properties (&videoenc->parent)) {
|
||||
g_print ("set_video_encoder_properties failed\n");
|
||||
if (videoenc)
|
||||
{
|
||||
if (V4L2_TYPE_IS_OUTPUT(v4l2object->type))
|
||||
{
|
||||
if (strcmp(klass->codec_name, "H264") == 0 || strcmp(klass->codec_name, "H265") == 0 || strcmp(klass->codec_name, "AV1") == 0)
|
||||
{
|
||||
if (!klass->set_encoder_properties(&videoenc->parent))
|
||||
{
|
||||
g_print("set_encoder_properties failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!klass->set_video_encoder_properties(&videoenc->parent))
|
||||
{
|
||||
g_print("set_video_encoder_properties failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (is_cuvid)
|
||||
{
|
||||
/* CUDA PRESETS are overridden if HW presets are set.*/
|
||||
if (!videoenc->hw_preset_level)
|
||||
{
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_CUDA_PRESET_ID;
|
||||
ctl.value = videoenc->cudaenc_preset_id;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_CUDA_TUNING_INFO;
|
||||
ctl.value = videoenc->cudaenc_tuning_info_id;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
}
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEO_CUDA_MEM_TYPE;
|
||||
ctl.value = videoenc->cudaenc_mem_type;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
v4l2_ctrl_video_constqp constqp;
|
||||
constqp.constQpI = videoenc->constQpI;
|
||||
constqp.constQpP = videoenc->constQpP;
|
||||
constqp.constQpB = videoenc->constQpB;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_CUDA_CONSTQP;
|
||||
ctl.string = (gchar *)&constqp;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
v4l2_ctrl_video_init_qp init_qp;
|
||||
init_qp.IInitQP = videoenc->IInitQP;
|
||||
init_qp.PInitQP = videoenc->PInitQP;
|
||||
init_qp.BInitQP = videoenc->BInitQP;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_INIT_FRAME_QP;
|
||||
ctl.string = (gchar *)&init_qp;
|
||||
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEO_MAXBITRATE;
|
||||
ctl.value = videoenc->maxbitrate;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_VBVBUFSIZE;
|
||||
ctl.value = videoenc->vbvbufsize;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_VBVINIT;
|
||||
ctl.value = videoenc->vbvinit;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_ENABLE_AQ;
|
||||
ctl.value = videoenc->aqStrength;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_ENABLE_TEMPORAL_AQ;
|
||||
ctl.value = videoenc->enableTemporalAQ;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_TARGET_QUALITY;
|
||||
ctl.value = videoenc->targetQuality;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl;
|
||||
ret = v4l2object->ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3901,108 +4037,6 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_cuvid == TRUE) {
|
||||
if (videoenc) {
|
||||
ctl.id = V4L2_CID_MPEG_VIDEO_CUDA_GPU_ID;
|
||||
ctl.value = videoenc->cudaenc_gpu_id;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_CUDA_PRESET_ID;
|
||||
ctl.value = videoenc->cudaenc_preset_id;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
v4l2_ctrl_video_constqp constqp;
|
||||
constqp.constQpI = videoenc->constQpI;
|
||||
constqp.constQpP = videoenc->constQpP;
|
||||
constqp.constQpB = videoenc->constQpB;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_CUDA_CONSTQP;
|
||||
ctl.string = (gchar *) &constqp;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
v4l2_ctrl_video_init_qp init_qp;
|
||||
init_qp.IInitQP = videoenc->IInitQP;
|
||||
init_qp.PInitQP = videoenc->PInitQP;
|
||||
init_qp.BInitQP = videoenc->BInitQP;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_INIT_FRAME_QP;
|
||||
ctl.string = (gchar *) &init_qp;
|
||||
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_CUDA_TUNING_INFO;
|
||||
ctl.value = videoenc->cudaenc_tuning_info_id;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEO_MAXBITRATE;
|
||||
ctl.value = videoenc->maxbitrate;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_VBVBUFSIZE;
|
||||
ctl.value = videoenc->vbvbufsize;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_VBVINIT;
|
||||
ctl.value = videoenc->vbvinit;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_ENABLE_AQ;
|
||||
ctl.value = videoenc->aqStrength;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_ENABLE_TEMPORAL_AQ;
|
||||
ctl.value = videoenc->enableTemporalAQ;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
ctl.id = V4L2_CID_MPEG_VIDEOENC_TARGET_QUALITY;
|
||||
ctl.value = videoenc->targetQuality;
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctl ;
|
||||
ret = v4l2object->ioctl (fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret)
|
||||
goto invalid_ctrl;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Got format of %dx%d, format "
|
||||
@@ -4337,6 +4371,27 @@ get_parm_failed:
|
||||
}
|
||||
set_parm_failed:
|
||||
{
|
||||
if ((v4l2object->is_encode == 1) && (is_cuvid == TRUE))
|
||||
{
|
||||
gchar err_msg[100] = "ENCODER INITIALIZATION FAILED";
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
strncpy (err_msg, "INVALID / UNSUPPORTED PARAM", 100);
|
||||
break;
|
||||
case ENODEV:
|
||||
strncpy (err_msg, "INVALID / UNSUPPORTED / NO ENCODE DEVICE", 100);
|
||||
break;
|
||||
case ENOSYS:
|
||||
strncpy (err_msg, "FEATURE UNIMPLEMENTED", 100);
|
||||
break;
|
||||
case EPERM:
|
||||
strncpy (err_msg, "OPERATION NOT PERMITTED", 100);
|
||||
break;
|
||||
}
|
||||
post_error_to_bus (v4l2object->element, err_msg);
|
||||
}
|
||||
|
||||
GST_V4L2_ERROR (error, RESOURCE, SETTINGS,
|
||||
(_("Video device did not accept new frame rate setting.")),
|
||||
GST_ERROR_SYSTEM);
|
||||
@@ -4387,7 +4442,7 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
|
||||
struct v4l2_rect *r = NULL;
|
||||
GstVideoFormat format;
|
||||
guint width, height;
|
||||
GstVideoAlignment align;
|
||||
GstVideoAlignment align = { 0, };
|
||||
|
||||
gst_video_info_init (info);
|
||||
gst_video_alignment_reset (&align);
|
||||
@@ -4547,7 +4602,7 @@ gboolean
|
||||
gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps)
|
||||
{
|
||||
GstStructure *config;
|
||||
GstCaps *oldcaps;
|
||||
GstCaps *oldcaps = NULL;
|
||||
gboolean ret;
|
||||
|
||||
if (!v4l2object->pool)
|
||||
@@ -4718,7 +4773,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||
GstCaps *caps;
|
||||
GstBufferPool *pool = NULL, *other_pool = NULL;
|
||||
GstStructure *config;
|
||||
guint size, min, max, own_min = 0;
|
||||
guint size = 0, min = 0, max = 0, own_min = 0;
|
||||
gboolean update;
|
||||
gboolean has_video_meta;
|
||||
gboolean can_share_own_pool, pushing_from_our_pool = FALSE;
|
||||
@@ -5023,7 +5078,7 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||
GstBufferPool *pool;
|
||||
/* we need at least 2 buffers to operate */
|
||||
guint size, min, max;
|
||||
GstCaps *caps;
|
||||
GstCaps *caps = NULL;
|
||||
gboolean need_pool;
|
||||
|
||||
/* Set defaults allocation parameters */
|
||||
@@ -5044,7 +5099,7 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||
gst_object_ref (pool);
|
||||
|
||||
if (pool != NULL) {
|
||||
GstCaps *pcaps;
|
||||
GstCaps *pcaps = NULL;
|
||||
GstStructure *config;
|
||||
|
||||
/* we had a pool, check caps */
|
||||
@@ -5114,8 +5169,7 @@ set_v4l2_video_mpeg_class (GstV4l2Object * v4l2object, guint label,
|
||||
|
||||
if (control.id == V4L2_CID_MPEG_VIDEOENC_VIRTUALBUFFER_SIZE) {
|
||||
control.string = (gchar *) &buffer_size;
|
||||
} else if ((control.id == V4L2_CID_MPEG_VIDEOENC_SLICE_INTRAREFRESH_PARAM) ||
|
||||
(control.id == V4L2_CID_MPEG_VIDEOENC_NUM_REFERENCE_FRAMES)) {
|
||||
} else if (control.id == V4L2_CID_MPEG_VIDEOENC_NUM_REFERENCE_FRAMES) {
|
||||
control.string = (gchar *) ¶ms;
|
||||
} else {
|
||||
control.value = params;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* 2006 Edgard Lima <edgard.lima@gmail.com>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* gstv4l2object.h: base class for V4L2 elements
|
||||
*
|
||||
@@ -59,6 +60,7 @@ typedef struct _GstV4l2ObjectClassHelper GstV4l2ObjectClassHelper;
|
||||
#define V4L2_DEVICE_PATH_NVENC "/dev/nvhost-msenc"
|
||||
#define V4L2_DEVICE_PATH_NVENC_ALT "/dev/v4l2-nvenc"
|
||||
#define V4L2_DEVICE_PATH_TEGRA_INFO "/sys/firmware/devicetree/base/compatible"
|
||||
#define V4L2_DEVICE_INFO_SOM_EEPROM "/sys/firmware/devicetree/base/chosen/ids"
|
||||
#endif
|
||||
|
||||
/* max frame width/height */
|
||||
@@ -226,6 +228,7 @@ struct _GstV4l2Object {
|
||||
GMutex cplane_stopped_lock;
|
||||
guint sei_payload_size;
|
||||
void* sei_payload;
|
||||
gchar *sei_uuid;
|
||||
#endif
|
||||
|
||||
/* funcs */
|
||||
@@ -371,6 +374,8 @@ gboolean gst_v4l2_get_attribute (GstV4l2Object * v4l2object, int attribute
|
||||
gboolean gst_v4l2_set_attribute (GstV4l2Object * v4l2object, int attribute, const int value);
|
||||
gboolean gst_v4l2_set_controls (GstV4l2Object * v4l2object, GstStructure * controls);
|
||||
|
||||
void post_error_to_bus(GstElement *element, const gchar *error_message);
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
gboolean set_v4l2_video_mpeg_class (GstV4l2Object * v4l2object, guint label,
|
||||
gint params);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Collabora Ltd.
|
||||
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -17,7 +19,6 @@
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@@ -46,6 +47,11 @@ GST_DEBUG_CATEGORY_STATIC (gst_v4l2_video_dec_debug);
|
||||
#define ENABLE_DRAIN 1
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_video_remove_padding (GstCapsFeatures * features,
|
||||
GstStructure * structure, gpointer user_data);
|
||||
|
||||
typedef enum {
|
||||
CAP_BUF_DYNAMIC_ALLOC_DISABLED,
|
||||
CAP_BUF_DYNAMIC_ALLOC_ENABLED_FOR_FW_PLAYBACK,
|
||||
@@ -68,7 +74,8 @@ gboolean default_sei_extract_data;
|
||||
gint default_num_extra_surfaces;
|
||||
|
||||
static gboolean enable_latency_measurement = FALSE;
|
||||
extern uint8_t *parse_sei_data (uint8_t *bs, guint size, uint32_t *payload_size, char *sei_uuid_string);
|
||||
extern uint8_t *parse_sei_data (uint8_t *bs, guint size, uint32_t *payload_size,
|
||||
char *sei_uuid_string, guint32 pixelformat);
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
GstVideoCodecFrame *
|
||||
@@ -154,6 +161,10 @@ gst_video_cudadec_mem_type (void)
|
||||
"memtype_pinned"},
|
||||
{V4L2_CUDA_MEM_TYPE_UNIFIED, "Memory type Unified",
|
||||
"memtype_unified"},
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
{V4L2_CUDA_MEM_TYPE_SURFACE_ARRAY, "Memory type Surface Array",
|
||||
"memtype_surface_array"},
|
||||
#endif
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -201,7 +212,9 @@ static GstStaticPadTemplate gst_v4l2dec_sink_template =
|
||||
"divxversion=(int) [4, 5], "
|
||||
"width=(int) [1,MAX], " "height=(int) [1,MAX]"
|
||||
";"
|
||||
"video/x-av1"
|
||||
"video/x-av1,"
|
||||
"stream-format = (string) { obu-stream },"
|
||||
"alignment = (string) { frame }"
|
||||
";"
|
||||
"video/x-vp8"
|
||||
";" "video/x-vp9," "width=(gint) [1,MAX]," "height=(gint) [1,MAX]" ";")
|
||||
@@ -239,6 +252,7 @@ enum
|
||||
PROP_ENABLE_ERROR_CHECK,
|
||||
PROP_ENABLE_MAX_PERFORMANCE,
|
||||
PROP_OPEN_MJPEG_BLOCK,
|
||||
PROP_IS_GDR_STREAM,
|
||||
/*Properties exposed on dGPU only*/
|
||||
PROP_CUDADEC_MEM_TYPE,
|
||||
PROP_CUDADEC_GPU_ID,
|
||||
@@ -389,6 +403,11 @@ gst_v4l2_video_dec_set_property_tegra (GObject * object,
|
||||
self->v4l2output->open_mjpeg_block = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_IS_GDR_STREAM:
|
||||
self->is_gdr_stream = g_value_get_boolean (value);
|
||||
self->enable_frame_type_reporting = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_CAP_BUF_DYNAMIC_ALLOCATION:
|
||||
self->cap_buf_dynamic_allocation = g_value_get_enum (value);
|
||||
break;
|
||||
@@ -440,6 +459,7 @@ gst_v4l2_video_dec_set_property_cuvid (GObject * object,
|
||||
break;
|
||||
|
||||
case PROP_CUDADEC_LOW_LATENCY:
|
||||
case PROP_DISABLE_DPB:
|
||||
self->cudadec_low_latency = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
@@ -516,6 +536,10 @@ gst_v4l2_video_dec_get_property_tegra (GObject * object,
|
||||
g_value_set_boolean (value, self->v4l2output->open_mjpeg_block);
|
||||
break;
|
||||
|
||||
case PROP_IS_GDR_STREAM:
|
||||
g_value_set_boolean (value, self->is_gdr_stream);
|
||||
break;
|
||||
|
||||
case PROP_CAP_BUF_DYNAMIC_ALLOCATION:
|
||||
g_value_set_enum (value, self->cap_buf_dynamic_allocation);
|
||||
break;
|
||||
@@ -566,6 +590,7 @@ gst_v4l2_video_dec_get_property_cuvid (GObject * object,
|
||||
break;
|
||||
|
||||
case PROP_CUDADEC_LOW_LATENCY:
|
||||
case PROP_DISABLE_DPB:
|
||||
g_value_set_boolean (value, self->cudadec_low_latency);
|
||||
break;
|
||||
|
||||
@@ -683,7 +708,7 @@ gst_v4l2_video_dec_start (GstVideoDecoder * decoder)
|
||||
self->decoded_picture_cnt = 0;
|
||||
#endif
|
||||
|
||||
self->hash_pts_systemtime = g_hash_table_new(NULL, NULL);
|
||||
self->hash_pts_systemtime = g_hash_table_new_full (NULL, NULL, NULL, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -714,6 +739,7 @@ gst_v4l2_video_dec_stop (GstVideoDecoder * decoder)
|
||||
gst_v4l2_object_stop (self->v4l2output);
|
||||
gst_v4l2_object_stop (self->v4l2capture);
|
||||
|
||||
g_hash_table_remove_all (self->hash_pts_systemtime);
|
||||
g_hash_table_destroy (self->hash_pts_systemtime);
|
||||
|
||||
if (self->input_state) {
|
||||
@@ -806,6 +832,15 @@ gboolean set_v4l2_controls (GstV4l2VideoDec *self)
|
||||
}
|
||||
}
|
||||
|
||||
if (self->is_gdr_stream) {
|
||||
if (!set_v4l2_video_mpeg_class (self->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEODEC_GDR_STREAM,
|
||||
self->is_gdr_stream)) {
|
||||
g_print ("S_EXT_CTRLS for GDR_STREAM failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
if (!set_v4l2_video_mpeg_class (self->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEO_CUDA_MEM_TYPE,
|
||||
@@ -848,12 +883,13 @@ gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
|
||||
if ((GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_H264) ||
|
||||
(GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_H265))
|
||||
{
|
||||
GST_INFO_OBJECT(self, "Pix format is h264 or h265. Bypassing set_format."
|
||||
"Reset done from handle_frame");
|
||||
self->output_flow = GST_FLOW_OK;
|
||||
self->set_format = true;
|
||||
return TRUE;
|
||||
GST_INFO_OBJECT(self, "Pix format is h264 or h265. Bypassing set_format."
|
||||
"Reset done from handle_frame");
|
||||
self->output_flow = GST_FLOW_OK;
|
||||
self->set_format = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
self->input_state = NULL;
|
||||
@@ -931,6 +967,13 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
|
||||
gst_v4l2_object_unlock_stop (self->v4l2output);
|
||||
gst_v4l2_object_unlock_stop (self->v4l2capture);
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
if (is_cuvid == TRUE) {
|
||||
/* Flush out low-level cuvid decoder buffers */
|
||||
set_v4l2_video_mpeg_class (self->v4l2output, V4L2_CID_MPEG_VIDEODEC_FLUSH_BUFFERS, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (self->v4l2output->pool)
|
||||
gst_v4l2_buffer_pool_flush (self->v4l2output->pool);
|
||||
|
||||
@@ -1248,10 +1291,12 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
|
||||
|
||||
if(enable_latency_measurement) /* TODO with better option */
|
||||
{
|
||||
gpointer in_time = g_hash_table_lookup (self->hash_pts_systemtime,
|
||||
&frame->pts);
|
||||
gdouble input_time = *((gdouble*)in_time);
|
||||
g_mutex_lock(&self->pts_hashtable_lock);
|
||||
gsize frame_pts = frame->pts;
|
||||
gpointer in_time = g_hash_table_lookup (self->hash_pts_systemtime, GSIZE_TO_POINTER(frame_pts));
|
||||
gdouble input_time = (gdouble) GPOINTER_TO_SIZE(in_time);
|
||||
gdouble output_time = get_current_system_timestamp ();
|
||||
|
||||
if (output_time < input_time)
|
||||
{
|
||||
gdouble time = G_MAXDOUBLE - input_time;
|
||||
@@ -1263,6 +1308,11 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
|
||||
GST_DEBUG_OBJECT (self, "True Decode Latency = %f \n",
|
||||
(output_time - input_time));
|
||||
}
|
||||
|
||||
//Remove the hash table entry for the frame pts
|
||||
g_hash_table_remove (self->hash_pts_systemtime, GSIZE_TO_POINTER(frame_pts));
|
||||
g_mutex_unlock(&self->pts_hashtable_lock);
|
||||
|
||||
GstCaps *reference = gst_caps_new_simple ("video/x-raw",
|
||||
"component_name", G_TYPE_STRING, GST_ELEMENT_NAME(self),
|
||||
"frame_num", G_TYPE_INT, self->frame_num++,
|
||||
@@ -1332,7 +1382,7 @@ gst_v4l2_video_remove_padding (GstCapsFeatures * features,
|
||||
if (!gst_structure_get_int (structure, "height", &height))
|
||||
return TRUE;
|
||||
#else
|
||||
guint width, height;
|
||||
guint width = 0, height = 0;
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", (gint *) & width))
|
||||
return TRUE;
|
||||
@@ -1484,18 +1534,12 @@ gst_v4l2_h265_stream_parser (GstV4l2VideoDec *self, gpointer data, guint32 size)
|
||||
break;
|
||||
case H265_PARSER_ERROR:
|
||||
/* should not really occur either */
|
||||
GST_ELEMENT_ERROR (self, STREAM, FORMAT,
|
||||
("Error parsing H.265 stream"), ("Invalid H.265 stream"));
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_WARNING_OBJECT (self, "Error parsing H.265 stream. Invalid H.265 stream");
|
||||
break;
|
||||
case H265_PARSER_NO_NAL:
|
||||
GST_ELEMENT_ERROR (self, STREAM, FORMAT,
|
||||
("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_WARNING_OBJECT (self, "No H.265 NAL unit found");
|
||||
break;
|
||||
default:
|
||||
ret = GST_FLOW_ERROR;
|
||||
//g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1543,18 +1587,12 @@ gst_v4l2_h264_stream_parser (GstV4l2VideoDec *self, gpointer data, guint32 size)
|
||||
break;
|
||||
case H264_PARSER_ERROR:
|
||||
/* should not really occur either */
|
||||
GST_ELEMENT_ERROR(self, STREAM, FORMAT,
|
||||
("Error parsing H.264 stream"), ("Invalid H.264 stream"));
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_WARNING_OBJECT(self, "Error parsing H.264 stream. Invalid H.264 stream");
|
||||
break;
|
||||
case H264_PARSER_NO_NAL:
|
||||
GST_ELEMENT_ERROR(self, STREAM, FORMAT,
|
||||
("Error parsing H.264 stream"), ("No H.264 NAL unit found"));
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_WARNING_OBJECT(self, "Error parsing H.264 stream. No H.264 NAL unit found");
|
||||
break;
|
||||
default:
|
||||
ret = GST_FLOW_ERROR;
|
||||
// g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1701,6 +1739,36 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
|
||||
gst_v4l2_video_dec_finish(decoder);
|
||||
gst_v4l2_object_stop(self->v4l2output);
|
||||
|
||||
{
|
||||
const GValue *framerate = NULL;
|
||||
GstStructure *src_pad_st = NULL, *sink_pad_st = NULL;
|
||||
GstCaps *dec_src_caps = gst_pad_get_current_caps(decoder->srcpad);
|
||||
GstCaps *dec_sink_caps = gst_pad_get_current_caps(decoder->sinkpad);
|
||||
if (dec_src_caps != NULL)
|
||||
{
|
||||
gint curr_width = self->current_width;
|
||||
gint curr_height = self->current_height;
|
||||
dec_src_caps = gst_caps_make_writable(dec_src_caps);
|
||||
sink_pad_st = gst_caps_get_structure(dec_sink_caps, 0);
|
||||
src_pad_st = gst_caps_get_structure(dec_src_caps, 0);
|
||||
gst_structure_set(src_pad_st, "width", G_TYPE_INT, curr_width,
|
||||
"height", G_TYPE_INT, curr_height,
|
||||
NULL);
|
||||
framerate = gst_structure_get_value(sink_pad_st, "framerate");
|
||||
if (framerate)
|
||||
gst_structure_set_value(src_pad_st, "framerate", framerate);
|
||||
/* Replace coded size with visible size, we want to negotiate visible size
|
||||
* with downstream, not coded size. */
|
||||
gst_caps_map_in_place(dec_src_caps, gst_v4l2_video_remove_padding, self);
|
||||
gst_pad_set_caps(decoder->srcpad, dec_src_caps);
|
||||
|
||||
GST_DEBUG_OBJECT(self, "dec_src_caps: %s", gst_caps_to_string(dec_src_caps));
|
||||
gst_caps_unref(dec_src_caps);
|
||||
gst_caps_unref(dec_sink_caps);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
GstCaps *caps = gst_pad_get_current_caps(decoder->srcpad);
|
||||
if (caps)
|
||||
@@ -1751,10 +1819,35 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
|
||||
set_v4l2_controls(self);
|
||||
GST_INFO_OBJECT(self, "Reset Done");
|
||||
|
||||
trigger_drc = false;
|
||||
self->set_format = false;
|
||||
}
|
||||
else if (self->set_format == true)
|
||||
{
|
||||
set_v4l2_controls(self);
|
||||
GstStructure *sink_pad_st = NULL, *src_pad_st = NULL;
|
||||
const GValue *framerate = NULL;
|
||||
GstCaps *dec_sink_caps = gst_pad_get_current_caps(decoder->sinkpad);
|
||||
GstCaps *dec_src_caps = gst_pad_get_current_caps(decoder->srcpad);
|
||||
if (G_UNLIKELY(dec_sink_caps != NULL) && G_UNLIKELY(dec_src_caps != NULL))
|
||||
{
|
||||
GST_DEBUG_OBJECT(self, "dec_sink_caps: %s", gst_caps_to_string(dec_sink_caps));
|
||||
dec_src_caps = gst_caps_make_writable(dec_src_caps);
|
||||
sink_pad_st = gst_caps_get_structure(dec_sink_caps, 0);
|
||||
src_pad_st = gst_caps_get_structure(dec_src_caps, 0);
|
||||
framerate = gst_structure_get_value(sink_pad_st, "framerate");
|
||||
if (framerate)
|
||||
gst_structure_set_value(src_pad_st, "framerate", framerate);
|
||||
|
||||
GST_DEBUG_OBJECT(self, "dec_src_caps: %s", gst_caps_to_string(dec_src_caps));
|
||||
|
||||
gst_pad_set_caps(decoder->srcpad, dec_src_caps);
|
||||
|
||||
gst_caps_unref(dec_sink_caps);
|
||||
gst_caps_unref(dec_src_caps);
|
||||
}
|
||||
set_v4l2_controls(self);
|
||||
self->set_format = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1762,8 +1855,10 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
* a frame. In case of RTSP inputs we drop the DELTA units which are not
|
||||
* decodable independently until we receive I / IDR frame.
|
||||
*/
|
||||
if ((GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_H264) ||
|
||||
(GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_H265))
|
||||
if (((GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_H264) ||
|
||||
(GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_H265) ||
|
||||
(GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_MPEG4)) &&
|
||||
self->is_gdr_stream == FALSE)
|
||||
{
|
||||
if ((GST_BUFFER_FLAG_IS_SET (GST_BUFFER_CAST(frame->input_buffer),
|
||||
GST_BUFFER_FLAG_DELTA_UNIT)) &&
|
||||
@@ -1782,7 +1877,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
// Decode only I Frames and drop others.
|
||||
if (GST_BUFFER_FLAG_IS_SET (GST_BUFFER_CAST(frame->input_buffer),
|
||||
GST_BUFFER_FLAG_DELTA_UNIT)) {
|
||||
gst_video_decoder_drop_frame (decoder, frame);
|
||||
gst_video_decoder_release_frame (GST_VIDEO_DECODER(self), frame);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
@@ -1790,8 +1885,12 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
|
||||
if (enable_latency_measurement)
|
||||
{
|
||||
self->buffer_in_time = get_current_system_timestamp ();
|
||||
g_hash_table_insert (self->hash_pts_systemtime, &frame->pts, &self->buffer_in_time);
|
||||
g_mutex_lock(&self->pts_hashtable_lock);
|
||||
gsize frame_pts = frame->pts;
|
||||
gsize current_time = get_current_system_timestamp ();;
|
||||
g_hash_table_insert (self->hash_pts_systemtime, GSIZE_TO_POINTER(frame_pts),
|
||||
GSIZE_TO_POINTER(current_time));
|
||||
g_mutex_unlock(&self->pts_hashtable_lock);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
|
||||
@@ -1809,7 +1908,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
|
||||
GstVideoInfo info = {0};
|
||||
GstVideoCodecState *output_state;
|
||||
GstBuffer *codec_data;
|
||||
GstBuffer *codec_data = NULL;
|
||||
GstCaps *acquired_caps, *available_caps, *caps, *filter;
|
||||
GstStructure *st;
|
||||
|
||||
@@ -1817,11 +1916,21 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
|
||||
codec_data = self->input_state->codec_data;
|
||||
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
/* For av1 stream with webm container, we have observed that codec_data field is received
|
||||
along with the caps and is a part of input_state, thus sending this to cuvidparser as
|
||||
first frame. cuvidparser does not require it. We should send the input frame directly */
|
||||
if ((GST_V4L2_PIXELFORMAT(obj) == V4L2_PIX_FMT_AV1)) {
|
||||
codec_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We are running in byte-stream mode, so we don't know the headers, but
|
||||
* we need to send something, otherwise the decoder will refuse to
|
||||
* intialize.
|
||||
*/
|
||||
if (codec_data) {
|
||||
GST_DEBUG_OBJECT (self, "codec_data field is valid. Using that as input for cuvidparser");
|
||||
gst_buffer_ref (codec_data);
|
||||
} else {
|
||||
codec_data = gst_buffer_ref (frame->input_buffer);
|
||||
@@ -1878,6 +1987,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
ret = self->output_flow;
|
||||
goto drop;
|
||||
} else if (ret != GST_FLOW_OK) {
|
||||
GST_DEBUG_OBJECT (self, "gst_v4l2_buffer_pool_process failed\n");
|
||||
goto process_failed;
|
||||
}
|
||||
}
|
||||
@@ -1891,25 +2001,27 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
if(!processed)
|
||||
{
|
||||
processed = TRUE;
|
||||
/* Wait for DQEVENT for 0.6 sec */
|
||||
/* Wait for DQEVENT for 1 sec */
|
||||
while (dqevent_loop_count < LOOP_COUNT_TO_WAIT_FOR_DQEVENT) {
|
||||
memset (&ev, 0, sizeof (ev));
|
||||
retval = obj->ioctl (obj->video_fd, VIDIOC_DQEVENT, &ev);
|
||||
dqevent_loop_count ++;
|
||||
if (retval != 0)
|
||||
{
|
||||
if (errno == EINVAL)
|
||||
if (errno == EINVAL) {
|
||||
GST_DEBUG_OBJECT (self, "VIDIOC_DQEVENT failed. Event Type: %d\n", ev.type);
|
||||
goto process_failed;
|
||||
}
|
||||
if (dqevent_loop_count == LOOP_COUNT_TO_WAIT_FOR_DQEVENT) {
|
||||
GST_DEBUG_OBJECT (self, "Stream format not found, dropping the frame\n");
|
||||
goto drop;
|
||||
}
|
||||
usleep (WAIT_TIME_PER_LOOP_FOR_DQEVENT); //TODO is this needed ?
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (dqevent_loop_count == LOOP_COUNT_TO_WAIT_FOR_DQEVENT) {
|
||||
g_print ("Stream format not found, dropping the frame\n");
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -1919,11 +2031,13 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
retval = obj->ioctl (obj->video_fd, VIDIOC_DQEVENT, &ev);
|
||||
if (retval != 0)
|
||||
{
|
||||
if (errno == EINVAL)
|
||||
if (errno == EINVAL) {
|
||||
GST_DEBUG_OBJECT (self, "VIDIOC_DQEVENT failed. Event Type: %d\n", ev.type);
|
||||
goto process_failed;
|
||||
}
|
||||
if (is_cuvid != TRUE) {
|
||||
if (ev.sequence == 0) {
|
||||
g_print ("Stream format not found, dropping the frame\n");
|
||||
GST_DEBUG_OBJECT (self, "Stream format not found, dropping the frame\n");
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
@@ -2004,6 +2118,12 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
if (output_state->caps)
|
||||
gst_caps_unref (output_state->caps);
|
||||
/* set colorimetry information returned from low level lib
|
||||
* tegrav4l2. For now it is guarded using cuvid variable to
|
||||
* avoid any regression on x86.
|
||||
*/
|
||||
if (!is_cuvid)
|
||||
output_state->info.colorimetry = info.colorimetry;
|
||||
output_state->caps = gst_video_info_to_caps (&output_state->info);
|
||||
GstCapsFeatures *features = gst_caps_features_new ("memory:NVMM", NULL);
|
||||
gst_caps_set_features (output_state->caps, 0, features);
|
||||
@@ -2065,34 +2185,6 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
if ((trigger_drc == false) && (self->set_format == true))
|
||||
{
|
||||
GstStructure *sink_pad_st = NULL, *src_pad_st = NULL;
|
||||
const GValue *framerate = NULL;
|
||||
GstCaps *dec_sink_caps = gst_pad_get_current_caps(decoder->sinkpad);
|
||||
GstCaps *dec_src_caps = gst_pad_get_current_caps(decoder->srcpad);
|
||||
if (G_UNLIKELY(dec_sink_caps != NULL) && G_UNLIKELY(dec_src_caps != NULL))
|
||||
{
|
||||
GST_DEBUG_OBJECT(self, "dec_sink_caps: %s", gst_caps_to_string(dec_sink_caps));
|
||||
dec_src_caps = gst_caps_make_writable(dec_src_caps);
|
||||
sink_pad_st = gst_caps_get_structure(dec_sink_caps, 0);
|
||||
src_pad_st = gst_caps_get_structure(dec_src_caps, 0);
|
||||
framerate = gst_structure_get_value(sink_pad_st, "framerate");
|
||||
if (framerate)
|
||||
gst_structure_set_value(src_pad_st, "framerate", framerate);
|
||||
|
||||
GST_DEBUG_OBJECT(self, "dec_src_caps: %s", gst_caps_to_string(dec_src_caps));
|
||||
|
||||
gst_pad_set_caps(decoder->srcpad, dec_src_caps);
|
||||
|
||||
gst_caps_unref(dec_sink_caps);
|
||||
gst_caps_unref(dec_src_caps);
|
||||
}
|
||||
}
|
||||
trigger_drc = false;
|
||||
self->set_format = false;
|
||||
#endif
|
||||
|
||||
task_state = gst_pad_get_task_state (GST_VIDEO_DECODER_SRC_PAD (self));
|
||||
if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
|
||||
@@ -2138,6 +2230,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
ret = GST_FLOW_OK;
|
||||
goto drop;
|
||||
}
|
||||
GST_DEBUG_OBJECT (self, "gst_v4l2_buffer_pool_process failed\n");
|
||||
goto process_failed;
|
||||
}
|
||||
}
|
||||
@@ -2151,7 +2244,8 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
GST_BUFFER_COPY_META, 0, 0);
|
||||
|
||||
/* Parse SEI data from the bitsream */
|
||||
if ((is_cuvid == TRUE) && (self->extract_sei_type5_data == TRUE))
|
||||
if ((is_cuvid == TRUE) && (self->extract_sei_type5_data == TRUE) &&
|
||||
((obj->fmtdesc->pixelformat == V4L2_PIX_FMT_H264) || (obj->fmtdesc->pixelformat == V4L2_PIX_FMT_H265)))
|
||||
{
|
||||
uint8_t *sei_type5_payload = NULL;
|
||||
GstMapInfo map = {0};
|
||||
@@ -2165,7 +2259,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
uint32_t payload_size = 0;
|
||||
uint8_t *stream_data = (uint8_t *)map.data;
|
||||
sei_type5_payload = parse_sei_data (stream_data, map.size,
|
||||
&payload_size, self->sei_uuid_string);
|
||||
&payload_size, self->sei_uuid_string, obj->fmtdesc->pixelformat);
|
||||
if (sei_type5_payload != NULL)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "sei_type5_payload found\n");
|
||||
@@ -2218,8 +2312,7 @@ start_task_failed:
|
||||
process_failed:
|
||||
{
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
|
||||
(_("Failed to process frame.")),
|
||||
("Maybe be due to not enough memory or failing driver"));
|
||||
(_("Failed to process frame.")), (NULL));
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto drop;
|
||||
}
|
||||
@@ -2263,7 +2356,7 @@ gst_v4l2_video_dec_src_query (GstVideoDecoder * decoder, GstQuery * query)
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CAPS:{
|
||||
GstCaps *filter, *result = NULL;
|
||||
GstCaps *filter = NULL, *result = NULL;
|
||||
GstPad *pad = GST_VIDEO_DECODER_SRC_PAD (decoder);
|
||||
|
||||
gst_query_parse_caps (query, &filter);
|
||||
@@ -2389,7 +2482,7 @@ gst_v4l2_video_dec_src_event (GstVideoDecoder * decoder, GstEvent * event)
|
||||
case GST_EVENT_SEEK:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate;
|
||||
gdouble rate = 0.0;
|
||||
GstSeekFlags flags;
|
||||
GstSeekType start_type, stop_type;
|
||||
gint64 start, stop;
|
||||
@@ -2467,6 +2560,7 @@ gst_v4l2_video_dec_finalize (GObject * object)
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
g_cond_clear (&self->v4l2capture->cplane_stopped_cond);
|
||||
g_mutex_clear (&self->v4l2capture->cplane_stopped_lock);
|
||||
g_mutex_clear (&self->pts_hashtable_lock);
|
||||
#endif
|
||||
|
||||
gst_v4l2_object_destroy (self->v4l2capture);
|
||||
@@ -2503,6 +2597,8 @@ gst_v4l2_video_dec_init (GstV4l2VideoDec * self)
|
||||
self->cudadec_low_latency = default_cudadec_low_latency;
|
||||
self->idr_received = FALSE;
|
||||
self->rate = 1;
|
||||
self->old_width = 0;
|
||||
self->old_height = 0;
|
||||
self->cap_buf_dynamic_allocation = DEFAULT_CAP_BUF_DYNAMIC_ALLOCATION;
|
||||
#endif
|
||||
|
||||
@@ -2528,6 +2624,9 @@ gst_v4l2_video_dec_subinstance_init (GTypeInstance * instance, gpointer g_class)
|
||||
gst_v4l2_get_output, gst_v4l2_set_output, NULL);
|
||||
self->v4l2output->no_initial_format = TRUE;
|
||||
self->v4l2output->keep_aspect = FALSE;
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
self->v4l2output->open_mjpeg_block = TRUE;
|
||||
#endif
|
||||
|
||||
self->v4l2capture = gst_v4l2_object_new (GST_ELEMENT (self),
|
||||
GST_OBJECT (GST_VIDEO_DECODER_SRC_PAD (self)),
|
||||
@@ -2538,6 +2637,7 @@ gst_v4l2_video_dec_subinstance_init (GTypeInstance * instance, gpointer g_class)
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
g_mutex_init (&self->v4l2capture->cplane_stopped_lock);
|
||||
g_cond_init (&self->v4l2capture->cplane_stopped_cond);
|
||||
g_mutex_init (&self->pts_hashtable_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2640,6 +2740,12 @@ gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass)
|
||||
"Enable max performance", "Set to enable max performance",
|
||||
DEFAULT_MAX_PERFORMANCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_IS_GDR_STREAM,
|
||||
g_param_spec_boolean ("is-gdr-stream",
|
||||
"is-gdr-stream",
|
||||
"Set the flag to allow GDR decode for H264/HEVC",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_CAP_BUF_DYNAMIC_ALLOCATION,
|
||||
g_param_spec_enum ("capture-buffer-dynamic-allocation",
|
||||
"Enable capture buffer dynamic allocation",
|
||||
@@ -2671,6 +2777,12 @@ gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass)
|
||||
default_cudadec_low_latency,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_DISABLE_DPB,
|
||||
g_param_spec_boolean ("disable-dpb",
|
||||
"Disable DPB buffer",
|
||||
"Set to disable DPB buffer for low latency",
|
||||
DEFAULT_DISABLE_DPB, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_EXTRACT_SEI_TYPE5_DATA,
|
||||
g_param_spec_boolean ("extract-sei-type5-data",
|
||||
"extract-sei-type5-data",
|
||||
@@ -2898,7 +3010,7 @@ void
|
||||
gst_v4l2_video_dec_register (GstPlugin * plugin, const gchar * basename,
|
||||
const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
|
||||
{
|
||||
GTypeQuery type_query;
|
||||
GTypeQuery type_query = { 0, };
|
||||
GTypeInfo type_info = { 0, };
|
||||
GType type, subtype;
|
||||
GstV4l2VideoDecCData *cdata;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Collabora Ltd.
|
||||
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
|
||||
* Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -48,7 +49,7 @@ G_BEGIN_DECLS
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
#define GstV4l2VideoDec GstNvV4l2VideoDec
|
||||
#define GstV4l2VideoDecClass GstNvV4l2VideoDecClass
|
||||
#define LOOP_COUNT_TO_WAIT_FOR_DQEVENT 6
|
||||
#define LOOP_COUNT_TO_WAIT_FOR_DQEVENT 10
|
||||
#define WAIT_TIME_PER_LOOP_FOR_DQEVENT 100*1000
|
||||
|
||||
#define VP8_START_BYTE_0 0x9D
|
||||
@@ -82,7 +83,6 @@ struct _GstV4l2VideoDec
|
||||
guint64 frame_num;
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
GHashTable* hash_pts_systemtime;
|
||||
gdouble buffer_in_time;
|
||||
guint64 decoded_picture_cnt;
|
||||
guint32 skip_frames;
|
||||
gboolean idr_received;
|
||||
@@ -95,6 +95,7 @@ struct _GstV4l2VideoDec
|
||||
gboolean enable_error_check;
|
||||
gboolean enable_max_performance;
|
||||
gboolean set_format;
|
||||
gboolean is_gdr_stream;
|
||||
guint32 cudadec_mem_type;
|
||||
guint32 cudadec_gpu_id;
|
||||
guint32 cudadec_num_surfaces;
|
||||
@@ -108,6 +109,7 @@ struct _GstV4l2VideoDec
|
||||
guint32 old_width;
|
||||
guint32 old_height;
|
||||
gboolean valid_vpx;
|
||||
GMutex pts_hashtable_lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* Authors Ayaka <ayaka@soulik.info>
|
||||
* Copyright (C) 2017 Collabora Ltd.
|
||||
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -79,8 +81,12 @@ gst_v4l2_video_enc_find_nearest_frame (GstV4l2VideoEnc *self,
|
||||
gboolean set_v4l2_video_encoder_properties (GstVideoEncoder * encoder);
|
||||
gboolean setQpRange (GstV4l2Object * v4l2object, guint label, guint MinQpI,
|
||||
guint MaxQpI, guint MinQpP, guint MaxQpP, guint MinQpB, guint MaxQpB);
|
||||
gboolean setIntraRefreshParams (GstV4l2Object * v4l2object, guint label, guint enableIntraRefresh,
|
||||
guint intraRefreshPeriod, guint intraRefreshCnt);
|
||||
gboolean setHWPresetType (GstV4l2Object * v4l2object, guint label,
|
||||
enum v4l2_enc_hw_preset_type type);
|
||||
gboolean setInitQPParams (GstV4l2Object * v4l2object,
|
||||
guint32 quantI, guint32 quantP, guint32 quantB);
|
||||
gint gst_v4l2_trace_file_open (FILE ** file);
|
||||
void gst_v4l2_trace_file_close (FILE * file);
|
||||
void gst_v4l2_trace_printf (FILE * file, const gchar *fmt, ...);
|
||||
@@ -92,20 +98,25 @@ gst_v4l2_video_enc_parse_initqp (GstV4l2VideoEnc * self, const gchar * arr);
|
||||
static gboolean
|
||||
gst_v4l2_video_enc_parse_quantization_range (GstV4l2VideoEnc * self,
|
||||
const gchar * arr);
|
||||
static GType gst_v4l2_videnc_hw_preset_level_get_type (void);
|
||||
static gboolean
|
||||
gst_v4l2_video_enc_parse_intra_refresh_params (GstV4l2VideoEnc * self,
|
||||
const gchar * arr);
|
||||
static GType gst_v4l2_videnc_tuning_info_get_type (void);
|
||||
static void gst_v4l2_video_encoder_forceIDR (GstV4l2VideoEnc * self);
|
||||
|
||||
static GType gst_v4l2_videnc_ratecontrol_get_type (void);
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
static GType gst_v4l2_videnc_hw_preset_level_get_type (void);
|
||||
static void gst_v4l2_video_encoder_forceIDR (GstV4l2VideoEnc * self);
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/* actions */
|
||||
SIGNAL_FORCE_IDR,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
static guint gst_v4l2_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum
|
||||
@@ -123,13 +134,16 @@ enum
|
||||
PROP_CUDAENC_CONSTQP,
|
||||
PROP_CUDAENC_INITQP,
|
||||
PROP_CUDAENC_TUNING_INFO_ID,
|
||||
PROP_CUDAENC_MEM_TYPE,
|
||||
PROP_MAXBITRATE,
|
||||
PROP_VBVBUFSIZE,
|
||||
PROP_VBVINIT,
|
||||
PROP_AQ,
|
||||
PROP_TEMPORAL_AQ,
|
||||
PROP_CQ,
|
||||
/* Properties exposed on Tegra only */
|
||||
PROP_INTRA_REFRESH,
|
||||
PROP_SEI_UUID,
|
||||
/* TEGRA PROPERTIES */
|
||||
PROP_PEAK_BITRATE,
|
||||
PROP_QUANT_I_FRAMES,
|
||||
PROP_QUANT_P_FRAMES,
|
||||
@@ -159,6 +173,7 @@ enum
|
||||
#define GST_V4L2_VIDEO_ENC_PEAK_BITRATE_DEFAULT (0)
|
||||
#define DEFAULT_RATE_CONTROL V4L2_MPEG_VIDEO_BITRATE_MODE_CBR
|
||||
#define DEFAULT_INTRA_FRAME_INTERVAL 30
|
||||
#define DEFAULT_INTRA_FRAME_INTERVAL_CUVID (0xffffffff) //GOP Length=INFINITE_GOPLENGTH
|
||||
#define DEFAULT_CUDAENC_GPU_ID 0
|
||||
#define DEFAULT_CUDAENC_PRESET_ID 1
|
||||
#define DEFAULT_CUDAENC_TUNING_INFO_ID 3
|
||||
@@ -167,12 +182,18 @@ enum
|
||||
#define GST_V4L2_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT (0xffffffff)
|
||||
#define GST_V4L2_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT (0xffffffff)
|
||||
#define DEFAULT_HW_PRESET_LEVEL V4L2_ENC_HW_PRESET_ULTRAFAST
|
||||
#define DEFAULT_HW_PRESET_LEVEL_CUVID 0
|
||||
#define DEFAULT_TUNING_INFO_PRESET V4L2_ENC_TUNING_INFO_LOW_LATENCY
|
||||
#define DEFAULT_CUDAENC_MEM_TYPE V4L2_CUDA_MEM_TYPE_DEVICE
|
||||
|
||||
#define GST_TYPE_V4L2_VID_CUDAENC_MEM_TYPE (gst_video_cudaenc_mem_type())
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
#define GST_TYPE_V4L2_VID_ENC_HW_PRESET_LEVEL (gst_v4l2_videnc_hw_preset_level_get_type ())
|
||||
#endif
|
||||
#define GST_TYPE_V4L2_VID_ENC_TUNING_INFO_PRESET (gst_v4l2_videnc_tuning_info_get_type ())
|
||||
#define GST_TYPE_V4L2_VID_ENC_RATECONTROL (gst_v4l2_videnc_ratecontrol_get_type())
|
||||
#define DEFAULT_VBV_SIZE 4000000
|
||||
#define DEFAULT_SEI_UUID "NVDS_CUSTOMMETA"
|
||||
#endif
|
||||
|
||||
#define gst_v4l2_video_enc_parent_class parent_class
|
||||
@@ -226,6 +247,31 @@ gst_v4l2_enc_capture_io_mode_get_type (void)
|
||||
}
|
||||
return v4l2_enc_capture_io_mode;
|
||||
}
|
||||
|
||||
static GType
|
||||
gst_video_cudaenc_mem_type (void)
|
||||
{
|
||||
static GType qtype = 0;
|
||||
|
||||
if (qtype == 0) {
|
||||
static const GEnumValue values[] = {
|
||||
{V4L2_CUDA_MEM_TYPE_DEVICE, "Memory type Device", "memtype_device"},
|
||||
{V4L2_CUDA_MEM_TYPE_PINNED, "Memory type Host Pinned",
|
||||
"memtype_pinned"},
|
||||
{V4L2_CUDA_MEM_TYPE_UNIFIED, "Memory type Unified",
|
||||
"memtype_unified"},
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
{V4L2_CUDA_MEM_TYPE_SURFACE_ARRAY, "Memory type Surface Array",
|
||||
"memtype_surface_array"},
|
||||
#endif
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
qtype = g_enum_register_static ("CudaEncMemType", values);
|
||||
}
|
||||
return qtype;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
@@ -268,7 +314,13 @@ gst_v4l2_video_enc_set_property_tegra (GObject * object,
|
||||
case PROP_QUANT_RANGE:
|
||||
gst_v4l2_video_enc_parse_quantization_range (self,
|
||||
g_value_get_string (value));
|
||||
self->set_qpRange = TRUE;
|
||||
if (self->MinQpP == (guint)-1 && self->MaxQpP == (guint)-1 &&
|
||||
self->MinQpI == (guint)-1 && self->MaxQpI == (guint)-1 &&
|
||||
self->MinQpB == (guint)-1 && self->MaxQpB == (guint)-1) {
|
||||
self->set_qpRange = FALSE;
|
||||
}
|
||||
else
|
||||
self->set_qpRange = TRUE;
|
||||
break;
|
||||
|
||||
case PROP_QUANT_I_FRAMES:
|
||||
@@ -356,6 +408,9 @@ gst_v4l2_video_enc_set_property_cuvid (GObject * object,
|
||||
break;
|
||||
|
||||
case PROP_VBVBUFSIZE:
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
case PROP_VIRTUAL_BUFFER_SIZE:
|
||||
#endif
|
||||
self->vbvbufsize = g_value_get_uint (value);
|
||||
break;
|
||||
|
||||
@@ -385,6 +440,21 @@ gst_v4l2_video_enc_set_property_cuvid (GObject * object,
|
||||
self->set_qpRange = TRUE;
|
||||
break;
|
||||
|
||||
case PROP_INTRA_REFRESH:
|
||||
gst_v4l2_video_enc_parse_intra_refresh_params (self,
|
||||
g_value_get_string (value));
|
||||
if (self->enableIntraRefresh)
|
||||
self->set_intrarefresh = TRUE;
|
||||
break;
|
||||
|
||||
case PROP_SEI_UUID:
|
||||
self->sei_uuid = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_CUDAENC_MEM_TYPE:
|
||||
self->cudaenc_mem_type = g_value_get_enum(value);
|
||||
break;
|
||||
|
||||
case PROP_CUDAENC_GPU_ID:
|
||||
self->cudaenc_gpu_id = g_value_get_uint (value);
|
||||
break;
|
||||
@@ -422,6 +492,35 @@ gst_v4l2_video_enc_set_property_cuvid (GObject * object,
|
||||
case PROP_COPY_METADATA:
|
||||
self->copy_meta = g_value_get_boolean (value);
|
||||
break;
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
case PROP_PEAK_BITRATE:
|
||||
self->peak_bitrate = g_value_get_uint(value);
|
||||
break;
|
||||
|
||||
case PROP_QUANT_I_FRAMES:
|
||||
self->quant_i_frames = g_value_get_uint(value);
|
||||
break;
|
||||
|
||||
case PROP_QUANT_P_FRAMES:
|
||||
self->quant_p_frames = g_value_get_uint(value);
|
||||
break;
|
||||
|
||||
case PROP_QUANT_B_FRAMES:
|
||||
self->quant_b_frames = g_value_get_uint(value);
|
||||
break;
|
||||
|
||||
case PROP_HW_PRESET_LEVEL:
|
||||
self->hw_preset_level = g_value_get_enum(value);
|
||||
break;
|
||||
|
||||
case PROP_MEASURE_LATENCY:
|
||||
self->measure_latency = g_value_get_boolean(value);
|
||||
break;
|
||||
|
||||
case PROP_RC_ENABLE:
|
||||
self->ratecontrol_enable = g_value_get_boolean(value);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* By default, only set on output */
|
||||
@@ -548,6 +647,9 @@ gst_v4l2_video_enc_get_property_cuvid (GObject * object,
|
||||
break;
|
||||
|
||||
case PROP_VBVBUFSIZE:
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
case PROP_VIRTUAL_BUFFER_SIZE:
|
||||
#endif
|
||||
g_value_set_uint (value, self->vbvbufsize);
|
||||
break;
|
||||
|
||||
@@ -567,8 +669,8 @@ gst_v4l2_video_enc_get_property_cuvid (GObject * object,
|
||||
g_value_set_uint (value, self->targetQuality);
|
||||
break;
|
||||
|
||||
case PROP_INTRA_FRAME_INTERVAL:
|
||||
g_value_set_uint (value, self->iframeinterval);
|
||||
case PROP_CUDAENC_MEM_TYPE:
|
||||
g_value_set_enum(value, self->cudaenc_mem_type);
|
||||
break;
|
||||
|
||||
case PROP_CUDAENC_GPU_ID:
|
||||
@@ -583,6 +685,14 @@ gst_v4l2_video_enc_get_property_cuvid (GObject * object,
|
||||
// gst_v4l2_video_enc_get_quantization_range (self, value);
|
||||
break;
|
||||
|
||||
case PROP_INTRA_REFRESH:
|
||||
g_value_set_string(value, "1,30,1");
|
||||
break;
|
||||
|
||||
case PROP_SEI_UUID:
|
||||
g_value_set_string (value, self->sei_uuid);
|
||||
break;
|
||||
|
||||
case PROP_CUDAENC_CONSTQP:
|
||||
break;
|
||||
|
||||
@@ -608,6 +718,40 @@ gst_v4l2_video_enc_get_property_cuvid (GObject * object,
|
||||
case PROP_COPY_METADATA:
|
||||
g_value_set_boolean (value, self->copy_meta);
|
||||
break;
|
||||
|
||||
case PROP_INTRA_FRAME_INTERVAL:
|
||||
g_value_set_uint(value, self->iframeinterval);
|
||||
break;
|
||||
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
case PROP_PEAK_BITRATE:
|
||||
g_value_set_uint(value, self->peak_bitrate);
|
||||
break;
|
||||
|
||||
case PROP_QUANT_I_FRAMES:
|
||||
g_value_set_uint(value, self->quant_i_frames);
|
||||
break;
|
||||
|
||||
case PROP_QUANT_P_FRAMES:
|
||||
g_value_set_uint(value, self->quant_p_frames);
|
||||
break;
|
||||
|
||||
case PROP_QUANT_B_FRAMES:
|
||||
g_value_set_uint(value, self->quant_b_frames);
|
||||
break;
|
||||
|
||||
case PROP_HW_PRESET_LEVEL:
|
||||
g_value_set_enum(value, self->hw_preset_level);
|
||||
break;
|
||||
|
||||
case PROP_MEASURE_LATENCY:
|
||||
g_value_set_boolean(value, self->measure_latency);
|
||||
break;
|
||||
|
||||
case PROP_RC_ENABLE:
|
||||
g_value_set_boolean(value, self->ratecontrol_enable);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* By default read from output */
|
||||
@@ -628,10 +772,6 @@ gst_v4l2_video_enc_open (GstVideoEncoder * encoder)
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
const gchar *mimetype;
|
||||
GstStructure *s;
|
||||
GstV4l2VideoEncClass *klass = NULL;
|
||||
if (is_cuvid == TRUE)
|
||||
klass = GST_V4L2_VIDEO_ENC_GET_CLASS (encoder);
|
||||
|
||||
#endif
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Opening");
|
||||
@@ -671,19 +811,6 @@ gst_v4l2_video_enc_open (GstVideoEncoder * encoder)
|
||||
} else
|
||||
g_print ("%s: failed to open trace file\n", __func__);
|
||||
}
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
if (strcmp (klass->codec_name, "H264") == 0
|
||||
|| strcmp (klass->codec_name, "H265") == 0){
|
||||
if (!klass->set_encoder_properties (encoder)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!set_v4l2_video_encoder_properties (encoder)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
|
||||
@@ -883,8 +1010,10 @@ gboolean is_drc (GstVideoEncoder *encoder, GstCaps *input_caps)
|
||||
gst_structure_get_int(input_caps_st, "height", &new_height);
|
||||
|
||||
GST_INFO_OBJECT(encoder, "curr resolution: [%dx%d], new resolution: [%dx%d]", curr_width, curr_height, new_width, new_height);
|
||||
if ((curr_width != new_width) || (curr_height != new_height))
|
||||
if ((curr_width != new_width) || (curr_height != new_height)) {
|
||||
gst_caps_unref(sink_caps);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gst_caps_unref(sink_caps);
|
||||
return FALSE;
|
||||
@@ -895,13 +1024,20 @@ void set_encoder_src_caps (GstVideoEncoder *encoder, GstCaps *input_caps)
|
||||
GstStructure *src_caps_st, *input_caps_st;
|
||||
const GValue *framerate = NULL;
|
||||
GstCaps *src_caps = gst_caps_make_writable(gst_pad_get_current_caps(encoder->srcpad));
|
||||
if (!src_caps) {
|
||||
GST_WARNING_OBJECT(encoder, "No current caps available on srcpad");
|
||||
return;
|
||||
}
|
||||
|
||||
src_caps_st = gst_caps_get_structure(src_caps, 0);
|
||||
input_caps_st = gst_caps_get_structure(input_caps, 0);
|
||||
framerate = gst_structure_get_value(input_caps_st, "framerate");
|
||||
if (framerate)
|
||||
gst_structure_set_value(src_caps_st, "framerate", framerate);
|
||||
|
||||
GST_DEBUG_OBJECT(encoder, "enc_src_caps: %s", gst_caps_to_string(src_caps));
|
||||
gchar *caps_str = gst_caps_to_string(src_caps);
|
||||
GST_DEBUG_OBJECT(encoder, "enc_src_caps: %s", caps_str);
|
||||
g_free(caps_str);
|
||||
gst_pad_set_caps(encoder->srcpad, src_caps);
|
||||
gst_caps_unref(src_caps);
|
||||
}
|
||||
@@ -921,6 +1057,11 @@ reconfigure_fps (GstVideoEncoder *encoder, GstCaps *input_caps, guint label)
|
||||
/*Check if current fps is same as in newly received caps */
|
||||
GstStructure *sink_pad_st, *input_caps_st;
|
||||
GstCaps *sink_caps = gst_pad_get_current_caps(encoder->sinkpad);
|
||||
if (!sink_caps) {
|
||||
GST_WARNING_OBJECT(encoder, "No current caps available on sinkpad");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sink_pad_st = gst_caps_get_structure(sink_caps, 0);
|
||||
input_caps_st = gst_caps_get_structure(input_caps, 0);
|
||||
gst_structure_get_fraction (sink_pad_st, "framerate", &curr_fps_n, &curr_fps_d);
|
||||
@@ -931,6 +1072,7 @@ reconfigure_fps (GstVideoEncoder *encoder, GstCaps *input_caps, guint label)
|
||||
enc_config.fps_d = new_fps_d;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT(encoder, "No change in framerate");
|
||||
gst_caps_unref(sink_caps);
|
||||
return TRUE;
|
||||
}
|
||||
memset (&control, 0, sizeof (control));
|
||||
@@ -946,9 +1088,11 @@ reconfigure_fps (GstVideoEncoder *encoder, GstCaps *input_caps, guint label)
|
||||
ret = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret < 0) {
|
||||
GST_WARNING_OBJECT (encoder, "Error in reconfiguring fps\n");
|
||||
gst_caps_unref(sink_caps);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_caps_unref(sink_caps);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
@@ -965,6 +1109,7 @@ gst_v4l2_video_enc_set_format (GstVideoEncoder * encoder,
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
const gchar *mimetype;
|
||||
GstStructure *s;
|
||||
gboolean drc = FALSE;
|
||||
#endif
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
|
||||
@@ -980,6 +1125,7 @@ gst_v4l2_video_enc_set_format (GstVideoEncoder * encoder,
|
||||
if (is_cuvid == TRUE) {
|
||||
if (is_drc (encoder, state->caps)) {
|
||||
/*TODO: Reset encoder to allocate new buffer size at encoder output plane*/
|
||||
drc = TRUE;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (self, "Not DRC. Reconfigure encoder with new fps if required");
|
||||
if (!reconfigure_fps(encoder, state->caps, V4L2_CID_MPEG_VIDEOENC_RECONFIG_FPS))
|
||||
@@ -999,6 +1145,12 @@ gst_v4l2_video_enc_set_format (GstVideoEncoder * encoder,
|
||||
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
self->input_state = NULL;
|
||||
|
||||
if (drc == TRUE) {
|
||||
g_print("Drc detected, reconfiguring encoder\n");
|
||||
gst_v4l2_video_enc_close(encoder);
|
||||
gst_v4l2_video_enc_open(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
outcaps = gst_pad_get_pad_template_caps (encoder->srcpad);
|
||||
@@ -1170,7 +1322,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
|
||||
|
||||
if (!failed && klass->level_cid && get_string_list (s, "level", &levels)) {
|
||||
GList *l;
|
||||
gchar *tier;
|
||||
gchar *tier = NULL;
|
||||
GQueue tiers = G_QUEUE_INIT;
|
||||
|
||||
for (l = levels.head; l; l = l->next) {
|
||||
@@ -1180,28 +1332,27 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
|
||||
|
||||
GST_TRACE_OBJECT (ctx->self, "Trying level %s", level);
|
||||
|
||||
if (is_cuvid == FALSE) {
|
||||
if (!strcmp (klass->codec_name, "H265")) {
|
||||
/* Setting default tier*/
|
||||
tier = "main";
|
||||
if (!strcmp (klass->codec_name, "H265")) {
|
||||
/* Setting default tier*/
|
||||
tier = "main";
|
||||
}
|
||||
|
||||
if (!failed && get_string_list(s, "tier", &tiers)) {
|
||||
GList *lt;
|
||||
|
||||
for (lt = tiers.head; lt; lt = lt->next) {
|
||||
tier = lt->data;
|
||||
GST_TRACE_OBJECT(ctx->self, "Trying tier %s", tier);
|
||||
}
|
||||
}
|
||||
|
||||
if (!failed && get_string_list(s, "tier", &tiers)) {
|
||||
GList *lt;
|
||||
if (!strcmp (klass->codec_name, "H265")) {
|
||||
gchar *separator = "_";
|
||||
gint size = strlen(level) + strlen(separator) + strlen(tier) + 1;
|
||||
gchar tier_level[size];
|
||||
|
||||
for (lt = tiers.head; lt; lt = lt->next) {
|
||||
tier = lt->data;
|
||||
GST_TRACE_OBJECT(ctx->self, "Trying tier %s", tier);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp (klass->codec_name, "H265")) {
|
||||
gint size = strlen(level) + strlen(tier) + 1;
|
||||
gchar tier_level[size];
|
||||
|
||||
stpcpy(stpcpy(tier_level, tier), level);
|
||||
level = tier_level;
|
||||
}
|
||||
stpcpy(stpcpy(stpcpy(tier_level, tier), separator), level);
|
||||
level = tier_level;
|
||||
}
|
||||
|
||||
control.id = klass->level_cid;
|
||||
@@ -1218,6 +1369,15 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
|
||||
|
||||
level = klass->level_to_string (control.value);
|
||||
|
||||
if (!strcmp(klass->codec_name, "H265"))
|
||||
{
|
||||
gchar **tier_level = g_strsplit(level, "_", 2);
|
||||
level = tier_level[1];
|
||||
tier = tier_level[0];
|
||||
ctx->tier = tier;
|
||||
free(tier_level);
|
||||
}
|
||||
|
||||
if (control.value == v4l2_level) {
|
||||
ctx->level = level;
|
||||
break;
|
||||
@@ -1227,6 +1387,9 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
|
||||
ctx->level = level;
|
||||
break;
|
||||
}
|
||||
|
||||
g_queue_foreach(&tiers, (GFunc)g_free, NULL);
|
||||
g_queue_clear(&tiers);
|
||||
}
|
||||
|
||||
if (levels.length && !ctx->level)
|
||||
@@ -1277,6 +1440,27 @@ gst_v4l2_video_enc_negotiate (GstVideoEncoder * encoder)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set CUDA ENC GPU ID. This should be set before calling S_FMT on the capture plane*/
|
||||
if (is_cuvid == TRUE) {
|
||||
GstV4l2Object *v4l2object = self->v4l2output;
|
||||
struct v4l2_ext_control control;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
memset(&control, 0, sizeof(control));
|
||||
memset(&ctrls, 0, sizeof(ctrls));
|
||||
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &control;
|
||||
ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
|
||||
|
||||
control.id = V4L2_CID_MPEG_VIDEO_CUDA_GPU_ID;
|
||||
control.value = self->cudaenc_gpu_id;
|
||||
|
||||
if (v4l2object->ioctl(v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) {
|
||||
GST_WARNING_OBJECT(self, "Error in setting CUDA ENC GPU ID\n");
|
||||
goto not_negotiated;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_V4L2_TARGET_NV
|
||||
if (klass->profile_cid && !ctx.profile) {
|
||||
struct v4l2_control control = { 0, };
|
||||
@@ -1547,6 +1731,16 @@ gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
|
||||
|
||||
g_free (in_time_pt);
|
||||
}
|
||||
|
||||
/* At this point, the delta unit buffer flag is already correctly set by
|
||||
* gst_v4l2_buffer_pool_process. Since gst_video_encoder_finish_frame
|
||||
* will overwrite it from GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame),
|
||||
* set that here.
|
||||
*/
|
||||
if (GST_BUFFER_FLAG_IS_SET (frame->output_buffer, GST_BUFFER_FLAG_DELTA_UNIT))
|
||||
GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
|
||||
else
|
||||
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
|
||||
#endif
|
||||
|
||||
ret = gst_video_encoder_finish_frame (encoder, frame);
|
||||
@@ -1677,6 +1871,7 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||
self->v4l2output->sei_payload = NULL;
|
||||
if (meta->sei_metadata_type == (guint)GST_USER_SEI_META)
|
||||
{
|
||||
self->v4l2output->sei_uuid = g_strdup (self->sei_uuid);
|
||||
self->v4l2output->sei_payload_size = meta->sei_metadata_size;
|
||||
self->v4l2output->sei_payload = (void *) meta->sei_metadata_ptr;
|
||||
}
|
||||
@@ -1704,6 +1899,13 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||
/* ERRORS */
|
||||
activate_failed:
|
||||
{
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
/* Release the entry added to the queue in the case of failure */
|
||||
if (self->tracing_file_enc) {
|
||||
in_time = g_queue_pop_tail (self->got_frame_pt);
|
||||
g_free (in_time);
|
||||
}
|
||||
#endif
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
|
||||
(_("Failed to allocate required memory.")),
|
||||
("Buffer pool activation failed"));
|
||||
@@ -1733,6 +1935,13 @@ process_failed:
|
||||
}
|
||||
drop:
|
||||
{
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
/* Release the entry added to the queue in the case of failure */
|
||||
if (self->tracing_file_enc) {
|
||||
in_time = g_queue_pop_tail (self->got_frame_pt);
|
||||
g_free (in_time);
|
||||
}
|
||||
#endif
|
||||
gst_video_encoder_finish_frame (encoder, frame);
|
||||
return ret;
|
||||
}
|
||||
@@ -2032,6 +2241,7 @@ gst_v4l2_video_enc_init (GstV4l2VideoEnc * self)
|
||||
self->MinQpB = (guint) - 1;
|
||||
self->MaxQpB = (guint) - 1;
|
||||
self->set_qpRange = FALSE;
|
||||
self->set_intrarefresh = FALSE;
|
||||
self->force_idr = FALSE;
|
||||
self->force_intra = FALSE;
|
||||
self->copy_timestamp = FALSE;
|
||||
@@ -2043,11 +2253,14 @@ gst_v4l2_video_enc_init (GstV4l2VideoEnc * self)
|
||||
self->slice_output = FALSE;
|
||||
self->best_prev = NULL;
|
||||
self->buf_pts_prev = GST_CLOCK_STIME_NONE;
|
||||
self->sei_uuid = DEFAULT_SEI_UUID;
|
||||
if (is_cuvid == TRUE)
|
||||
{
|
||||
self->cudaenc_gpu_id = DEFAULT_CUDAENC_GPU_ID;
|
||||
self->cudaenc_preset_id = DEFAULT_CUDAENC_PRESET_ID;
|
||||
self->cudaenc_tuning_info_id = DEFAULT_TUNING_INFO_PRESET;
|
||||
self->iframeinterval = DEFAULT_INTRA_FRAME_INTERVAL_CUVID;
|
||||
self->hw_preset_level = 0;
|
||||
}
|
||||
|
||||
const gchar * latency = g_getenv("NVDS_ENABLE_LATENCY_MEASUREMENT");
|
||||
@@ -2122,20 +2335,21 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
"Set bitrate for v4l2 encode",
|
||||
0, G_MAXUINT, GST_V4L2_VIDEO_ENC_BITRATE_DEFAULT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
GST_PARAM_MUTABLE_PLAYING));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_INTRA_FRAME_INTERVAL,
|
||||
g_param_spec_uint ("iframeinterval", "Intra Frame interval",
|
||||
"Encoding Intra Frame occurance frequency",
|
||||
0, G_MAXUINT, DEFAULT_INTRA_FRAME_INTERVAL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
g_param_spec_uint ("iframeinterval", "Intra Frame interval",
|
||||
"Encoding Intra Frame occurance frequency",
|
||||
0, G_MAXUINT, (is_cuvid == TRUE) ? DEFAULT_INTRA_FRAME_INTERVAL_CUVID:
|
||||
DEFAULT_INTRA_FRAME_INTERVAL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_QUANT_RANGE,
|
||||
g_param_spec_string ("qp-range", "qpp-range",
|
||||
"Qunatization range for P, I and B frame,\n"
|
||||
"\t\t\t Use string with unsigned integer values of Qunatization Range \n"
|
||||
"\t\t\t in MinQpP,MaxQpP:MinQpI,MaxQpI:MinQpB,MaxQpB order, to set the property.",
|
||||
"Quantization range for P, I and B frame,\n"
|
||||
"\t\t\tUse string with unsigned integer values of Qunatization Range \n"
|
||||
"\t\t\tin MinQpP,MaxQpP:MinQpI,MaxQpI:MinQpB,MaxQpB order, to set the property.",
|
||||
"-1,-1:-1,-1:-1,-1",
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
@@ -2147,6 +2361,28 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
if (is_cuvid == TRUE) {
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_CUDAENC_MEM_TYPE,
|
||||
g_param_spec_enum ("cudaenc-memtype",
|
||||
"Memory type for cuda encoder YUV buffers",
|
||||
"Set to specify memory type for cuda input buffers",
|
||||
GST_TYPE_V4L2_VID_CUDAENC_MEM_TYPE, DEFAULT_CUDAENC_MEM_TYPE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_INTRA_REFRESH,
|
||||
g_param_spec_string ("intra-refresh", "intra-refresh",
|
||||
"Intra Refresh Parameters,\n"
|
||||
"\t\t\tUse string with unsigned integer values of Intra Refresh \n"
|
||||
"\t\t\tin enableIntraRefresh,intraRefreshPeriod,intraRefreshCnt in same order to set the property. e.g. 1,30,1",
|
||||
"0,0,0",
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT)));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_SEI_UUID,
|
||||
g_param_spec_string ("sei-uuid",
|
||||
"SEI UUID String of 16 bytes",
|
||||
"SEI UUID String of 16 bytes to be set into SEI data",
|
||||
DEFAULT_SEI_UUID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_CUDAENC_GPU_ID,
|
||||
g_param_spec_uint ("gpu-id",
|
||||
"GPU Device ID",
|
||||
@@ -2251,11 +2487,30 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
} else if (is_cuvid == FALSE) {
|
||||
g_object_class_install_property (gobject_class, PROP_COPY_TIMESTAMP,
|
||||
g_param_spec_boolean ("copy-timestamp",
|
||||
"Set the copy timestamp flag",
|
||||
"Enabling the flag allows to copy the timestamps from input to the capture stream.",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_MAX_PERF,
|
||||
g_param_spec_boolean ("maxperf-enable",
|
||||
"Enable or Disable Max Performance mode. [Deprecated]",
|
||||
"Enable or Disable Max Performance mode [Deprecated]",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
}
|
||||
|
||||
/* Common properties */
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
{
|
||||
g_object_class_install_property (gobject_class, PROP_PEAK_BITRATE,
|
||||
g_param_spec_uint ("peak-bitrate", "Peak Bitrate",
|
||||
"Peak bitrate in variable control-rate\n"
|
||||
"\t\t\t The value must be >= bitrate\n"
|
||||
"\t\t\t (1.2*bitrate) is set by default(Default: 0)",
|
||||
"\t\t\tThe value must be >= bitrate\n"
|
||||
"\t\t\t(1.2*bitrate) is set by default(Default: 0)\n"
|
||||
"\t\t\tThis will be deprecated in future for Thor. Use the new defined property \"maxbitrate\"",
|
||||
0, G_MAXUINT, GST_V4L2_VIDEO_ENC_PEAK_BITRATE_DEFAULT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_PLAYING));
|
||||
@@ -2263,8 +2518,9 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
g_object_class_install_property (gobject_class, PROP_QUANT_I_FRAMES,
|
||||
g_param_spec_uint ("quant-i-frames", "I-Frame Quantization",
|
||||
"Quantization parameter for I-frames (0xffffffff=component default),\n"
|
||||
"\t\t\t use with ratecontrol-enable = 0\n"
|
||||
"\t\t\t and preset-level = 0",
|
||||
"\t\t\tuse with ratecontrol-enable = 0\n"
|
||||
"\t\t\tand preset-level = 0\n"
|
||||
"\t\t\tThis will be deprecated in future for Thor. Use the new defined property \"initqp\"",
|
||||
0, G_MAXUINT, GST_V4L2_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
@@ -2272,8 +2528,9 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
g_object_class_install_property (gobject_class, PROP_QUANT_P_FRAMES,
|
||||
g_param_spec_uint ("quant-p-frames", "P-Frame Quantization",
|
||||
"Quantization parameter for P-frames (0xffffffff=component default),\n"
|
||||
"\t\t\t use with ratecontrol-enable = 0\n"
|
||||
"\t\t\t and preset-level = 0",
|
||||
"\t\t\tuse with ratecontrol-enable = 0\n"
|
||||
"\t\t\tand preset-level = 0\n"
|
||||
"\t\t\tThis will be deprecated in future for Thor. Use the new defined property \"initqp\"",
|
||||
0, G_MAXUINT, GST_V4L2_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
@@ -2281,23 +2538,26 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
g_object_class_install_property (gobject_class, PROP_QUANT_B_FRAMES,
|
||||
g_param_spec_uint ("quant-b-frames", "B-Frame Quantization",
|
||||
"Quantization parameter for B-frames (0xffffffff=component default),\n"
|
||||
"\t\t\t use with ratecontrol-enable = 0\n"
|
||||
"\t\t\t and preset-level = 0",
|
||||
"\t\t\tuse with ratecontrol-enable = 0\n"
|
||||
"\t\t\tand preset-level = 0\n"
|
||||
"\t\t\tThis will be deprecated in future for Thor. Use the new defined property \"initqp\"",
|
||||
0, G_MAXUINT, GST_V4L2_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_HW_PRESET_LEVEL,
|
||||
g_param_spec_enum ("preset-level", "HWpresetlevelforencoder",
|
||||
"HW preset level for encoder",
|
||||
GST_TYPE_V4L2_VID_ENC_HW_PRESET_LEVEL,
|
||||
"HW preset level for encoder\n"
|
||||
"\t\t\tThis will be deprecated in future for Thor. Use the new defined property \"preset-id\" and \"tuning-info-id\"",
|
||||
GST_TYPE_V4L2_VID_ENC_HW_PRESET_LEVEL, (is_cuvid == TRUE) ? 0 :
|
||||
DEFAULT_HW_PRESET_LEVEL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_VIRTUAL_BUFFER_SIZE,
|
||||
g_param_spec_uint ("vbv-size", "vb size attribute",
|
||||
"virtual buffer size ",
|
||||
"virtual buffer size\n"
|
||||
"\t\t\tThis will be deprecated in future for Thor. Use the new defined property \"vbvbufsize\"",
|
||||
0, G_MAXUINT, DEFAULT_VBV_SIZE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
@@ -2312,24 +2572,10 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
g_object_class_install_property (gobject_class, PROP_RC_ENABLE,
|
||||
g_param_spec_boolean ("ratecontrol-enable",
|
||||
"Enable or Disable rate control mode",
|
||||
"Enable or Disable rate control mode",
|
||||
"Enable or Disable rate control mode\n"
|
||||
"\t\t\tThis will be deprecated in future for Thor. Use the new defined property \"constqp\"",
|
||||
TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_COPY_TIMESTAMP,
|
||||
g_param_spec_boolean ("copy-timestamp",
|
||||
"Set the copy timestamp flag",
|
||||
"Enabling the flag allows to copy the timestamps from input to the capture stream.",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_MAX_PERF,
|
||||
g_param_spec_boolean ("maxperf-enable",
|
||||
"Enable or Disable Max Performance mode",
|
||||
"Enable or Disable Max Performance mode",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
GST_PARAM_MUTABLE_READY));
|
||||
|
||||
/* Signals */
|
||||
gst_v4l2_signals[SIGNAL_FORCE_IDR] =
|
||||
g_signal_new ("force-IDR",
|
||||
@@ -2340,6 +2586,7 @@ gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
|
||||
|
||||
klass->force_IDR = gst_v4l2_video_encoder_forceIDR;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
video_encoder_class->open = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_open);
|
||||
@@ -2449,7 +2696,7 @@ gst_v4l2_video_enc_register (GstPlugin * plugin, GType type,
|
||||
const char *codec, const gchar * basename, const gchar * device_path,
|
||||
GstCaps * sink_caps, GstCaps * codec_caps, GstCaps * src_caps)
|
||||
{
|
||||
GTypeQuery type_query;
|
||||
GTypeQuery type_query = { 0, };
|
||||
GTypeInfo type_info = { 0, };
|
||||
GType subtype;
|
||||
gchar *type_name;
|
||||
@@ -2574,6 +2821,7 @@ gst_v4l2_videnc_tuning_info_get_type (void)
|
||||
return qtype;
|
||||
}
|
||||
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
static GType
|
||||
gst_v4l2_videnc_hw_preset_level_get_type (void)
|
||||
{
|
||||
@@ -2595,6 +2843,7 @@ gst_v4l2_videnc_hw_preset_level_get_type (void)
|
||||
}
|
||||
return qtype;
|
||||
}
|
||||
#endif
|
||||
|
||||
static GType
|
||||
gst_v4l2_videnc_ratecontrol_get_type (void)
|
||||
@@ -2682,6 +2931,20 @@ gst_v4l2_video_enc_parse_quantization_range (GstV4l2VideoEnc * self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_video_enc_parse_intra_refresh_params (GstV4l2VideoEnc * self,
|
||||
const gchar * arr)
|
||||
{
|
||||
gchar *str;
|
||||
self->enableIntraRefresh = atoi (arr);
|
||||
str = g_strstr_len (arr, -1, ",") + 1;
|
||||
self->intraRefreshPeriod = atoi (str);
|
||||
str = g_strstr_len (str, -1, ",") + 1;
|
||||
self->intraRefreshCnt = atoi (str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
setHWPresetType (GstV4l2Object * v4l2object, guint label,
|
||||
enum v4l2_enc_hw_preset_type type)
|
||||
@@ -2709,6 +2972,70 @@ setHWPresetType (GstV4l2Object * v4l2object, guint label,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
setInitQPParams(GstV4l2Object *v4l2object,
|
||||
guint32 quantI, guint32 quantP, guint32 quantB)
|
||||
{
|
||||
struct v4l2_ext_control control;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
gint ret;
|
||||
v4l2_ctrl_video_init_qp init_qp;
|
||||
|
||||
memset(&control, 0, sizeof(control));
|
||||
memset(&ctrls, 0, sizeof(ctrls));
|
||||
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &control;
|
||||
ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
|
||||
|
||||
init_qp.IInitQP = quantI;
|
||||
init_qp.PInitQP = quantP;
|
||||
init_qp.BInitQP = quantB;
|
||||
|
||||
control.id = V4L2_CID_MPEG_VIDEOENC_INIT_FRAME_QP;
|
||||
control.string = (gchar *)&init_qp;
|
||||
|
||||
ret = v4l2object->ioctl(v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret < 0)
|
||||
{
|
||||
g_print("Error while setting Init Frame QP params\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
setIntraRefreshParams (GstV4l2Object * v4l2object, guint label, guint enableIntraRefresh,
|
||||
guint intraRefreshPeriod, guint intraRefreshCnt)
|
||||
{
|
||||
v4l2_ctrl_intra_refresh intrarefresh;
|
||||
struct v4l2_ext_control control;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
gint ret;
|
||||
|
||||
memset (&control, 0, sizeof (control));
|
||||
memset (&ctrls, 0, sizeof (ctrls));
|
||||
|
||||
intrarefresh.enableIntraRefresh = enableIntraRefresh;
|
||||
intrarefresh.intraRefreshPeriod = intraRefreshPeriod;
|
||||
intrarefresh.intraRefreshCnt = intraRefreshCnt;
|
||||
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &control;
|
||||
ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
|
||||
|
||||
control.id = V4L2_CID_MPEG_VIDEOENC_INTRA_REFRESH;
|
||||
control.string = (gchar *) &intrarefresh;
|
||||
|
||||
ret = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls);
|
||||
if (ret < 0) {
|
||||
g_print ("Error while setting qp range\n");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
setQpRange (GstV4l2Object * v4l2object, guint label, guint MinQpI, guint MaxQpI,
|
||||
guint MinQpP, guint MaxQpP, guint MinQpB, guint MaxQpB)
|
||||
@@ -2743,6 +3070,7 @@ setQpRange (GstV4l2Object * v4l2object, guint label, guint MinQpI, guint MaxQpI,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if !defined(USE_V4L2_TARGET_NV_X86) && !defined(AARCH64_IS_SBSA)
|
||||
static void
|
||||
gst_v4l2_video_encoder_forceIDR (GstV4l2VideoEnc * self)
|
||||
{
|
||||
@@ -2766,7 +3094,7 @@ gst_v4l2_video_encoder_forceIDR (GstV4l2VideoEnc * self)
|
||||
if (ret < 0)
|
||||
g_print ("Error while signalling force IDR\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
gboolean
|
||||
set_v4l2_video_encoder_properties (GstVideoEncoder * encoder)
|
||||
{
|
||||
@@ -2828,11 +3156,14 @@ set_v4l2_video_encoder_properties (GstVideoEncoder * encoder)
|
||||
}
|
||||
}
|
||||
|
||||
/* Only one of either HW PRESETS or CUDA PRESETS are set at a time.
|
||||
* If CUDA Presets are given, HW Preset in overridden in CUVID path
|
||||
*/
|
||||
if (video_enc->hw_preset_level) {
|
||||
if (!setHWPresetType (video_enc->v4l2output,
|
||||
if (!setHWPresetType(video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_HW_PRESET_TYPE_PARAM,
|
||||
video_enc->hw_preset_level)) {
|
||||
g_print ("S_EXT_CTRLS for HW_PRESET_TYPE_PARAM failed\n");
|
||||
g_print("S_EXT_CTRLS for HW_PRESET_TYPE_PARAM failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -2846,26 +3177,24 @@ set_v4l2_video_encoder_properties (GstVideoEncoder * encoder)
|
||||
}
|
||||
}
|
||||
|
||||
if (video_enc->quant_i_frames != 0xffffffff && !video_enc->ratecontrol_enable) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, video_enc->quant_i_frames)) {
|
||||
g_print ("S_EXT_CTRLS for H264_I_FRAME_QP failed\n");
|
||||
if (video_enc->set_intrarefresh) {
|
||||
if (!setIntraRefreshParams(video_enc->v4l2output, V4L2_CID_MPEG_VIDEOENC_INTRA_REFRESH,
|
||||
video_enc->enableIntraRefresh, video_enc->intraRefreshPeriod,
|
||||
video_enc->intraRefreshCnt))
|
||||
{
|
||||
g_print ("S_EXT_CTRLS for INTRA_REFRESH failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (video_enc->quant_p_frames != 0xffffffff && !video_enc->ratecontrol_enable) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, video_enc->quant_p_frames)) {
|
||||
g_print ("S_EXT_CTRLS for H264_P_FRAME_QP failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (video_enc->quant_b_frames != 0xffffffff && !video_enc->ratecontrol_enable) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, video_enc->quant_b_frames)) {
|
||||
g_print ("S_EXT_CTRLS for H264_B_FRAME_QP failed\n");
|
||||
if (video_enc->quant_i_frames != 0xffffffff &&
|
||||
video_enc->quant_p_frames != 0xffffffff &&
|
||||
video_enc->quant_b_frames != 0xffffffff)
|
||||
{
|
||||
if (!setInitQPParams (video_enc->v4l2output,
|
||||
video_enc->quant_i_frames, video_enc->quant_p_frames,
|
||||
video_enc->quant_b_frames)) {
|
||||
g_print ("S_EXT_CTRLS for V4L2_CID_MPEG_VIDEOENC_INIT_FRAME_QP failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -2886,11 +3215,13 @@ set_v4l2_video_encoder_properties (GstVideoEncoder * encoder)
|
||||
}
|
||||
}
|
||||
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_VIRTUALBUFFER_SIZE,
|
||||
video_enc->virtual_buffer_size)) {
|
||||
g_print ("S_EXT_CTRLS for VIRTUALBUFFER_SIZE failed\n");
|
||||
return FALSE;
|
||||
if (is_cuvid == false) {
|
||||
if (!set_v4l2_video_mpeg_class (video_enc->v4l2output,
|
||||
V4L2_CID_MPEG_VIDEOENC_VIRTUALBUFFER_SIZE,
|
||||
video_enc->virtual_buffer_size)) {
|
||||
g_print ("S_EXT_CTRLS for VIRTUALBUFFER_SIZE failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2014 SUMOMO Computer Association.
|
||||
* Author: ayaka <ayaka@soulik.info>
|
||||
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LGPL-2.0-only
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -76,6 +77,10 @@ struct _GstV4l2VideoEnc
|
||||
guint32 PInitQP;
|
||||
guint32 BInitQP;
|
||||
gboolean set_qpRange;
|
||||
gboolean set_intrarefresh;
|
||||
guint32 enableIntraRefresh;
|
||||
guint32 intraRefreshPeriod;
|
||||
guint32 intraRefreshCnt;
|
||||
gboolean enableTemporalAQ;
|
||||
guint32 aqStrength;
|
||||
guint32 targetQuality;
|
||||
@@ -85,10 +90,12 @@ struct _GstV4l2VideoEnc
|
||||
gboolean ratecontrol_enable;
|
||||
gboolean force_idr;
|
||||
gboolean force_intra;
|
||||
gchar *sei_uuid;
|
||||
gboolean maxperf_enable;
|
||||
gboolean copy_timestamp;
|
||||
FILE *tracing_file_enc;
|
||||
GQueue *got_frame_pt;
|
||||
guint32 cudaenc_mem_type;
|
||||
guint32 cudaenc_gpu_id;
|
||||
guint32 cudaenc_preset_id;
|
||||
guint32 cudaenc_tuning_info_id;
|
||||
@@ -98,6 +105,7 @@ struct _GstV4l2VideoEnc
|
||||
gdouble buffer_in_time;
|
||||
GHashTable* hash_pts_systemtime;
|
||||
gboolean copy_meta;
|
||||
gboolean enable_hwpreset;
|
||||
#endif
|
||||
|
||||
/* < private > */
|
||||
|
||||
@@ -26,13 +26,15 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include "gstv4l2object.h"
|
||||
|
||||
#define UUID_SIZE 16
|
||||
#define USER_DATA_UNREGISTERED_TYPE 5
|
||||
|
||||
gboolean check_uuid(uint8_t *stream, char *sei_uuid_string);
|
||||
uint8_t* parse_sei_unit(uint8_t * bs_ptr, guint *size, char *sei_uuid_string);
|
||||
uint8_t *parse_sei_data (uint8_t *bs, uint32_t size, uint32_t *payload_size, char *sei_uuid_string);
|
||||
uint8_t *parse_sei_data (uint8_t *bs, uint32_t size, uint32_t *payload_size,
|
||||
char *sei_uuid_string, guint32 pixelformat);
|
||||
|
||||
gboolean check_uuid(uint8_t *stream, char *sei_uuid_string)
|
||||
{
|
||||
@@ -86,12 +88,16 @@ uint8_t* parse_sei_unit(uint8_t * bs_ptr, guint *size, char *sei_uuid_string)
|
||||
for (i = 0; i < (payload_size - UUID_SIZE); i++)
|
||||
{
|
||||
payload[i] = *bs_ptr;
|
||||
// drop emulation prevention bytes
|
||||
if ((*(bs_ptr) == 0x03)
|
||||
&& (*(bs_ptr - 1) == 0x00)
|
||||
&& (*(bs_ptr - 2) == 0x00))
|
||||
|
||||
if (strncmp (sei_uuid_string, "VST_CUSTOM_META", (UUID_SIZE-1)) != 0)
|
||||
{
|
||||
i--;
|
||||
// drop emulation prevention bytes
|
||||
if ((*(bs_ptr) == 0x03)
|
||||
&& (*(bs_ptr - 1) == 0x00)
|
||||
&& (*(bs_ptr - 2) == 0x00))
|
||||
{
|
||||
i--;
|
||||
}
|
||||
}
|
||||
bs_ptr++;
|
||||
}
|
||||
@@ -103,7 +109,25 @@ uint8_t* parse_sei_unit(uint8_t * bs_ptr, guint *size, char *sei_uuid_string)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *parse_sei_data (uint8_t *bs, uint32_t size, uint32_t *payload_size, char *sei_uuid_string)
|
||||
|
||||
/*************************************************************
|
||||
|
||||
+------H264-----+
|
||||
|0|1|2|3|4|5|6|7|
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|F|NRI| Type |
|
||||
+---------------+
|
||||
|
||||
+------------H265---------------+
|
||||
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|F| Type | LayerId | TID |
|
||||
+-------------+-----------------+
|
||||
|
||||
*************************************************************/
|
||||
|
||||
uint8_t *parse_sei_data (uint8_t *bs, uint32_t size, uint32_t *payload_size,
|
||||
char *sei_uuid_string, guint32 pixelformat)
|
||||
{
|
||||
if (sei_uuid_string == NULL)
|
||||
return NULL;
|
||||
@@ -120,8 +144,11 @@ uint8_t *parse_sei_data (uint8_t *bs, uint32_t size, uint32_t *payload_size, cha
|
||||
checklen++;
|
||||
else if (checklen == 3 && *bs_ptr++ == 0x01)
|
||||
checklen++;
|
||||
else if (checklen == 4 && *bs_ptr++ == 0x06)
|
||||
else if (checklen == 4 && ((pixelformat == V4L2_PIX_FMT_H264) ? *bs_ptr == 0x06 : (((*bs_ptr >> 1) & 0x3f) == 0x27)))
|
||||
{
|
||||
bs_ptr++;
|
||||
if (pixelformat == V4L2_PIX_FMT_H265)
|
||||
bs_ptr++;
|
||||
payload = parse_sei_unit(bs_ptr, &sei_payload_size, sei_uuid_string);
|
||||
checklen = 0;
|
||||
if (payload != NULL)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* 2006 Edgard Lima <edgard.lima@gmail.com>
|
||||
* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* v4l2_calls.c - generic V4L2 calls handling
|
||||
*
|
||||
@@ -52,12 +52,20 @@
|
||||
|
||||
#include "gst/gst-i18n-plugin.h"
|
||||
#include <ctype.h>
|
||||
#include "wsl_utils.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
|
||||
#define GST_CAT_DEFAULT v4l2_debug
|
||||
|
||||
static GMutex guard_dev_node;
|
||||
static GMutex guard_wsl_check;
|
||||
#ifdef USE_V4L2_TARGET_NV
|
||||
void __attribute__((constructor)) gstv4l2_constructor_init(void);
|
||||
static bool is_wsl_system = 0;
|
||||
|
||||
void __attribute__((constructor)) gstv4l2_constructor_init(void)
|
||||
{
|
||||
is_wsl_system = is_running_in_WSL();
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* gst_v4l2_get_capabilities():
|
||||
@@ -519,56 +527,6 @@ gst_v4l2_adjust_buf_type (GstV4l2Object * v4l2object)
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to create a dummy dev node in case of WSL setup */
|
||||
static gboolean create_dummy_dev_node(void)
|
||||
{
|
||||
/* check if node already exists before creating */
|
||||
g_mutex_lock(&guard_dev_node);
|
||||
if (access("/dev/nvidia0", F_OK) == -1) {
|
||||
const char *command = "cp -a /dev/null /dev/nvidia0";
|
||||
int status = system(command);
|
||||
|
||||
if (status != 0) {
|
||||
g_print("ERROR: create_dummy_dev_node /dev/nvidia0 failed.\n");
|
||||
g_mutex_unlock(&guard_dev_node);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock(&guard_dev_node);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Function to check if running inside Windows Subsystem For Linux (WSL) */
|
||||
static gboolean is_running_in_WSL(void)
|
||||
{
|
||||
static volatile gboolean verified = false;
|
||||
static volatile gboolean ret = false;
|
||||
|
||||
g_mutex_lock(&guard_wsl_check);
|
||||
if (!verified) {
|
||||
verified = true;
|
||||
FILE *versionFile = fopen("/proc/version", "r");
|
||||
if (versionFile != NULL) {
|
||||
char versionInfo[512];
|
||||
if (fgets(versionInfo, sizeof(versionInfo), versionFile) != NULL) {
|
||||
for (int i=0; versionInfo[i] != '\0'; i++) {
|
||||
versionInfo[i] = tolower((unsigned char)versionInfo[i]);
|
||||
}
|
||||
if (strstr(versionInfo, "microsoft") != NULL) {
|
||||
g_print("Running in WSL\n");
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
fclose(versionFile);
|
||||
} else {
|
||||
g_print("ERROR: opening /proc/version failed\n");
|
||||
}
|
||||
}
|
||||
g_mutex_unlock(&guard_wsl_check);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* gst_v4l2_open():
|
||||
* open the video device (v4l2object->videodev)
|
||||
@@ -580,13 +538,6 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
|
||||
struct stat st;
|
||||
int libv4l2_fd = -1;
|
||||
|
||||
if (is_running_in_WSL())
|
||||
{
|
||||
/* WSL system doesn't have /dev/nvidia0 node. Use /dev/null as /dev/nvidia0.
|
||||
We can use a dummy node since the ioctl calls we use are not true ioctls */
|
||||
create_dummy_dev_node();
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Trying to open device %s",
|
||||
v4l2object->videodev);
|
||||
|
||||
@@ -602,7 +553,14 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
|
||||
if (is_cuvid == TRUE) {
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
g_snprintf(buf, sizeof(buf), "/dev/nvidia%d", i);
|
||||
if (is_wsl_system) {
|
||||
/* WSL system doesn't have /dev/nvidia0 node. Use /dev/null instead.
|
||||
We can use a dummy node since the ioctl calls we use are not true ioctls */
|
||||
GST_INFO_OBJECT(v4l2object->dbg_obj, "Running inside WSL");
|
||||
g_snprintf(buf, sizeof(buf), "/dev/null");
|
||||
} else {
|
||||
g_snprintf(buf, sizeof(buf), "/dev/nvidia%d", i);
|
||||
}
|
||||
v4l2object->video_fd =
|
||||
open (buf, O_RDWR /* | O_NONBLOCK */ );
|
||||
if (v4l2object->video_fd != -1)
|
||||
|
||||
41
gst-v4l2/wsl_utils.c
Normal file
41
gst-v4l2/wsl_utils.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2024-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
||||
*
|
||||
* NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
|
||||
* property and proprietary rights in and to this material, related
|
||||
* documentation and any modifications thereto. Any use, reproduction,
|
||||
* disclosure or distribution of this material and related documentation
|
||||
* without an express license agreement from NVIDIA CORPORATION or
|
||||
* its affiliates is strictly prohibited.
|
||||
*/
|
||||
|
||||
#include "wsl_utils.h"
|
||||
|
||||
bool is_running_in_WSL(void)
|
||||
{
|
||||
static volatile bool verified = false;
|
||||
static volatile bool ret = false;
|
||||
|
||||
if (!verified) {
|
||||
verified = true;
|
||||
FILE *versionFile = fopen("/proc/version", "r");
|
||||
if (versionFile != NULL) {
|
||||
char versionInfo[512];
|
||||
if (fgets(versionInfo, sizeof(versionInfo), versionFile) != NULL) {
|
||||
for (int i=0; versionInfo[i] != '\0'; i++) {
|
||||
versionInfo[i] = tolower((unsigned char)versionInfo[i]);
|
||||
}
|
||||
if (strstr(versionInfo, "microsoft") != NULL) {
|
||||
/* Yes, Running inside WSL */
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
fclose(versionFile);
|
||||
} else {
|
||||
printf("ERROR: opening /proc/version failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
24
gst-v4l2/wsl_utils.h
Normal file
24
gst-v4l2/wsl_utils.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2024-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
||||
*
|
||||
* NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
|
||||
* property and proprietary rights in and to this material, related
|
||||
* documentation and any modifications thereto. Any use, reproduction,
|
||||
* disclosure or distribution of this material and related documentation
|
||||
* without an express license agreement from NVIDIA CORPORATION or
|
||||
* its affiliates is strictly prohibited.
|
||||
*/
|
||||
|
||||
#ifndef _WSL_UTILS_
|
||||
#define _WSL_UTILS_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Function to check if running inside Windows Subsystem For Linux (WSL) */
|
||||
bool is_running_in_WSL(void);
|
||||
|
||||
#endif //_WSL_UTILS_
|
||||
261
nvbufsurface.h
261
nvbufsurface.h
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
||||
*
|
||||
* NVIDIA Corporation and its licensors retain all intellectual property
|
||||
* and proprietary rights in and to this software, related documentation
|
||||
* and any modifications thereto. Any use, reproduction, disclosure or
|
||||
* distribution of this software and related documentation without an express
|
||||
* license agreement from NVIDIA Corporation is strictly prohibited.
|
||||
* NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
|
||||
* property and proprietary rights in and to this material, related
|
||||
* documentation and any modifications thereto. Any use, reproduction,
|
||||
* disclosure or distribution of this material and related documentation
|
||||
* without an express license agreement from NVIDIA CORPORATION or
|
||||
* its affiliates is strictly prohibited.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -280,6 +282,36 @@ typedef enum
|
||||
NVBUF_COLOR_FORMAT_NV12_12LE_709_ER,
|
||||
/** Specifies 8 bit GRAY scale ER - single plane */
|
||||
NVBUF_COLOR_FORMAT_GRAY8_ER,
|
||||
/** Specifies BT.709 colorspace - Y/CbCr 4:2:2 planar */
|
||||
NVBUF_COLOR_FORMAT_UYVY_709,
|
||||
/** Specifies BT.709 colorspace - Y/CbCr ER 4:2:2 planar */
|
||||
NVBUF_COLOR_FORMAT_UYVY_709_ER,
|
||||
/** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 planar */
|
||||
NVBUF_COLOR_FORMAT_UYVY_2020,
|
||||
/** Specifies 16 bit GRAY scale - single plane */
|
||||
NVBUF_COLOR_FORMAT_GRAY16_LE,
|
||||
/** Specifies 64 bit BGRA (B16 G16 R16 A16) interleaved */
|
||||
NVBUF_COLOR_FORMAT_BGRA64_LE,
|
||||
/** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 multi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_2020,
|
||||
/** Specifies BT.601_ER colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_10LE_ER,
|
||||
/** Specifies BT.709 colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_10LE_709,
|
||||
/** Specifies BT.709_ER colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_10LE_709_ER,
|
||||
/** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_10LE_2020,
|
||||
/** Specifies BT.601 colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_12LE,
|
||||
/** Specifies BT.601_ER colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_12LE_ER,
|
||||
/** Specifies BT.709 colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_12LE_709,
|
||||
/** Specifies BT.709_ER colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_12LE_709_ER,
|
||||
/** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
|
||||
NVBUF_COLOR_FORMAT_NV16_12LE_2020,
|
||||
NVBUF_COLOR_FORMAT_LAST
|
||||
} NvBufSurfaceColorFormat;
|
||||
|
||||
@@ -343,7 +375,9 @@ typedef struct NvBufSurfacePlaneParamsEx
|
||||
uint32_t physicaladdress[NVBUF_MAX_PLANES];
|
||||
/** flags associated with planes */
|
||||
uint64_t flags[NVBUF_MAX_PLANES];
|
||||
|
||||
/** DRM modifier for plane */
|
||||
uint64_t drmModifier[NVBUF_MAX_PLANES];
|
||||
/** Holds the reserved space for future use. */
|
||||
void * _reserved[STRUCTURE_PADDING * NVBUF_MAX_PLANES];
|
||||
} NvBufSurfacePlaneParamsEx;
|
||||
|
||||
@@ -366,19 +400,25 @@ typedef struct NvBufSurfacePlaneParams
|
||||
uint32_t psize[NVBUF_MAX_PLANES];
|
||||
/** Holds the number of bytes occupied by a pixel in each plane. */
|
||||
uint32_t bytesPerPix[NVBUF_MAX_PLANES];
|
||||
|
||||
/** Holds the reserved space for future use. */
|
||||
void * _reserved[STRUCTURE_PADDING * NVBUF_MAX_PLANES];
|
||||
} NvBufSurfacePlaneParams;
|
||||
|
||||
|
||||
/**
|
||||
* Holds Chroma Subsampling parameters for NvBufSurface allocation.
|
||||
* The members chromaLocHoriz and chromaLocVert accept these values:
|
||||
* 0: Left horizontal or top vertical position
|
||||
* 1: Center horizontal or center vertical position
|
||||
* 2: Right horizontal or bottom vertical position
|
||||
*/
|
||||
typedef struct NvBufSurfaceChromaSubsamplingParams
|
||||
{
|
||||
/** location settings */
|
||||
uint8_t chromaLocHoriz;
|
||||
uint8_t chromaLocVert;
|
||||
/** Reserved for alignment */
|
||||
uint8_t _reserved[6];
|
||||
} NvBufSurfaceChromaSubsamplingParams;
|
||||
|
||||
/**
|
||||
@@ -404,6 +444,8 @@ typedef struct NvBufSurfaceCreateParams {
|
||||
NvBufSurfaceLayout layout;
|
||||
/** Holds the type of memory to be allocated. */
|
||||
NvBufSurfaceMemType memType;
|
||||
/** Holds the reserved space for future use. */
|
||||
void * _reserved[STRUCTURE_PADDING];
|
||||
} NvBufSurfaceCreateParams;
|
||||
|
||||
/**
|
||||
@@ -411,24 +453,24 @@ typedef struct NvBufSurfaceCreateParams {
|
||||
* (Applicable for NvBufSurfaceAllocate API)
|
||||
*/
|
||||
typedef struct NvBufSurfaceAllocateParams {
|
||||
/** Hold legacy NvBufSurface creation parameters */
|
||||
/** Hold legacy NvBufSurface creation parameters */
|
||||
NvBufSurfaceCreateParams params;
|
||||
/** Display scan format */
|
||||
/** Display scan format */
|
||||
NvBufSurfaceDisplayScanFormat displayscanformat;
|
||||
/** Chroma Subsampling parameters */
|
||||
/** Chroma Subsampling parameters */
|
||||
NvBufSurfaceChromaSubsamplingParams chromaSubsampling;
|
||||
/** components tag to be used for memory allocation */
|
||||
/** components tag to be used for memory allocation */
|
||||
NvBufSurfaceTag memtag;
|
||||
/** disable pitch padding allocation only applicable for cuda and system memory allocation
|
||||
pitch would be width times bytes per pixel for the plane, for odd width it would be
|
||||
multiple of 2, also note for some non standard video resolution cuda kernels may fail
|
||||
/** disable pitch padding allocation only applicable for cuda and system memory allocation
|
||||
pitch would be width times bytes per pixel for the plane, for odd width it would be
|
||||
multiple of 2, also note for some non standard video resolution cuda kernels may fail
|
||||
due to unaligned pitch
|
||||
*/
|
||||
*/
|
||||
bool disablePitchPadding;
|
||||
/** Used void* from custom param for 64 bit machine, using other uint32_t param */
|
||||
/** Used void* from custom param for 64 bit machine, using other uint32_t param */
|
||||
uint32_t _reservedParam;
|
||||
|
||||
void * _reserved[STRUCTURE_PADDING-1];
|
||||
/** Holds the reserved space for future use. */
|
||||
void * _reserved[STRUCTURE_PADDING];
|
||||
} NvBufSurfaceAllocateParams;
|
||||
|
||||
/**
|
||||
@@ -439,7 +481,11 @@ typedef struct NvBufSurfaceMappedAddr {
|
||||
void * addr[NVBUF_MAX_PLANES];
|
||||
/** Holds a pointer to a mapped EGLImage. */
|
||||
void *eglImage;
|
||||
|
||||
/** Holds a pointer to a mapped NVRM memory */
|
||||
void *nvmmPtr;
|
||||
/** Holds a pointer to a mapped CUDA memory */
|
||||
void *cudaPtr;
|
||||
/** Holds the reserved space for future use. */
|
||||
void * _reserved[STRUCTURE_PADDING];
|
||||
} NvBufSurfaceMappedAddr;
|
||||
|
||||
@@ -464,6 +510,32 @@ typedef struct NvBufSurfaceParamsEx {
|
||||
void * _reserved[STRUCTURE_PADDING];
|
||||
} NvBufSurfaceParamsEx;
|
||||
|
||||
/**
|
||||
* Holds information of CUDA buffer.
|
||||
* Applicable for tegra OpenRM only.
|
||||
*/
|
||||
typedef struct NvBufSurfaceCudaBuffer {
|
||||
/**
|
||||
* Holds a base pointer to allocated CUDA memory.
|
||||
* It is different from dataPtr when CUDA allocated
|
||||
* address is not page aligned for image buffers.
|
||||
* It is same as dataPtr for other buffers.
|
||||
*/
|
||||
void *basePtr;
|
||||
/**
|
||||
* Holds a page aligned data pointer to CUDA memory for image buffers
|
||||
* if CUDA allocated address is not page aligned.
|
||||
* It is same as basePtr for other buffers.
|
||||
*/
|
||||
void *dataPtr;
|
||||
/** Holds a pointer to external CUDA memory for imported CUDA buffers */
|
||||
void *extMem;
|
||||
/** Holds a pointer to external CUDA mipmaped array for imported CUDA buffers */
|
||||
void *mipmap;
|
||||
/** Reserved */
|
||||
uint8_t reserved[64];
|
||||
} NvBufSurfaceCudaBuffer;
|
||||
|
||||
/**
|
||||
* Hold the information of single buffer in the batch.
|
||||
*/
|
||||
@@ -493,8 +565,10 @@ typedef struct NvBufSurfaceParams {
|
||||
NvBufSurfaceMappedAddr mappedAddr;
|
||||
/** pointers of extended parameters of single buffer in the batch.*/
|
||||
NvBufSurfaceParamsEx *paramex;
|
||||
/** Holds a pointer to CUDA buffer. Applicable for only CUDA Device and CUDA Host memory on tegra OpenRM.*/
|
||||
NvBufSurfaceCudaBuffer *cudaBuffer;
|
||||
|
||||
void * _reserved[STRUCTURE_PADDING - 1];
|
||||
void * _reserved[STRUCTURE_PADDING];
|
||||
} NvBufSurfaceParams;
|
||||
|
||||
/**
|
||||
@@ -515,6 +589,8 @@ typedef struct NvBufSurface {
|
||||
NvBufSurfaceMemType memType;
|
||||
/** Holds a pointer to an array of batched buffers. */
|
||||
NvBufSurfaceParams *surfaceList;
|
||||
/** Holds a flag for Imported buffer. */
|
||||
bool isImportedBuf;
|
||||
|
||||
void * _reserved[STRUCTURE_PADDING];
|
||||
} NvBufSurface;
|
||||
@@ -544,6 +620,23 @@ typedef struct NvBufSurfaceMapPlaneParams
|
||||
uint8_t reserved[64];
|
||||
} NvBufSurfaceMapPlaneParams;
|
||||
|
||||
/**
|
||||
* CUDA IPC memory handle for NvBufSurface
|
||||
*/
|
||||
typedef struct NvBufSurfaceCudaIpcMemHandle_t
|
||||
{
|
||||
char reserved[64];
|
||||
} NvBufSurfaceCudaIpcMemHandle;
|
||||
|
||||
/**
|
||||
* The extended map parameters NvBufSurface
|
||||
*/
|
||||
typedef struct NvBufSurfaceExtendedMapParams_t
|
||||
{
|
||||
NvBufSurfaceCudaIpcMemHandle memHandle;
|
||||
void *reserved[64];
|
||||
} NvBufSurfaceExtendedMapParams;
|
||||
|
||||
/**
|
||||
* Holds buffer parameters to map the buffer received from another process.
|
||||
*/
|
||||
@@ -568,9 +661,44 @@ typedef struct NvBufSurfaceMapParams {
|
||||
NvBufSurfaceChromaSubsamplingParams chromaSubsampling;
|
||||
/** Holds plane parameters */
|
||||
NvBufSurfaceMapPlaneParams planes[NVBUF_MAX_PLANES];
|
||||
/** Holds the extended Map parameters */
|
||||
void *extendedMapParams;
|
||||
/** Holds the reserved space for future use. */
|
||||
void *_reserved[STRUCTURE_PADDING];
|
||||
} NvBufSurfaceMapParams;
|
||||
|
||||
/**
|
||||
* Holds information about mapped CUDA buffer
|
||||
*/
|
||||
typedef struct NvBufSurfaceNvmmBuffer {
|
||||
/** Holds a pointer to mapped nvmm memory */
|
||||
void *dataPtr;
|
||||
/** Holds a DMABUF FD */
|
||||
uint64_t bufferDesc;
|
||||
/** Reserved */
|
||||
uint8_t reserved[64];
|
||||
} NvBufSurfaceMapParams;
|
||||
} NvBufSurfaceNvmmBuffer;
|
||||
|
||||
/**
|
||||
* Defines the type of underlying kernel driver detected for GPU access.
|
||||
*/
|
||||
typedef enum {
|
||||
NVBUF_DRIVER_TYPE_UNKNOWN = 0,
|
||||
NVBUF_DRIVER_TYPE_NVGPU,
|
||||
NVBUF_DRIVER_TYPE_RM
|
||||
} NvBufSurfaceDriverType;
|
||||
|
||||
/**
|
||||
* Holds information about the underlying device.
|
||||
*/
|
||||
typedef struct NvBufSurfaceDeviceInfo {
|
||||
/** The detected device type (nvgpu, OpenRM, etc.). */
|
||||
NvBufSurfaceDriverType driverType;
|
||||
/** Indicates if VIC is present on the platform. */
|
||||
bool isVicPresent;
|
||||
/** Reserved for future use. */
|
||||
uint8_t reserved[64];
|
||||
} NvBufSurfaceDeviceInfo;
|
||||
|
||||
/**
|
||||
* \brief Allocates a batch of buffers.
|
||||
@@ -852,7 +980,94 @@ int NvBufSurfaceImport (NvBufSurface **out_nvbuf_surf, const NvBufSurfaceMapPara
|
||||
*/
|
||||
int NvBufSurfaceGetMapParams (const NvBufSurface *surf, int index, NvBufSurfaceMapParams *params);
|
||||
|
||||
/** @} */
|
||||
/**
|
||||
* \brief Creates an CUDA buffer from the memory of one or more
|
||||
* \ref NvBufSurface buffers.
|
||||
*
|
||||
* Only memory type \ref NVBUF_MEM_SURFACE_ARRAY is supported.
|
||||
*
|
||||
* This function returns the created CUDA buffer by storing its address at
|
||||
* \a surf->surfaceList->mappedAddr->cudaPtr. (\a surf is a pointer to
|
||||
* an NvBufSurface. \a surfaceList is a pointer to an \ref NvBufSurfaceParams.
|
||||
* \a mappedAddr is a pointer to an \ref NvBufSurfaceMappedAddr.
|
||||
* \a cudaPtr is a pointer to an \ref NvBufSurfaceCudaBuffer.
|
||||
*
|
||||
* You can use this function in scenarios where a CUDA operation on Jetson
|
||||
* hardware memory (identified by \ref NVBUF_MEM_SURFACE_ARRAY) is required.
|
||||
* The NvBufSurfaceCudaBuffer struct provided by this function can be used
|
||||
* to get dataPtr of CUDA memory.
|
||||
*
|
||||
* @param[in,out] surf A pointer to an NvBufSurface structure. The function
|
||||
* stores a pointer to the created CUDA buffer in
|
||||
* a descendant of this structure; see the notes above.
|
||||
* @param[in] index Index of a buffer in the batch. -1 specifies all buffers
|
||||
* in the batch.
|
||||
*
|
||||
* @return 0 for success, or -1 otherwise.
|
||||
*/
|
||||
int NvBufSurfaceMapCudaBuffer (NvBufSurface *surf, int index);
|
||||
|
||||
/**
|
||||
* \brief Destroys the previously created CUDA buffer.
|
||||
*
|
||||
* @param[in] surf A pointer to an \ref NvBufSurface structure.
|
||||
* @param[in] index The index of a buffer in the batch. -1 specifies all
|
||||
* buffers in the batch.
|
||||
*
|
||||
* @return 0 if successful, or -1 otherwise.
|
||||
*/
|
||||
int NvBufSurfaceUnMapCudaBuffer (NvBufSurface *surf, int index);
|
||||
|
||||
/**
|
||||
* \brief Creates an NVMM buffer from the memory of one or more
|
||||
* \ref NvBufSurface buffers.
|
||||
*
|
||||
* Only memory type \ref NVBUF_MEM_CUDA_DEVICE and \ref NVBUF_MEM_CUDA_PINNED
|
||||
* are supported.
|
||||
*
|
||||
* This function returns the created NVMM buffer by storing its address at
|
||||
* \a surf->surfaceList->mappedAddr->nvmmPtr. (\a surf is a pointer to
|
||||
* an NvBufSurface. \a surfaceList is a pointer to an \ref NvBufSurfaceParams.
|
||||
* \a mappedAddr is a pointer to an \ref NvBufSurfaceMappedAddr.
|
||||
* \a nvmmPtr is a pointer to NVMM buffer of memory type \ref NVBUF_MEM_SURFACE_ARRAY.
|
||||
*
|
||||
* You can use this function in scenarios where a NVBUF_MEM_SURFACE_ARRAY operation
|
||||
* on Jetson hardware memory identified by \ref NVBUF_MEM_CUDA_DEVICE and
|
||||
* \ref NVBUF_MEM_CUDA_PINNED are required.
|
||||
*
|
||||
* @param[in,out] surf A pointer to an NvBufSurface structure. The function
|
||||
* stores a pointer to the created NVMM buffer in
|
||||
* a descendant of this structure; see the notes above.
|
||||
* @param[in] index Index of a buffer in the batch. -1 specifies all buffers
|
||||
* in the batch.
|
||||
*
|
||||
* @return 0 for success, or -1 otherwise.
|
||||
*/
|
||||
int NvBufSurfaceMapNvmmBuffer (NvBufSurface *surf, int index);
|
||||
|
||||
/**
|
||||
* \brief Destroys the previously created NVMM buffer.
|
||||
*
|
||||
* @param[in] surf A pointer to an \ref NvBufSurface structure.
|
||||
* @param[in] index The index of a buffer in the batch. -1 specifies all
|
||||
* buffers in the batch.
|
||||
*
|
||||
* @return 0 if successful, or -1 otherwise.
|
||||
*/
|
||||
int NvBufSurfaceUnMapNvmmBuffer (NvBufSurface *surf, int index);
|
||||
|
||||
/**
|
||||
* \brief Retrieves information about the underlying GPU device driver.
|
||||
*
|
||||
* @param[out] info Pointer to NvBufSurfaceDeviceInfo structure.
|
||||
*
|
||||
* @return 0 if successful, or -1 otherwise.
|
||||
*
|
||||
* This function attempts to determine if the system is using 'nvgpu' or
|
||||
* an OpenRM-based driver by checking loaded kernel modules. Also it checks
|
||||
* if VIC is present on the platform.
|
||||
*/
|
||||
int NvBufSurfaceGetDeviceInfo (NvBufSurfaceDeviceInfo *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
jetson_36.2
|
||||
daily-2025.08.25.1_l4t/l4t-r38.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user