Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for gpu_direct in ffmepg ffmpeg plugin #967

Merged
merged 6 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions ecosystem/ffmpeg_plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,46 @@ ffmpeg -stream_loop -1 -i test.wav -p_port 0000:af:01.1 -p_sip 192.168.96.3 -p_t

ffmpeg -p_port 0000:af:01.0 -p_sip 192.168.96.2 -p_rx_ip 239.168.85.20 -udp_port 30000 -payload_type 111 -pcm_fmt pcm16 -at 1ms -ac 2 -f mtl_st30p -i "0" dump_pcm16.wav -y
```

### Enabling experimental MTL_GPU_DIRECT in FFmpeg with ST20p Support

The MTL_GPU_DIRECT experimental feature aims at enhancing FFmpeg's performance by allowing direct access to GPU memory, which can be particularly beneficial when working with high-throughput video streams such as those handled by the MTL ST20 codec plugin.

#### Building FFmpeg with MTL_GPU_DIRECT Enabled
To take advantage of the MTL_GPU_DIRECT feature FFmpeg has to be built with this option enabled. Here’s how to do it:

```bash
./configure --enable-shared --disable-static --enable-nonfree --enable-pic --enable-gpl --enable-libopenh264 --enable-encoder=libopenh264 --enable-mtl --extra-cflags="-DMTL_GPU_DIRECT_ENABLED"
```
or use
```bash
./build_ffmpeg_plugin.sh -g
```

Reading a ST2110-20 10bit YUV422 stream on "239.168.85.20:20000" with payload_type 112 and
enabled gpu_direct:

```bash
./ffmpeg -p_port 0000:af:01.0 -p_sip 192.168.96.2 -p_rx_ip 239.168.85.20 -udp_port 20000 -payload_type 112 -fps 59.94 -pix_fmt yuv422p10le -video_size 1920x1080 -gpu_direct 1 -gpu_driver 0 -gpu_device 0 -f mtl_st20p -i "k" -f rawvideo /dev/null -y
```

#### Additional Notes
**GPU Direct Flag:** When compiling FFmpeg with the MTL_GPU_DIRECT feature enabled, ensure that your system's GPU drivers and hardware support direct GPU memory access.
GPU device IDs and GPU driver IDs are printed during initialization.

**Options:**
1. `-gpu_device`
1. `-gpu_driver`

Both default to 0, but if your device doesn't initialize, adjust it using the information printed during initialization.

**Example:**
```plaintext
Drivers count: 1
Driver: 0: Device: 0: Name: Intel(R) Data Center GPU Flex 170, Type: 1, VendorID: 8086, DeviceID: 22208
```


[GPU Documentation](../../doc/gpu.md)

By following these steps, you can effectively build and utilize FFmpeg with the MTL_GPU_DIRECT feature enabled.
64 changes: 52 additions & 12 deletions ecosystem/ffmpeg_plugin/build_ffmpeg_plugin.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,51 @@
#!/bin/bash

# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2024 Intel Corporation
# SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
DawidWesierski4 marked this conversation as resolved.
Show resolved Hide resolved

set -e

if [ -n "$1" ]; then
ffmpeg_ver=$1
else
# default to latest 7.0
ffmpeg_ver=7.0
fi
# Default values
ffmpeg_ver="7.0"
enable_gpu=false
script_path="$(dirname "$(readlink -f "$0")")"

# Help message function
usage() {
echo "Usage: $0 [options]"
echo "Options:"
echo " -v <version> Specify the FFmpeg version to build (default is $ffmpeg_ver)"
echo " -g Enable GPU direct mode during compilation"
echo " -h Display this help and exit"
}

# Parse command-line options
while getopts ":v:hg" opt; do
case "${opt}" in
v)
ffmpeg_ver=${OPTARG}
;;
g)
enable_gpu=true
;;
h)
usage
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done

build_openh264() {
rm openh264 -rf
rm -rf openh264
git clone https://github.com/cisco/openh264.git
cd openh264
git checkout openh264v2.4.0
Expand All @@ -24,13 +56,21 @@ build_openh264() {
}

build_ffmpeg() {
rm FFmpeg -rf
rm -rf FFmpeg
git clone https://github.com/FFmpeg/FFmpeg.git
cd FFmpeg
git checkout release/"$ffmpeg_ver"
cp -f ../mtl_* ./libavdevice/
git am ../"$ffmpeg_ver"/*.patch
./configure --enable-shared --disable-static --enable-nonfree --enable-pic --enable-gpl --enable-libopenh264 --enable-encoder=libopenh264 --enable-mtl
cp -f "$script_path"/mtl_* ./libavdevice/
git am "$script_path"/"$ffmpeg_ver"/*.patch

if [ "$enable_gpu" = true ]; then
echo "Building with MTL_GPU_DIRECT_ENABLED"
extra_config_flags="--extra-cflags=-DMTL_GPU_DIRECT_ENABLED"
else
extra_config_flags=""
fi

./configure --enable-shared --disable-static --enable-nonfree --enable-pic --enable-gpl --enable-libopenh264 --enable-encoder=libopenh264 --enable-mtl $extra_config_flags
make -j "$(nproc)"
sudo make install
sudo ldconfig
Expand Down
60 changes: 60 additions & 0 deletions ecosystem/ffmpeg_plugin/mtl_st20p_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
*/

#include "mtl_common.h"
#ifdef MTL_GPU_DIRECT_ENABLED
#include <mtl_gpu_direct/gpu.h>
#endif /* MTL_GPU_DIRECT_ENABLED */

typedef struct MtlSt20pDemuxerContext {
const AVClass* class; /**< Class for private options. */
Expand All @@ -39,6 +42,13 @@ typedef struct MtlSt20pDemuxerContext {
st20p_rx_handle rx_handle;

int64_t frame_counter;

#ifdef MTL_GPU_DIRECT_ENABLED
bool gpu_direct_enabled;
int gpu_driver_index;
int gpu_device_index;
void* gpu_context;
#endif /* MTL_GPU_DIRECT_ENABLED */
} MtlSt20pDemuxerContext;

static int mtl_st20p_read_close(AVFormatContext* ctx) {
Expand All @@ -58,6 +68,12 @@ static int mtl_st20p_read_close(AVFormatContext* ctx) {
s->dev_handle = NULL;
}

#ifdef MTL_GPU_DIRECT_ENABLED
if (s->gpu_direct_enabled) {
free_gpu_context(s->gpu_context);
}
#endif /* MTL_GPU_DIRECT_ENABLED */

info(ctx, "%s(%d), frame_counter %" PRId64 "\n", __func__, s->idx, s->frame_counter);
return 0;
}
Expand Down Expand Up @@ -148,6 +164,24 @@ static int mtl_st20p_read_header(AVFormatContext* ctx) {
dbg(ctx, "%s, fb_cnt: %d\n", __func__, s->fb_cnt);
ops_rx.framebuff_cnt = s->fb_cnt;

#ifdef MTL_GPU_DIRECT_ENABLED
if (s->gpu_direct_enabled) {
/* create context for one gpu device */
GpuContext gpu_ctx = {0};
DawidWesierski4 marked this conversation as resolved.
Show resolved Hide resolved

/* print GPU device and driver IDs */
print_gpu_drivers_and_devices();

ret = init_gpu_device(&gpu_ctx, s->gpu_driver_index, s->gpu_device_index);
if (ret < 0) {
err(ctx, "%s, app gpu initialization failed %d\n", __func__, ret);
return -ENXIO;
}
ops_rx.gpu_context = (void*)(&gpu_ctx);
ops_rx.flags |= ST20P_RX_FLAG_USE_GPU_DIRECT_FRAMEBUFFERS;
}
#endif /* MTL_GPU_DIRECT_ENABLED */

// get mtl dev
s->dev_handle = mtl_dev_get(ctx, &s->devArgs, &s->idx);
if (!s->dev_handle) {
Expand Down Expand Up @@ -296,6 +330,32 @@ static const AVOption mtl_st20p_rx_options[] = {
3,
8,
DEC},
#ifdef MTL_GPU_DIRECT_ENABLED
{"gpu_direct",
"Store frames in framebuffer directly on GPU",
OFFSET(gpu_direct_enabled),
AV_OPT_TYPE_BOOL,
{.i64 = 0},
0,
1,
DEC},
{"gpu_driver",
"Index of the GPU driver",
OFFSET(gpu_driver_index),
AV_OPT_TYPE_INT,
{.i64 = 0},
0,
60,
DEC},
{"gpu_device",
"Index of the GPU device",
OFFSET(gpu_device_index),
AV_OPT_TYPE_INT,
{.i64 = 0},
0,
60,
DEC},
#endif /* MTL_GPU_DIRECT_ENABLED */
{NULL},
};

Expand Down