### Install NV-Codec Headers - Make Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Installs the NVIDIA codec headers with a specified prefix. This command is run from within the nv-codec-headers directory. ```bash make install PREFIX=/usr ``` -------------------------------- ### Install MSYS2 Packages - Pacman Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Installs essential packages (diffutils, make, pkg-config, yasm) using the pacman package manager within the MinGW64 environment. These are required for the compilation process. ```bash pacman -S diffutils make pkg-config yasm ``` -------------------------------- ### Compile FFmpeg - Make Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Compiles the FFmpeg source code using the 'make' command with parallel execution (using -j 8). This command should be run from the FFmpeg installation folder. ```bash make -j 8 ``` -------------------------------- ### FFmpeg 1:1 HWACCEL Transcode with Scaling Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Performs a 1:1 hardware-accelerated transcode using FFmpeg. It reads an input MP4 file, transcodes it to H.264 at 720p resolution, and copies the audio codec. This example utilizes the built-in resizer in the CUVID decoder. Dependencies include FFmpeg with CUDA support. ```bash ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda –resize 1280x720 -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4 ``` -------------------------------- ### Configure Decoder for Scaling with CUVIDDECODECREATEINFO Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvdec-video-decoder-api-prog-guide/index This C code snippet demonstrates how to configure the CUVIDDECODECREATEINFO structure for scaling video output. It sets the target width and height for scaling the decoded video to a new resolution (1920x1080 in this example) before creating the decoder instance using cuvidCreateDecoder(). ```c // Scaling. Source size is 1280x960. Scale to 1920x1080. CUresult rResult; unsigned int uScaleW, uScaleH; uScaleW = 1920; uScaleH = 1080; ... CUVIDDECODECREATEINFO stDecodeCreateInfo; memset(&stDecodeCreateInfo, 0, sizeof(CUVIDDECODECREATEINFO)); ... // Setup the remaining structure members stDecodeCreateInfo.ulTargetWidth = uScaleWidth; stDecodeCreateInfo.ulTargetHeight = uScaleHeight; rResult = cuvidCreateDecoder(&hDecoder, &stDecodeCreateInfo); ... ``` -------------------------------- ### Configure Decoder for Aspect Ratio Conversion - C/C++ Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvdec-video-decoder-api-prog-guide/index Sets up the target rectangle for a CUDA video decoder to perform aspect ratio conversion. This example converts a 4:3 source (1280x960) to a 16:9 aspect ratio. ```c // Aspect Ratio Conversion. Source size is 1280x960(4:3). Convert to // 16:9 CUresult rResult; unsigned int uCropL, uCropR, uCropT, uCropB; uDispAR_L = 0; uDispAR_R = 1280; uDispAR_T = 70; uDispAR_B = 790; ... CUVIDDECODECREATEINFO stDecodeCreateInfo; memset(&stDecodeCreateInfo, 0, sizeof(CUVIDDECODECREATEINFO)); ... // setup structure members stDecodeCreateInfo.target_rect.left = uDispAR_L; stDecodeCreateInfo.target_rect.right = uDispAR_R; stDecodeCreateInfo.target_rect.top = uDispAR_T; stDecodeCreateInfo.target_rect.bottom = uDispAR_B; reResult = cuvidCreateDecoder(&hDecoder, &stDecodeCreateInfo); ... ``` -------------------------------- ### Map and Unmap Decoded Video Frames (C++) Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvdec-video-decoder-api-prog-guide/index Demonstrates the usage of cuvidMapVideoFrame to retrieve a CUDA device pointer and pitch for a decoded frame, and cuvidUnmapVideoFrame to release it. This involves allocating host memory, performing a device-to-host memcpy, and freeing host memory. Assumes necessary setup and handles frame queue operations. ```cpp // MapFrame: Call cuvidMapVideoFrame and get the devptr and associated // pitch. Copy this surface (in device memory) to host memory using // CUDA device to host memcpy. bool MapFrame() { CUVIDPARSEDISPINFO stDispInfo; CUVIDPROCPARAMS stProcParams; CUresult rResult; unsigned int cuDevPtr; int nPitch, nPicIdx; unsigned char* pHostPtr; memset(&stDispInfo, 0, sizeof(CUVIDPARSEDISPINFO)); memset(&stProcParams, 0, sizeof(CUVIDPROCPARAMS)); ... // setup stProcParams if required // retrieve the frames from the Frame Display Queue. This Queue is // is populated in HandlePictureDisplay. if (g_pFrameQueue->dequeue(&stDispInfo)) { nPicIdx = stDispInfo.picture_index; rResult = cuvidMapVideoFrame(&hDecoder, nPicIdx, &cuDevPtr, &nPitch, &stProcParams); // use CUDA based Device to Host memcpy pHostPtr = cuMemAllocHost((void** )&pHostPtr, nPitch); if (pHostPtr) { rResult = cuMemcpyDtoH(pHostPtr, cuDevPtr, nPitch); } rResult = cuvidUnmapVideoFrame(&hDecoder, cuDevPtr); } ... // Dump YUV to a file if (pHostPtr) { cuMemFreeHost(pHostPtr); } ... } ``` -------------------------------- ### Add Compilation Paths - Export Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Adds necessary directories to the system's PATH environment variable. This includes the Visual Studio build tools and the CUDA toolkit's bin directory, allowing the compiler and linker to find required executables and libraries. ```bash export PATH="/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/amd64/”:$PATH export PATH="/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/”:$PATH ``` -------------------------------- ### Create Resources for Input/Output Data Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvenc-video-encoder-api-prog-guide/index Clients need to allocate buffers for input pictures and reference frames using `NvEncCreateInputBuffer`. Output resources for motion vectors are allocated via `NvEncCreateMVBuffer`. The client is responsible for populating input data. ```APIDOC ## Create Resources for Input/Output Data ### Description The client should allocate at least one buffer for the input picture by calling `NvEncCreateInputBuffer` API and should also allocate one buffer for the reference frame by using `NvEncCreateInputBuffer` API. The client is responsible for filling in valid input data. After input resources are created, client needs to allocate resources for the output data by using `NvEncCreateMVBuffer` API. ### Method N/A (API Usage Description) ### Endpoint N/A (API Usage Description) ### Parameters N/A (API Usage Description) ### Request Example N/A ### Response N/A ``` -------------------------------- ### Clone NVIDIA Codec Headers - Git Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Clones the nv-codec-headers repository from its GIT URL. This is a prerequisite for compiling FFmpeg with NVIDIA support. ```bash git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git ``` -------------------------------- ### Writing an Efficient Decode Application Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvdec-video-decoder-api-prog-guide/index This section details the process of building an efficient video decode application using NVIDIA's NVDEC engine. It covers the stages involved, from de-muxing to preparing frames for further processing, and provides optimization strategies. ```APIDOC ## Writing an Efficient Decode Application ### Description This section details the process of building an efficient video decode application using NVIDIA's NVDEC engine. It covers the stages involved, from de-muxing to preparing frames for further processing, and provides optimization strategies. ### Stages of a Decode Application 1. **De-Muxing**: Separating the video bitstream from the container format. This is typically handled by third-party components like FFmpeg. 2. **Video Bitstream Parsing and Decoding**: Parsing the bitstream and utilizing the NVDEC hardware for decoding. This involves calling functions like `cuvidDecodePicture()`. 3. **Preparing the Frame for Further Processing**: Mapping the decoded frame to a CUDA device pointer using `cuvidMapVideoFrame()` for subsequent operations. ### Optimization Strategies * **Threading**: Employ independent threads for de-muxing, parsing, decoding, and processing to maximize parallelism. * **Pipelining**: The NVDEC driver internally maintains a queue of frames for efficient pipelining, ensuring continuous utilization of the hardware decoder. * **PCIe Link Width**: For performance-intensive applications, ensure the PCIe link width is set to the maximum available value. This can be checked using `nvidia-smi -q` and configured in the system's BIOS. * **Reconfiguration**: Use `cuvidReconfigureDecoder()` instead of destroying and recreating the decoder instance when there are frequent changes in decode resolution or post-processing parameters. ### Optimizing Video Memory Usage 1. **`ulNumDecodeSurfaces`**: Set `CUVIDDECODECREATEINFO::ulNumDecodeSurfaces` to `CUVIDEOFORMAT::min_num_decode_surfaces` to allocate the minimum required decode surfaces. Adjust upwards slightly if performance decreases. Find an optimal balance between throughput and memory. 2. **`ulNumOutputSurfaces`**: Determine `CUVIDDECODECREATEINFO::ulNumOutputSurfaces` through experimentation to balance decoder throughput and memory consumption. 3. **`DeinterlaceMode`**: For interlaced content, set `CUVIDDECODECREATEINFO::DeinterlaceMode` to `cudaVideoDeinterlaceMode::cudaVideoDeinterlaceMode_Weave` or `cudaVideoDeinterlaceMode::cudaVideoDeinterlaceMode_Bob` for minimum memory consumption. `cudaVideoDeinterlaceMode::cudaVideoDeinterlaceMode_Adaptive` offers higher quality but uses more memory. If not specified, the driver defaults to `cudaVideoDeinterlaceMode::cudaVideoDeinterlaceMode_Adaptive`. 4. **CUDA Context Sharing**: When decoding multiple streams, allocate a minimum number of CUDA contexts and share them across sessions to reduce memory overhead. ### Key Functions * `cuvidDecodePicture()`: Kicks off the decoding process. * `cuvidMapVideoFrame()`: Maps a decoded video frame to a CUDA device pointer. * `cuvidReconfigureDecoder()`: Reconfigures an existing decoder instance. ``` -------------------------------- ### Clone FFmpeg Repository - Git Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Clones the FFmpeg public GIT repository. This is the main FFmpeg source code that will be compiled with NVIDIA acceleration. ```bash git clone https://git.ffmpeg.org/ffmpeg.git ``` -------------------------------- ### Emphasis Map Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvenc-video-encoder-api-prog-guide/index This section explains the Emphasis Map feature, which allows specifying regions of a frame to be encoded at different quality levels at the macroblock granularity. It details how QP adjustments are made and the steps to enable and use this feature. ```APIDOC ## Emphasis Map ### Description The Emphasis Map feature enables encoding specific regions of a frame with varying quality levels at the macroblock granularity. The encoder adjusts the quantization parameter (QP) for each macroblock based on its emphasis level and the QP determined by the rate control algorithm. This feature is useful for prioritizing quality in complex image areas, even if it potentially leads to VBV/rate violations. ### Enable Emphasis Map Feature 1. **Query Availability**: - Use `NvEncGetEncodeCaps` and check `NV_ENC_CAPS_SUPPORT_EMPHASIS_LEVEL_MAP`. 2. **Set QP Map Mode**: - Set `NV_ENC_RC_PARAMS::qpMapMode = NV_ENC_QP_MAP_EMPHASIS`. 3. **Fill QP Delta Map**: - Populate `NV_ENC_PIC_PARAMS::qpDeltaMap` (a signed byte array per macroblock) with values from the `NV_ENC_EMPHASIS_MAP_LEVEL` enum. ### Emphasis Level Interpretation - Higher values in `NV_ENC_EMPHASIS_MAP_LEVEL` result in a greater negative adjustment to the QP, thus emphasizing the quality of that macroblock. ### Notes - QP adjustment occurs after rate control, potentially causing VBV/rate violations. - This feature is not supported when Spatial/Temporal AQ is enabled. ``` -------------------------------- ### FFmpeg 1:1 HWACCEL Transcode with Scale Filters Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Demonstrates 1:1 hardware-accelerated transcoding using FFmpeg with alternative scaling filters. It reads an input MP4 file and transcodes it to H.264 at 1280x720 resolution using either the `scale_cuda` or `scale_npp` filter for resizing. Audio is copied, and the output is saved as MP4. Dependencies include FFmpeg with CUDA support. ```bash ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -vf scale_cuda=1280:720 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4 ``` ```bash ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -vf scale_npp=1280:720 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4 ``` -------------------------------- ### Configure FFmpeg for NVIDIA Build - Bash Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Configures FFmpeg for compilation with NVIDIA support using the MSVC toolchain. It enables CUDA SDK, NPP, and specifies paths for the custom NV SDK headers and libraries. ```bash ./configure --enable-nonfree –disable-shared --enable-cuda-sdk --enable-libnpp –-toolchain=msvc --extra-cflags=-I../nv_sdk --extra-ldflags=-libpath:../nv_sdk ``` -------------------------------- ### Query NVDEC Capabilities (C/C++) Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvdec-video-decoder-api-prog-guide/index This C/C++ snippet demonstrates how to query the capabilities of the NVDEC hardware using the cuvidGetDecoderCaps() API. It involves initializing a CUVIDDECODECAPS structure with codec type, chroma format, and bit depth, then calling the API. The returned structure provides information on hardware support, resolution limits, and macroblock counts. ```c++ CUVIDDECODECAPS decodeCaps = {}; // set IN params for decodeCaps decodeCaps.eCodecType = cudaVideoCodec_HEVC; // HEVC decodeCaps.eChromaFormat = cudaVideoChromaFormat_420; // YUV 4:2:0 decodeCaps.nBitDepthMinus8 = 2; // 10 bit result = cuvidGetDecoderCaps(&decodeCaps); ``` -------------------------------- ### FFmpeg Video Encoding (720p YUV to H.264 MP4) Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index This command encodes a 720p YUV input file into an MP4 container with H.264 encoded video using the NVENC encoder. It demonstrates basic video encoding acceleration. ```bash ffmpeg -y -vsync 0 –s 1280x720 –i input.yuv -c:v h264_nvenc output.mp4 ``` -------------------------------- ### Initialize Decoder with Display Area - C/C++ Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvdec-video-decoder-api-prog-guide/index Initializes a CUDA video decoder with specific display area parameters for cropping. It uses the CUVIDDECODECREATEINFO structure to set the display area before creating the decoder handle. ```c memset(&stDecodeCreateInfo, 0, sizeof(CUVIDDECODECREATEINFO)); stDecodeCreateInfo.display_area.left = uCropL; stDecodeCreateInfo.display_area.right = uCropR; stDecodeCreateInfo.display_area.top = uCropT; stDecodeCreateInfo.display_area.bottom = uCropB; rResult = cuvidCreateDecoder(&hDecoder, &stDecodeCreateInfo); ``` -------------------------------- ### B-Frames As Reference Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvenc-video-encoder-api-prog-guide/index This section describes how to use B-frames as a reference to improve encoded quality without impacting performance. It includes steps for checking feature availability and enabling the feature during encoder initialization. ```APIDOC ## B-Frames As Reference ### Description Using B-frames as references enhances both subjective and objective encoded quality with no performance overhead. This feature is highly recommended for users enabling multiple B-frames. ### Usage Steps 1. **Query Availability**: Check for `NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE` using the `NvEncGetEncodeCaps` API. 2. **Enable Feature**: During encoder initialization, set `NV_ENC_CONFIG_H264::useBFramesAsRef` to `NV_ENC_BFRAME_REF_MODE_MIDDLE`. This designates the (N/2)th B-frame as a reference, where N is the number of B-frames. If N is odd, the (N-1)/2th frame is used. ``` -------------------------------- ### Reconfigure API Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/nvenc-video-encoder-api-prog-guide/index The `NvEncReconfigureEncoder` API allows dynamic modification of encoder initialization parameters without terminating the existing session, thus avoiding latency. It supports changes to bitrate, frame rate, and resolution, but has limitations on certain parameters like GOP structure and encoding mode. ```APIDOC ## Reconfigure API (`NvEncReconfigureEncoder`) ### Description The `NvEncReconfigureEncoder` API enables clients to alter encoder initialization parameters specified in `NV_ENC_INITIALIZE_PARAMS` without closing and re-creating the encoding session. This minimizes latency, making it beneficial for scenarios like video conferencing and game streaming where transmission mediums can be unstable. The API allows dynamic changes to parameters such as bit-rate, frame-rate, and resolution. ### Supported Reconfigurations - Bit-rate - Frame-rate - Resolution (requires `NV_ENC_INITIALIZE_PARAMS::maxEncodeWidth` and `NV_ENC_INITIALIZE_PARAMS::maxEncodeHeight` to be set during session creation) ### Unsupported Reconfigurations - GOP structure (`NV_ENC_CONFIG_H264::idrPeriod`, `NV_ENC_CONFIG::gopLength`, `NV_ENC_CONFIG::frameIntervalP`) - Switching between synchronous and asynchronous encoding modes. - Changing `NV_ENC_INITIALIZE_PARAMS::maxEncodeWidth` and `NV_ENC_INITIALIZE_PARAMS::maxEncodeHeight` after initialization. - Changing picture type decision (`NV_ENC_INITIALIZE_PARAMS::enablePTD`). - Changing bit-depth. ### API Usage Parameters - **`NV_ENC_RECONFIGURE_PARAMS::reInitEncodeParams`**: Contains the reconfigured initialization parameters. - **`NV_ENC_RECONFIGURE_PARAMS::forceIDR`**: Set to 1 to force the next frame after reconfiguration to be an IDR frame, especially recommended when changing resolution. - **`NV_ENC_RECONFIGURE_PARAMS::resetEncoder`**: Set to 1 to reset the internal rate control states. ### Error Handling - The API will fail if attempts are made to reconfigure unsupported parameters. - Resolution changes are only possible if `maxEncodeWidth` and `maxEncodeHeight` were specified during encoder session creation. ``` -------------------------------- ### FFmpeg Low Latency Transcoding with LLHQ Preset Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index This command uses FFmpeg with NVENC to perform low-latency, high-quality transcoding. It copies the audio stream, encodes the video using H.264 with the 'llhq' preset for a balance of quality and latency, and sets specific bitrate and buffer configurations. Input and output files are specified, along with hardware acceleration. ```bash ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:a copy -c:v h264_nvenc -preset llhq -profile high -b:v 5M -bufsize 167K -maxrate 5M -g 999999 -bf 0 output.mp4 ``` -------------------------------- ### Hardware Accelerated Transcode Test - FFmpeg Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Performs a 1:1 hardware-accelerated transcode of an input video file to an output file using the CUDA-enabled H.264 encoder (h264_nvenc). This command is used for basic testing after compilation. ```bash ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4 ``` -------------------------------- ### Set Environment Variables for GPU Transcoding (Bash) Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index These environment variables configure CUDA for optimal GPU transcoding. CUDA_VISIBLE_DEVICES selects the GPU, and CUDA_DEVICE_MAX_CONNECTIONS controls the number of concurrent connections to the device. This is crucial for minimizing initialization overhead when running multiple transcode sessions. ```bash export CUDA_VISIBLE_DEVICES=0 export CUDA_DEVICE_MAX_CONNECTIONS=2 ``` -------------------------------- ### FFmpeg 1:N HWACCEL Transcode from YUV/RAW Data Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index Transcodes YUV or RAW data into multiple H.264 outputs using hardware acceleration with FFmpeg. This command reads a YUV input file, uploads it to CUDA, splits it, and encodes four versions at different bitrates (8M, 10M, 12M, 14M) for 1080p resolution. It is optimized for efficient disk I/O, especially when using SSDs. The pixel format should be adjusted based on the input YUV type (e.g., yuv444p, p010). ```bash ffmpeg -y -vsync 0 -pix_fmt yuv420p -s 1920x1080 -i input.yuv -filter_complex "[0:v]hwupload_cuda,split=4[o1][o2][o3][o4]" -map "[o1]" -c:v h264_nvenc -b:v 8M output1.mp4 -map "[o2]" -c:v h264_nvenc -b:v 10M output2.mp4 -map "[o3]" -c:v h264_nvenc -b:v 12M output3.mp4 -map "[o4]" -c:v h264_nvenc -b:v 14M output4.mp4 ``` -------------------------------- ### FFmpeg Multiple 1:N Transcode with Scaling (SW Decode HW Scaling HW Encode) Source: https://docs.nvidia.com/video-technologies/video-codec-sdk/10.0/ffmpeg-with-nvidia-gpu/index This command performs multiple 1:N transcodes from two input files. It decodes one input in software, scales the input in hardware using NPP, and encodes to H.264 using NVENC. The second input is also transcoded to different resolutions. ```bash ffmpeg -y -init_hw_device cuda=foo:bar -filter_hw_device foo \ -i input1.mp4 -i input2.mp4 \ -map 0:0 -vf hwupload,scale_npp=640:480 –c:v h264_nvenc -b:v 1M \ output11.mp4 \ -map 0:0 -vf hwupload,scale_npp=320:240 –c:v h264_nvenc -b:v 500k \ output12.mp4 \ -map 1:0 -vf hwupload,scale_npp=1280:720 –c:v h264_nvenc -b:v 2M \ output21.mp4 \ -map 1:0 -vf hwupload,scale_npp=640:480 –c:v h264_nvenc -b:v 1M \ output22.mp4 ```