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.
- PyNvVideoCodec/PyNvVideoCodec_121.cp312-win_arm64.pyd +0 -0
- PyNvVideoCodec/PyNvVideoCodec_130.cp312-win_arm64.pyd +0 -0
- PyNvVideoCodec/VersionCheck.cp312-win_arm64.pyd +0 -0
- PyNvVideoCodec/__init__.py +251 -0
- PyNvVideoCodec/avformat-62.dll +0 -0
- PyNvVideoCodec/avutil-60.dll +0 -0
- PyNvVideoCodec/decoders/SimpleDecoder.py +273 -0
- PyNvVideoCodec/decoders/ThreadedDecoder.py +129 -0
- PyNvVideoCodec/decoders/__init__.py +22 -0
- PyNvVideoCodec/transcoder/Transcoder.py +55 -0
- PyNvVideoCodec/transcoder/__init__.py +22 -0
- benchmarks/cached_decoder_benchmark.py +813 -0
- benchmarks/frame_sampling_benchmark.py +765 -0
- benchmarks/requirements.txt +52 -0
- benchmarks/segmented_transcode_benchmark.py +1546 -0
- benchmarks/setup_pycuda_win_arm64.bat +531 -0
- pynvvideocodec-2.2.1.data/data/external/ffmpeg/readme.txt +39 -0
- pynvvideocodec-2.2.1.data/data/external/ffmpeg/src/ffmpeg-8.1.2.tar.xz +0 -0
- pynvvideocodec-2.2.1.dist-info/METADATA +97 -0
- pynvvideocodec-2.2.1.dist-info/RECORD +63 -0
- pynvvideocodec-2.2.1.dist-info/WHEEL +5 -0
- pynvvideocodec-2.2.1.dist-info/licenses/LICENSE.txt +22 -0
- pynvvideocodec-2.2.1.dist-info/licenses/NOTICES.txt +167 -0
- pynvvideocodec-2.2.1.dist-info/top_level.txt +3 -0
- samples/advanced/decode.py +173 -0
- samples/advanced/decode_from_memory_buffer.py +204 -0
- samples/advanced/decode_perf.py +299 -0
- samples/advanced/decode_reconfigure.py +184 -0
- samples/advanced/decode_sei_msg.py +193 -0
- samples/advanced/decode_with_cuda_control.py +214 -0
- samples/advanced/decode_with_low_latency.py +183 -0
- samples/advanced/encode_config.json +12 -0
- samples/advanced/encode_config_lowlatency.json +13 -0
- samples/advanced/encode_perf.py +338 -0
- samples/advanced/encode_reconfigure.py +211 -0
- samples/advanced/encode_sei_msg.py +188 -0
- samples/advanced/simple_decode_from_memory.py +151 -0
- samples/advanced/simple_decode_stats.py +179 -0
- samples/advanced/transcode.py +288 -0
- samples/basic/create_video_segments.py +187 -0
- samples/basic/encode.py +574 -0
- samples/basic/segments.txt +3 -0
- samples/basic/simple_decode_sampling.py +182 -0
- samples/basic/transcode_config.json +6 -0
- samples/jupyter/ReconfigureDecoder.png +0 -0
- samples/jupyter/SimpleDecoderAPIs.png +0 -0
- samples/jupyter/ThreadedDecoder.png +0 -0
- samples/jupyter/coco_classes.pickle +0 -0
- samples/jupyter/face_protect_tutorial.ipynb +881 -0
- samples/jupyter/object_detection_tutorial.ipynb +781 -0
- samples/jupyter/simple_decode_tutorial.ipynb +674 -0
- samples/requirements.txt +84 -0
- samples/setup_pycuda_win_arm64.bat +531 -0
- samples/utils/Utils.py +405 -0
- samples/utils/__init__.py +36 -0
- samples/utils/decode_parser.py +642 -0
- samples/utils/decode_stats_writer.py +177 -0
- samples/utils/encode_parallel_utils.py +174 -0
- samples/utils/encode_parser.py +379 -0
- samples/utils/frame_utils.py +89 -0
- samples/utils/sei_message_parser.py +223 -0
- samples/utils/sei_parser.py +223 -0
- 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)
|