Skip to content

Commit

Permalink
Fix: Framerate parsing in gst mtl plugins (#1063)
Browse files Browse the repository at this point in the history
- Use GST_TYPE_FRACTION as the type for the framerate parameter in the
plugins instead of hardcoded enums.
- Update parameters description in README
- Remove fps parameter from gst_mtl_st20p_tx, gst_mtl_st30p_tx,
gst_mtl_st30p_rx

This fixes fractional fps support

---------

Signed-off-by: Kasiewicz, Marek <[email protected]>
  • Loading branch information
Sakoram authored Feb 6, 2025
1 parent 3e732d1 commit f53dd3a
Show file tree
Hide file tree
Showing 16 changed files with 158 additions and 283 deletions.
87 changes: 42 additions & 45 deletions ecosystem/gstreamer_plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,33 +116,29 @@ These are also general parameters accepted by plugins, but the functionality the

### 2.3. General capabilities

Some structures describe the capabilities generally

#### 2.3.1. Supported video fps codes gst_mtl_supported_fps
```c
enum gst_mtl_supported_fps {
GST_MTL_SUPPORTED_FPS_23_98 = 2398, // 23.98 fps
GST_MTL_SUPPORTED_FPS_24 = 24, // 24 fps
GST_MTL_SUPPORTED_FPS_25 = 25, // 25 fps
GST_MTL_SUPPORTED_FPS_29_97 = 2997, // 29.97 fps
GST_MTL_SUPPORTED_FPS_30 = 30, // 30 fps
GST_MTL_SUPPORTED_FPS_50 = 50, // 50 fps
GST_MTL_SUPPORTED_FPS_59_94 = 5994, // 59.94 fps
GST_MTL_SUPPORTED_FPS_60 = 60, // 60 fps
GST_MTL_SUPPORTED_FPS_100 = 100, // 100 fps
GST_MTL_SUPPORTED_FPS_119_88 = 11988, // 119.88 fps
GST_MTL_SUPPORTED_FPS_120 = 120 // 120 fps
};
```

#### 2.3.2. Supported Audio Sampling Rates gst_mtl_supported_audio_sampling
```c
enum gst_mtl_supported_audio_sampling {
GST_MTL_SUPPORTED_AUDIO_SAMPLING_44_1K = 44100, // 44.1 kHz
GST_MTL_SUPPORTED_AUDIO_SAMPLING_48K = 48000, // 48 kHz
GST_MTL_SUPPORTED_AUDIO_SAMPLING_96K = 96000 // 96 kHz
};
```
#### 2.3.1. Supported video fps fractions

| Frame Rate | Fraction |
|------------|-------------|
| 23.98 fps | `2398/100` |
| 24 fps | `24` |
| 25 fps | `25` |
| 29.97 fps | `2997/100` |
| 30 fps | `30` |
| 50 fps | `50` |
| 59.94 fps | `5994/100` |
| 60 fps | `60` |
| 100 fps | `100` |
| 119.88 fps | `11988/100` |
| 120 fps | `120` |

#### 2.3.2. Supported Audio Sampling Rates

| Sampling Rate | Value |
|---------------|---------|
| 44.1 kHz | `44100` |
| 48 kHz | `48000` |
| 96 kHz | `96000` |

## 3. SMPTE ST 2110-20 Rawvideo plugins

Expand All @@ -165,15 +161,15 @@ The `mtl_st20p_tx` plugin supports the following pad capabilities:
- **Formats**: `v210`, `I422_10LE`
- **Width Range**: 64 to 16384
- **Height Range**: 64 to 8704
- **Framerate Range**: 24, 25, 30, 50, 60, 100, 120
- **Framerate Range**: `2398/100`, `24`, `25`, `2997/100`, `30`, `50`, `5994/100`, `60`, `100`,
`11988/100`, `120`

[More information about GStreamer capabilities (GstCaps)](https://gstreamer.freedesktop.org/documentation/gstreamer/gstcaps.html)

**Arguments**
| Property Name | Type | Description | Range | Default Value |
|---------------------|--------|-------------------------------------------------------|-------------------------|---------------|
| retry | uint | Number of times the MTL will try to get a frame. | 0 to G_MAXUINT | 10 |
| tx-fps | uint | Framerate of the video. | [gst_mtl_supported_fps](#231-supported-video-fps-codes-gst_mtl_supported_fps) | 0 |
| tx-framebuff-num | uint | Number of framebuffers to be used for transmission. | 0 to 8 | 3 |

#### 3.1.2. Preparing Input Video
Expand Down Expand Up @@ -203,7 +199,7 @@ export VFIO_PORT_T="pci_address_of_the_device"
# video pipeline y210 FHD 60fps on port 20000
gst-launch-1.0 filesrc location=$INPUT ! \
rawvideoparse format=v210 height=1080 width=1920 framerate=60/1 ! \
rawvideoparse format=v210 height=1080 width=1920 framerate=25/1 ! \
mtl_st20p_tx tx-queues=4 rx-queues=0 udp-port=20000 payload-type=112 dev-ip="192.168.96.3" ip="239.168.75.30" dev-port=$VFIO_PORT_T \
--gst-plugin-path $GSTREAMER_PLUGINS_PATH
```
Expand All @@ -217,18 +213,19 @@ The `mtl_st20p_rx` plugin supports the following pad capabilities:
- **Formats**: `v210`, `I422_10LE`
- **Width Range**: 64 to 16384
- **Height Range**: 64 to 8704
- **Framerate Range**: 0 to MAX
- **Framerate Range**: `2398/100`, `24`, `25`, `2997/100`, `30`, `50`, `5994/100`, `60`, `100`,
`11988/100`, `120`

**Arguments**
| Property Name | Type | Description | Range | Default Value |
|---------------------|---------|-----------------------------------------------------|----------------------------|---------------|
| retry | uint | Number of times the MTL will try to get a frame. | 0 to G_MAXUINT | 10 |
| rx-fps | uint | Framerate of the video. | [gst_mtl_supported_fps](#231-supported-video-fps-codes-gst_mtl_supported_fps) | 0 |
| rx-framebuff-num | uint | Number of framebuffers to be used for transmission. | 0 to 8 | 3 |
| rx-width | uint | Width of the video. | 0 to G_MAXUINT | 1920 |
| rx-height | uint | Height of the video. | 0 to G_MAXUINT | 1080 |
| rx-interlaced | boolean | Whether the video is interlaced. | TRUE/FALSE | FALSE |
| rx-pixel-format | string | Pixel format of the video. | `v210`, `YUV444PLANAR10LE` | `v210` |
| Property Name | Type | Description | Range | Default Value |
|---------------------|----------|-----------------------------------------------------|----------------------------|---------------|
| retry | uint | Number of times the MTL will try to get a frame. | 0 to G_MAXUINT | 10 |
| rx-fps | fraction | Framerate of the video. | [Supported video fps fractions](#231-supported-video-fps-fractions) | 25/1 |
| rx-framebuff-num | uint | Number of framebuffers to be used for transmission. | 0 to 8 | 3 |
| rx-width | uint | Width of the video. | 0 to G_MAXUINT | 1920 |
| rx-height | uint | Height of the video. | 0 to G_MAXUINT | 1080 |
| rx-interlaced | boolean | Whether the video is interlaced. | TRUE/FALSE | FALSE |
| rx-pixel-format | string | Pixel format of the video. | `v210`, `YUV444PLANAR10LE` | `v210` |

#### 3.2.2. Preparing output path

Expand All @@ -250,7 +247,7 @@ To run the `mtl_st20p_rx` plugin, use the following command to specify the input
export VFIO_PORT_R="pci_address_of_the_device"
# Run the receiver pipeline y210 FHD 60fps on port 20000
gst-launch-1.0 mtl_st20p_rx rx-queues=4 udp-port=20000 payload-type=112 dev-ip="192.168.96.3" ip="239.168.75.30" dev-port=$VFIO_PORT_R rx-pixel-format=v210 rx-height=1080 rx-width=1920 rx-fps=25 ! \
gst-launch-1.0 mtl_st20p_rx rx-queues=4 udp-port=20000 payload-type=112 dev-ip="192.168.96.3" ip="239.168.75.30" dev-port=$VFIO_PORT_R rx-pixel-format=v210 rx-height=1080 rx-width=1920 rx-fps=25/1 ! \
filesink location=$OUTPUT --gst-plugin-path $GSTREAMER_PLUGINS_PATH
```

Expand All @@ -273,7 +270,7 @@ The `mtl_st30p_tx` plugin supports the following pad capabilities:
**Arguments**
| Property Name | Type | Description | Range | Default Value |
|---------------------|--------|-------------------------------------------------------|-------------------------|---------------|
| tx-samplerate | uint | Sample rate of the audio. | [gst_mtl_supported_audio_sampling](#232-supported-audio-sampling-rates-gst_mtl_supported_audio_sampling) | 0 |
| tx-samplerate | uint | Sample rate of the audio. | [Supported Audio Sampling Rates](#232-supported-audio-sampling-rates) | 0 |
| tx-channels | uint | Number of audio channels. | 1 to 8 | 2 |
| tx-ptime | string | Packetization time for the audio stream. | `1ms`, `125us`, `250us`, `333us`, `4ms`, `80us`, `1.09ms`, `0.14ms`, `0.09ms` | `1.09ms` for 44.1kHz, `1ms` for others |

Expand Down Expand Up @@ -309,7 +306,7 @@ The `mtl_st30p_rx` plugin supports the following pad capabilities:
|---------------------|---------|-------------------------------------------------------|-------------------------|---------------|
| rx-framebuff-num | uint | Number of framebuffers to be used for transmission. | 0 to G_MAXUINT | 3 |
| rx-channel | uint | Audio channel number. | 0 to G_MAXUINT | 2 |
| rx-sampling | uint | Audio sampling rate. | [gst_mtl_supported_audio_sampling](#232-supported-audio-sampling-rates-gst_mtl_supported_audio_sampling) | 48000 |
| rx-sampling | uint | Audio sampling rate. | [Supported Audio Sampling Rates](#232-supported-audio-sampling-rates) | 48000 |
| rx-audio-format | string | Audio format type. | `S8`, `S16LE`, `S24LE` | `S16LE` |
| rx-ptime | string | Packetization time for the audio stream. | `1ms`, `125us`, `250us`, `333us`, `4ms`, `80us`, `1.09ms`, `0.14ms`, `0.09ms` | `1.09ms` for 44.1kHz, `1ms` for others |

Expand Down Expand Up @@ -356,7 +353,7 @@ The `mtl_st40p_tx` plugin supports all pad capabilities (the data is not checked
| Property Name | Type | Description | Range | Default Value |
|-------------------|------|--------------------------------------------------------------------|---------------|---------------|
| tx-framebuff-cnt | uint | Number of framebuffers to be used for transmission. | 0 to G_MAXUINT| 3 |
| tx-fps | uint | Framerate of the video to which the ancillary data is synchronized.| 0 to G_MAXUINT| 60 |
| tx-fps | uint | Framerate of the video to which the ancillary data is synchronized.| [Supported video fps fractions](#231-supported-video-fps-fractions) | 25/1 |
| tx-did | uint | Data ID for the ancillary data. | 0 to 255 | 0 |
| tx-sdid | uint | Secondary Data ID for the ancillary data. | 0 to 255 | 0 |

Expand All @@ -370,7 +367,7 @@ To run the `mtl_st40p_tx` plugin, use the following command:
export VFIO_PORT_T="pci_address_of_the_device"
# Ancillary data pipeline on port 40000
gst-launch-1.0 filesrc location=$INPUT ! mtl_st40p_tx tx-queues=4 udp-port=40000 payload-type=113 dev-ip="192.168.96.3" ip="239.168.75.30" dev-port=$VFIO_PORT_T tx-framebuff-cnt=3 tx-fps=60 tx-did=67 tx-sdid=2 --gst-plugin-path $GSTREAMER_PLUGINS_PATH
gst-launch-1.0 filesrc location=$INPUT ! mtl_st40p_tx tx-queues=4 udp-port=40000 payload-type=113 dev-ip="192.168.96.3" ip="239.168.75.30" dev-port=$VFIO_PORT_T tx-framebuff-cnt=3 tx-fps=25/1 tx-did=67 tx-sdid=2 --gst-plugin-path $GSTREAMER_PLUGINS_PATH
```

This command sets up the transmission pipeline with the specified parameters and sends the ancillary data using the `mtl_st40p_tx` plugin.
Expand Down
81 changes: 0 additions & 81 deletions ecosystem/gstreamer_plugin/gst_mtl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,87 +31,6 @@ gboolean gst_mtl_common_parse_input_finfo(const GstVideoFormatInfo* finfo,
return TRUE;
}

gboolean gst_mtl_common_parse_fps_code(gint fps_code, enum st_fps* fps) {
if (!fps) {
GST_ERROR("Invalid fps pointer");
return FALSE;
}

switch (fps_code) {
case GST_MTL_SUPPORTED_FPS_120:
*fps = ST_FPS_P120;
break;
case GST_MTL_SUPPORTED_FPS_119_88:
*fps = ST_FPS_P119_88;
break;
case GST_MTL_SUPPORTED_FPS_100:
*fps = ST_FPS_P100;
break;
case GST_MTL_SUPPORTED_FPS_60:
*fps = ST_FPS_P60;
break;
case GST_MTL_SUPPORTED_FPS_59_94:
*fps = ST_FPS_P59_94;
break;
case GST_MTL_SUPPORTED_FPS_50:
*fps = ST_FPS_P50;
break;
case GST_MTL_SUPPORTED_FPS_30:
*fps = ST_FPS_P30;
break;
case GST_MTL_SUPPORTED_FPS_29_97:
*fps = ST_FPS_P29_97;
break;
case GST_MTL_SUPPORTED_FPS_25:
*fps = ST_FPS_P25;
break;
case GST_MTL_SUPPORTED_FPS_24:
*fps = ST_FPS_P24;
break;
case GST_MTL_SUPPORTED_FPS_23_98:
*fps = ST_FPS_P23_98;
break;
default:
return FALSE;
}

return TRUE;
}

gboolean gst_mtl_common_parse_fps(GstVideoInfo* info, enum st_fps* fps) {
gint fps_div;
if (info->fps_n <= 0 || info->fps_d <= 0) {
return FALSE;
}

fps_div = info->fps_n / info->fps_d;

switch (fps_div) {
case 24:
*fps = ST_FPS_P24;
break;
case 25:
*fps = ST_FPS_P25;
break;
case 30:
*fps = ST_FPS_P30;
break;
case 50:
*fps = ST_FPS_P50;
break;
case 60:
*fps = ST_FPS_P60;
break;
case 120:
*fps = ST_FPS_P120;
break;
default:
return FALSE;
}

return TRUE;
}

/* includes all formats supported by the library for future support */
gboolean gst_mtl_common_parse_pixel_format(const char* format, enum st_frame_fmt* fmt) {
if (!fmt || !format) {
Expand Down
18 changes: 2 additions & 16 deletions ecosystem/gstreamer_plugin/gst_mtl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#define NS_PER_S (1000 * NS_PER_MS)
#endif

#define DEFAULT_FRAMERATE 25

enum {
PROP_GENERAL_0,
PROP_GENERAL_LOG_LEVEL,
Expand All @@ -42,20 +44,6 @@ enum {
PROP_GENERAL_MAX
};

enum gst_mtl_supported_fps {
GST_MTL_SUPPORTED_FPS_23_98 = 2398,
GST_MTL_SUPPORTED_FPS_24 = 24,
GST_MTL_SUPPORTED_FPS_25 = 25,
GST_MTL_SUPPORTED_FPS_29_97 = 2997,
GST_MTL_SUPPORTED_FPS_30 = 30,
GST_MTL_SUPPORTED_FPS_50 = 50,
GST_MTL_SUPPORTED_FPS_59_94 = 5994,
GST_MTL_SUPPORTED_FPS_60 = 60,
GST_MTL_SUPPORTED_FPS_100 = 100,
GST_MTL_SUPPORTED_FPS_119_88 = 11988,
GST_MTL_SUPPORTED_FPS_120 = 120
};

enum gst_mtl_supported_audio_sampling {
GST_MTL_SUPPORTED_AUDIO_SAMPLING_44_1K = 44100,
GST_MTL_SUPPORTED_AUDIO_SAMPLING_48K = 48000,
Expand All @@ -79,8 +67,6 @@ typedef struct SessionPortArgs {

gboolean gst_mtl_common_parse_input_finfo(const GstVideoFormatInfo* finfo,
enum st_frame_fmt* fmt);
gboolean gst_mtl_common_parse_fps(GstVideoInfo* info, enum st_fps* fps);
gboolean gst_mtl_common_parse_fps_code(gint fps_code, enum st_fps* fps);
gboolean gst_mtl_common_parse_pixel_format(const char* format, enum st_frame_fmt* fmt);

gboolean gst_mtl_common_parse_audio_format(const char* format, enum st30_fmt* audio);
Expand Down
33 changes: 22 additions & 11 deletions ecosystem/gstreamer_plugin/gst_mtl_st20p_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ static void gst_mtl_st20p_rx_class_init(Gst_Mtl_St20p_RxClass* klass) {

g_object_class_install_property(
gobject_class, PROP_ST20P_RX_FRAMERATE,
g_param_spec_uint("rx-fps", "Video framerate", "Framerate of the video.", 0,
G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_param_spec_fraction("rx-fps", "Video framerate", "Framerate of the video", 1, 1,
G_MAXINT, 1, DEFAULT_FRAMERATE, 1,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

g_object_class_install_property(
gobject_class, PROP_ST20P_RX_FRAMEBUFF_NUM,
Expand Down Expand Up @@ -235,8 +236,9 @@ static gboolean gst_mtl_st20p_rx_start(GstBaseSrc* basesrc) {
ops_rx->interlaced = src->interlaced;
ops_rx->flags |= ST20P_RX_FLAG_BLOCK_GET;

if (!src->framerate || !gst_mtl_common_parse_fps_code(src->framerate, &ops_rx->fps)) {
GST_ERROR("Failed to parse custom ops_rx fps code %d", src->framerate);
ops_rx->fps = st_frame_rate_to_st_fps((double)src->fps_n / src->fps_d);
if (ops_rx->fps == ST_FPS_MAX) {
GST_ERROR("Invalid framerate: %d/%d", src->fps_n, src->fps_d);
return FALSE;
}

Expand Down Expand Up @@ -300,6 +302,9 @@ static void gst_mtl_st20p_rx_init(Gst_Mtl_St20p_Rx* src) {
GstElement* element = GST_ELEMENT(src);
GstPad* srcpad;

src->fps_n = DEFAULT_FRAMERATE;
src->fps_d = 1;

srcpad = gst_element_get_static_pad(element, "src");
if (!srcpad) {
GST_ERROR_OBJECT(src, "Failed to get src pad from child element");
Expand All @@ -322,7 +327,8 @@ static void gst_mtl_st20p_rx_set_property(GObject* object, guint prop_id,
self->retry_frame = g_value_get_uint(value);
break;
case PROP_ST20P_RX_FRAMERATE:
self->framerate = g_value_get_uint(value);
self->fps_n = gst_value_get_fraction_numerator(value);
self->fps_d = gst_value_get_fraction_denominator(value);
break;
case PROP_ST20P_RX_FRAMEBUFF_NUM:
self->framebuffer_num = g_value_get_uint(value);
Expand Down Expand Up @@ -360,7 +366,7 @@ static void gst_mtl_st20p_rx_get_property(GObject* object, guint prop_id, GValue
g_value_set_uint(value, src->retry_frame);
break;
case PROP_ST20P_RX_FRAMERATE:
g_value_set_uint(value, src->framerate);
gst_value_set_fraction(value, src->fps_n, src->fps_d);
break;
case PROP_ST20P_RX_FRAMEBUFF_NUM:
g_value_set_uint(value, src->framebuffer_num);
Expand Down Expand Up @@ -407,6 +413,11 @@ static gboolean gst_mtl_st20p_rx_negotiate(GstBaseSrc* basesrc) {
*/
info->interlace_mode = src->interlaced;

info->width = src->width;
info->height = src->height;
info->fps_n = src->fps_n;
info->fps_d = src->fps_d;

switch (ops_rx->output_fmt) {
case ST_FRAME_FMT_V210:
info->finfo = gst_video_format_get_info(GST_VIDEO_FORMAT_v210);
Expand All @@ -420,11 +431,11 @@ static gboolean gst_mtl_st20p_rx_negotiate(GstBaseSrc* basesrc) {
return FALSE;
}

caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING,
gst_video_format_to_string(info->finfo->format), "width",
G_TYPE_INT, info->width, "height", G_TYPE_INT, info->height,
"framerate", GST_TYPE_FRACTION, info->fps_n, 1,
"interlace-mode", G_TYPE_BOOLEAN, src->interlaced, NULL);
caps = gst_caps_new_simple(
"video/x-raw", "format", G_TYPE_STRING,
gst_video_format_to_string(info->finfo->format), "width", G_TYPE_INT, info->width,
"height", G_TYPE_INT, info->height, "framerate", GST_TYPE_FRACTION, info->fps_n,
info->fps_d, "interlace-mode", G_TYPE_BOOLEAN, info->interlace_mode, NULL);

if (!caps) caps = gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(basesrc));

Expand Down
2 changes: 1 addition & 1 deletion ecosystem/gstreamer_plugin/gst_mtl_st20p_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ struct _Gst_Mtl_St20p_Rx {
gboolean interlaced;
gchar pixel_format[MTL_PORT_MAX_LEN];
guint framebuffer_num;
guint framerate;
guint fps_n, fps_d;

/* TODO add support for gpu direct */
#ifdef MTL_GPU_DIRECT_ENABLED
Expand Down
Loading

0 comments on commit f53dd3a

Please sign in to comment.