spdl.io.NvDecDecoder

class NvDecDecoder[source]

Decods video packets using NVDEC hardware acceleration.

Use nvdec_decoder() to instantiate.

To decode videos with NVDEC, first you initialize the decoder, then feed video packets. Finally, call flush to let the decoder know that it reached the end of the video stream, so that the decoder flushes its internally buffered frames.

Note

To decode H264 and HEVC videos, the packets must be Annex B format. You can convert video packets to Annex B format by applying bit stream filter while demuxing or after demuxing. See the examples bellow.

Example - decoding the whole video

See also

decode_packets_nvdec(): Decode video packets using NVDEC.

cuda_config = spdl.io.cuda_config(device_index=0)

packets = spdl.io.demux_video(src)
# Convert to Annex B format
if (c := packets.codec.name) in ("h264", "hevc"):
    packets = spdl.io.apply_bsf(f"{c}_mp4toannexb")

# Initialize the decoder
decoder = nvdec_decoder()
decoder.init(cuda_config, packets.codec, ...)

# Decode packets
frames = decoder.decode(packets)

# Done
frames += decoder.flush()

# Convert (and batch) the NV12 frames into RGB
frames = spdl.io.nv12_to_rgb(frames)

Example - incremental decoding

cuda_config = spdl.io.cuda_config(device_index=0)

demuxer = spdl.io.Demuxer(src)
codec = demuxer.video_codec

match codec.name:
    case "h264" | "hevc":
        bsf = f"{codec.name}_mp4toannexb"
    case _:
        bsf = None

decoder = nvdec_decoder()
decoder.init(cuda_config, codec, ...)

for packets in demuxer.streaming_demux_video(10, bsf=bsf):
    buffer = decoder.decode(packets)
    buffer = spdl.io.nv12_to_rgb(buffer)
    # Process buffer here

buffer = decoder.flush()
buffer = spdl.io.nv12_to_rgb(buffer)

Methods

decode(packets)

Decode video frames from the give packets.

flush()

Notify the decoder the end of video stream, and fetch buffered frames.

init(cuda_config, codec, *[, crop_left, ...])

Initialize the decoder.

decode(packets: VideoPackets) list[CUDABuffer][source]

Decode video frames from the give packets.

Note

Due to how video codec works, the number of returned frames do not necessarily match the number of packets provided.

The method can return less number of frames or more number of frames.

Parameters:

packets – Video packets.

Returns:

The decoded frames.

flush() list[CUDABuffer][source]

Notify the decoder the end of video stream, and fetch buffered frames.

Returns:

The decoded frames. (can be empty)

init(cuda_config: CUDAConfig, codec: VideoCodec, *, crop_left: int = 0, crop_top: int = 0, crop_right: int = 0, crop_bottom: int = 0, scale_width: int = -1, scale_height: int = -1) None[source]

Initialize the decoder.

This funciton must be called before decoding can happen.

Note

Creation of underlying decoder object is expensive. Typically, it takes about 300ms or more.

To mitigate this the implementaion tries to reuse the decoder. This works if the new video uses the same codecs as the previous one, and the difference is limited to the resolution of the video.

If you are processing videos of different codecs, then the decoder has to be re-created.

Parameters:
  • cuda_config – The device configuration. Specifies the GPU of which video decoder chip is used, the CUDA memory allocator and CUDA stream used to fetch the result from the decoder engine.

  • codec – The information of the source video.

  • crop_left (int) – Optional: Crop the given number of pixels from each side.

  • crop_top (int) – Optional: Crop the given number of pixels from each side.

  • crop_right (int) – Optional: Crop the given number of pixels from each side.

  • crop_bottom (int) – Optional: Crop the given number of pixels from each side.

  • scale_width (int) – Optional: Resize the frame. Resizing is applied after cropping.

  • scale_height (int) – Optional: Resize the frame. Resizing is applied after cropping.