mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 04:36:20 +00:00
Add support for extracting CEA608 S334-1 Closed Captions and add a property to select which ones to extract
This commit is contained in:
parent
eadd35363a
commit
e53a017ee7
4 changed files with 131 additions and 3 deletions
|
@ -1057,6 +1057,34 @@ GType gst_aja_timecode_index_get_type(void) {
|
||||||
return (GType)id;
|
return (GType)id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GType gst_aja_closed_caption_capture_mode_get_type(void) {
|
||||||
|
static gsize id = 0;
|
||||||
|
static const GEnumValue modes[] = {
|
||||||
|
{GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_AND_CEA608,
|
||||||
|
"cea708-and-cea608",
|
||||||
|
"CEA708 S334-2 and CEA608 S334-1 Annex A Closed Captions"},
|
||||||
|
{GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_OR_CEA608, "cea708-or-cea608",
|
||||||
|
"CEA708 S334-2 or if not existing CEA608 S334-1 Annex A Closed "
|
||||||
|
"Captions"},
|
||||||
|
{GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA608_OR_CEA708, "cea608-or-cea708",
|
||||||
|
"CEA608 S334-1 Annex A or if not existing CEA708 S334-2 Closed "
|
||||||
|
"Captions"},
|
||||||
|
{GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_ONLY, "cea708-only",
|
||||||
|
"CEA708 S334-2 Closed Captions only"},
|
||||||
|
{GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA608_ONLY, "cea608-only",
|
||||||
|
"CEA608 S334-1 Annex A Closed Captions only"},
|
||||||
|
{GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_NONE, "none",
|
||||||
|
"Don't capture Closed Captions"},
|
||||||
|
{0, NULL, NULL}};
|
||||||
|
|
||||||
|
if (g_once_init_enter(&id)) {
|
||||||
|
GType tmp = g_enum_register_static("GstAjaClosedCaptionCaptureMode", modes);
|
||||||
|
g_once_init_leave(&id, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (GType)id;
|
||||||
|
}
|
||||||
|
|
||||||
void gst_aja_common_init(void) {
|
void gst_aja_common_init(void) {
|
||||||
GST_DEBUG_CATEGORY_INIT(gst_aja_debug, "aja", 0,
|
GST_DEBUG_CATEGORY_INIT(gst_aja_debug, "aja", 0,
|
||||||
"Debug category for AJA plugin");
|
"Debug category for AJA plugin");
|
||||||
|
|
|
@ -277,6 +277,20 @@ typedef enum {
|
||||||
G_GNUC_INTERNAL
|
G_GNUC_INTERNAL
|
||||||
GType gst_aja_timecode_index_get_type(void);
|
GType gst_aja_timecode_index_get_type(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_AND_CEA608,
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_OR_CEA608,
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA608_OR_CEA708,
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_ONLY,
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA608_ONLY,
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_NONE,
|
||||||
|
} GstAjaClosedCaptionCaptureMode;
|
||||||
|
|
||||||
|
#define GST_TYPE_AJA_CLOSED_CAPTION_CAPTURE_MODE \
|
||||||
|
(gst_aja_closed_caption_capture_mode_get_type())
|
||||||
|
G_GNUC_INTERNAL
|
||||||
|
GType gst_aja_closed_caption_capture_mode_get_type(void);
|
||||||
|
|
||||||
G_GNUC_INTERNAL
|
G_GNUC_INTERNAL
|
||||||
void gst_aja_common_init(void);
|
void gst_aja_common_init(void);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <ajaanc/includes/ancillarydata_cea608_vanc.h>
|
||||||
#include <ajaanc/includes/ancillarydata_cea708.h>
|
#include <ajaanc/includes/ancillarydata_cea708.h>
|
||||||
#include <ajaanc/includes/ancillarylist.h>
|
#include <ajaanc/includes/ancillarylist.h>
|
||||||
#include <ajantv2/includes/ntv2rp188.h>
|
#include <ajantv2/includes/ntv2rp188.h>
|
||||||
|
@ -41,6 +42,8 @@ GST_DEBUG_CATEGORY_STATIC(gst_aja_src_debug);
|
||||||
#define DEFAULT_AUDIO_SOURCE (GST_AJA_AUDIO_SOURCE_EMBEDDED)
|
#define DEFAULT_AUDIO_SOURCE (GST_AJA_AUDIO_SOURCE_EMBEDDED)
|
||||||
#define DEFAULT_TIMECODE_INDEX (GST_AJA_TIMECODE_INDEX_VITC)
|
#define DEFAULT_TIMECODE_INDEX (GST_AJA_TIMECODE_INDEX_VITC)
|
||||||
#define DEFAULT_REFERENCE_SOURCE (GST_AJA_REFERENCE_SOURCE_FREERUN)
|
#define DEFAULT_REFERENCE_SOURCE (GST_AJA_REFERENCE_SOURCE_FREERUN)
|
||||||
|
#define DEFAULT_CLOSED_CAPTION_CAPTURE_MODE \
|
||||||
|
(GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_AND_CEA608)
|
||||||
#define DEFAULT_QUEUE_SIZE (16)
|
#define DEFAULT_QUEUE_SIZE (16)
|
||||||
#define DEFAULT_START_FRAME (8)
|
#define DEFAULT_START_FRAME (8)
|
||||||
#define DEFAULT_END_FRAME (8)
|
#define DEFAULT_END_FRAME (8)
|
||||||
|
@ -57,6 +60,7 @@ enum {
|
||||||
PROP_AUDIO_SOURCE,
|
PROP_AUDIO_SOURCE,
|
||||||
PROP_TIMECODE_INDEX,
|
PROP_TIMECODE_INDEX,
|
||||||
PROP_REFERENCE_SOURCE,
|
PROP_REFERENCE_SOURCE,
|
||||||
|
PROP_CLOSED_CAPTION_CAPTURE_MODE,
|
||||||
PROP_START_FRAME,
|
PROP_START_FRAME,
|
||||||
PROP_END_FRAME,
|
PROP_END_FRAME,
|
||||||
PROP_QUEUE_SIZE,
|
PROP_QUEUE_SIZE,
|
||||||
|
@ -218,6 +222,16 @@ static void gst_aja_src_class_init(GstAjaSrcClass *klass) {
|
||||||
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
G_PARAM_CONSTRUCT)));
|
G_PARAM_CONSTRUCT)));
|
||||||
|
|
||||||
|
g_object_class_install_property(
|
||||||
|
gobject_class, PROP_CLOSED_CAPTION_CAPTURE_MODE,
|
||||||
|
g_param_spec_enum(
|
||||||
|
"closed-caption-capture-mode", "Closed Caption Capture Mode",
|
||||||
|
"Closed Caption Capture Mode",
|
||||||
|
GST_TYPE_AJA_CLOSED_CAPTION_CAPTURE_MODE,
|
||||||
|
DEFAULT_CLOSED_CAPTION_CAPTURE_MODE,
|
||||||
|
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
|
G_PARAM_CONSTRUCT)));
|
||||||
|
|
||||||
g_object_class_install_property(
|
g_object_class_install_property(
|
||||||
gobject_class, PROP_CAPTURE_CPU_CORE,
|
gobject_class, PROP_CAPTURE_CPU_CORE,
|
||||||
g_param_spec_uint(
|
g_param_spec_uint(
|
||||||
|
@ -274,6 +288,7 @@ static void gst_aja_src_init(GstAjaSrc *self) {
|
||||||
self->audio_source = DEFAULT_AUDIO_SOURCE;
|
self->audio_source = DEFAULT_AUDIO_SOURCE;
|
||||||
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->closed_caption_capture_mode = DEFAULT_CLOSED_CAPTION_CAPTURE_MODE;
|
||||||
self->capture_cpu_core = DEFAULT_CAPTURE_CPU_CORE;
|
self->capture_cpu_core = DEFAULT_CAPTURE_CPU_CORE;
|
||||||
|
|
||||||
self->queue =
|
self->queue =
|
||||||
|
@ -326,6 +341,10 @@ void gst_aja_src_set_property(GObject *object, guint property_id,
|
||||||
case PROP_REFERENCE_SOURCE:
|
case PROP_REFERENCE_SOURCE:
|
||||||
self->reference_source = (GstAjaReferenceSource)g_value_get_enum(value);
|
self->reference_source = (GstAjaReferenceSource)g_value_get_enum(value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CLOSED_CAPTION_CAPTURE_MODE:
|
||||||
|
self->closed_caption_capture_mode =
|
||||||
|
(GstAjaClosedCaptionCaptureMode)g_value_get_enum(value);
|
||||||
|
break;
|
||||||
case PROP_CAPTURE_CPU_CORE:
|
case PROP_CAPTURE_CPU_CORE:
|
||||||
self->capture_cpu_core = g_value_get_uint(value);
|
self->capture_cpu_core = g_value_get_uint(value);
|
||||||
break;
|
break;
|
||||||
|
@ -376,6 +395,9 @@ void gst_aja_src_get_property(GObject *object, guint property_id, GValue *value,
|
||||||
case PROP_REFERENCE_SOURCE:
|
case PROP_REFERENCE_SOURCE:
|
||||||
g_value_set_enum(value, self->reference_source);
|
g_value_set_enum(value, self->reference_source);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CLOSED_CAPTION_CAPTURE_MODE:
|
||||||
|
g_value_set_enum(value, self->closed_caption_capture_mode);
|
||||||
|
break;
|
||||||
case PROP_CAPTURE_CPU_CORE:
|
case PROP_CAPTURE_CPU_CORE:
|
||||||
g_value_set_uint(value, self->capture_cpu_core);
|
g_value_set_uint(value, self->capture_cpu_core);
|
||||||
break;
|
break;
|
||||||
|
@ -1680,17 +1702,80 @@ static GstFlowReturn gst_aja_src_create(GstPushSrc *psrc, GstBuffer **buffer) {
|
||||||
//
|
//
|
||||||
// See AJA SDK support ticket #4844.
|
// See AJA SDK support ticket #4844.
|
||||||
guint32 n_vanc_packets = anc_packets.CountAncillaryData();
|
guint32 n_vanc_packets = anc_packets.CountAncillaryData();
|
||||||
|
|
||||||
|
// Check if we have either CEA608 or CEA708 packets, or both.
|
||||||
|
bool have_cea608 = false;
|
||||||
|
bool have_cea708 = false;
|
||||||
|
for (guint32 i = 0; i < n_vanc_packets; i++) {
|
||||||
|
AJAAncillaryData *packet = anc_packets.GetAncillaryDataAtIndex(i);
|
||||||
|
|
||||||
|
if (packet->GetDID() == AJAAncillaryData_Cea608_Vanc_DID &&
|
||||||
|
packet->GetSID() == AJAAncillaryData_Cea608_Vanc_SID &&
|
||||||
|
packet->GetPayloadData() && packet->GetPayloadByteCount() &&
|
||||||
|
AJA_SUCCESS(packet->ParsePayloadData())) {
|
||||||
|
GST_TRACE_OBJECT(
|
||||||
|
self, "Found CEA608 VANC of %" G_GSIZE_FORMAT " bytes at line %u",
|
||||||
|
packet->GetPayloadByteCount(), packet->GetLocationLineNumber());
|
||||||
|
have_cea608 = true;
|
||||||
|
} else if (packet->GetDID() == AJAAncillaryData_CEA708_DID &&
|
||||||
|
packet->GetSID() == AJAAncillaryData_CEA708_SID &&
|
||||||
|
packet->GetPayloadData() && packet->GetPayloadByteCount() &&
|
||||||
|
AJA_SUCCESS(packet->ParsePayloadData())) {
|
||||||
|
GST_TRACE_OBJECT(
|
||||||
|
self, "Found CEA708 CDP VANC of %" G_GSIZE_FORMAT " bytes at line %u",
|
||||||
|
packet->GetPayloadByteCount(), packet->GetLocationLineNumber());
|
||||||
|
have_cea708 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decide based on the closed-caption-capture-mode property and closed
|
||||||
|
// caption availability which ones to add as metadata to the output buffer.
|
||||||
|
bool want_cea608 =
|
||||||
|
have_cea608 &&
|
||||||
|
(self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_AND_CEA608 ||
|
||||||
|
self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA608_OR_CEA708 ||
|
||||||
|
self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA608_ONLY ||
|
||||||
|
(!have_cea708 &&
|
||||||
|
self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_OR_CEA608));
|
||||||
|
|
||||||
|
bool want_cea708 =
|
||||||
|
have_cea708 &&
|
||||||
|
(self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_AND_CEA608 ||
|
||||||
|
self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_OR_CEA608 ||
|
||||||
|
self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA708_ONLY ||
|
||||||
|
(!have_cea608 &&
|
||||||
|
self->closed_caption_capture_mode ==
|
||||||
|
GST_AJA_CLOSED_CAPTION_CAPTURE_MODE_CEA608_OR_CEA708));
|
||||||
|
|
||||||
bool aspect_ratio_flag = false;
|
bool aspect_ratio_flag = false;
|
||||||
bool have_afd_bar = false;
|
bool have_afd_bar = false;
|
||||||
for (guint32 i = 0; i < n_vanc_packets; i++) {
|
for (guint32 i = 0; i < n_vanc_packets; i++) {
|
||||||
AJAAncillaryData *packet = anc_packets.GetAncillaryDataAtIndex(i);
|
AJAAncillaryData *packet = anc_packets.GetAncillaryDataAtIndex(i);
|
||||||
|
|
||||||
if (packet->GetDID() == AJAAncillaryData_CEA708_DID &&
|
if (want_cea608 && packet->GetDID() == AJAAncillaryData_Cea608_Vanc_DID &&
|
||||||
packet->GetSID() == AJAAncillaryData_CEA708_SID &&
|
packet->GetSID() == AJAAncillaryData_Cea608_Vanc_SID &&
|
||||||
packet->GetPayloadData() && packet->GetPayloadByteCount() &&
|
packet->GetPayloadData() && packet->GetPayloadByteCount() &&
|
||||||
AJA_SUCCESS(packet->ParsePayloadData())) {
|
AJA_SUCCESS(packet->ParsePayloadData())) {
|
||||||
GST_TRACE_OBJECT(
|
GST_TRACE_OBJECT(
|
||||||
self, "Found CEA708 CDP VANC of %" G_GSIZE_FORMAT " bytes at line %u",
|
self, "Adding CEA608 VANC of %" G_GSIZE_FORMAT " bytes at line %u",
|
||||||
|
packet->GetPayloadByteCount(), packet->GetLocationLineNumber());
|
||||||
|
gst_buffer_add_video_caption_meta(
|
||||||
|
*buffer, GST_VIDEO_CAPTION_TYPE_CEA608_S334_1A,
|
||||||
|
packet->GetPayloadData(), packet->GetPayloadByteCount());
|
||||||
|
} else if (want_cea708 && packet->GetDID() == AJAAncillaryData_CEA708_DID &&
|
||||||
|
packet->GetSID() == AJAAncillaryData_CEA708_SID &&
|
||||||
|
packet->GetPayloadData() && packet->GetPayloadByteCount() &&
|
||||||
|
AJA_SUCCESS(packet->ParsePayloadData())) {
|
||||||
|
GST_TRACE_OBJECT(
|
||||||
|
self,
|
||||||
|
"Adding CEA708 CDP VANC of %" G_GSIZE_FORMAT " bytes at line %u",
|
||||||
packet->GetPayloadByteCount(), packet->GetLocationLineNumber());
|
packet->GetPayloadByteCount(), packet->GetLocationLineNumber());
|
||||||
gst_buffer_add_video_caption_meta(
|
gst_buffer_add_video_caption_meta(
|
||||||
*buffer, GST_VIDEO_CAPTION_TYPE_CEA708_CDP, packet->GetPayloadData(),
|
*buffer, GST_VIDEO_CAPTION_TYPE_CEA708_CDP, packet->GetPayloadData(),
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct _GstAjaSrc {
|
||||||
GstAjaAudioSource audio_source;
|
GstAjaAudioSource audio_source;
|
||||||
GstAjaTimecodeIndex timecode_index;
|
GstAjaTimecodeIndex timecode_index;
|
||||||
GstAjaReferenceSource reference_source;
|
GstAjaReferenceSource reference_source;
|
||||||
|
GstAjaClosedCaptionCaptureMode closed_caption_capture_mode;
|
||||||
guint queue_size;
|
guint queue_size;
|
||||||
guint start_frame, end_frame;
|
guint start_frame, end_frame;
|
||||||
guint capture_cpu_core;
|
guint capture_cpu_core;
|
||||||
|
|
Loading…
Reference in a new issue