PyNvVideoCodec 2.2.1__cp312-cp312-win_arm64.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 (63) hide show
  1. PyNvVideoCodec/PyNvVideoCodec_121.cp312-win_arm64.pyd +0 -0
  2. PyNvVideoCodec/PyNvVideoCodec_130.cp312-win_arm64.pyd +0 -0
  3. PyNvVideoCodec/VersionCheck.cp312-win_arm64.pyd +0 -0
  4. PyNvVideoCodec/__init__.py +251 -0
  5. PyNvVideoCodec/avformat-62.dll +0 -0
  6. PyNvVideoCodec/avutil-60.dll +0 -0
  7. PyNvVideoCodec/decoders/SimpleDecoder.py +273 -0
  8. PyNvVideoCodec/decoders/ThreadedDecoder.py +129 -0
  9. PyNvVideoCodec/decoders/__init__.py +22 -0
  10. PyNvVideoCodec/transcoder/Transcoder.py +55 -0
  11. PyNvVideoCodec/transcoder/__init__.py +22 -0
  12. benchmarks/cached_decoder_benchmark.py +813 -0
  13. benchmarks/frame_sampling_benchmark.py +765 -0
  14. benchmarks/requirements.txt +52 -0
  15. benchmarks/segmented_transcode_benchmark.py +1546 -0
  16. benchmarks/setup_pycuda_win_arm64.bat +531 -0
  17. pynvvideocodec-2.2.1.data/data/external/ffmpeg/readme.txt +39 -0
  18. pynvvideocodec-2.2.1.data/data/external/ffmpeg/src/ffmpeg-8.1.2.tar.xz +0 -0
  19. pynvvideocodec-2.2.1.dist-info/METADATA +97 -0
  20. pynvvideocodec-2.2.1.dist-info/RECORD +63 -0
  21. pynvvideocodec-2.2.1.dist-info/WHEEL +5 -0
  22. pynvvideocodec-2.2.1.dist-info/licenses/LICENSE.txt +22 -0
  23. pynvvideocodec-2.2.1.dist-info/licenses/NOTICES.txt +167 -0
  24. pynvvideocodec-2.2.1.dist-info/top_level.txt +3 -0
  25. samples/advanced/decode.py +173 -0
  26. samples/advanced/decode_from_memory_buffer.py +204 -0
  27. samples/advanced/decode_perf.py +299 -0
  28. samples/advanced/decode_reconfigure.py +184 -0
  29. samples/advanced/decode_sei_msg.py +193 -0
  30. samples/advanced/decode_with_cuda_control.py +214 -0
  31. samples/advanced/decode_with_low_latency.py +183 -0
  32. samples/advanced/encode_config.json +12 -0
  33. samples/advanced/encode_config_lowlatency.json +13 -0
  34. samples/advanced/encode_perf.py +338 -0
  35. samples/advanced/encode_reconfigure.py +211 -0
  36. samples/advanced/encode_sei_msg.py +188 -0
  37. samples/advanced/simple_decode_from_memory.py +151 -0
  38. samples/advanced/simple_decode_stats.py +179 -0
  39. samples/advanced/transcode.py +288 -0
  40. samples/basic/create_video_segments.py +187 -0
  41. samples/basic/encode.py +574 -0
  42. samples/basic/segments.txt +3 -0
  43. samples/basic/simple_decode_sampling.py +182 -0
  44. samples/basic/transcode_config.json +6 -0
  45. samples/jupyter/ReconfigureDecoder.png +0 -0
  46. samples/jupyter/SimpleDecoderAPIs.png +0 -0
  47. samples/jupyter/ThreadedDecoder.png +0 -0
  48. samples/jupyter/coco_classes.pickle +0 -0
  49. samples/jupyter/face_protect_tutorial.ipynb +881 -0
  50. samples/jupyter/object_detection_tutorial.ipynb +781 -0
  51. samples/jupyter/simple_decode_tutorial.ipynb +674 -0
  52. samples/requirements.txt +84 -0
  53. samples/setup_pycuda_win_arm64.bat +531 -0
  54. samples/utils/Utils.py +405 -0
  55. samples/utils/__init__.py +36 -0
  56. samples/utils/decode_parser.py +642 -0
  57. samples/utils/decode_stats_writer.py +177 -0
  58. samples/utils/encode_parallel_utils.py +174 -0
  59. samples/utils/encode_parser.py +379 -0
  60. samples/utils/frame_utils.py +89 -0
  61. samples/utils/sei_message_parser.py +223 -0
  62. samples/utils/sei_parser.py +223 -0
  63. samples/utils/transcode_parser.py +218 -0
@@ -0,0 +1,642 @@
1
+ # This copyright notice applies to this file only
2
+ #
3
+ # SPDX-FileCopyrightText: Copyright (c) 2026 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
+ """
25
+ Common argument parser for PyNvVideoCodec sample applications.
26
+ Provides standardized command-line arguments and parameter groups for different decoder types.
27
+
28
+ Available parameter groups:
29
+ - Basic: GPU ID, input/output files
30
+ - Decode: Device memory, frame count
31
+ - Low Latency: Decode latency modes
32
+ - Multi-instance: Number of instances, execution mode (thread/process)
33
+ """
34
+ import argparse
35
+ from pathlib import Path
36
+ from typing import Optional, Union
37
+
38
+ def add_common_args(parser: argparse.ArgumentParser) -> None:
39
+ """Add common arguments to an existing parser.
40
+
41
+ Adds the following arguments:
42
+ gpu_id (int): GPU device ID to use
43
+ encoded_file_path (Path): Input video file path
44
+ raw_file_path (Path): Output decoded file path
45
+ """
46
+ parser.add_argument(
47
+ "-g", "--gpu_id",
48
+ type=int,
49
+ default=0,
50
+ help="GPU ID to use (check nvidia-smi). Default: 0"
51
+ )
52
+ parser.add_argument(
53
+ "-i", "--encoded_file_path",
54
+ type=Path,
55
+ required=True,
56
+ help="Input encoded video file"
57
+ )
58
+ parser.add_argument(
59
+ "-o", "--raw_file_path",
60
+ type=Path,
61
+ help="Output raw video file. Default: <input_name>.yuv"
62
+ )
63
+
64
+ def add_decode_args(parser: argparse.ArgumentParser) -> None:
65
+ """Add decoder-specific arguments to parser.
66
+
67
+ Adds the following arguments:
68
+ use_device_memory (int): Use GPU (1) or CPU (0) memory for output
69
+ frame_count (int): Maximum number of frames to decode
70
+ """
71
+ parser.add_argument(
72
+ "-d", "--use_device_memory",
73
+ type=int,
74
+ choices=[0, 1],
75
+ default=1,
76
+ help="Use device memory (1) or host memory (0). Default: 1"
77
+ )
78
+ parser.add_argument(
79
+ "-f", "--frame_count",
80
+ type=int,
81
+ help="Maximum frames to decode. Default: all frames"
82
+ )
83
+
84
+ def add_low_latency_args(parser: argparse.ArgumentParser) -> None:
85
+ """Add low-latency specific arguments to parser.
86
+
87
+ Adds the following arguments:
88
+ decode_latency (int): Latency mode for decoding
89
+ 0: NATIVE - Standard 4-frame latency with display order output
90
+ 1: LOW - Zero frame latency with display order output
91
+ 2: ZERO - Zero frame latency with decode order output
92
+ """
93
+ parser.add_argument(
94
+ "-dl", "--decode_latency",
95
+ type=int,
96
+ default=0,
97
+ choices=[0, 1, 2],
98
+ help="""Decoder latency mode:
99
+ 0 - NATIVE: 4 frame latency, output in display order
100
+ 1 - LOW: 0 frame latency, output in display order
101
+ 2 - ZERO: 0 frame latency, output in decode order"""
102
+ )
103
+
104
+ def add_sei_args(parser: argparse.ArgumentParser) -> None:
105
+ """Add SEI-specific arguments to parser.
106
+
107
+ Adds the following arguments:
108
+ sei_file_path (Path): Path to output file for SEI messages
109
+ """
110
+ parser.add_argument(
111
+ "-s", "--sei_file_path",
112
+ type=Path,
113
+ default="sei_message.txt",
114
+ help="SEI message output file (write to). Default: sei_message.txt"
115
+ )
116
+
117
+ def add_stats_args(parser: argparse.ArgumentParser) -> None:
118
+ """Add decode statistics specific arguments to parser.
119
+
120
+ Adds the following arguments:
121
+ stats_file_path (Path): Path to output file for decode statistics
122
+ """
123
+ parser.add_argument(
124
+ "-p", "--stats_file_path",
125
+ type=Path,
126
+ help="Text file for parsed decode statistics. Default: <input_file_name>_stats.txt"
127
+ )
128
+
129
+ def add_reconfigure_args(parser: argparse.ArgumentParser) -> None:
130
+ """Add reconfigure-specific arguments to parser.
131
+
132
+ Adds the following arguments:
133
+ input_file1 (Path): First input encoded video file
134
+ input_file2 (Path): Second input encoded video file
135
+ raw_file_path1 (Path): First output raw video file
136
+ raw_file_path2 (Path): Second output raw video file
137
+ """
138
+ parser.add_argument(
139
+ "-i1", "--input_file1",
140
+ type=Path,
141
+ required=True,
142
+ help="First input encoded video file"
143
+ )
144
+ parser.add_argument(
145
+ "-i2", "--input_file2",
146
+ type=Path,
147
+ required=True,
148
+ help="Second input encoded video file (with different dimensions)"
149
+ )
150
+ parser.add_argument(
151
+ "-o1", "--raw_file_path1",
152
+ type=Path,
153
+ help="First output raw video file. Default: <input_file1_name>.yuv"
154
+ )
155
+ parser.add_argument(
156
+ "-o2", "--raw_file_path2",
157
+ type=Path,
158
+ help="Second output raw video file. Default: <input_file2_name>.yuv"
159
+ )
160
+
161
+ def add_detection_args(parser: argparse.ArgumentParser) -> None:
162
+ """Add object detection specific arguments to parser.
163
+
164
+ Adds the following arguments:
165
+ detection_output_file_path (Path): Output file for detection results
166
+ confidence_threshold (float): Confidence threshold for detections
167
+ display_output (bool): Whether to display detection visualization
168
+ """
169
+ parser.add_argument(
170
+ "-do", "--detection_output_file_path",
171
+ type=Path,
172
+ help="Detection output file path. Default: <input_file_name>_detection.txt"
173
+ )
174
+ parser.add_argument(
175
+ "-c", "--confidence_threshold",
176
+ type=float,
177
+ default=0.8,
178
+ help="Confidence score above which the bounding box and label is considered a valid detection"
179
+ )
180
+ parser.add_argument(
181
+ "-d", "--display_output",
182
+ action='store_true',
183
+ help="Enable output display"
184
+ )
185
+
186
+ def add_sampling_args(parser: argparse.ArgumentParser) -> None:
187
+ """Add sampling-specific arguments to parser.
188
+
189
+ Adds the following arguments:
190
+ video_files (list): List of video files to process
191
+ frames (int): Number of frames to sample per video
192
+ """
193
+ parser.add_argument(
194
+ "video_files",
195
+ nargs="+",
196
+ type=str,
197
+ help="Video files to process"
198
+ )
199
+ parser.add_argument(
200
+ "-f", "--frames",
201
+ type=int,
202
+ default=8,
203
+ help="Number of frames to sample per video (default: 8)"
204
+ )
205
+
206
+ def add_scanned_metadata_args(parser: argparse.ArgumentParser) -> None:
207
+ """Add scanned stream metadata arguments to parser.
208
+
209
+ Adds the following arguments:
210
+ need_scanned_stream_metadata (bool): Whether to scan stream for detailed metadata
211
+ When enabled, provides access to frame-level information like keyframe locations.
212
+ This requires scanning the entire stream upfront which adds initialization time.
213
+ """
214
+ parser.add_argument(
215
+ "-sm", "--need_scanned_stream_metadata",
216
+ action="store_true",
217
+ default=False,
218
+ help="Enable scanning stream for detailed metadata (keyframe locations, etc.). Default: False"
219
+ )
220
+
221
+ def add_multi_instance_args(parser: argparse.ArgumentParser) -> None:
222
+ """Add multi-instance specific arguments to parser.
223
+
224
+ Adds the following arguments:
225
+ num_instances (int): Number of parallel decoder instances to run
226
+ mode (str): Execution mode for parallel decoding
227
+ 'thread': Use Python threading (shared memory space)
228
+ 'process': Use multiprocessing (separate memory spaces)
229
+ """
230
+ parser.add_argument(
231
+ "-n", "--num_instances",
232
+ type=int,
233
+ default=1,
234
+ help="Number of parallel decode instances to run. Default: 1"
235
+ )
236
+ parser.add_argument(
237
+ "-m", "--mode",
238
+ choices=['thread', 'process'],
239
+ default='thread',
240
+ help="Parallel execution mode: 'thread' for multithreading or 'process' for multiprocessing. Default: thread"
241
+ )
242
+
243
+ def create_basic_parser(description: str) -> argparse.ArgumentParser:
244
+ """Create a parser with common arguments."""
245
+ parser = argparse.ArgumentParser(description=description)
246
+ add_common_args(parser)
247
+ return parser
248
+
249
+ def create_decode_parser(description: str) -> argparse.ArgumentParser:
250
+ """Create a parser with common and decode-specific arguments."""
251
+ parser = create_basic_parser(description)
252
+ add_decode_args(parser)
253
+ return parser
254
+
255
+ def parse_low_latency_args() -> argparse.Namespace:
256
+ """Parse and validate arguments for low latency decode applications.
257
+
258
+ Returns all decode_args plus:
259
+ decode_latency (int): Latency mode (default: 0)
260
+ 0: NATIVE - 4 frame latency, display order
261
+ 1: LOW - 0 frame latency, display order
262
+ 2: ZERO - 0 frame latency, decode order
263
+ """
264
+ parser = create_decode_parser(
265
+ "Low latency video decoding with NVIDIA GPU acceleration. "
266
+ "Supports different latency modes for reduced decode delay and custom output ordering."
267
+ )
268
+ add_low_latency_args(parser)
269
+ args = parser.parse_args()
270
+ return convert_path_args(args)
271
+
272
+ def parse_multi_instance_args() -> argparse.Namespace:
273
+ """Parse and validate arguments for multi-instance decode applications.
274
+
275
+ Returns all decode_args plus:
276
+ num_instances (int): Number of parallel decoders (default: 1)
277
+ mode (str): Execution mode - 'thread' or 'process' (default: thread)
278
+ thread: Uses Python threading for parallel decoding
279
+ process: Uses multiprocessing for true parallel execution
280
+
281
+ Note: This parser does not include output file argument as multi-instance apps
282
+ are typically used for performance testing without file output.
283
+ """
284
+ parser = argparse.ArgumentParser(
285
+ description="Multi-instance video decoding with NVIDIA GPU acceleration. "
286
+ "Supports parallel decoding using multiple threads or processes for improved throughput."
287
+ )
288
+ # Add common args without output file
289
+ parser.add_argument(
290
+ "-g", "--gpu_id",
291
+ type=int,
292
+ default=0,
293
+ help="GPU ID to use (check nvidia-smi). Default: 0"
294
+ )
295
+ parser.add_argument(
296
+ "-i", "--encoded_file_path",
297
+ type=Path,
298
+ required=True,
299
+ help="Input encoded video file"
300
+ )
301
+ # Add decode args
302
+ add_decode_args(parser)
303
+ # Add multi-instance args
304
+ add_multi_instance_args(parser)
305
+ args = parser.parse_args()
306
+
307
+ # Convert input path to string and validate
308
+ if hasattr(args, 'encoded_file_path') and args.encoded_file_path is not None:
309
+ args.encoded_file_path = validate_input_file(args.encoded_file_path).as_posix()
310
+
311
+ return args
312
+
313
+ def validate_input_file(file_path: Union[str, Path]) -> Path:
314
+ """Validate that input file exists."""
315
+ path = Path(file_path)
316
+ if not path.is_file():
317
+ raise FileNotFoundError(f"Input file not found: {path}")
318
+ return path
319
+
320
+ def get_output_path(input_path: Path, output_path: Optional[Path] = None, suffix: str = '.yuv') -> Path:
321
+ """Get output path, using input path as base if output not specified."""
322
+ if output_path is None:
323
+ return input_path.with_suffix(suffix)
324
+ return output_path
325
+
326
+ def convert_path_args(args: argparse.Namespace) -> argparse.Namespace:
327
+ """Convert any Path objects in args to strings."""
328
+ # Convert input path
329
+ if hasattr(args, 'encoded_file_path') and args.encoded_file_path is not None:
330
+ args.encoded_file_path = validate_input_file(args.encoded_file_path).as_posix()
331
+ elif hasattr(args, 'input_file') and args.input_file is not None:
332
+ args.encoded_file_path = validate_input_file(args.input_file).as_posix()
333
+ delattr(args, 'input_file') # Remove old attribute to standardize
334
+
335
+ # Convert output path
336
+ if hasattr(args, 'raw_file_path') and args.raw_file_path is not None:
337
+ args.raw_file_path = Path(args.raw_file_path).as_posix()
338
+ elif hasattr(args, 'yuv_file_path') and args.yuv_file_path is not None:
339
+ args.raw_file_path = Path(args.yuv_file_path).as_posix()
340
+ delattr(args, 'yuv_file_path') # Remove old attribute to standardize
341
+
342
+ # Set default output path if not provided
343
+ if not hasattr(args, 'raw_file_path') or args.raw_file_path is None:
344
+ input_path = Path(args.encoded_file_path)
345
+ args.raw_file_path = input_path.with_suffix('.yuv').as_posix()
346
+
347
+ return args
348
+
349
+ def create_stats_parser(description: str) -> argparse.ArgumentParser:
350
+ """Create a parser specifically for SEI message extraction without raw file output."""
351
+ parser = argparse.ArgumentParser(description=description)
352
+ parser.add_argument(
353
+ "-g", "--gpu_id",
354
+ type=int,
355
+ default=0,
356
+ help="GPU ID to use (check nvidia-smi). Default: 0"
357
+ )
358
+ parser.add_argument(
359
+ "-i", "--encoded_file_path",
360
+ type=Path,
361
+ required=True,
362
+ help="Input encoded video file"
363
+ )
364
+ parser.add_argument(
365
+ "-d", "--use_device_memory",
366
+ type=int,
367
+ choices=[0, 1],
368
+ default=1,
369
+ help="Use device memory (1) or host memory (0). Default: 1"
370
+ )
371
+ parser.add_argument(
372
+ "-p", "--stats_file_path",
373
+ type=Path,
374
+ help="Text file for parsed decode statistics. Default: <input_file_name>_stats.txt"
375
+ )
376
+ add_scanned_metadata_args(parser)
377
+ return parser
378
+
379
+ def parse_stats_args(description: str = None) -> argparse.Namespace:
380
+ """Parse and validate arguments for decode statistics extraction applications.
381
+
382
+ Args:
383
+ description (str, optional): Custom parser description. If None, uses default.
384
+
385
+ Returns args with:
386
+ gpu_id (int): GPU to use (default: 0)
387
+ encoded_file_path (str): Input video file path
388
+ use_device_memory (int): Use GPU memory (1) or CPU memory (0) (default: 1)
389
+ stats_file_path (str): Path to output file for decode statistics (default: input_name_stats.txt)
390
+ """
391
+ if description is None:
392
+ description = (
393
+ "Video decoding with statistics extraction using NVIDIA GPU acceleration. "
394
+ "Decodes input video and extracts detailed decode statistics to a separate file."
395
+ )
396
+
397
+ parser = create_stats_parser(description)
398
+ args = parser.parse_args()
399
+
400
+ # Set default stats file path if not provided
401
+ if hasattr(args, 'stats_file_path'):
402
+ if args.stats_file_path is None:
403
+ input_path = Path(args.encoded_file_path)
404
+ args.stats_file_path = input_path.parent / (input_path.stem + '_stats.txt')
405
+ args.stats_file_path = args.stats_file_path.as_posix()
406
+
407
+ # Convert input path to string and validate
408
+ if hasattr(args, 'encoded_file_path') and args.encoded_file_path is not None:
409
+ args.encoded_file_path = validate_input_file(args.encoded_file_path).as_posix()
410
+
411
+ return args
412
+
413
+ def parse_reconfigure_args(description: str = None) -> argparse.Namespace:
414
+ """Parse and validate arguments for decoder reconfiguration applications.
415
+
416
+ Args:
417
+ description (str, optional): Custom parser description. If None, uses default.
418
+
419
+ Returns args with:
420
+ input_file1 (str): First input encoded video file path
421
+ input_file2 (str): Second input encoded video file path
422
+ raw_file_path1 (str): First output decoded file path (default: input_file1_name.yuv)
423
+ raw_file_path2 (str): Second output decoded file path (default: input_file2_name.yuv)
424
+ gpu_id (int): GPU to use
425
+ use_device_memory (int): Use GPU memory (1) or CPU memory (0)
426
+ frame_count (int, optional): Number of frames to decode
427
+ """
428
+ if description is None:
429
+ description = (
430
+ "Video decoding with decoder reconfiguration using NVIDIA GPU acceleration. "
431
+ "Decodes two input videos with different dimensions by reconfiguring the decoder."
432
+ )
433
+
434
+ # Create parser with only GPU argument, then add reconfigure-specific and decode args
435
+ parser = argparse.ArgumentParser(description=description)
436
+ parser.add_argument(
437
+ "-g", "--gpu_id",
438
+ type=int,
439
+ default=0,
440
+ help="GPU ID to use (check nvidia-smi). Default: 0"
441
+ )
442
+ add_reconfigure_args(parser)
443
+ add_decode_args(parser)
444
+ args = parser.parse_args()
445
+
446
+ # Convert paths to strings and validate for input_file1
447
+ if hasattr(args, 'input_file1'):
448
+ args.input_file1 = validate_input_file(args.input_file1).as_posix()
449
+ if hasattr(args, 'raw_file_path1'):
450
+ if args.raw_file_path1 is None:
451
+ input_path = Path(args.input_file1)
452
+ args.raw_file_path1 = input_path.with_suffix('.yuv').as_posix()
453
+ else:
454
+ args.raw_file_path1 = Path(args.raw_file_path1).as_posix()
455
+
456
+ # Convert paths to strings and validate for input_file2
457
+ if hasattr(args, 'input_file2'):
458
+ args.input_file2 = validate_input_file(args.input_file2).as_posix()
459
+ if hasattr(args, 'raw_file_path2'):
460
+ if args.raw_file_path2 is None:
461
+ input_path = Path(args.input_file2)
462
+ args.raw_file_path2 = input_path.with_suffix('.yuv').as_posix()
463
+ else:
464
+ args.raw_file_path2 = Path(args.raw_file_path2).as_posix()
465
+
466
+ return args
467
+
468
+ def parse_sei_args(description: str = None) -> argparse.Namespace:
469
+ """Parse and validate arguments for SEI message extraction applications.
470
+
471
+ Args:
472
+ description (str, optional): Custom parser description. If None, uses default.
473
+
474
+ Returns args with:
475
+ gpu_id (int): GPU to use (default: 0)
476
+ encoded_file_path (str): Input video file path
477
+ use_device_memory (int): Use GPU memory (1) or CPU memory (0) (default: 1)
478
+ sei_file_path (str): Path to output file for SEI messages (default: sei_message.bin)
479
+ """
480
+ if description is None:
481
+ description = (
482
+ "SEI message extraction using NVIDIA GPU acceleration. "
483
+ "Extracts SEI messages from video stream without saving decoded frames."
484
+ )
485
+
486
+ parser = argparse.ArgumentParser(description=description)
487
+ # Add basic arguments
488
+ parser.add_argument(
489
+ "-g", "--gpu_id",
490
+ type=int,
491
+ default=0,
492
+ help="GPU ID to use (check nvidia-smi). Default: 0"
493
+ )
494
+ parser.add_argument(
495
+ "-i", "--encoded_file_path",
496
+ type=Path,
497
+ required=True,
498
+ help="Input encoded video file"
499
+ )
500
+ parser.add_argument(
501
+ "-d", "--use_device_memory",
502
+ type=int,
503
+ choices=[0, 1],
504
+ default=1,
505
+ help="Use device memory (1) or host memory (0). Default: 1"
506
+ )
507
+ # Add SEI-specific argument
508
+ parser.add_argument(
509
+ "-s", "--sei_file_path",
510
+ type=Path,
511
+ default="sei_message.bin",
512
+ help="SEI message output file (write to). Default: sei_message.bin. Sei type message is written to sei_type_message.bin"
513
+ )
514
+ parser.add_argument(
515
+ "-st", "--sei_type_file_path",
516
+ type=Path,
517
+ default="sei_type_message.bin",
518
+ help="SEI type message output file (write to). Default: sei_type_message.bin"
519
+ )
520
+ args = parser.parse_args()
521
+
522
+ # Convert paths to strings and validate
523
+ args.encoded_file_path = validate_input_file(args.encoded_file_path).as_posix()
524
+ args.sei_file_path = Path(args.sei_file_path).as_posix()
525
+ args.sei_type_file_path = Path(args.sei_type_file_path).as_posix()
526
+ return args
527
+
528
+ def parse_detection_args(description: str = None) -> argparse.Namespace:
529
+ """Parse and validate arguments for object detection applications.
530
+
531
+ Args:
532
+ description (str, optional): Custom parser description. If None, uses default.
533
+
534
+ Returns args with:
535
+ gpu_id (int): GPU to use (default: 0)
536
+ encoded_file_path (str): Input video file path
537
+ detection_output_file_path (str): Output file for detection results (-do flag)
538
+ confidence_threshold (float): Confidence threshold (default: 0.8)
539
+ display_output (bool): Whether to display visualization
540
+ """
541
+ if description is None:
542
+ description = (
543
+ "Object detection using PyNvVideoCodec's ThreadedDecoder. "
544
+ "Uses FasterRCNN model to detect objects in video frames with zero-copy tensor interop."
545
+ )
546
+
547
+ parser = create_basic_parser(description)
548
+ add_detection_args(parser)
549
+ args = parser.parse_args()
550
+
551
+ # Set default detection output path if not provided
552
+ if args.detection_output_file_path is None:
553
+ input_path = Path(args.encoded_file_path)
554
+ args.detection_output_file_path = input_path.with_name(f"{input_path.stem}_detection.txt")
555
+
556
+ return convert_path_args(args)
557
+
558
+ def parse_sampling_args(description: str = None) -> tuple:
559
+ """Parse and validate arguments for video sampling applications.
560
+
561
+ Args:
562
+ description (str, optional): Custom parser description. If None, uses default.
563
+
564
+ Returns:
565
+ tuple: (args, valid_files) where:
566
+ args: Namespace with:
567
+ gpu_id (int): GPU to use (default: 0)
568
+ frames (int): Frames to sample per video (default: 8)
569
+ video_files (list): List of video files to process
570
+ valid_files (list): List of validated video file paths
571
+ """
572
+ if description is None:
573
+ description = (
574
+ "Video frame sampling with NVIDIA GPU acceleration. "
575
+ "Samples evenly distributed frames from multiple video files."
576
+ )
577
+
578
+ parser = argparse.ArgumentParser(
579
+ description=description,
580
+ epilog="""
581
+ Examples:
582
+ %(prog)s video1.mp4 video2.mp4 video3.mp4 # Process multiple specific files
583
+ %(prog)s /path/to/videos/*.mp4 # Process all MP4 files in directory
584
+ %(prog)s video.mp4 -g 1 -f 16 # Use GPU 1 and sample 16 frames per video
585
+ """,
586
+ formatter_class=argparse.RawDescriptionHelpFormatter
587
+ )
588
+
589
+ parser.add_argument(
590
+ "-g", "--gpu_id",
591
+ type=int,
592
+ default=0,
593
+ help="GPU ID to use (check nvidia-smi). Default: 0"
594
+ )
595
+ add_sampling_args(parser)
596
+ add_scanned_metadata_args(parser)
597
+ args = parser.parse_args()
598
+
599
+ # Validate video files
600
+ valid_files = []
601
+ for video_file in args.video_files:
602
+ try:
603
+ valid_files.append(validate_input_file(video_file))
604
+ except FileNotFoundError:
605
+ print(f"Warning: File not found: {video_file}")
606
+
607
+ if not valid_files:
608
+ raise FileNotFoundError("No valid video files found")
609
+
610
+ # Check CUDA availability
611
+ import torch
612
+ if not torch.cuda.is_available():
613
+ raise RuntimeError("CUDA is not available. This application requires CUDA.")
614
+
615
+ # Validate GPU ID
616
+ if args.gpu_id >= torch.cuda.device_count():
617
+ raise ValueError(f"GPU ID {args.gpu_id} not available. Available GPUs: 0-{torch.cuda.device_count()-1}")
618
+
619
+ return args, valid_files
620
+
621
+ def parse_decode_args(description: str = None) -> argparse.Namespace:
622
+ """Parse and validate command line arguments for decode applications.
623
+
624
+ Args:
625
+ description (str, optional): Custom parser description. If None, uses default.
626
+
627
+ Returns args with:
628
+ gpu_id (int): GPU to use (default: 0)
629
+ encoded_file_path (str): Input video file path
630
+ raw_file_path (str): Output decoded file path (default: input_name.yuv)
631
+ use_device_memory (int): Use GPU memory (1) or CPU memory (0) (default: 1)
632
+ frame_count (int, optional): Number of frames to decode (default: all)
633
+ """
634
+ if description is None:
635
+ description = (
636
+ "Video decoding with NVIDIA GPU acceleration. "
637
+ "Decodes input video to raw format with configurable GPU/CPU memory usage and frame limits."
638
+ )
639
+
640
+ parser = create_decode_parser(description)
641
+ args = parser.parse_args()
642
+ return convert_path_args(args)