PyNvVideoCodec 2.0.0__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. PyNvVideoCodec/PyNvVideoCodec_121.cp313-win_amd64.pyd +0 -0
  2. PyNvVideoCodec/PyNvVideoCodec_130.cp313-win_amd64.pyd +0 -0
  3. PyNvVideoCodec/VersionCheck.cp313-win_amd64.pyd +0 -0
  4. PyNvVideoCodec/__init__.py +237 -0
  5. PyNvVideoCodec/avcodec-58.dll +0 -0
  6. PyNvVideoCodec/avcodec-61.dll +0 -0
  7. PyNvVideoCodec/avcodec.dll +0 -0
  8. PyNvVideoCodec/avdevice-58.dll +0 -0
  9. PyNvVideoCodec/avdevice-61.dll +0 -0
  10. PyNvVideoCodec/avdevice.dll +0 -0
  11. PyNvVideoCodec/avfilter-10.dll +0 -0
  12. PyNvVideoCodec/avfilter-7.dll +0 -0
  13. PyNvVideoCodec/avfilter.dll +0 -0
  14. PyNvVideoCodec/avformat-58.dll +0 -0
  15. PyNvVideoCodec/avformat-61.dll +0 -0
  16. PyNvVideoCodec/avformat.dll +0 -0
  17. PyNvVideoCodec/avutil-56.dll +0 -0
  18. PyNvVideoCodec/avutil-59.dll +0 -0
  19. PyNvVideoCodec/avutil.dll +0 -0
  20. PyNvVideoCodec/decoders/SimpleDecoder.py +225 -0
  21. PyNvVideoCodec/decoders/ThreadedDecoder.py +119 -0
  22. PyNvVideoCodec/decoders/__init__.py +22 -0
  23. PyNvVideoCodec/swresample-3.dll +0 -0
  24. PyNvVideoCodec/swresample-5.dll +0 -0
  25. PyNvVideoCodec/swresample.dll +0 -0
  26. PyNvVideoCodec/swscale-5.dll +0 -0
  27. PyNvVideoCodec/swscale-8.dll +0 -0
  28. PyNvVideoCodec/swscale.dll +0 -0
  29. PyNvVideoCodec/transcoder/Transcoder.py +55 -0
  30. PyNvVideoCodec/transcoder/__init__.py +22 -0
  31. PyNvVideoCodec-2.0.0.data/data/external/ffmpeg/readme.txt +10 -0
  32. PyNvVideoCodec-2.0.0.data/data/external/ffmpeg/src/ffmpeg-7.0.2.tar.xz +0 -0
  33. PyNvVideoCodec-2.0.0.dist-info/METADATA +77 -0
  34. PyNvVideoCodec-2.0.0.dist-info/RECORD +64 -0
  35. PyNvVideoCodec-2.0.0.dist-info/WHEEL +5 -0
  36. PyNvVideoCodec-2.0.0.dist-info/licenses/LICENSE.txt +22 -0
  37. PyNvVideoCodec-2.0.0.dist-info/licenses/NOTICES.txt +167 -0
  38. PyNvVideoCodec-2.0.0.dist-info/top_level.txt +3 -0
  39. benchmarks/cached_decoder_benchmark.py +635 -0
  40. benchmarks/frame_sampling_benchmark.py +610 -0
  41. benchmarks/segmented_transcode_benchmark.py +1072 -0
  42. samples/Decode.py +194 -0
  43. samples/DecodeMultiprocessing.py +162 -0
  44. samples/DecodePerf.py +215 -0
  45. samples/DecodeSEIMsgExtraction.py +338 -0
  46. samples/DemuxFromByteArray.py +185 -0
  47. samples/Encode.py +189 -0
  48. samples/EncodeFromCPUBuffer.py +220 -0
  49. samples/EncodeMultiprocessing.py +268 -0
  50. samples/EncodePerf.py +380 -0
  51. samples/EncodeReconfigure.py +201 -0
  52. samples/EncodeSEIMsgInsertion.py +189 -0
  53. samples/ObjectDetection.py +218 -0
  54. samples/SimpleDecoder/EnsembleApp.py +416 -0
  55. samples/SimpleDecoder/SubsamplingAndReconfigure.py +341 -0
  56. samples/SimpleDecoder/fileLists.txt +4 -0
  57. samples/SimpleDecoder/segments.txt +3 -0
  58. samples/SimpleDecoder/timeListInSeconds.txt +5 -0
  59. samples/SimpleDecoder/transcode_config.json +6 -0
  60. samples/Utils.py +290 -0
  61. samples/coco_classes.pickle +0 -0
  62. samples/encode_config.json +16 -0
  63. samples/encode_config_lowlatency.json +11 -0
  64. samples/encode_config_perf.json +9 -0
@@ -0,0 +1,341 @@
1
+ # This copyright notice applies to this file only
2
+ #
3
+ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4
+ # SPDX-License-Identifier: MIT
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a
7
+ # copy of this software and associated documentation files (the "Software"),
8
+ # to deal in the Software without restriction, including without limitation
9
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ # and/or sell copies of the Software, and to permit persons to whom the
11
+ # Software is furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ # DEALINGS IN THE SOFTWARE.
23
+
24
+ import argparse
25
+ import os
26
+ import sys
27
+ from pathlib import Path
28
+ from typing import List, Optional, Tuple
29
+ import numpy as np
30
+ import pycuda.driver as cuda
31
+ import PyNvVideoCodec as nvc
32
+ from os.path import join, dirname, abspath
33
+
34
+ # Add the parent directory to Python path in a way that works from any working directory
35
+ current_dir = dirname(abspath(__file__))
36
+ parent_dir = dirname(current_dir)
37
+ if parent_dir not in sys.path:
38
+ sys.path.append(parent_dir)
39
+
40
+ from Utils import cast_address_to_1d_bytearray
41
+
42
+
43
+ class CUDAInitializationError(Exception):
44
+ """Exception raised when CUDA initialization fails."""
45
+ def __init__(self, message: str, gpu_id: int):
46
+ self.message = message
47
+ self.gpu_id = gpu_id
48
+ super().__init__(f"{message} (GPU ID: {gpu_id})")
49
+
50
+
51
+ class SubsamplingAndReconfigure:
52
+ """
53
+ A class that handles video frame subsampling and decoder reconfiguration.
54
+
55
+ This class provides functionality to:
56
+ 1. Extract frames from videos at specified target frame rates
57
+ 2. Reuse the same decoder instance for multiple video files
58
+ 3. Verify decoded frames against golden reference files
59
+ 4. Save decoded frames in YUV format
60
+ """
61
+
62
+ def __init__(self, create_cuda: bool, gpu_id: int) -> None:
63
+ """
64
+ Initialize the SubsamplingAndReconfigure instance.
65
+
66
+ Args:
67
+ create_cuda: If True, performs CUDA initialization in the sample app
68
+ gpu_id: ID of the GPU to use
69
+
70
+ Raises:
71
+ CUDAInitializationError: If CUDA initialization fails due to invalid GPU ID
72
+ """
73
+ self.simple_decoder: Optional[nvc.SimpleDecoder] = None
74
+ self.cuda_ctx: Optional[cuda.Context] = None
75
+ self.cuda_stream: Optional[cuda.Stream] = None
76
+ self.cuda_device: Optional[cuda.Device] = None
77
+ self.gpu_id: int = gpu_id
78
+
79
+ if create_cuda:
80
+ try:
81
+ device_id = self.gpu_id
82
+ self.cuda_device = cuda.Device(device_id)
83
+ self.cuda_ctx = self.cuda_device.retain_primary_context()
84
+ except Exception as e:
85
+ raise CUDAInitializationError(str(e), gpu_id)
86
+
87
+ def _process_frame_data(self, frame, decoded_frame_size: int, use_device_memory: bool) -> np.ndarray:
88
+ """
89
+ Process frame data from either device or host memory.
90
+
91
+ Args:
92
+ frame: Frame object to process
93
+ decoded_frame_size: Size of the frame in bytes
94
+ use_device_memory: Whether to fetch frame data from device memory
95
+
96
+ Returns:
97
+ numpy.ndarray: Processed frame data
98
+ """
99
+ reference = np.ndarray(shape=decoded_frame_size, dtype=np.uint8)
100
+ luma_base_addr = frame.GetPtrToPlane(0)
101
+
102
+ if use_device_memory:
103
+ cuda.memcpy_dtoh(reference, luma_base_addr)
104
+ else:
105
+ reference = cast_address_to_1d_bytearray(
106
+ base_address=luma_base_addr,
107
+ size=decoded_frame_size
108
+ )
109
+
110
+ return reference
111
+
112
+ def verify(self, input_file_name: str, indices_list: List[int],
113
+ target_frames: List[nvc.DecodedFrame], decoded_frame_size: int,
114
+ use_device_memory: bool) -> bool:
115
+ """
116
+ Verify decoded frames against a golden reference YUV file.
117
+
118
+ The golden file should be generated using the Decode sample application and follow
119
+ the naming convention: <base_name_of_input_file>_golden.yuv
120
+
121
+ Args:
122
+ input_file_name: Base name to derive the golden file name
123
+ indices_list: List of frame indices to verify
124
+ target_frames: Decoded frame objects
125
+ decoded_frame_size: Size of each decoded frame in bytes
126
+ use_device_memory: Whether to fetch frame data from device memory
127
+
128
+ Returns:
129
+ bool: True if all frames match the golden reference, False otherwise
130
+ """
131
+ golden_file = f"{input_file_name}_golden.yuv"
132
+ matching = True
133
+
134
+ try:
135
+ with open(golden_file, "rb") as testfile:
136
+ for i, frame in zip(indices_list, target_frames):
137
+ testfile.seek(i * decoded_frame_size, 0)
138
+ golden = testfile.read(decoded_frame_size)
139
+ npgolden = np.frombuffer(golden, dtype=np.uint8)
140
+
141
+ reference = self._process_frame_data(frame, decoded_frame_size, use_device_memory)
142
+
143
+ if not (npgolden == reference).all():
144
+ matching = False
145
+ print(f"Reference for frame {i} does not match golden file")
146
+ except FileNotFoundError:
147
+ print(f"Warning: Golden reference file {golden_file} not found")
148
+ matching = False
149
+
150
+ return matching
151
+
152
+
153
+ def _initialize_decoder(self, input_file_path: str, create_cuda: bool,
154
+ use_device_memory: bool) -> None:
155
+ """
156
+ Initialize or reconfigure the decoder.
157
+
158
+ Args:
159
+ input_file_path: Path to the input video file
160
+ create_cuda: Whether to create CUDA context and stream
161
+ use_device_memory: Whether to use device memory for frame processing
162
+ """
163
+ try:
164
+ if self.simple_decoder is None:
165
+ if create_cuda:
166
+ print("Initializing CUDA in the sample application...")
167
+ self.cuda_stream = cuda.Stream()
168
+ self.simple_decoder = nvc.SimpleDecoder(
169
+ input_file_path,
170
+ gpu_id=self.gpu_id,
171
+ cuda_context=self.cuda_ctx.handle,
172
+ cuda_stream=self.cuda_stream.handle,
173
+ use_device_memory=use_device_memory
174
+ )
175
+ else:
176
+ print("Using default CUDA initialization...")
177
+ self.simple_decoder = nvc.SimpleDecoder(
178
+ input_file_path,
179
+ gpu_id=self.gpu_id,
180
+ use_device_memory=use_device_memory
181
+ )
182
+ else:
183
+ print("Reconfiguring existing decoder...")
184
+ self.simple_decoder.reconfigure_decoder(input_file_path)
185
+ except Exception as e:
186
+ print(f"Error initializing decoder: {e}")
187
+
188
+ def sub_sampling(self, input_file_path: str, target_fps: float, create_cuda: bool,
189
+ use_device_memory: bool, verify_with_golden_yuv: int = 0) -> None:
190
+ """
191
+ Extract frames from a video at a specified target frame rate.
192
+
193
+ This method calculates which frames to extract to achieve the desired frame rate,
194
+ creates batches of frame indices (up to 8 frames per batch) for efficient processing,
195
+ and optionally verifies the output against a golden reference file.
196
+
197
+ Args:
198
+ input_file_path: Path to the input video file
199
+ target_fps: Desired output frame rate in frames per second
200
+ create_cuda: If True, performs CUDA initialization in the sample app
201
+ use_device_memory: Whether to use device memory for frame processing
202
+ verify_with_golden_yuv: If 1, verifies output against golden reference file
203
+
204
+ Example:
205
+ If video_fps = 30, target_fps = 10, and total_frames = 100:
206
+ - Will extract every 3rd frame (30/10 = 3)
207
+ """
208
+ try:
209
+ if create_cuda and self.cuda_ctx is not None:
210
+ self.cuda_ctx.push()
211
+
212
+ self._initialize_decoder(input_file_path, create_cuda, use_device_memory)
213
+
214
+ # Get video metadata
215
+ metadata = self.simple_decoder.get_stream_metadata()
216
+ total_frames = metadata.num_frames
217
+ video_fps = metadata.average_fps
218
+
219
+ print(f"Video FPS = {video_fps}, Total Frames = {total_frames}")
220
+
221
+ # Calculate frame indices for target FPS
222
+ step = int(video_fps / target_fps)
223
+ step_list = list(range(0, total_frames, step))
224
+
225
+ # Split into batches of up to 8 frames
226
+ step_list_of_lists = [step_list[i:i + 8] for i in range(0, len(step_list), 8)]
227
+
228
+ input_file_name = os.path.splitext(os.path.basename(input_file_path))[0]
229
+ matching = True
230
+
231
+ # Open output file once for all batches
232
+ dec_file_path = f"{str(input_file_name)}.yuv"
233
+ with open(dec_file_path, "wb") as decFile:
234
+ # Process each batch
235
+ for batch_indices in step_list_of_lists:
236
+ batch_frames = self.simple_decoder.get_batch_frames_by_index(batch_indices)
237
+
238
+ if verify_with_golden_yuv:
239
+ matching = (matching and self.verify(
240
+ input_file_name,
241
+ batch_indices,
242
+ batch_frames,
243
+ batch_frames[0].framesize(),
244
+ use_device_memory
245
+ ))
246
+
247
+ # Save frames to the already open file
248
+ for frame in batch_frames:
249
+ decoded_frame_size = frame.framesize()
250
+ reference = self._process_frame_data(frame, decoded_frame_size, use_device_memory)
251
+ decFile.write(bytearray(reference))
252
+
253
+ if verify_with_golden_yuv and matching:
254
+ print(f"All frames match golden reference for {input_file_name}.yuv")
255
+
256
+ if create_cuda and self.cuda_ctx is not None:
257
+ self.cuda_ctx.pop()
258
+
259
+ print(f"Frames saved successfully in {input_file_name}.yuv\n")
260
+
261
+ except Exception as e:
262
+ print(f"An unexpected error occurred: {e}")
263
+ if create_cuda and self.cuda_ctx is not None:
264
+ self.cuda_ctx.pop()
265
+
266
+
267
+ if __name__ == "__main__":
268
+ parser = argparse.ArgumentParser(
269
+ description="This sample application demonstrates reusing the same decoder instance "
270
+ "for subsampling multiple video files using Simple Decoder."
271
+ )
272
+
273
+ parser.add_argument(
274
+ "-i", "--input_file_list",
275
+ type=Path,
276
+ default=join(current_dir, "fileLists.txt"),
277
+ help="Text file containing video file paths, one per line. "
278
+ "Each line should contain the absolute or relative path to a video file. "
279
+ "Default: fileLists.txt in the same directory"
280
+ )
281
+
282
+ parser.add_argument(
283
+ "-fps", "--target_fps",
284
+ default=2,
285
+ type=int,
286
+ help="Desired output frame rate in frames per second. Default is 2."
287
+ )
288
+
289
+ parser.add_argument(
290
+ "-c", "--create_cuda",
291
+ type=int,
292
+ choices=[0, 1],
293
+ default=1,
294
+ help="Set to 1 to enable CUDA stream and context, 0 for using default initializations. Default is 1."
295
+ )
296
+
297
+ parser.add_argument(
298
+ "-d", "--use_device_memory",
299
+ choices=[0, 1],
300
+ default=1,
301
+ type=int,
302
+ help="Decoder output surface is in device memory (1) else in host memory (0). Default is 1."
303
+ )
304
+
305
+ parser.add_argument(
306
+ "-v", "--verify_with_golden_yuv",
307
+ choices=[0, 1],
308
+ default=0,
309
+ type=int,
310
+ help="Set to 1 to enable verification against a golden YUV file; default is 0."
311
+ )
312
+
313
+ parser.add_argument(
314
+ "-g", "--gpu_id",
315
+ type=int,
316
+ default=0,
317
+ help="GPU ID to use. Default is 0."
318
+ )
319
+
320
+ args = parser.parse_args()
321
+
322
+ try:
323
+ simple_dec_reconfigure = SubsamplingAndReconfigure(args.create_cuda, args.gpu_id)
324
+
325
+ with open(args.input_file_list, 'r') as file:
326
+ for line in file:
327
+ if line.strip():
328
+ input_file_path = line.strip()
329
+ simple_dec_reconfigure.sub_sampling(
330
+ input_file_path,
331
+ args.target_fps,
332
+ args.create_cuda,
333
+ args.use_device_memory,
334
+ args.verify_with_golden_yuv
335
+ )
336
+ except CUDAInitializationError as e:
337
+ print(f"Error initializing CUDA: {e}")
338
+ sys.exit(1)
339
+ except Exception as e:
340
+ print(f"An unexpected error occurred: {e}")
341
+ sys.exit(1)
@@ -0,0 +1,4 @@
1
+ humming_bird_1s_keyframes_only_no_audio.mp4
2
+ reordered.mp4
3
+ mandelbrot_1920x1080_120s_60fps_600gop_libx264_yuv420p.mp4
4
+
@@ -0,0 +1,3 @@
1
+ 0.3 0.8
2
+ 2 4
3
+ 3 8
@@ -0,0 +1,5 @@
1
+ 0.2
2
+ 0.4
3
+ 0.6
4
+ 0.8
5
+ 0.9
@@ -0,0 +1,6 @@
1
+ {
2
+ "codec" : "h264",
3
+ "preset" : "P3",
4
+ "tuning_info" : "high_quality",
5
+ "bf" : "3"
6
+ }
samples/Utils.py ADDED
@@ -0,0 +1,290 @@
1
+ # This copyright notice applies to this file only
2
+ #
3
+ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4
+ # SPDX-License-Identifier: MIT
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a
7
+ # copy of this software and associated documentation files (the "Software"),
8
+ # to deal in the Software without restriction, including without limitation
9
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ # and/or sell copies of the Software, and to permit persons to whom the
11
+ # Software is furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ # DEALINGS IN THE SOFTWARE.
23
+
24
+ import sys
25
+ import logging
26
+
27
+ from struct import pack
28
+ import sys
29
+ import os
30
+ import argparse
31
+ from pathlib import Path
32
+ from enum import Enum
33
+
34
+ import pycuda.driver as cuda
35
+ import PyNvVideoCodec as nvc
36
+ import numpy as np
37
+ from pycuda.compiler import SourceModule
38
+ import ctypes as C
39
+
40
+ import pycuda.autoinit as context
41
+ import json
42
+
43
+ from contextlib import contextmanager
44
+
45
+ import io
46
+ import tempfile
47
+
48
+ SERVICE_LOGGING_FORMAT = (
49
+ "[{filename:s}][{funcName:s}:{lineno:d}]" + "[{levelname:s}] {message:s}"
50
+ )
51
+ SERVICE_LOGGING_STREAM = sys.stdout
52
+
53
+
54
+ def get_logger(logger_name, log_level="info"):
55
+ SERVICE_LOGGING_LEVEL = getattr(logging, log_level.upper(), None)
56
+
57
+ logger = logging.getLogger(logger_name)
58
+ logger.setLevel(SERVICE_LOGGING_LEVEL)
59
+ ch = logging.StreamHandler(SERVICE_LOGGING_STREAM)
60
+ formatter = logging.Formatter(SERVICE_LOGGING_FORMAT, style="{")
61
+ ch.setFormatter(formatter)
62
+ ch.setLevel(SERVICE_LOGGING_LEVEL)
63
+ logger.addHandler(ch)
64
+ logger.propagate = False
65
+
66
+ return logger
67
+
68
+
69
+ logger = get_logger(__file__)
70
+
71
+
72
+ def cast_address_to_1d_bytearray(base_address, size):
73
+ return np.ctypeslib.as_array(C.cast(base_address, C.POINTER(C.c_uint8)),
74
+ shape=(size,))
75
+
76
+
77
+ from contextlib import contextmanager
78
+ import ctypes
79
+ import io
80
+ import os, sys
81
+ import tempfile
82
+
83
+ class AppCAI:
84
+ def __init__(self, shape, stride, typestr, gpualloc):
85
+ shape_int = tuple([int(x) for x in shape])
86
+ stride_int = tuple([int(x) for x in stride])
87
+ self.__cuda_array_interface__ = {"shape": shape_int, "strides": stride_int, "data": (int(gpualloc), False),
88
+ "typestr": typestr, "version": 3}
89
+
90
+
91
+ class AppFrame:
92
+ def __init__(self, width, height, format):
93
+ if format == "NV12":
94
+ nv12_frame_size = int(width * height * 3 / 2)
95
+ self.gpuAlloc = cuda.mem_alloc(nv12_frame_size)
96
+ self.cai = []
97
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
98
+ chroma_alloc = int(self.gpuAlloc) + width * height
99
+ self.cai.append(AppCAI((int(height / 2), int(width / 2), 2), (width, 2, 1), "|u1", chroma_alloc))
100
+ self.frameSize = nv12_frame_size
101
+ if format == "ARGB" or format == "ABGR":
102
+ self.frameSize = width * height * 4
103
+ self.gpuAlloc = cuda.mem_alloc(self.frameSize)
104
+ self.cai = AppCAI((height, width, 4), (4 * width, 4, 1), "|u1", self.gpuAlloc)
105
+ if format == "YUV444":
106
+ self.frameSize = width * height * 3
107
+ self.gpuAlloc = cuda.mem_alloc(self.frameSize)
108
+ self.cai = []
109
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
110
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", int(self.gpuAlloc) + width * height))
111
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", int(self.gpuAlloc) + 2 * width * height))
112
+ if format == "YUV420":
113
+ self.frameSize = int(width * height * 3 / 2)
114
+ self.gpuAlloc = cuda.mem_alloc(self.frameSize)
115
+ self.cai = []
116
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
117
+ self.cai.append(
118
+ AppCAI((height / 2, width / 2, 1), (width / 2, 1, 1), "|u1", int(self.gpuAlloc) + width * height))
119
+ self.cai.append(AppCAI((height / 2, width / 2, 1), (width / 2, 1, 1), "|u1",
120
+ int(self.gpuAlloc) + width * height + width / 2 * height / 2))
121
+ if format == "P010" or format == "YUV420_10BIT":
122
+ self.frameSize = int(width * height * 3 / 2 * 2)
123
+ self.gpuAlloc = cuda.mem_alloc(self.frameSize)
124
+ self.cai = []
125
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", self.gpuAlloc))
126
+ chroma_alloc = int(self.gpuAlloc) + width * height * 2
127
+ self.cai.append(AppCAI((int(height / 2), int(width / 2), 2), (width*2, 2, 1), "|u2", chroma_alloc))
128
+ if format == "P016" or format == "YUV444_16BIT":
129
+ self.frameSize = int(width * height * 3 * 2)
130
+ self.gpuAlloc = cuda.mem_alloc(self.frameSize)
131
+ self.cai = []
132
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", self.gpuAlloc))
133
+ self.cai.append(
134
+ AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", int(self.gpuAlloc) + width * height * 2))
135
+ self.cai.append(
136
+ AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", int(self.gpuAlloc) + width * height * 4))
137
+
138
+ if format == "NV16":
139
+ self.frameSize = width * height * 2
140
+ self.gpuAlloc = cuda.mem_alloc(self.frameSize)
141
+ self.cai = []
142
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
143
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1 ), "|u1", int(self.gpuAlloc) + width * height))
144
+
145
+ if format == "P210":
146
+ self.frameSize = width * height * 2 * 2
147
+ self.gpuAlloc = cuda.mem_alloc(self.frameSize)
148
+ self.cai = []
149
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", self.gpuAlloc))
150
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", int(self.gpuAlloc) + width * height * 2))
151
+
152
+
153
+
154
+ def cuda(self):
155
+ return self.cai
156
+
157
+
158
+ class AppFramePerf:
159
+ def __init__(self, width, height, format, dataptr, frame_idx):
160
+ if format == "NV12":
161
+ nv12_frame_size = int(width * height * 3 / 2)
162
+ self.gpuAlloc = int(dataptr) + (frame_idx * nv12_frame_size)
163
+ self.cai = []
164
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
165
+ chroma_alloc = int(self.gpuAlloc) + width * height
166
+ self.cai.append(AppCAI((int(height / 2), int(width / 2), 2), (width, 2, 1), "|u1", chroma_alloc))
167
+ self.frameSize = nv12_frame_size
168
+ if format == "ARGB" or format == "ABGR":
169
+ self.frameSize = width * height * 4
170
+ self.gpuAlloc = int(dataptr) + (frame_idx * self.frameSize)
171
+ self.cai = AppCAI((height, width, 4), (4 * width, 4, 1), "|u1", self.gpuAlloc)
172
+ if format == "YUV444":
173
+ self.frameSize = width * height * 3
174
+ self.gpuAlloc = int(dataptr) + (frame_idx * self.frameSize)
175
+ self.cai = []
176
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
177
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", int(self.gpuAlloc) + width * height))
178
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", int(self.gpuAlloc) + 2 * width * height))
179
+ if format == "YUV420":
180
+ self.frameSize = int(width * height * 3 / 2)
181
+ self.gpuAlloc = int(dataptr) + (frame_idx * self.frameSize)
182
+ self.cai = []
183
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
184
+ self.cai.append(
185
+ AppCAI((height / 2, width / 2, 1), (width / 2, 1, 1), "|u1", int(self.gpuAlloc) + width * height))
186
+ self.cai.append(AppCAI((height / 2, width / 2, 1), (width / 2, 1, 1), "|u1",
187
+ int(self.gpuAlloc) + width * height + width / 2 * height / 2))
188
+ if format == "P010" or format == "YUV420_10BIT":
189
+ self.frameSize = int(width * height * 3 / 2 * 2)
190
+ self.gpuAlloc = int(dataptr) + (frame_idx * self.frameSize)
191
+ self.cai = []
192
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", self.gpuAlloc))
193
+ chroma_alloc = int(self.gpuAlloc) + width * height * 2
194
+ self.cai.append(AppCAI((int(height / 2), int(width / 2), 2), (width*2, 2, 1), "|u2", chroma_alloc))
195
+ if format == "P016" or format == "YUV444_16BIT":
196
+ self.frameSize = int(width * height * 3 * 2)
197
+ self.gpuAlloc = int(dataptr) + (frame_idx * self.frameSize)
198
+ self.cai = []
199
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", self.gpuAlloc))
200
+ self.cai.append(
201
+ AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", int(self.gpuAlloc) + width * height * 2))
202
+ self.cai.append(
203
+ AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", int(self.gpuAlloc) + width * height * 4))
204
+ if format == "NV16":
205
+ self.frameSize = width * height * 2
206
+ self.gpuAlloc = int(dataptr) + (frame_idx * self.frameSize)
207
+ self.cai = []
208
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", self.gpuAlloc))
209
+ self.cai.append(AppCAI((height, width, 1), (width, 1, 1), "|u1", int(self.gpuAlloc) + width * height))
210
+ if format == "P210":
211
+ self.frameSize = width * height * 2 * 2
212
+ self.gpuAlloc = int(dataptr) + (frame_idx * self.frameSize)
213
+ self.cai = []
214
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", self.gpuAlloc))
215
+ self.cai.append(AppCAI((height, width, 1), (width * 2, 2, 1), "|u2", int(self.gpuAlloc) + width * height * 2))
216
+
217
+ def cuda(self):
218
+ return self.cai
219
+
220
+
221
+ def FetchGPUFrame(input_frame_list, GetCPUFrameFunc, num_frames):
222
+ for i in range(num_frames):
223
+ n = i % len(input_frame_list)
224
+ raw_frame = GetCPUFrameFunc()
225
+ if not raw_frame.size:
226
+ return
227
+ cuda.memcpy_htod(input_frame_list[n].gpuAlloc, raw_frame)
228
+ cuda.Context.synchronize()
229
+ yield input_frame_list[n]
230
+
231
+
232
+
233
+ def FetchCPUFrame(dec_file, frame_size):
234
+ def InnerFunc():
235
+ return np.fromfile(dec_file, np.uint8, count=frame_size)
236
+
237
+ return InnerFunc
238
+
239
+ def GetChromaFormat(demuxer):
240
+ strFormat = "NV12"
241
+
242
+ bitdepth = demuxer.BitDepth()
243
+ chromaformat = demuxer.ChromaFormat()
244
+
245
+ #print (" bitdepth : " + str(bitdepth))
246
+ #print (" chromaformat : " + str(chromaformat))
247
+
248
+ if str(chromaformat) == str("cudaVideoChromaFormat.444"):
249
+ if bitdepth == 10:
250
+ strFormat = "YUV444_10BIT"
251
+ elif bitdepth == 16:
252
+ strFormat = "YUV444_16BIT"
253
+ elif bitdepth == 12:
254
+ strFormat = "YUV444_16BIT"
255
+ print ("Unsupported bitdepth for YUV444 12BIT. It will be treated as YUV444_16BIT" )
256
+ elif bitdepth == 8:
257
+ strFormat = "YUV444"
258
+ elif str(chromaformat) == str("cudaVideoChromaFormat.420"):
259
+ if bitdepth == 8:
260
+ strFormat = "NV12"
261
+ elif bitdepth == 10:
262
+ strFormat = "YUV420_10BIT"
263
+ elif bitdepth == 16:
264
+ strFormat = "P016"
265
+ elif str(chromaformat) == str("cudaVideoChromaFormat.422"):
266
+ if bitdepth == 10:
267
+ strFormat = "YUV422_10BIT"
268
+ elif bitdepth == 16:
269
+ strFormat = "YUV422_16BIT"
270
+ elif bitdepth == 8:
271
+ strFormat = "YUV422"
272
+
273
+ #print (" strFormat : " + str(strFormat))
274
+
275
+ return strFormat
276
+
277
+
278
+ def GetVideoCodec(demuxer):
279
+ codec=str(demuxer.GetNvCodecId())
280
+ #print (" codec : " + str(codec))
281
+
282
+ # Common prefix to remove
283
+ common_prefix = "cudaVideoCodec."
284
+
285
+ strCodec = codec.removeprefix(common_prefix)
286
+
287
+ #print (" codec : " + str(strCodec))
288
+ return str(strCodec)
289
+
290
+
Binary file
@@ -0,0 +1,16 @@
1
+ {
2
+ "gpu_id": 0,
3
+ "preset" : "P3",
4
+ "tuning_info" : "high_quality",
5
+ "rc": "vbr",
6
+ "fps" : 30,
7
+ "gop" : 250,
8
+ "bf" : 3,
9
+ "bitrate" : "10M",
10
+ "maxbitrate" : 0,
11
+ "vbvinit" : 0,
12
+ "vbvbufsize" : 0,
13
+ "qmin" : "0,0,0",
14
+ "qmax" : "0,0,0",
15
+ "initqp" : "0,0,0"
16
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "preset": "P3",
3
+ "tuning_info": "low_latency",
4
+ "rc": "cbr",
5
+ "fps": 30,
6
+ "bf": 1,
7
+ "multipass":"fullres",
8
+ "bitrate": 3000000,
9
+ "maxbitrate": 3000000,
10
+ "vbvbufsize": 100000
11
+ }