Skip to content

Commit 5a2dd4c

Browse files
Fix: st40_pipeline_tx.c meta_num handling
We process the meta_num incorrectly in st40_pipeline_tx.c, leading to potential issues with frame metadata handling. Fix it by overwriting the anc_frame meta_num and treating the framebuff from pipeline anc size as the only source of truth. Fix the inproper handling of the CAPS negotiation signal, for now just ignore consecutive signals TODO: Checking and reinitialization of the session. Add the ability for the st40 gstreamer plugin to parse multiple ancillary packages, including support for different payload types and dynamic reconfiguration. Add the ability for st20 video plugin to work without metadata with assumed bit configuration. Add the st40p meta insertion into the metadata element Test the changes by adding the ability for the pytest framework to generate data from both the Rx simplified rfc8331 and the Tx rfc8331 custom formats (ancgenerator) For more advanced anc frames testing. Add the ability for the testing framework in gstreamer to run user pacing scanrios TODO: Add tests for user pacing TODO: Add lipsync for gstreamer Fix: fix the way we handle killing and signal handling in gstreamer engine. Fix: error reporting for paths in testing framework For easier debugging and maintenance. reverts: fc4c95a
1 parent 274025a commit 5a2dd4c

27 files changed

+1218
-192
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ dkms.conf
5555
.*
5656
*.log
5757
*.log_*
58+
tests/validation/logs
5859
logs_*
5960
*.patch
6061
!patches/**/*.patch

ecosystem/gstreamer_plugin/gst_mtl_st20p_tx.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,11 @@ static gboolean gst_mtl_st20p_tx_sink_event(GstPad* pad, GstObject* parent,
446446

447447
switch (GST_EVENT_TYPE(event)) {
448448
case GST_EVENT_CAPS:
449+
if (sink->session_capabilites_set) {
450+
GST_WARNING("Capabilities already set, ignoring");
451+
return gst_pad_event_default(pad, parent, event);
452+
}
453+
449454
gst_event_parse_caps(event, &caps);
450455
if (sink->async_session_create) {
451456
thread_data = malloc(sizeof(GstMtlSt20pTxThreadData));
@@ -460,6 +465,7 @@ static gboolean gst_mtl_st20p_tx_sink_event(GstPad* pad, GstObject* parent,
460465
return FALSE;
461466
}
462467
}
468+
sink->session_capabilites_set = TRUE;
463469
ret = gst_pad_event_default(pad, parent, event);
464470
break;
465471
case GST_EVENT_EOS:
@@ -562,12 +568,8 @@ static GstFlowReturn gst_mtl_st20p_tx_zero_copy(Gst_Mtl_St20p_Tx* sink, GstBuffe
562568
GstSt20pTxExternalDataParent* parent;
563569
struct st_frame* frame;
564570
struct st_ext_frame ext_frame;
565-
GstVideoMeta* video_meta = gst_buffer_get_video_meta(buf);
571+
GstVideoMeta* video_meta = NULL;
566572
gint buffer_n = gst_buffer_n_memory(buf);
567-
if (!video_meta) {
568-
g_print("Failed to get video meta from buffer\n");
569-
return GST_FLOW_ERROR;
570-
}
571573

572574
parent = malloc(sizeof(GstSt20pTxExternalDataParent));
573575
if (!parent) {
@@ -615,11 +617,30 @@ static GstFlowReturn gst_mtl_st20p_tx_zero_copy(Gst_Mtl_St20p_Tx* sink, GstBuffe
615617
frame->tfmt = ST10_TIMESTAMP_FMT_TAI;
616618
}
617619

618-
for (int i = 0; i < video_meta->n_planes; i++) {
619-
ext_frame.addr[i] = child->map_info.data + video_meta->offset[i];
620-
ext_frame.linesize[i] = video_meta->stride[i];
621-
ext_frame.iova[i] = 0;
620+
video_meta = gst_buffer_get_video_meta(buf);
621+
if (video_meta) {
622+
for (int i = 0; i < video_meta->n_planes; i++) {
623+
ext_frame.addr[i] = child->map_info.data + video_meta->offset[i];
624+
ext_frame.linesize[i] = video_meta->stride[i];
625+
ext_frame.iova[i] = 0;
626+
}
627+
628+
} else {
629+
ext_frame.addr[0] = child->map_info.data;
630+
ext_frame.iova[0] = 0;
631+
ext_frame.linesize[0] = st_frame_least_linesize(frame->fmt, frame->width, 0);
632+
guint8 planes = st_frame_fmt_planes(frame->fmt);
633+
634+
/* Assume video planes are stored contiguously in memory */
635+
for (gint plane = 1; plane < planes; plane++) {
636+
ext_frame.linesize[plane] =
637+
st_frame_least_linesize(frame->fmt, frame->width, plane);
638+
ext_frame.addr[plane] = (guint8*)ext_frame.addr[plane - 1] +
639+
ext_frame.linesize[plane - 1] * frame->height;
640+
ext_frame.iova[plane] = 0;
641+
}
622642
}
643+
623644
ext_frame.size = child->map_info.size;
624645
ext_frame.opaque = child;
625646
frame->opaque = NULL;

ecosystem/gstreamer_plugin/gst_mtl_st20p_tx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct _Gst_Mtl_St20p_Tx {
6262
gboolean zero_copy;
6363

6464
gboolean session_ready;
65+
gboolean session_capabilites_set;
6566
pthread_mutex_t session_mutex;
6667
pthread_t session_thread;
6768

ecosystem/gstreamer_plugin/gst_mtl_st30p_tx.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,11 @@ static gboolean gst_mtl_st30p_tx_sink_event(GstPad* pad, GstObject* parent,
455455

456456
switch (GST_EVENT_TYPE(event)) {
457457
case GST_EVENT_CAPS:
458+
if (sink->session_capabilites_set) {
459+
GST_WARNING("Capabilities already set, ignoring");
460+
return gst_pad_event_default(pad, parent, event);
461+
}
462+
458463
gst_event_parse_caps(event, &caps);
459464
if (sink->async_session_create) {
460465
thread_data = malloc(sizeof(GstMtlSt30pTxThreadData));
@@ -470,6 +475,7 @@ static gboolean gst_mtl_st30p_tx_sink_event(GstPad* pad, GstObject* parent,
470475
}
471476
}
472477

478+
sink->session_capabilites_set = TRUE;
473479
ret = gst_pad_event_default(pad, parent, event);
474480
break;
475481
case GST_EVENT_EOS:

ecosystem/gstreamer_plugin/gst_mtl_st30p_tx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct _Gst_Mtl_St30p_Tx {
6161
guint frame_size;
6262

6363
gboolean session_ready;
64+
gboolean session_capabilites_set;
6465
pthread_mutex_t session_mutex;
6566
pthread_t session_thread;
6667

ecosystem/gstreamer_plugin/gst_mtl_st40_rx.c

Lines changed: 105 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ GST_DEBUG_CATEGORY_STATIC(gst_mtl_st40_rx_debug);
9696
enum {
9797
PROP_ST40_RX_BUFFER_SIZE = PROP_GENERAL_MAX,
9898
PROP_ST40_RX_TIMEOUT_MBUF_GET,
99+
PROP_ST40_RX_INCLUDE_METADATA_IN_BUFFER,
99100
PROP_MAX
100101
};
101102

@@ -108,8 +109,6 @@ G_DEFINE_TYPE_WITH_CODE(Gst_Mtl_St40_Rx, gst_mtl_st40_rx, GST_TYPE_BASE_SRC,
108109
GST_DEBUG_CATEGORY_INIT(gst_mtl_st40_rx_debug, "mtl_st40_rx", 0,
109110
"MTL St2110 st40 transmission src"));
110111

111-
#define IS_POWER_OF_2(x) (((x) & ((x)-1)) == 0)
112-
113112
GST_ELEMENT_REGISTER_DEFINE(mtl_st40_rx, "mtl_st40_rx", GST_RANK_NONE,
114113
GST_TYPE_MTL_ST40_RX);
115114

@@ -131,6 +130,8 @@ static GstFlowReturn gst_mtl_st40_rx_fill_buffer(Gst_Mtl_St40_Rx* src, GstBuffer
131130
void* usrptr);
132131
static guint gst_mtl_st40_rx_parse_port_arguments(struct st40_rx_ops* ops_rx,
133132
SessionPortArgs* portArgs);
133+
static struct st40_rfc8331_payload_hdr* gst_mtl_st40_rx_shift_payload_hdr(
134+
struct st40_rfc8331_payload_hdr* payload_hdr, int udw_size);
134135

135136
static gint gst_mtl_st40_rx_mbuff_available(void* priv) {
136137
Gst_Mtl_St40_Rx* src = (Gst_Mtl_St40_Rx*)priv;
@@ -179,6 +180,12 @@ static void gst_mtl_st40_rx_class_init(Gst_Mtl_St40_RxClass* klass) {
179180
g_param_spec_uint("timeout", "Timeout for Mbuf",
180181
"Timeout in seconds for getting mbuf", 0, G_MAXUINT, 10,
181182
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
183+
184+
g_object_class_install_property(
185+
gobject_class, PROP_ST40_RX_INCLUDE_METADATA_IN_BUFFER,
186+
g_param_spec_boolean("include-metadata-in-buffer", "Include Metadata in Buffer",
187+
"Whether to include metadata in the output buffer", FALSE,
188+
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
182189
}
183190

184191
static guint gst_mtl_st40_rx_parse_port_arguments(struct st40_rx_ops* ops_rx,
@@ -319,6 +326,9 @@ static void gst_mtl_st40_rx_set_property(GObject* object, guint prop_id,
319326
case PROP_ST40_RX_TIMEOUT_MBUF_GET:
320327
self->timeout_mbuf_get_seconds = g_value_get_uint(value);
321328
break;
329+
case PROP_ST40_RX_INCLUDE_METADATA_IN_BUFFER:
330+
self->include_metadata_in_buffer = g_value_get_boolean(value);
331+
break;
322332
default:
323333
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
324334
break;
@@ -342,6 +352,9 @@ static void gst_mtl_st40_rx_get_property(GObject* object, guint prop_id, GValue*
342352
case PROP_ST40_RX_TIMEOUT_MBUF_GET:
343353
g_value_set_uint(value, src->timeout_mbuf_get_seconds);
344354
break;
355+
case PROP_ST40_RX_INCLUDE_METADATA_IN_BUFFER:
356+
g_value_set_boolean(value, src->include_metadata_in_buffer);
357+
break;
345358
default:
346359
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
347360
break;
@@ -372,42 +385,100 @@ static void* gst_mtl_st40_rx_get_mbuf_with_timeout(Gst_Mtl_St40_Rx* src,
372385
return mbuf;
373386
}
374387

388+
static struct st40_rfc8331_payload_hdr* gst_mtl_st40_rx_shift_payload_hdr(
389+
struct st40_rfc8331_payload_hdr* payload_hdr, int udw_size) {
390+
int package_size;
391+
int payload_len;
392+
393+
package_size = ((3 + udw_size + 1) * 10) / 8;
394+
package_size = (4 - package_size % 4) + package_size;
395+
payload_len = sizeof(struct st40_rfc8331_payload_hdr) - 4 + package_size;
396+
397+
return (struct st40_rfc8331_payload_hdr*)((uint8_t*)payload_hdr + payload_len);
398+
}
399+
375400
static GstFlowReturn gst_mtl_st40_rx_fill_buffer(Gst_Mtl_St40_Rx* src, GstBuffer** buffer,
376401
void* usrptr) {
377402
struct st40_rfc8331_rtp_hdr* hdr;
378-
struct st40_rfc8331_payload_hdr *payload_hdr, payload_hdr_swapped;
403+
struct st40_rfc8331_payload_hdr *payload_hdr;
379404
GstMapInfo dest_info;
380-
guint16 data, fill_size;
381-
gint udw_size;
405+
guint16 data;
406+
gint udw_size, anc_count;
407+
guint buffer_size = 0, meta_offset;
382408

383409
hdr = (struct st40_rfc8331_rtp_hdr*)usrptr;
410+
anc_count = hdr->anc_count;
411+
412+
413+
if (anc_count == 0 || anc_count > ST40_RFC8331_PAYLOAD_MAX_ANCILLARY_COUNT) {
414+
GST_ERROR("Ancillary data count: %d (must be between 1 and %d)", anc_count, ST40_RFC8331_PAYLOAD_MAX_ANCILLARY_COUNT);
415+
return GST_FLOW_ERROR;
416+
}
417+
418+
/* local is fine anc_count will not be bigger than 20*/
419+
guint8* anc_data[anc_count];
420+
guint8 anc_data_count[anc_count];
384421

385422
payload_hdr = (struct st40_rfc8331_payload_hdr*)(&hdr[1]);
423+
for (int i = 0; i < anc_count; i++) {
424+
payload_hdr->swapped_first_hdr_chunk = ntohl(payload_hdr->swapped_first_hdr_chunk);
425+
payload_hdr->swapped_second_hdr_chunk = ntohl(payload_hdr->swapped_second_hdr_chunk);
426+
if (!st40_check_parity_bits(payload_hdr->second_hdr_chunk.did)) {
427+
GST_ERROR("Parity check failed for DID");
428+
return GST_FLOW_ERROR;
429+
}
430+
if (!st40_check_parity_bits(payload_hdr->second_hdr_chunk.sdid)) {
431+
GST_ERROR("Parity check failed for SDID");
432+
return GST_FLOW_ERROR;
433+
}
434+
if (!st40_check_parity_bits(payload_hdr->second_hdr_chunk.data_count)) {
435+
GST_ERROR("Parity check failed for Data Count");
436+
return GST_FLOW_ERROR;
437+
}
386438

387-
hdr->swapped_first_hdr_chunk = ntohl(hdr->swapped_first_hdr_chunk);
439+
udw_size = payload_hdr->second_hdr_chunk.data_count & 0xff;
440+
anc_data_count[i] = udw_size;
441+
meta_offset = 0;
442+
buffer_size += udw_size;
443+
444+
if (src->include_metadata_in_buffer) {
445+
buffer_size += ST40_BYTE_SIZE_OF_PAYLOAD_METADATA;
446+
anc_data[i] = malloc(udw_size + ST40_BYTE_SIZE_OF_PAYLOAD_METADATA);
447+
anc_data[i][meta_offset++] = payload_hdr->first_hdr_chunk.c;
448+
anc_data[i][meta_offset++] = payload_hdr->first_hdr_chunk.line_number;
449+
anc_data[i][meta_offset++] = payload_hdr->first_hdr_chunk.horizontal_offset;
450+
anc_data[i][meta_offset++] = payload_hdr->first_hdr_chunk.s;
451+
anc_data[i][meta_offset++] = payload_hdr->first_hdr_chunk.stream_num;
452+
anc_data[i][meta_offset++] = payload_hdr->second_hdr_chunk.did & 0xff;
453+
anc_data[i][meta_offset++] = payload_hdr->second_hdr_chunk.sdid & 0xff;
454+
anc_data[i][meta_offset++] = payload_hdr->second_hdr_chunk.data_count & 0xff;
455+
} else {
456+
anc_data[i] = malloc(udw_size);
457+
}
388458

389-
payload_hdr_swapped.swapped_second_hdr_chunk =
390-
ntohl(payload_hdr->swapped_second_hdr_chunk);
391-
udw_size = payload_hdr_swapped.second_hdr_chunk.data_count & 0xff;
459+
payload_hdr->swapped_second_hdr_chunk = htonl(payload_hdr->swapped_second_hdr_chunk);
460+
if (!anc_data[i]) {
461+
GST_ERROR("Failed to allocate memory for ancillary data");
462+
for (int j = 0; j < i; j++)
463+
free(anc_data[j]);
464+
return GST_FLOW_ERROR;
465+
}
392466

393-
if (udw_size == 0) {
394-
GST_ERROR("Ancillary data size is 0");
395-
return GST_FLOW_ERROR;
396-
} else if (src->udw_size == 0) {
397-
src->udw_size = udw_size;
398-
src->anc_data = (char*)malloc(udw_size);
399-
} else if (src->udw_size != udw_size) {
400-
GST_INFO("Size of received ancillary data has changed");
401-
if (src->anc_data) {
402-
free(src->anc_data);
403-
src->anc_data = NULL;
467+
for (int d = 0; d < udw_size; d++) {
468+
data = st40_get_udw(d + 3, (uint8_t*)&payload_hdr->second_hdr_chunk);
469+
if (!st40_check_parity_bits(data)) {
470+
GST_ERROR("Ancillary data parity bits check failed, data=0x%03x", data & 0x3FF);
471+
for (int j = 0; j < i; j++)
472+
free(anc_data[j]);
473+
return GST_FLOW_ERROR;
474+
}
475+
anc_data[i][d + meta_offset] = data & 0xff;
404476
}
405477

406-
src->udw_size = udw_size;
407-
src->anc_data = (char*)malloc(udw_size);
478+
payload_hdr = gst_mtl_st40_rx_shift_payload_hdr(payload_hdr, udw_size);
408479
}
409480

410-
*buffer = gst_buffer_new_allocate(NULL, src->udw_size, NULL);
481+
*buffer = gst_buffer_new_allocate(NULL, buffer_size, NULL);
411482
if (!*buffer) {
412483
GST_ERROR("Failed to allocate space for the buffer");
413484
return GST_FLOW_ERROR;
@@ -418,21 +489,21 @@ static GstFlowReturn gst_mtl_st40_rx_fill_buffer(Gst_Mtl_St40_Rx* src, GstBuffer
418489
return GST_FLOW_ERROR;
419490
}
420491

421-
for (int i = 0; i < udw_size; i++) {
422-
data = st40_get_udw(i + 3, (uint8_t*)&payload_hdr->second_hdr_chunk);
423-
if (!st40_check_parity_bits(data)) {
424-
GST_ERROR("Ancillary data parity bits check failed");
425-
return GST_FLOW_ERROR;
426-
}
427-
src->anc_data[i] = data & 0xff;
492+
guint fill_size = 0;
493+
for (int i = 0; i < anc_count; i++) {
494+
fill_size += gst_buffer_fill(*buffer, fill_size, anc_data[i], anc_data_count[i] + meta_offset);
495+
free(anc_data[i]);
496+
}
497+
/* Print the whole buffer for debugging */
498+
for (guint i = 0; i < buffer_size; i++) {
499+
printf("%02x ", dest_info.data[i]);
428500
}
501+
printf("\n");
429502

430-
fill_size = gst_buffer_fill(*buffer, 0, src->anc_data, udw_size);
431503
gst_buffer_unmap(*buffer, &dest_info);
432504

433-
if (fill_size != src->udw_size) {
434-
GST_ERROR("Failed to fill buffer");
435-
return GST_FLOW_ERROR;
505+
if (fill_size != buffer_size) {
506+
GST_ERROR("Failed to fill buffer (buffer size = %d, fill size = %d)", buffer_size, fill_size);;
436507
}
437508

438509
return GST_FLOW_OK;
@@ -478,8 +549,6 @@ static GstFlowReturn gst_mtl_st40_rx_create(GstBaseSrc* basesrc, guint64 offset,
478549
static void gst_mtl_st40_rx_finalize(GObject* object) {
479550
Gst_Mtl_St40_Rx* src = GST_MTL_ST40_RX(object);
480551

481-
if (src->anc_data) free(src->anc_data);
482-
483552
if (src->rx_handle) {
484553
if (st40_rx_free(src->rx_handle)) {
485554
GST_ERROR("Failed to free rx handle");

ecosystem/gstreamer_plugin/gst_mtl_st40_rx.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@
4747
#ifndef __GST_MTL_ST40_RX_H__
4848
#define __GST_MTL_ST40_RX_H__
4949

50+
#define IS_POWER_OF_2(x) (((x) & ((x)-1)) == 0)
51+
#define ST40_RFC8331_PAYLOAD_MAX_ANCILLARY_COUNT 20
52+
/**
53+
* ST40_SIZE_OF_PAYLOAD_METADATA:
54+
* Defines the size (in bytes) of the payload metadata for ST40 streams.
55+
* This value is set to 8 to accommodate the following fields:
56+
* c | line_number | horizontal_offset | s | stream_num | did | sdid | data_count
57+
*/
58+
#define ST40_BYTE_SIZE_OF_PAYLOAD_METADATA 8
59+
5060
#include <gst/base/gstbasesrc.h>
5161

5262
#include "gst_mtl_common.h"
@@ -70,8 +80,7 @@ struct _Gst_Mtl_St40_Rx {
7080
SessionPortArgs portArgs; /* imtl session device */
7181
guint timeout_mbuf_get_seconds;
7282
guint16 mbuff_size;
73-
guint16 udw_size;
74-
char* anc_data;
83+
gboolean include_metadata_in_buffer;
7584
};
7685

7786
G_END_DECLS

ecosystem/gstreamer_plugin/gst_mtl_st40p_tx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ static GstFlowReturn gst_mtl_st40p_tx_parse_8331_anc_words(
567567
data_count = payload_header.second_hdr_chunk.data_count & 0xff;
568568

569569
/* data count * 10 bits + 10 bit checksum*/
570-
udw_byte_size = (data_count * UDW_WORD_BIT_SIZE) + UDW_WORD_BIT_SIZE;
570+
udw_byte_size = (data_count * UDW_WORD_BIT_SIZE) + UDW_WORD_BIT_SIZE - 2;
571571
/* round up to the nearest byte */
572572
udw_byte_size = (udw_byte_size + 7) / 8;
573573

0 commit comments

Comments
 (0)