PyNvVideoCodec 2.0.0__cp312-cp312-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.cp312-win_amd64.pyd +0 -0
  2. PyNvVideoCodec/PyNvVideoCodec_130.cp312-win_amd64.pyd +0 -0
  3. PyNvVideoCodec/VersionCheck.cp312-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,189 @@
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 PyNvVideoCodec as nvc
25
+ import json
26
+ import argparse
27
+ from pathlib import Path
28
+ import io
29
+ import sys
30
+ import os
31
+ from os.path import join, dirname, abspath
32
+
33
+ # Add the parent directory to Python path in a way that works from any working directory
34
+ current_dir = dirname(abspath(__file__))
35
+ parent_dir = dirname(current_dir)
36
+ if parent_dir not in sys.path:
37
+ sys.path.append(parent_dir)
38
+
39
+ from Utils import AppFrame
40
+ from Utils import FetchCPUFrame
41
+ from Utils import FetchGPUFrame
42
+
43
+
44
+ # Constants
45
+ TOTAL_NUM_FRAMES = 1000
46
+ SEI_MESSAGE_1 = [0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef]
47
+ SEI_MESSAGE_2 = [0x12, 0x67, 0x56, 0xda, 0xef, 0x99, 0x00, 0xbb, 0x6a, 0xc4, 0xd8, 0x10, 0xf9, 0xe3, 0x3e, 0x8f]
48
+
49
+
50
+ def encode(gpu_id, dec_file_path, enc_file_path, width, height, fmt, config_params):
51
+ """
52
+ Encode frames with SEI message insertion into the bitstream using CUDA device buffers as input.
53
+
54
+ This function reads image data from a file and loads it to CUDA input buffers using FetchGPUFrame().
55
+ The encoder copies the CUDA buffers and SEI message data and submits them to NVENC hardware for encoding.
56
+ Video memory buffer is allocated to get the NVENC hardware output, which is then copied to host memory
57
+ for file storage.
58
+
59
+ Parameters:
60
+ gpu_id (int): Ordinal of GPU to use [Parameter not in use]
61
+ dec_file_path (str): Path to file to be decoded
62
+ enc_file_path (str): Path to output file for encoded frames
63
+ width (int): Width of encoded frame
64
+ height (int): Height of encoded frame
65
+ fmt (str): Surface format string in uppercase (e.g., "NV12")
66
+ config_params (dict): Key-value pairs providing fine-grained control on encoding
67
+
68
+ Returns:
69
+ None
70
+
71
+ Example:
72
+ >>> encode(0, "input.yuv", "output.h264", 1920, 1080, "NV12", {"codec": "h264"})
73
+ Encode 1080p NV12 raw YUV into elementary bitstream using H.264 codec with SEI messages
74
+ """
75
+ try:
76
+ # Determine SEI type based on codec
77
+ if config_params["codec"] in ["hevc", "h264"]:
78
+ sei_info = {"sei_type": 5}
79
+ elif config_params["codec"] == "av1":
80
+ sei_info = {"sei_type": 6}
81
+ else:
82
+ raise ValueError(f"Unsupported codec: {config_params['codec']}")
83
+
84
+ # Create SEI messages list
85
+ sei_messages = [(sei_info, SEI_MESSAGE_1), (sei_info, SEI_MESSAGE_2)]
86
+
87
+ with open(dec_file_path, "rb") as decFile, open(enc_file_path, "wb") as encFile:
88
+ # Create encoder object
89
+ config_params["gpu_id"] = gpu_id
90
+ nvenc = nvc.CreateEncoder(width, height, fmt, False, **config_params)
91
+
92
+ # Create input frame list
93
+ input_frame_list = [AppFrame(width, height, fmt) for _ in range(1, 5)]
94
+
95
+ # Process frames
96
+ for input_gpu_frame in FetchGPUFrame(
97
+ input_frame_list,
98
+ FetchCPUFrame(decFile, input_frame_list[0].frameSize),
99
+ TOTAL_NUM_FRAMES
100
+ ):
101
+ bitstream = nvenc.Encode(input_gpu_frame, 0, sei_messages)
102
+ encFile.write(bytearray(bitstream))
103
+
104
+ # Flush encoder queue
105
+ bitstream = nvenc.EndEncode()
106
+ encFile.write(bytearray(bitstream))
107
+
108
+ print(f"Encoded frames written to {enc_file_path} with SEI messages")
109
+
110
+ except nvc.PyNvVCExceptionUnsupported as e:
111
+ print(f"CreateEncoder failure: {e}")
112
+ except Exception as e:
113
+ print(f"An unexpected error occurred: {e}")
114
+
115
+
116
+ if __name__ == "__main__":
117
+ parser = argparse.ArgumentParser(
118
+ description="This sample application illustrates encoding of frames with SEI message insertion."
119
+ )
120
+
121
+ parser.add_argument(
122
+ "-g", "--gpu_id",
123
+ type=int,
124
+ default=0,
125
+ help="Check nvidia-smi for available GPUs. Default: 0"
126
+ )
127
+ parser.add_argument(
128
+ "-i", "--raw_file_path",
129
+ type=Path,
130
+ required=True,
131
+ help="Raw video file (read from)"
132
+ )
133
+ parser.add_argument(
134
+ "-o", "--encoded_file_path",
135
+ type=Path,
136
+ help="Encoded video file (write to). Default: <input_file_name>.h264"
137
+ )
138
+ parser.add_argument(
139
+ "-s", "--size",
140
+ type=str,
141
+ required=True,
142
+ help="WidthxHeight of raw frame (e.g., 1920x1080)"
143
+ )
144
+ parser.add_argument(
145
+ "-if", "--format",
146
+ type=str,
147
+ default="NV12",
148
+ help="Format of input file (default is NV12)"
149
+ )
150
+ parser.add_argument(
151
+ "-c", "--codec",
152
+ type=str,
153
+ default="H264",
154
+ help="Video codec (HEVC, H264, AV1). Default is H264"
155
+ )
156
+ parser.add_argument(
157
+ "-json", "--config_file",
158
+ type=str,
159
+ default=join(current_dir, "encode_config.json"),
160
+ help="Path of JSON config file (default: encode_config.json in the same directory)"
161
+ )
162
+
163
+ args = parser.parse_args()
164
+ config = {}
165
+
166
+ # Set default encoded_file_path if not provided
167
+ if args.encoded_file_path is None:
168
+ input_path = Path(args.raw_file_path)
169
+ args.encoded_file_path = input_path.with_suffix('.h264')
170
+
171
+ if args.config_file:
172
+ with open(args.config_file) as jsonFile:
173
+ config = json.loads(jsonFile.read())
174
+ config["preset"] = config["preset"].upper()
175
+
176
+ args.codec = args.codec.lower()
177
+ args.format = args.format.upper()
178
+ config["codec"] = args.codec
179
+ width, height = map(int, args.size.split("x"))
180
+
181
+ encode(
182
+ args.gpu_id,
183
+ args.raw_file_path.as_posix(),
184
+ args.encoded_file_path.as_posix(),
185
+ width,
186
+ height,
187
+ args.format,
188
+ config
189
+ )
@@ -0,0 +1,218 @@
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 argparse
26
+ import numpy as np
27
+ import torch
28
+ import torchvision
29
+ from pathlib import Path
30
+ import pycuda.driver as cuda
31
+ import PyNvVideoCodec as nvc
32
+ from pycuda.autoinit import context
33
+ import os
34
+ from os.path import join, dirname, abspath
35
+ from itertools import zip_longest
36
+
37
+ # Add the parent directory to Python path in a way that works from any working directory
38
+ current_dir = dirname(abspath(__file__))
39
+ parent_dir = dirname(current_dir)
40
+ if parent_dir not in sys.path:
41
+ sys.path.append(parent_dir)
42
+
43
+ # Torch and Torchvision related imports
44
+ import torch
45
+ from torchvision.utils import save_image
46
+ from torchvision.transforms import Normalize
47
+ import torchvision.models.detection as models
48
+
49
+ # Output Display related imports
50
+ import numpy as np
51
+ import matplotlib
52
+ import matplotlib.pyplot as plt
53
+ import torchvision.transforms.functional as F
54
+ from torchvision.utils import draw_bounding_boxes
55
+ import time
56
+
57
+ CLASSES = []
58
+
59
+
60
+ # Label class mapping for COCO dataset
61
+ import pickle
62
+ script_dir = dirname(abspath(__file__))
63
+ coco_classes_path = join(script_dir, "coco_classes.pickle")
64
+ with open(coco_classes_path, "rb") as f:
65
+ CLASSES = pickle.load(f)
66
+
67
+ def show(imgs, fig = None, axs = None, im = None):
68
+ '''Function to show batch images. Takes in images as input.'''
69
+ if not isinstance(imgs, list):
70
+ imgs = [imgs]
71
+
72
+ img = F.to_pil_image(imgs[0])
73
+ if fig is None or axs is None or im is None:
74
+ plt.ion()
75
+ fig, axs = plt.subplots()
76
+ im = axs.imshow(np.asarray(img), cmap='viridis')
77
+ else:
78
+ im.set_data(np.asarray(img))
79
+
80
+ for i, img in enumerate(imgs):
81
+ img = img.detach()
82
+ img = F.to_pil_image(img)
83
+ im.set_data(np.asarray(img))
84
+ fig.canvas.flush_events()
85
+ time.sleep(0.1)
86
+ return fig, axs, im
87
+
88
+
89
+ def get_filtered_output(input, confidence_threshold):
90
+ '''Function to filter out boxes based on confidence scores'''
91
+ output = {}
92
+ valid_indices = [i for i, conf in enumerate(input['scores']) if conf >= confidence_threshold]
93
+
94
+ if not valid_indices:
95
+ print("No boxes above the confidence threshold.")
96
+ return
97
+
98
+ # Filter boxes, labels, and confidences
99
+ input_boxes = input["boxes"]
100
+ input_labels = input["labels"]
101
+ input_scores = input["scores"]
102
+
103
+ output["boxes"] = input_boxes[valid_indices]
104
+ output["labels"] = filtered_labels = [input_labels[i] for i in valid_indices]
105
+ output["scores"] = [input_scores[i] for i in valid_indices]
106
+ output["labels_confidence_string"] = [f"{CLASSES[label]} {confidence:.2f}" for label, confidence in zip(filtered_labels, output["scores"])]
107
+
108
+ return output
109
+
110
+ def print_and_write(message, file_path):
111
+ '''Function to print and write message '''
112
+ print(message)
113
+
114
+ with open(file_path, 'a') as file:
115
+ file.write(message + '\n')
116
+
117
+ def decode_and_detect(enc_file_path, detection_output_file_path, confidence_threshold, display_output, gpu_id):
118
+ '''Function to decode and detect the objects in the video frames.
119
+ This used ThreadedDecoder from PyNvC for batch decoding. ThreadedDecoder
120
+ runs in a separate thread and is launched on instance creation. Its aim
121
+ is to provide better pipelining.
122
+ It uses FasterRCNN(resnet50) model for object detection
123
+ '''
124
+ # Cuda initialization and threaded decoder creation
125
+ try:
126
+ cuda.init()
127
+ cudaDevice = cuda.Device(gpu_id)
128
+ cudaCtx = cudaDevice.retain_primary_context()
129
+ cudaCtx.push()
130
+ cudaStreamNvDec = cuda.Stream()
131
+ decoder = nvc.ThreadedDecoder(enc_file_path, buffer_size=12, gpu_id=gpu_id, cuda_context=cudaCtx.handle,
132
+ cuda_stream=cudaStreamNvDec.handle, use_device_memory = True,
133
+ output_color_type=nvc.OutputColorType.RGBP)
134
+ except Exception as e:
135
+ print(f"Error initializing CUDA: {e}")
136
+ return
137
+
138
+ # Loading FasterRCNN model
139
+ model = models.fasterrcnn_resnet50_fpn(pretrained=True)
140
+ model.to(torch.device('cuda'))
141
+ model.eval()
142
+
143
+ fig = None
144
+ axs = None
145
+ axs_im = None
146
+ # Decoder loop
147
+ while True:
148
+ frames = decoder.get_batch_frames(3)
149
+ src_tensor_list = []
150
+ image_list = []
151
+ for frame in frames:
152
+ # Get the interoperable tensor from PyNVC without any copy
153
+ # This tensor is in planar RGB format. That is R of all pixels followed
154
+ # by G of all pixels followed by B of all all pixels
155
+ src_tensor = torch.from_dlpack(frame)
156
+ # Store image for display if needed
157
+ if display_output:
158
+ image_list.append(src_tensor)
159
+ # Model expects float values in [0, 1]
160
+ src_tensor = src_tensor.float() / 255.0
161
+ src_tensor_list.append(src_tensor)
162
+
163
+ # Loop break conditions. No more frames to decode
164
+ if len(frames) == 0:
165
+ break
166
+
167
+ # Display needs images in bytes and 0-255 range.
168
+ if display_output:
169
+ image_for_disp = torch.stack(image_list)
170
+ else:
171
+ image_for_disp = torch.empty(1,1)
172
+
173
+ # Run the inference on batch input
174
+ with torch.no_grad():
175
+ outputs = model(src_tensor_list)
176
+
177
+ # Print the bounding box, associated class label and the confidence score
178
+ for output, im in zip_longest(outputs, image_for_disp):
179
+ filtered_output = get_filtered_output(output, confidence_threshold)
180
+ if filtered_output is None:
181
+ continue
182
+ for box, label, score in zip(filtered_output['boxes'], filtered_output['labels'], filtered_output['scores']):
183
+ print_and_write(f"Box: {box}, Label: {CLASSES[label]}, Score: {score}", detection_output_file_path)
184
+ if display_output:
185
+ print (display_output)
186
+ boxes = draw_bounding_boxes(im, boxes=filtered_output['boxes'], labels=filtered_output['labels_confidence_string'], width = 4)
187
+ fig, axs, axs_im = show(boxes, fig, axs, axs_im)
188
+
189
+ cudaCtx.pop()
190
+ print(f"Detection output written to {detection_output_file_path}")
191
+
192
+
193
+ if __name__ == "__main__":
194
+ parser = argparse.ArgumentParser(
195
+ " This sample application demonstartes Object Detection using PyNvC's ThreadedDecoder. It creates an instance of \
196
+ ThreadedDecoder class, and then loops over requesting for a batch frames in each iteration of the loop. The \
197
+ returned frames are directly interoperable with pytorch with zero copy. The frames are then used for object detection \
198
+ in a FasterRCNN model. The box coordinates, class label and confidence scores are printed."
199
+ )
200
+ parser.add_argument(
201
+ "-i", "--encoded_file_path", type=Path, required=True, help="Encoded video file (read from)")
202
+ parser.add_argument(
203
+ "-o", "--detection_output_file_path", type=Path, help="Detection output file path. Default: <input_file_name>_detection.txt")
204
+ parser.add_argument(
205
+ "-c", "--confidence_threshold", type=float, default=0.8, help="Confidence score above which the bounding box and label is considered a valid detection")
206
+ parser.add_argument(
207
+ "-d", "--display_output", action='store_true', help="Enable output display")
208
+ parser.add_argument(
209
+ "-g", "--gpu_id", type=int, default=0, help="Check nvidia-smi for available GPUs. Default: 0")
210
+ args = parser.parse_args()
211
+
212
+ # Set default detection_output_file_path if not provided
213
+ if args.detection_output_file_path is None:
214
+ input_path = Path(args.encoded_file_path)
215
+ args.detection_output_file_path = input_path.with_name(f"{input_path.stem}_detection.txt")
216
+
217
+ print ("Args value: ", args.display_output)
218
+ decode_and_detect(args.encoded_file_path.as_posix(), args.detection_output_file_path.as_posix(), args.confidence_threshold, args.display_output, args.gpu_id)