44# This source code is licensed under the BSD-style license found in the
55# LICENSE file in the root directory of this source tree.
66"""
7- Accelerated video decoding with NVDEC
7+ CUDA Decoding on Nvidia GPUs
88=====================================
99
10- .. _nvdec_tutorial :
10+ .. _ndecoderec_tutorial :
1111
12- **Author**: `Ahmad Sharif <[email protected] >`__ 13-
14- TorchCodec can use Nvidia hardware to speed-up video decoding. This is called "CUDA Decoding".
12+ TorchCodec can use supported Nvidia hardware (see support matrix here
13+ <https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new>) to speed-up
14+ video decoding. This is called "CUDA Decoding".
1515CUDA Decoding can be faster than CPU Decoding for the actual decoding step and also for
1616subsequent transform steps like scaling, cropping or rotating. This is because the decode step leaves
1717the decoded tensor in GPU memory so the GPU doesn't have to fetch from main memory before
3030Here are situations where CUDA Decoding may not make sense:
3131
3232#. You want bit-exact results compared to CPU Decoding
33- #. If you have small resolution videos and the PCI-e transfer latency is large
34- #. If your GPU is already busy and CPU is not
33+ #. You have small resolution videos and the PCI-e transfer latency is large
34+ #. Your GPU is already busy and CPU is not
3535
3636It's best to experiment with CUDA Decoding to see if it improves your use-case. With
3737TorchCodec you can simply pass in a device parameter to the
3838:class:`~torchcodec.decoders.VideoDecoder` class to use CUDA Decoding.
3939
4040
41- In order use CUDA Decoding will need the following installed in your environment:
41+ In order to use CUDA Decoding will need the following installed in your environment:
4242
43- #. CUDA-enabled pytorch
44- #. FFmpeg binaries that support NVDEC-enabled codecs
43+ #. An Nvidia GPU that supports decoding the video format you want to decode. See
44+ the support matrix here <https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new>
45+ #. `CUDA-enabled pytorch <https://pytorch.org/get-started/locally/>`_
46+ #. FFmpeg binaries that support NdecoderEC-enabled codecs
4547#. libnpp and nvrtc (these are usually installed when you install the full cuda-toolkit)
4648
4749
48- FFmpeg versions 5, 6 and 7 from conda-forge are built with NVDEC support and you can
50+ FFmpeg versions 5, 6 and 7 from conda-forge are built with NdecoderEC support and you can
4951install them with conda. For example, to install FFmpeg version 7:
5052
5153.. code-block:: bash
52- # These libraries are needed for CUDA decoding with TorchCodec
5354 conda install ffmpeg=7 -c conda-forge
5455 conda install libnpp cuda-nvrtc -c nvidia
5556"""
5657
5758# %%
58- ######################################################################
5959# Checking if Pytorch has CUDA enabled
60- ######################################################################
60+ # -------------------------------------
6161#
6262# .. note::
6363#
7272
7373
7474# %%
75- ######################################################################
7675# Downloading the video
77- ######################################################################
76+ # -------------------------------------
7877#
7978# We will use the following video which has the following properties;
8079#
9897
9998
10099# %%
101- ######################################################################
102100# CUDA Decoding using VideoDecoder
103- ######################################################################
101+ # -------------------------------------
104102#
105103# To use CUDA decoder, you need to pass in a cuda device to the decoder.
106104#
107105from torchcodec .decoders import VideoDecoder
108106
109- vd = VideoDecoder (video_file , device = "cuda:0 " )
110- frame = vd [0 ]
107+ decoder = VideoDecoder (video_file , device = "cuda" )
108+ frame = decoder [0 ]
111109
112110# %%
113111#
123121
124122
125123# %%
126- ######################################################################
127124# Visualizing Frames
128- ######################################################################
125+ # -------------------------------------
129126#
130127# Let's look at the frames decoded by CUDA decoder and compare them
131128# against equivalent results from the CPU decoders.
132- import matplotlib .pyplot as plt
133129
134130
135131def get_frames (timestamps : list [float ], device : str ):
@@ -148,25 +144,43 @@ def get_numpy_images(frames):
148144
149145timestamps = [12 , 19 , 45 , 131 , 180 ]
150146cpu_frames = get_frames (timestamps , device = "cpu" )
151- cuda_frames = get_frames (timestamps , device = "cuda:0 " )
147+ cuda_frames = get_frames (timestamps , device = "cuda" )
152148cpu_numpy_images = get_numpy_images (cpu_frames )
153149cuda_numpy_images = get_numpy_images (cuda_frames )
154150
155151
156- def plot_cpu_and_cuda_images ():
157- n_rows = len (timestamps )
158- fig , axes = plt .subplots (n_rows , 2 , figsize = [12.8 , 16.0 ])
159- for i in range (n_rows ):
160- axes [i ][0 ].imshow (cpu_numpy_images [i ])
161- axes [i ][1 ].imshow (cuda_numpy_images [i ])
152+ def plot (
153+ frames1 : List [torch .Tensor ],
154+ frames2 : List [torch .Tensor ],
155+ title1 : Optional [str ] = None ,
156+ title2 : Optional [str ] = None ,
157+ ):
158+ try :
159+ import matplotlib .pyplot as plt
160+ from torchvision .transforms .v2 .functional import to_pil_image
161+ from torchvision .utils import make_grid
162+ except ImportError :
163+ print ("Cannot plot, please run `pip install torchvision matplotlib`" )
164+ return
165+
166+ plt .rcParams ["savefig.bbox" ] = "tight"
167+
168+ fig , ax = plt .subplots (1 , 2 )
169+
170+ ax [0 ].imshow (to_pil_image (make_grid (frames1 )))
171+ ax [0 ].set (xticklabels = [], yticklabels = [], xticks = [], yticks = [])
172+ if title1 is not None :
173+ ax [0 ].set_title (title1 )
174+
175+ ax [1 ].imshow (to_pil_image (make_grid (frames2 )))
176+ ax [1 ].set (xticklabels = [], yticklabels = [], xticks = [], yticks = [])
177+ if title2 is not None :
178+ ax [1 ].set_title (title2 )
162179
163- axes [0 ][0 ].set_title ("CPU decoder" )
164- axes [0 ][1 ].set_title ("CUDA decoder" )
165- plt .setp (axes , xticks = [], yticks = [])
166180 plt .tight_layout ()
167181
168182
169- plot_cpu_and_cuda_images ( )
183+ plot ( cpu_frames , cuda_frames , "CPU decoder" , "CUDA decoder" )
170184
171185# %%
172186#
0 commit comments