Compare commits

..

3 Commits

Author SHA1 Message Date
svcmobrel-release
7ace13fff7 Updating prebuilts and/or headers
44b0e909f18f7e2f457ba501fc47d80ecedd150b - nvbufsurface.h
2c5c20979e5fca5ed70b425187c3d09b39c03171 - v4l2_nv_extensions.h
d27a433ddeaefb9f42d0312c23472514b0cd6a45 - gst-nvcustomevent.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
34adbcb7d5cf5a360d28432429b735710bfe49c5 - gst-v4l2/wsl_utils.h
afc982d855f80b1e21ce1831930a9f327c41832b - gst-v4l2/gstv4l2h265enc.c
55a2c81ab3ffd72e07fc680369683d9635a3665c - gst-v4l2/gstv4l2h265enc.h
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
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
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

Change-Id: I9d677ff7205bafc8da61d43d54304538b6a3af19
2025-08-25 17:17:34 -07:00
svcmobrel-release
addfd10d83 Updating prebuilts and/or headers
44b0e909f18f7e2f457ba501fc47d80ecedd150b - nvbufsurface.h
2c5c20979e5fca5ed70b425187c3d09b39c03171 - v4l2_nv_extensions.h
d27a433ddeaefb9f42d0312c23472514b0cd6a45 - gst-nvcustomevent.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
34adbcb7d5cf5a360d28432429b735710bfe49c5 - gst-v4l2/wsl_utils.h
afc982d855f80b1e21ce1831930a9f327c41832b - gst-v4l2/gstv4l2h265enc.c
55a2c81ab3ffd72e07fc680369683d9635a3665c - gst-v4l2/gstv4l2h265enc.h
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
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
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

Change-Id: I88c51ba8d29ee886a2bea8f015356229b222b8d8
2025-08-25 14:20:53 -07:00
svcmobrel-release
3f221c626f Updating prebuilts and/or headers
44b0e909f18f7e2f457ba501fc47d80ecedd150b - nvbufsurface.h
2c5c20979e5fca5ed70b425187c3d09b39c03171 - v4l2_nv_extensions.h
d27a433ddeaefb9f42d0312c23472514b0cd6a45 - gst-nvcustomevent.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
34adbcb7d5cf5a360d28432429b735710bfe49c5 - gst-v4l2/wsl_utils.h
afc982d855f80b1e21ce1831930a9f327c41832b - gst-v4l2/gstv4l2h265enc.c
55a2c81ab3ffd72e07fc680369683d9635a3665c - gst-v4l2/gstv4l2h265enc.h
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
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
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

Change-Id: I434c689e81fa8bc261202840a7a285a3c08d4f94
2025-08-25 10:23:32 -07:00
24 changed files with 2495 additions and 790 deletions

View File

@@ -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

View File

@@ -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 \

View File

@@ -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

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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",

View File

@@ -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;

View File

@@ -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 (&params);
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

View File

@@ -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

View File

@@ -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 *)&param;
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;
}

View File

@@ -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 *)&param;
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;
}

View File

@@ -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 *) &params;
} else {
control.value = params;

View File

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

View File

@@ -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;

View File

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

View File

@@ -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;

View File

@@ -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 > */

View File

@@ -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)

View File

@@ -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
View 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
View 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_

View File

@@ -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
}

View File

@@ -1 +1 @@
jetson_36.2
daily-2025.08.25.1_l4t/l4t-r38.2

View File

File diff suppressed because it is too large Load Diff