mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
decklinkvideosink: Add 3G-SDI Level A output support
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2544>
This commit is contained in:
parent
91b7d3679e
commit
1818374de2
5 changed files with 159 additions and 0 deletions
|
@ -11581,6 +11581,18 @@
|
|||
"type": "GstDecklinkKeyerMode",
|
||||
"writable": true
|
||||
},
|
||||
"mapping-format": {
|
||||
"blurb": "3G-SDI Mapping Format (Level A/B)",
|
||||
"conditionally-available": false,
|
||||
"construct": true,
|
||||
"construct-only": false,
|
||||
"controllable": false,
|
||||
"default": "default (0)",
|
||||
"mutable": "null",
|
||||
"readable": true,
|
||||
"type": "GstDecklinkMappingFormat",
|
||||
"writable": true
|
||||
},
|
||||
"mode": {
|
||||
"blurb": "Video Mode to use for playback",
|
||||
"conditionally-available": false,
|
||||
|
@ -11955,6 +11967,26 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"GstDecklinkMappingFormat": {
|
||||
"kind": "enum",
|
||||
"values": [
|
||||
{
|
||||
"desc": "Default, don't change mapping format",
|
||||
"name": "default",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"desc": "Level A",
|
||||
"name": "level-a",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"desc": "Level B",
|
||||
"name": "level-b",
|
||||
"value": "2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"GstDecklinkModes": {
|
||||
"kind": "enum",
|
||||
"values": [
|
||||
|
|
|
@ -202,6 +202,36 @@ gst_decklink_profile_id_get_type (void)
|
|||
return (GType) id;
|
||||
}
|
||||
|
||||
/**
|
||||
* GstDecklinkMappingFormat:
|
||||
* @GST_DECKLINK_MAPPING_FORMAT_DEFAULT: Don't change the mapping format
|
||||
* @GST_DECKLINK_MAPPING_FORMAT_LEVEL_A: Level A
|
||||
* @GST_DECKLINK_MAPPING_FORMAT_LEVEL_B: Level B
|
||||
*
|
||||
* 3G-SDI mapping format (SMPTE ST 425-1:2017)
|
||||
*
|
||||
* Since: 1.22
|
||||
*/
|
||||
GType
|
||||
gst_decklink_mapping_format_get_type (void)
|
||||
{
|
||||
static gsize id = 0;
|
||||
static const GEnumValue mappingformats[] = {
|
||||
{GST_DECKLINK_MAPPING_FORMAT_DEFAULT, "Default, don't change mapping format",
|
||||
"default"},
|
||||
{GST_DECKLINK_MAPPING_FORMAT_LEVEL_A, "Level A", "level-a"},
|
||||
{GST_DECKLINK_MAPPING_FORMAT_LEVEL_B, "Level B", "level-b"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
if (g_once_init_enter (&id)) {
|
||||
GType tmp = g_enum_register_static ("GstDecklinkMappingFormat", mappingformats);
|
||||
g_once_init_leave (&id, tmp);
|
||||
}
|
||||
|
||||
return (GType) id;
|
||||
}
|
||||
|
||||
GType
|
||||
gst_decklink_timecode_format_get_type (void)
|
||||
{
|
||||
|
@ -386,6 +416,13 @@ enum ProfileSetOperationResult
|
|||
PROFILE_SET_FAILURE
|
||||
};
|
||||
|
||||
enum MappingFormatSetOperationResult
|
||||
{
|
||||
MAPPING_FORMAT_SET_UNSUPPORTED,
|
||||
MAPPING_FORMAT_SET_SUCCESS,
|
||||
MAPPING_FORMAT_SET_FAILURE
|
||||
};
|
||||
|
||||
enum DuplexModeSetOperationResult
|
||||
{
|
||||
DUPLEX_MODE_SET_UNSUPPORTED,
|
||||
|
@ -867,6 +904,8 @@ struct _Device
|
|||
|
||||
static ProfileSetOperationResult gst_decklink_configure_profile (Device *
|
||||
device, GstDecklinkProfileId profile_id);
|
||||
static MappingFormatSetOperationResult gst_decklink_configure_mapping_format (Device *
|
||||
device, GstDecklinkMappingFormat mapping_format);
|
||||
|
||||
class GStreamerDecklinkInputCallback:public IDeckLinkInputCallback
|
||||
{
|
||||
|
@ -1718,6 +1757,10 @@ gst_decklink_acquire_nth_output (gint n, GstElement * sink, gboolean is_audio)
|
|||
videosink->profile_id) == PROFILE_SET_FAILURE) {
|
||||
return NULL;
|
||||
}
|
||||
if (gst_decklink_configure_mapping_format (device,
|
||||
videosink->mapping_format) == MAPPING_FORMAT_SET_FAILURE) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_mutex_lock (&output->lock);
|
||||
|
@ -1905,6 +1948,49 @@ gst_decklink_configure_profile (Device * device,
|
|||
}
|
||||
}
|
||||
|
||||
static MappingFormatSetOperationResult
|
||||
gst_decklink_configure_mapping_format (Device * device,
|
||||
GstDecklinkMappingFormat mapping_format)
|
||||
{
|
||||
HRESULT res;
|
||||
|
||||
bool level_a_output;
|
||||
switch (mapping_format) {
|
||||
case GST_DECKLINK_MAPPING_FORMAT_LEVEL_A:
|
||||
level_a_output = true;
|
||||
break;
|
||||
case GST_DECKLINK_MAPPING_FORMAT_LEVEL_B:
|
||||
level_a_output = false;
|
||||
break;
|
||||
default:
|
||||
case GST_DECKLINK_MAPPING_FORMAT_DEFAULT:
|
||||
return MAPPING_FORMAT_SET_SUCCESS;
|
||||
}
|
||||
|
||||
// Make sure Level A is supported
|
||||
bool supports_level_a_output = false;
|
||||
res = device->output.attributes->GetFlag(BMDDeckLinkSupportsSMPTELevelAOutput,
|
||||
&supports_level_a_output);
|
||||
if (res != S_OK || !supports_level_a_output) {
|
||||
if (level_a_output) {
|
||||
GST_DEBUG ("Device does not support Level A mapping format");
|
||||
return MAPPING_FORMAT_SET_UNSUPPORTED;
|
||||
} else {
|
||||
// Level B is the only supported option
|
||||
return MAPPING_FORMAT_SET_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
res = device->input.config->SetFlag(bmdDeckLinkConfigSMPTELevelAOutput, level_a_output);
|
||||
if (res == S_OK) {
|
||||
GST_DEBUG ("Successfully set mapping format");
|
||||
return MAPPING_FORMAT_SET_SUCCESS;
|
||||
} else {
|
||||
GST_ERROR ("Failed to set mapping format");
|
||||
return MAPPING_FORMAT_SET_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (GstDecklinkClock, gst_decklink_clock, GST_TYPE_SYSTEM_CLOCK);
|
||||
|
||||
static GstClockTime gst_decklink_clock_get_internal_time (GstClock * clock);
|
||||
|
|
|
@ -173,6 +173,14 @@ typedef enum {
|
|||
#define GST_TYPE_DECKLINK_PROFILE_ID (gst_decklink_profile_id_get_type ())
|
||||
GType gst_decklink_profile_id_get_type (void);
|
||||
|
||||
typedef enum {
|
||||
GST_DECKLINK_MAPPING_FORMAT_DEFAULT,
|
||||
GST_DECKLINK_MAPPING_FORMAT_LEVEL_A, /* bmdDeckLinkConfigSMPTELevelAOutput = true */
|
||||
GST_DECKLINK_MAPPING_FORMAT_LEVEL_B, /* bmdDeckLinkConfigSMPTELevelAOutput = false */
|
||||
} GstDecklinkMappingFormat;
|
||||
#define GST_TYPE_DECKLINK_MAPPING_FORMAT (gst_decklink_mapping_format_get_type ())
|
||||
GType gst_decklink_mapping_format_get_type (void);
|
||||
|
||||
typedef enum {
|
||||
GST_DECKLINK_TIMECODE_FORMAT_RP188VITC1, /*bmdTimecodeRP188VITC1 */
|
||||
GST_DECKLINK_TIMECODE_FORMAT_RP188VITC2, /*bmdTimecodeRP188VITC2 */
|
||||
|
|
|
@ -232,6 +232,14 @@ private:
|
|||
gint m_refcount;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstDecklinkMappingFormat:
|
||||
* @GST_DECKLINK_MAPPING_FORMAT_DEFAULT: Don't change the mapping format
|
||||
* @GST_DECKLINK_MAPPING_FORMAT_LEVEL_A: Level A
|
||||
* @GST_DECKLINK_MAPPING_FORMAT_LEVEL_B: Level B
|
||||
*
|
||||
* Since: 1.22
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
@ -245,6 +253,7 @@ enum
|
|||
PROP_HW_SERIAL_NUMBER,
|
||||
PROP_CC_LINE,
|
||||
PROP_AFD_BAR_LINE,
|
||||
PROP_MAPPING_FORMAT,
|
||||
};
|
||||
|
||||
static void gst_decklink_video_sink_set_property (GObject * object,
|
||||
|
@ -407,6 +416,20 @@ gst_decklink_video_sink_class_init (GstDecklinkVideoSinkClass * klass)
|
|||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT)));
|
||||
|
||||
/**
|
||||
* GstDecklinkVideoSink:mapping-format
|
||||
*
|
||||
* Specifies the 3G-SDI mapping format to use (SMPTE ST 425-1:2017).
|
||||
*
|
||||
* Since: 1.22
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_MAPPING_FORMAT,
|
||||
g_param_spec_enum ("mapping-format", "3G-SDI Mapping Format",
|
||||
"3G-SDI Mapping Format (Level A/B)",
|
||||
GST_TYPE_DECKLINK_MAPPING_FORMAT, GST_DECKLINK_MAPPING_FORMAT_DEFAULT,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT)));
|
||||
|
||||
templ_caps = gst_decklink_mode_get_template_caps (FALSE);
|
||||
templ_caps = gst_caps_make_writable (templ_caps);
|
||||
/* For output we support any framerate and only really care about timestamps */
|
||||
|
@ -422,6 +445,8 @@ gst_decklink_video_sink_class_init (GstDecklinkVideoSinkClass * klass)
|
|||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_decklink_video_sink_debug, "decklinkvideosink",
|
||||
0, "debug category for decklinkvideosink element");
|
||||
|
||||
gst_type_mark_as_plugin_api(GST_TYPE_DECKLINK_MAPPING_FORMAT, (GstPluginAPIFlags)0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -435,6 +460,7 @@ gst_decklink_video_sink_init (GstDecklinkVideoSink * self)
|
|||
self->timecode_format = bmdTimecodeRP188Any;
|
||||
self->caption_line = 0;
|
||||
self->afd_bar_line = 0;
|
||||
self->mapping_format = GST_DECKLINK_MAPPING_FORMAT_DEFAULT;
|
||||
|
||||
gst_base_sink_set_max_lateness (GST_BASE_SINK_CAST (self), 20 * GST_MSECOND);
|
||||
gst_base_sink_set_qos_enabled (GST_BASE_SINK_CAST (self), TRUE);
|
||||
|
@ -490,6 +516,9 @@ gst_decklink_video_sink_set_property (GObject * object, guint property_id,
|
|||
case PROP_AFD_BAR_LINE:
|
||||
self->afd_bar_line = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_MAPPING_FORMAT:
|
||||
self->mapping_format = (GstDecklinkMappingFormat) g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -538,6 +567,9 @@ gst_decklink_video_sink_get_property (GObject * object, guint property_id,
|
|||
case PROP_AFD_BAR_LINE:
|
||||
g_value_set_int (value, self->afd_bar_line);
|
||||
break;
|
||||
case PROP_MAPPING_FORMAT:
|
||||
g_value_set_enum (value, self->mapping_format);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -75,6 +75,7 @@ struct _GstDecklinkVideoSink
|
|||
guint16 cdp_hdr_sequence_cntr;
|
||||
|
||||
gint afd_bar_line;
|
||||
GstDecklinkMappingFormat mapping_format;
|
||||
};
|
||||
|
||||
struct _GstDecklinkVideoSinkClass
|
||||
|
|
Loading…
Reference in a new issue