ajasink: Add HANC/VANC ancillary data from GstAncillaryMeta

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5488>
This commit is contained in:
Sebastian Dröge 2024-01-16 16:50:11 +02:00 committed by GStreamer Marge Bot
parent efa7e70d16
commit 3ca5a2554f
3 changed files with 72 additions and 1 deletions

View file

@ -559,6 +559,18 @@
"type": "guint", "type": "guint",
"writable": true "writable": true
}, },
"handle-ancillary-meta": {
"blurb": "Handle ancillary meta on video frames",
"conditionally-available": false,
"construct": true,
"construct-only": false,
"controllable": false,
"default": "false",
"mutable": "null",
"readable": true,
"type": "gboolean",
"writable": true
},
"output-cpu-core": { "output-cpu-core": {
"blurb": "Sets the affinity of the output thread to this CPU core (-1=disabled)", "blurb": "Sets the affinity of the output thread to this CPU core (-1=disabled)",
"conditionally-available": false, "conditionally-available": false,

View file

@ -74,6 +74,7 @@ GST_DEBUG_CATEGORY_STATIC(gst_aja_sink_debug);
#define DEFAULT_START_FRAME (0) #define DEFAULT_START_FRAME (0)
#define DEFAULT_END_FRAME (0) #define DEFAULT_END_FRAME (0)
#define DEFAULT_OUTPUT_CPU_CORE (G_MAXUINT) #define DEFAULT_OUTPUT_CPU_CORE (G_MAXUINT)
#define DEFAULT_HANDLE_ANCILLARY_META (FALSE)
enum { enum {
PROP_0, PROP_0,
@ -91,6 +92,7 @@ enum {
PROP_START_FRAME, PROP_START_FRAME,
PROP_END_FRAME, PROP_END_FRAME,
PROP_OUTPUT_CPU_CORE, PROP_OUTPUT_CPU_CORE,
PROP_HANDLE_ANCILLARY_META,
}; };
typedef enum { typedef enum {
@ -271,6 +273,22 @@ static void gst_aja_sink_class_init(GstAjaSinkClass *klass) {
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT))); G_PARAM_CONSTRUCT)));
/**
* GstAjaSink:handle-ancillary-meta:
*
* If set to %TRUE handle any #GstAncillaryMeta present on buffers
*
* Since: 1.24
*/
g_object_class_install_property(
gobject_class, PROP_HANDLE_ANCILLARY_META,
g_param_spec_boolean(
"handle-ancillary-meta", "Handle Ancillary Meta",
"Handle ancillary meta on video frames",
DEFAULT_HANDLE_ANCILLARY_META,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT)));
element_class->change_state = GST_DEBUG_FUNCPTR(gst_aja_sink_change_state); element_class->change_state = GST_DEBUG_FUNCPTR(gst_aja_sink_change_state);
basesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_aja_sink_set_caps); basesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_aja_sink_set_caps);
@ -309,6 +327,7 @@ static void gst_aja_sink_init(GstAjaSink *self) {
self->timecode_index = DEFAULT_TIMECODE_INDEX; self->timecode_index = DEFAULT_TIMECODE_INDEX;
self->reference_source = DEFAULT_REFERENCE_SOURCE; self->reference_source = DEFAULT_REFERENCE_SOURCE;
self->output_cpu_core = DEFAULT_OUTPUT_CPU_CORE; self->output_cpu_core = DEFAULT_OUTPUT_CPU_CORE;
self->handle_ancillary_meta = DEFAULT_HANDLE_ANCILLARY_META;
self->queue = self->queue =
gst_queue_array_new_for_struct(sizeof(QueueItem), self->queue_size); gst_queue_array_new_for_struct(sizeof(QueueItem), self->queue_size);
@ -363,6 +382,9 @@ void gst_aja_sink_set_property(GObject *object, guint property_id,
case PROP_OUTPUT_CPU_CORE: case PROP_OUTPUT_CPU_CORE:
self->output_cpu_core = g_value_get_uint(value); self->output_cpu_core = g_value_get_uint(value);
break; break;
case PROP_HANDLE_ANCILLARY_META:
self->handle_ancillary_meta = g_value_get_boolean(value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break; break;
@ -416,6 +438,9 @@ void gst_aja_sink_get_property(GObject *object, guint property_id,
case PROP_OUTPUT_CPU_CORE: case PROP_OUTPUT_CPU_CORE:
g_value_set_uint(value, self->output_cpu_core); g_value_set_uint(value, self->output_cpu_core);
break; break;
case PROP_HANDLE_ANCILLARY_META:
g_value_set_boolean(value, self->handle_ancillary_meta);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break; break;
@ -1709,6 +1734,39 @@ static GstFlowReturn gst_aja_sink_render(GstBaseSink *bsink,
} }
} }
if (self->handle_ancillary_meta) {
GstAncillaryMeta *anc_meta;
iter = NULL;
while ((anc_meta = (GstAncillaryMeta *)gst_buffer_iterate_meta_filtered(
buffer, &iter, GST_ANCILLARY_META_API_TYPE))) {
const AJAAncillaryDataLocation loc(
AJAAncillaryDataLink_A,
anc_meta->c_not_y_channel ? AJAAncillaryDataChannel_C
: AJAAncillaryDataVideoStream_Y,
AJAAncillaryDataSpace_VANC, anc_meta->line, anc_meta->offset);
AJAAncillaryData pkt;
guint8 data[256];
pkt.SetDID(anc_meta->DID);
pkt.SetSID(anc_meta->SDID_block_number);
pkt.SetDataLocation(loc);
pkt.SetDataCoding(AJAAncillaryDataCoding_Digital);
for (gsize i = 0; i < (anc_meta->data_count & 0xff); i++) {
data[i] = anc_meta->data[i] & 0xff;
}
pkt.SetPayloadData(data, anc_meta->data_count & 0xff);
GST_TRACE_OBJECT(self,
"Adding ANC of %" G_GSIZE_FORMAT " bytes at (%u,%u)",
pkt.GetPayloadByteCount(), pkt.GetLocationLineNumber(),
pkt.GetLocationHorizOffset());
anc_packet_list.AddAncillaryData(pkt);
}
}
if (!anc_packet_list.IsEmpty()) { if (!anc_packet_list.IsEmpty()) {
if (self->vanc_mode == ::NTV2_VANCMODE_OFF && if (self->vanc_mode == ::NTV2_VANCMODE_OFF &&
::NTV2DeviceCanDoCustomAnc(self->device_id)) { ::NTV2DeviceCanDoCustomAnc(self->device_id)) {
@ -2177,7 +2235,7 @@ restart:
} }
} }
out : { out: {
// Make sure to globally lock here as the routing settings and others are // Make sure to globally lock here as the routing settings and others are
// global shared state // global shared state
ShmMutexLocker locker; ShmMutexLocker locker;

View file

@ -78,6 +78,7 @@ struct _GstAjaSink {
GstAjaTimecodeIndex timecode_index; GstAjaTimecodeIndex timecode_index;
gboolean rp188; gboolean rp188;
GstAjaReferenceSource reference_source; GstAjaReferenceSource reference_source;
gboolean handle_ancillary_meta;
gint cea608_line_number; gint cea608_line_number;
gint cea708_line_number; gint cea708_line_number;