From e309de8447a0a2544bfcdd05456e84039fffaa12 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Tue, 24 Nov 2020 12:46:28 +0100 Subject: [PATCH 01/82] gstpad: check EOS / FLUSHING again after running probes in chain When for example a probe sends out an EOS event, we don't want to run the chain function with the buffer that triggered the probe. --- subprojects/gstreamer/gst/gstpad.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subprojects/gstreamer/gst/gstpad.c b/subprojects/gstreamer/gst/gstpad.c index 3b28c08e51..9a28dee23d 100644 --- a/subprojects/gstreamer/gst/gstpad.c +++ b/subprojects/gstreamer/gst/gstpad.c @@ -4539,6 +4539,12 @@ gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data) PROBE_HANDLE (pad, type, data, probe_stopped, probe_handled); + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + ACQUIRE_PARENT (pad, parent, no_parent); GST_OBJECT_UNLOCK (pad); From 6f1d35be71430db0e9d04fe41079bbf3fab5cf2e Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 11 Aug 2021 18:57:59 +0900 Subject: [PATCH 02/82] ccextractor: Add force-expose-caption-pad property When this property is enabled, ccextractor will expose caption pad on the first buffer even if caption meta is not attached in the buffer. This feature can be useful when caption branch needs to be strictly synchronized with video branch via pushed GAP event. For instance, application might want to produce text related data even if it doesn't exist (as a dummy or similar form). Live encoding would be a likely scenario. But by the nature of text, stream might not contain any caption data at the beginning then ccextractor cannot notify downstream of emptiness via GAP event since caption pad is not added yet. --- .../gst/closedcaption/gstccextractor.c | 112 ++++++++++++++---- .../gst/closedcaption/gstccextractor.h | 1 + 2 files changed, 92 insertions(+), 21 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.c b/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.c index 8b44df039b..aaae65308b 100644 --- a/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.c +++ b/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.c @@ -45,8 +45,11 @@ enum { PROP_0, PROP_REMOVE_CAPTION_META, + PROP_FORCE_EXPOSE_CAPTION_PAD, }; +#define DEFAULT_FORCE_EXPOSE_CAPTION_PAD FALSE + static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -112,6 +115,23 @@ gst_cc_extractor_class_init (GstCCExtractorClass * klass) "Remove caption meta from outgoing video buffers", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstCCExtractor:force-expose-caption-pad + * + * Exposes caption pad on the first buffer even if caption meta is not + * attached on the buffer. When this mode is used, user should configure + * ccconverter element so that downstream can handle any caption type update. + * + * Since: 1.22 + */ + g_object_class_install_property (gobject_class, PROP_FORCE_EXPOSE_CAPTION_PAD, + g_param_spec_boolean ("force-expose-caption-pad", + "Force expose caption pad", + "Force expose caption pad on the first buffer", + DEFAULT_FORCE_EXPOSE_CAPTION_PAD, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY | + G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_cc_extractor_change_state); @@ -340,15 +360,9 @@ forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) } static GstFlowReturn -gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf, - GstVideoCaptionMeta * meta, GstVideoTimeCodeMeta * tc_meta) +gst_cc_extractor_ensure_caption_pad (GstCCExtractor * filter, + GstVideoCaptionType caption_type) { - GstBuffer *outbuf = NULL; - GstFlowReturn flow; - - GST_DEBUG_OBJECT (filter, "Handling meta"); - - /* Check if the meta type matches the configured one */ if (filter->captionpad == NULL) { GST_DEBUG_OBJECT (filter, "Creating new caption pad"); @@ -359,24 +373,55 @@ gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf, GST_DEBUG_FUNCPTR (gst_cc_extractor_iterate_internal_links)); gst_pad_set_active (filter->captionpad, TRUE); - filter->caption_type = meta->caption_type; + /* When force_expose_caption_pad == TRUE */ + if (caption_type == GST_VIDEO_CAPTION_TYPE_UNKNOWN) { + GstCaps *caps = NULL; - gst_pad_sticky_events_foreach (filter->sinkpad, forward_sticky_events, - filter); + /* caption type is unknow at this moment. Adds caption pad first and + * picks one caption type supported by downstream (if it's linked) */ + gst_element_add_pad (GST_ELEMENT (filter), filter->captionpad); + gst_flow_combiner_add_pad (filter->combiner, filter->captionpad); - if (!gst_pad_has_current_caps (filter->captionpad)) { - GST_ERROR_OBJECT (filter, "Unknown/invalid caption type"); - return GST_FLOW_NOT_NEGOTIATED; - } + /* caption pad may be linked on pad-added signal, then query downstream */ + caps = gst_pad_get_allowed_caps (filter->captionpad); + if (!caps || gst_caps_is_any (caps)) { + gst_clear_caps (&caps); + caps = gst_pad_get_pad_template_caps (filter->captionpad); + } + + caps = gst_caps_fixate (caps); + caption_type = gst_video_caption_type_from_caps (caps); + gst_caps_unref (caps); + + if (caption_type == GST_VIDEO_CAPTION_TYPE_UNKNOWN) { + GST_ERROR_OBJECT (filter, "Failed to determine CC type"); + return GST_FLOW_NOT_NEGOTIATED; + } + + filter->caption_type = caption_type; - gst_element_add_pad (GST_ELEMENT (filter), filter->captionpad); - gst_flow_combiner_add_pad (filter->combiner, filter->captionpad); - } else if (meta->caption_type != filter->caption_type) { + gst_pad_sticky_events_foreach (filter->sinkpad, forward_sticky_events, + filter); + } else { + filter->caption_type = caption_type; + + gst_pad_sticky_events_foreach (filter->sinkpad, forward_sticky_events, + filter); + + if (!gst_pad_has_current_caps (filter->captionpad)) { + GST_ERROR_OBJECT (filter, "Unknown/invalid caption type"); + return GST_FLOW_NOT_NEGOTIATED; + } + + gst_element_add_pad (GST_ELEMENT (filter), filter->captionpad); + gst_flow_combiner_add_pad (filter->combiner, filter->captionpad); + } + } else if (caption_type != filter->caption_type) { GstCaps *caption_caps = - create_caps_from_caption_type (meta->caption_type, &filter->video_info); + create_caps_from_caption_type (caption_type, &filter->video_info); GST_DEBUG_OBJECT (filter, "Caption type changed from %d to %d", - filter->caption_type, meta->caption_type); + filter->caption_type, caption_type); if (caption_caps == NULL) { GST_ERROR_OBJECT (filter, "Unknown/invalid caption type"); return GST_FLOW_NOT_NEGOTIATED; @@ -385,9 +430,25 @@ gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf, gst_pad_push_event (filter->captionpad, gst_event_new_caps (caption_caps)); gst_caps_unref (caption_caps); - filter->caption_type = meta->caption_type; + filter->caption_type = caption_type; } + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf, + GstVideoCaptionMeta * meta, GstVideoTimeCodeMeta * tc_meta) +{ + GstBuffer *outbuf = NULL; + GstFlowReturn flow; + + GST_DEBUG_OBJECT (filter, "Handling meta"); + + flow = gst_cc_extractor_ensure_caption_pad (filter, meta->caption_type); + if (flow != GST_FLOW_OK) + return flow; + GST_DEBUG_OBJECT (filter, "Creating new buffer of size %" G_GSIZE_FORMAT " bytes", meta->size); /* Extract caption data into new buffer with identical buffer timestamps */ @@ -428,6 +489,9 @@ gst_cc_extractor_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) gboolean had_cc_meta = FALSE; gpointer iter = NULL; + if (filter->force_expose_caption_pad) + flow = gst_cc_extractor_ensure_caption_pad (filter, filter->caption_type); + tc_meta = gst_buffer_get_video_time_code_meta (buf); while ((cc_meta = @@ -513,6 +577,9 @@ gst_cc_extractor_set_property (GObject * object, guint prop_id, case PROP_REMOVE_CAPTION_META: filter->remove_caption_meta = g_value_get_boolean (value); break; + case PROP_FORCE_EXPOSE_CAPTION_PAD: + filter->force_expose_caption_pad = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -529,6 +596,9 @@ gst_cc_extractor_get_property (GObject * object, guint prop_id, GValue * value, case PROP_REMOVE_CAPTION_META: g_value_set_boolean (value, filter->remove_caption_meta); break; + case PROP_FORCE_EXPOSE_CAPTION_PAD: + g_value_set_boolean (value, filter->force_expose_caption_pad); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.h b/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.h index 36b0ef9bf4..1532b5266f 100644 --- a/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.h +++ b/subprojects/gst-plugins-bad/gst/closedcaption/gstccextractor.h @@ -52,6 +52,7 @@ struct _GstCCExtractor GstFlowCombiner *combiner; gboolean remove_caption_meta; + gboolean force_expose_caption_pad; }; struct _GstCCExtractorClass From 254411368aa7927c2c4a1b8503cab1c32b985111 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 30 Dec 2021 02:18:19 +0900 Subject: [PATCH 03/82] filesrc: Port to FILE struct ... in order to make use of OS layer file I/O abstraction/optimiztion --- .../gstreamer/plugins/elements/gstfilesrc.c | 69 ++++++++----------- .../gstreamer/plugins/elements/gstfilesrc.h | 5 +- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.c b/subprojects/gstreamer/plugins/elements/gstfilesrc.c index 7c5712ae56..52514f8ff7 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.c @@ -38,7 +38,6 @@ #endif #include -#include #include "gstfilesrc.h" #include "gstcoreelementselements.h" @@ -52,6 +51,10 @@ * variants, so explicitly define it that way. */ #undef lseek #define lseek _lseeki64 +#ifndef HAVE_FSEEKO +/* fseeko is not defined in Windows SDK's stdio.h */ +#define fseeko _fseeki64 +#endif #undef off_t #define off_t guint64 /* Prevent stat.h from defining the stat* functions as @@ -190,12 +193,6 @@ gst_file_src_class_init (GstFileSrcClass * klass) static void gst_file_src_init (GstFileSrc * src) { - src->filename = NULL; - src->fd = 0; - src->uri = NULL; - - src->is_regular = FALSE; - gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE); } @@ -315,7 +312,7 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, { GstFileSrc *src; guint to_read, bytes_read; - int ret; + gsize ret; GstMapInfo info; guint8 *data; @@ -324,8 +321,8 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, if (G_UNLIKELY (offset != -1 && src->read_position != offset)) { off_t res; - res = lseek (src->fd, offset, SEEK_SET); - if (G_UNLIKELY (res == (off_t) - 1 || res != offset)) + res = fseeko (src->fp, offset, SEEK_SET); + if (G_UNLIKELY (res != 0)) goto seek_failed; src->read_position = offset; @@ -341,7 +338,7 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x", to_read, offset + bytes_read); errno = 0; - ret = read (src->fd, data + bytes_read, to_read); + ret = fread (data + bytes_read, 1, to_read, src->fp); if (G_UNLIKELY (ret < 0)) { if (errno == EAGAIN || errno == EINTR) continue; @@ -447,38 +444,39 @@ gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size) * succeed, and wrongly say our length is zero. */ return FALSE; } + + if (!src->fp) + return FALSE; + #ifdef G_OS_WIN32 { - HANDLE h = gst_file_src_win32_get_osfhandle (src->fd); + HANDLE h = (HANDLE) _get_osfhandle (_fileno (src->fp)); LARGE_INTEGER file_size; if (h == INVALID_HANDLE_VALUE) - goto could_not_stat; + return FALSE; - if (!GetFileSizeEx (h, &file_size)) { - goto could_not_stat; - } + if (!GetFileSizeEx (h, &file_size)) + return FALSE; *size = file_size.QuadPart; } #else { struct_stat stat_results; + int fd = fileno (src->fp); - if (fstat (src->fd, &stat_results) < 0) - goto could_not_stat; + if (fd == -1) + return FALSE; + + if (fstat (fileno (src->fp), &stat_results) < 0) + return FALSE; *size = stat_results.st_size; } #endif return TRUE; - - /* ERROR */ -could_not_stat: - { - return FALSE; - } } /* open the file, necessary to go to READY state */ @@ -486,10 +484,6 @@ static gboolean gst_file_src_start (GstBaseSrc * basesrc) { GstFileSrc *src = GST_FILE_SRC (basesrc); - int flags = O_RDONLY | O_BINARY; -#if defined (__BIONIC__) - flags |= O_LARGEFILE; -#endif if (src->filename == NULL || src->filename[0] == '\0') goto no_filename; @@ -497,14 +491,14 @@ gst_file_src_start (GstBaseSrc * basesrc) GST_INFO_OBJECT (src, "opening file %s", src->filename); /* open the file */ - src->fd = g_open (src->filename, flags, 0); + src->fp = fopen (src->filename, "rb"); - if (src->fd < 0) + if (!src->fp) goto open_failed; #ifdef G_OS_WIN32 { - HANDLE h = gst_file_src_win32_get_osfhandle (src->fd); + HANDLE h = (HANDLE) _get_osfhandle (_fileno (src->fp)); FILE_STANDARD_INFO file_info; if (h == INVALID_HANDLE_VALUE) @@ -525,7 +519,7 @@ gst_file_src_start (GstBaseSrc * basesrc) struct_stat stat_results; /* check if it is a regular file, otherwise bail out */ - if (fstat (src->fd, &stat_results) < 0) + if (fstat (fileno (src->fp), &stat_results) < 0) goto no_stat; if (S_ISDIR (stat_results.st_mode)) @@ -544,14 +538,14 @@ gst_file_src_start (GstBaseSrc * basesrc) /* We need to check if the underlying file is seekable. */ { - off_t res = lseek (src->fd, 0, SEEK_END); + off_t res = fseeko (src->fp, 0, SEEK_END); if (res == (off_t) - 1) { GST_LOG_OBJECT (src, "disabling seeking, lseek failed: %s", g_strerror (errno)); src->seekable = FALSE; } else { - res = lseek (src->fd, 0, SEEK_SET); + res = fseeko (src->fp, 0, SEEK_SET); if (res == (off_t) - 1) { /* We really don't like not being able to go back to 0 */ @@ -621,7 +615,7 @@ gst_file_src_start (GstBaseSrc * basesrc) goto error_close; } error_close: - close (src->fd); + g_clear_pointer (&src->fp, fclose); error_exit: return FALSE; } @@ -632,11 +626,8 @@ gst_file_src_stop (GstBaseSrc * basesrc) { GstFileSrc *src = GST_FILE_SRC (basesrc); - /* close the file */ - g_close (src->fd, NULL); + g_clear_pointer (&src->fp, fclose); - /* zero out a lot of our state */ - src->fd = 0; src->is_regular = FALSE; return TRUE; diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.h b/subprojects/gstreamer/plugins/elements/gstfilesrc.h index e73cfc3d5e..72b7241bdc 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.h +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.h @@ -28,6 +28,7 @@ #include #include +#include G_BEGIN_DECLS @@ -57,8 +58,8 @@ struct _GstFileSrc { /*< private >*/ gchar *filename; /* filename */ gchar *uri; /* caching the URI */ - gint fd; /* open file descriptor */ - guint64 read_position; /* position of fd */ + FILE *fp; + guint64 read_position; /* position of file stream */ gboolean seekable; /* whether the file is seekable */ gboolean is_regular; /* whether it's a (symlink to a) From fdca958c66b3dbc70530db8acf716cbe7ac64ca8 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 30 Dec 2021 02:32:16 +0900 Subject: [PATCH 04/82] filesrc: Add buffer-size property ... for user to be able to specify the size of read buffer. Depending on use cases, larger buffer size than default value can optimize the read pattern and it would be able to save the cost resulting from too frequent read access to the underlying storage hardware. --- .../docs/plugins/gst_plugins_cache.json | 14 +++++++ .../gstreamer/plugins/elements/gstfilesrc.c | 42 ++++++++++++++++++- .../gstreamer/plugins/elements/gstfilesrc.h | 2 + 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json b/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json index 4c102dc041..d74c667831 100644 --- a/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json @@ -1029,6 +1029,20 @@ } }, "properties": { + "buffer-size": { + "blurb": "Size of the buffer passed to setvbuf(). If a non-zero value is set, it will be rounded down to the nearest multiple of 2.", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2147483647", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "guint", + "writable": true + }, "location": { "blurb": "Location of the file to read", "conditionally-available": false, diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.c b/subprojects/gstreamer/plugins/elements/gstfilesrc.c index 52514f8ff7..9b5244d52d 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.c @@ -116,11 +116,13 @@ enum }; #define DEFAULT_BLOCKSIZE 4*1024 +#define DEFAULT_BUFFER_SIZE 0 enum { PROP_0, - PROP_LOCATION + PROP_LOCATION, + PROP_BUFFER_SIZE, }; static void gst_file_src_finalize (GObject * object); @@ -169,6 +171,24 @@ gst_file_src_class_init (GstFileSrcClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY)); + /** + * GstFileSrc:buffer-size: + * + * Size of the buffer passed to setvbuf POSIX function. Depending on system, + * or read pattern (e.g., sequencial or randon-access), larger buffer size can + * improve throughput or reduce file access overhead. + * + * Since: 1.22 + */ + g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE, + g_param_spec_uint ("buffer-size", "Buffer Size", + "Size of the buffer passed to setvbuf(). If a non-zero value is set, " + "it will be rounded down to the nearest multiple of 2.", + /* NOTE: allowed max size on Windows is INT_MAX */ + 0, G_MAXINT32, DEFAULT_BUFFER_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + gobject_class->finalize = gst_file_src_finalize; gst_element_class_set_static_metadata (gstelement_class, @@ -193,6 +213,8 @@ gst_file_src_class_init (GstFileSrcClass * klass) static void gst_file_src_init (GstFileSrc * src) { + src->buffer_size = DEFAULT_BUFFER_SIZE; + gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE); } @@ -203,6 +225,7 @@ gst_file_src_finalize (GObject * object) src = GST_FILE_SRC (object); + g_free (src->buffer); g_free (src->filename); g_free (src->uri); @@ -270,6 +293,11 @@ gst_file_src_set_property (GObject * object, guint prop_id, case PROP_LOCATION: gst_file_src_set_location (src, g_value_get_string (value), NULL); break; + case PROP_BUFFER_SIZE: + src->buffer_size = g_value_get_uint (value); + if (src->buffer_size > 0) + src->buffer_size = GST_ROUND_DOWN_2 (src->buffer_size); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -290,6 +318,9 @@ gst_file_src_get_property (GObject * object, guint prop_id, GValue * value, case PROP_LOCATION: g_value_set_string (value, src->filename); break; + case PROP_BUFFER_SIZE: + g_value_set_uint (value, src->buffer_size); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -563,6 +594,14 @@ gst_file_src_start (GstBaseSrc * basesrc) gst_base_src_set_dynamic_size (basesrc, src->seekable); + if (src->buffer_size) { + src->buffer = g_malloc (src->buffer_size); + if (setvbuf (src->fp, (char *) src->buffer, _IOFBF, src->buffer_size) != 0) { + GST_WARNING_OBJECT (src, "setvbuf() failed"); + g_clear_pointer (&src->buffer, g_free); + } + } + return TRUE; /* ERROR */ @@ -627,6 +666,7 @@ gst_file_src_stop (GstBaseSrc * basesrc) GstFileSrc *src = GST_FILE_SRC (basesrc); g_clear_pointer (&src->fp, fclose); + g_clear_pointer (&src->buffer, g_free); src->is_regular = FALSE; diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.h b/subprojects/gstreamer/plugins/elements/gstfilesrc.h index 72b7241bdc..99702623a3 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.h +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.h @@ -64,6 +64,8 @@ struct _GstFileSrc { gboolean seekable; /* whether the file is seekable */ gboolean is_regular; /* whether it's a (symlink to a) regular file */ + gsize buffer_size; + guint8 *buffer; }; struct _GstFileSrcClass { From 9376a8587cba35198289519ccc7eae9c505972bd Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Mon, 2 May 2022 15:07:47 -0400 Subject: [PATCH 05/82] Set default filesrc buffer-size to 10MB --- subprojects/gstreamer/plugins/elements/gstfilesrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.c b/subprojects/gstreamer/plugins/elements/gstfilesrc.c index 9b5244d52d..5e27186ce0 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.c @@ -116,7 +116,7 @@ enum }; #define DEFAULT_BLOCKSIZE 4*1024 -#define DEFAULT_BUFFER_SIZE 0 +#define DEFAULT_BUFFER_SIZE 10*1024 enum { From 15c26b15fef6d01dad53a1b9b6eaa3e491d56267 Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Thu, 26 May 2022 16:00:44 -0400 Subject: [PATCH 06/82] Increase default filesrc buffer to 20MB --- subprojects/gstreamer/plugins/elements/gstfilesrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.c b/subprojects/gstreamer/plugins/elements/gstfilesrc.c index 5e27186ce0..3b1eb495fb 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.c @@ -116,7 +116,7 @@ enum }; #define DEFAULT_BLOCKSIZE 4*1024 -#define DEFAULT_BUFFER_SIZE 10*1024 +#define DEFAULT_BUFFER_SIZE 20*1024*1024 enum { From 94502bfa1ed44cf0f94887e5d95e36f2a176f2b0 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Fri, 26 Mar 2021 00:28:39 +0100 Subject: [PATCH 07/82] WIP: Video audio meta --- .../gst-libs/gst/video/gstvideometa.c | 85 +++++++++++++++++++ .../gst-libs/gst/video/gstvideometa.h | 20 +++++ 2 files changed, 105 insertions(+) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c index 931966353f..dd2bc28fa9 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.c @@ -1734,3 +1734,88 @@ gst_buffer_add_video_time_code_meta_full (GstBuffer * buffer, guint fps_n, return meta; } + +GType +gst_video_audio_meta_api_get_type (void) +{ + static volatile GType type; + + if (g_once_init_enter (&type)) { + static const gchar *tags[] = { NULL }; + GType _type = gst_meta_api_type_register ("GstVideoAudioMetaAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + + +static gboolean +gst_video_audio_meta_transform (GstBuffer * dest, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstVideoAudioMeta *dmeta, *smeta; + + if (GST_META_TRANSFORM_IS_COPY (type)) { + smeta = (GstVideoAudioMeta *) meta; + + GST_DEBUG ("copy video audio metadata"); + dmeta = gst_buffer_add_video_audio_meta (dest, smeta->buffer); + if (!dmeta) + return FALSE; + } else { + /* return FALSE, if transform type is not supported */ + return FALSE; + } + return TRUE; +} + +static gboolean +gst_video_audio_meta_init (GstMeta * meta, gpointer params, GstBuffer * buffer) +{ + GstVideoAudioMeta *emeta = (GstVideoAudioMeta *) meta; + + emeta->buffer = NULL; + + return TRUE; +} + +static void +gst_video_audio_meta_free (GstMeta * meta, GstBuffer * buffer) +{ + GstVideoAudioMeta *emeta = (GstVideoAudioMeta *) meta; + + gst_buffer_replace (&emeta->buffer, NULL); +} + +const GstMetaInfo * +gst_video_audio_meta_get_info (void) +{ + static const GstMetaInfo *meta_info = NULL; + + if (g_once_init_enter ((GstMetaInfo **) & meta_info)) { + const GstMetaInfo *mi = gst_meta_register (GST_VIDEO_AUDIO_META_API_TYPE, + "GstVideoAudioMeta", + sizeof (GstVideoAudioMeta), + gst_video_audio_meta_init, + gst_video_audio_meta_free, + gst_video_audio_meta_transform); + g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) mi); + } + return meta_info; +} + +GstVideoAudioMeta * +gst_buffer_add_video_audio_meta (GstBuffer * buffer, GstBuffer * audio_buffer) +{ + GstVideoAudioMeta *meta; + + g_return_val_if_fail (buffer != NULL, NULL); + g_return_val_if_fail (audio_buffer != NULL, NULL); + + meta = (GstVideoAudioMeta *) gst_buffer_add_meta (buffer, + GST_VIDEO_AUDIO_META_INFO, NULL); + + meta->buffer = gst_buffer_ref (audio_buffer); + + return meta; +} diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.h b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.h index a87dfd30ec..5f989c40e1 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.h +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideometa.h @@ -495,6 +495,26 @@ gst_buffer_add_video_time_code_meta_full (GstBuffer guint frames, guint field_count); +typedef struct { + GstMeta meta; + + GstBuffer *buffer; +} GstVideoAudioMeta; + +GST_VIDEO_API +GType gst_video_audio_meta_api_get_type (void); +#define GST_VIDEO_AUDIO_META_API_TYPE (gst_video_audio_meta_api_get_type()) + +GST_VIDEO_API +const GstMetaInfo *gst_video_audio_meta_get_info (void); +#define GST_VIDEO_AUDIO_META_INFO (gst_video_audio_meta_get_info()) + +#define gst_buffer_get_video_audio_meta(b) \ + ((GstVideoAudioMeta*)gst_buffer_get_meta((b),GST_VIDEO_AUDIO_META_API_TYPE)) + +GST_VIDEO_API +GstVideoAudioMeta *gst_buffer_add_video_audio_meta (GstBuffer * buffer, GstBuffer * audio_buffer); + G_END_DECLS #endif /* __GST_VIDEO_META_H__ */ From ea97096a0a7eb3260a2ef05bed8641c770bacf2a Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 27 Aug 2022 22:35:45 +0900 Subject: [PATCH 08/82] mpegvideoparse: Update pixel-aspect-ratio if resolution is updated This parse element updates resolution with parsed value which can be different from upstream one but pixel-aspect-ratio is not updated. Updates pixel-aspect-ratio as well if resolution is updated since the upstream information is likely incorrect. --- .../gst/videoparsers/gstmpegvideoparse.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/gst/videoparsers/gstmpegvideoparse.c b/subprojects/gst-plugins-bad/gst/videoparsers/gstmpegvideoparse.c index 3c4f7eec67..4b752dcdee 100644 --- a/subprojects/gst-plugins-bad/gst/videoparsers/gstmpegvideoparse.c +++ b/subprojects/gst-plugins-bad/gst/videoparsers/gstmpegvideoparse.c @@ -765,6 +765,7 @@ gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse) { GstCaps *caps = NULL; GstStructure *s = NULL; + gboolean update_par = FALSE; /* only update if no src caps yet or explicitly triggered */ if (G_LIKELY (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (mpvparse)) && @@ -794,6 +795,7 @@ gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse) if (mpvparse->sequencehdr.width > 0 && mpvparse->sequencehdr.height > 0) { GstMpegVideoSequenceDisplayExt *seqdispext; gint width, height; + gint upstream_width, upstream_height; width = mpvparse->sequencehdr.width; height = mpvparse->sequencehdr.height; @@ -810,6 +812,15 @@ gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse) width, height); } } + + /* upstream resolution is different from one we parsed and updated. + * uses parsed par in this case */ + if (s && gst_structure_get_int (s, "width", &upstream_width) && + gst_structure_get_int (s, "height", &upstream_height) && + (upstream_width != width || upstream_height != height)) { + update_par = TRUE; + } + gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); } @@ -836,7 +847,8 @@ gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse) /* or pixel-aspect-ratio */ if (mpvparse->sequencehdr.par_w && mpvparse->sequencehdr.par_h > 0 && - (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) { + (!s || !gst_structure_has_field (s, "pixel-aspect-ratio") + || update_par)) { gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION, mpvparse->sequencehdr.par_w, mpvparse->sequencehdr.par_h, NULL); } From efe13e26436ead6e6e69d0f07add210d8d9e2e65 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 30 Aug 2022 21:49:29 +0900 Subject: [PATCH 09/82] videodecoder: Always prefer DTS as PTS if PTS is unknown Use given DTS value as the PTS instead of accumulating frame duration. The frame duration accumulation will be reliable only if it's very accuration, and if not, that will cause out of sync issue. --- .../gst-libs/gst/video/gstvideodecoder.c | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideodecoder.c b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideodecoder.c index c657b6b723..c379bcc4d4 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideodecoder.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideodecoder.c @@ -3282,27 +3282,23 @@ gst_video_decoder_prepare_finish_frame (GstVideoDecoder * } if (frame->pts == GST_CLOCK_TIME_NONE) { - /* Last ditch timestamp guess: Just add the duration to the previous - * frame. If it's the first frame, just use the segment start. */ - if (frame->duration != GST_CLOCK_TIME_NONE) { + if (frame->dts != GST_CLOCK_TIME_NONE) { + frame->pts = frame->dts; + GST_LOG_OBJECT (decoder, + "Setting DTS as PTS %" GST_TIME_FORMAT " for frame...", + GST_TIME_ARGS (frame->pts)); + } else if (frame->duration != GST_CLOCK_TIME_NONE) { + /* Last ditch timestamp guess: Just add the duration to the previous + * frame. If it's the first frame, just use the segment start. */ if (GST_CLOCK_TIME_IS_VALID (priv->last_timestamp_out)) frame->pts = priv->last_timestamp_out + frame->duration; - else if (frame->dts != GST_CLOCK_TIME_NONE) { - frame->pts = frame->dts; - GST_LOG_OBJECT (decoder, - "Setting DTS as PTS %" GST_TIME_FORMAT " for frame...", - GST_TIME_ARGS (frame->pts)); - } else if (decoder->output_segment.rate > 0.0) + else if (decoder->output_segment.rate > 0.0) frame->pts = decoder->output_segment.start; + GST_INFO_OBJECT (decoder, "Guessing PTS=%" GST_TIME_FORMAT " for frame... DTS=%" GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (frame->dts)); - } else if (sync && frame->dts != GST_CLOCK_TIME_NONE) { - frame->pts = frame->dts; - GST_LOG_OBJECT (decoder, - "Setting DTS as PTS %" GST_TIME_FORMAT " for frame...", - GST_TIME_ARGS (frame->pts)); } } From bf8eaaf8cbaa9f103c21a661b064715cf05f9013 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 30 Mar 2023 00:13:12 +0900 Subject: [PATCH 10/82] ccconverter: Don't assert on error --- .../gst/closedcaption/gstccconverter.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/closedcaption/gstccconverter.c b/subprojects/gst-plugins-bad/gst/closedcaption/gstccconverter.c index 5290253272..9837f912c5 100644 --- a/subprojects/gst-plugins-bad/gst/closedcaption/gstccconverter.c +++ b/subprojects/gst-plugins-bad/gst/closedcaption/gstccconverter.c @@ -1566,14 +1566,20 @@ can_generate_output (GstCCConverter * self) /* compute the relative frame count for each */ if (!gst_util_fraction_multiply (self->in_fps_d, self->in_fps_n, - self->input_frames, 1, &input_frame_n, &input_frame_d)) - /* we should never overflow */ - g_assert_not_reached (); + self->input_frames, 1, &input_frame_n, &input_frame_d)) { + GST_ERROR_OBJECT (self, + "Couldn't get input rate, fps: %d/%d, input frames %d", + self->in_fps_n, self->in_fps_d, self->input_frames); + return FALSE; + } if (!gst_util_fraction_multiply (self->out_fps_d, self->out_fps_n, - self->output_frames, 1, &output_frame_n, &output_frame_d)) - /* we should never overflow */ - g_assert_not_reached (); + self->output_frames, 1, &output_frame_n, &output_frame_d)) { + GST_ERROR_OBJECT (self, + "Couldn't get output rate, fps: %d/%d, output frames %d", + self->out_fps_n, self->out_fps_d, self->output_frames); + return FALSE; + } output_time_cmp = gst_util_fraction_compare (input_frame_n, input_frame_d, output_frame_n, output_frame_d); From 1719b570c2b3baf1144e7684981a56ae9302413f Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 31 Dec 2022 21:09:13 +0900 Subject: [PATCH 11/82] decklink2: Import SDK v12.4.2 files --- .../sys/decklink2/linux/DeckLinkAPI.h | 1299 ++++++++++++++++ .../linux/DeckLinkAPIConfiguration.h | 269 ++++ .../linux/DeckLinkAPIConfiguration_v10_11.h | 84 + .../linux/DeckLinkAPIConfiguration_v10_2.h | 73 + .../linux/DeckLinkAPIConfiguration_v10_4.h | 76 + .../linux/DeckLinkAPIConfiguration_v10_5.h | 73 + .../linux/DeckLinkAPIConfiguration_v10_9.h | 75 + .../decklink2/linux/DeckLinkAPIDeckControl.h | 223 +++ .../decklink2/linux/DeckLinkAPIDiscovery.h | 79 + .../decklink2/linux/DeckLinkAPIDispatch.cpp | 188 +++ .../linux/DeckLinkAPIDispatch_v10_11.cpp | 173 +++ .../linux/DeckLinkAPIDispatch_v10_8.cpp | 159 ++ .../linux/DeckLinkAPIDispatch_v7_6.cpp | 122 ++ .../linux/DeckLinkAPIDispatch_v8_0.cpp | 146 ++ .../sys/decklink2/linux/DeckLinkAPIModes.h | 289 ++++ .../sys/decklink2/linux/DeckLinkAPITypes.h | 132 ++ .../sys/decklink2/linux/DeckLinkAPIVersion.h | 50 + .../DeckLinkAPIVideoEncoderInput_v10_11.h | 87 ++ .../linux/DeckLinkAPIVideoInput_v10_11.h | 90 ++ .../linux/DeckLinkAPIVideoInput_v11_4.h | 89 ++ .../linux/DeckLinkAPIVideoInput_v11_5_1.h | 102 ++ .../linux/DeckLinkAPIVideoOutput_v10_11.h | 107 ++ .../linux/DeckLinkAPIVideoOutput_v11_4.h | 100 ++ .../sys/decklink2/linux/DeckLinkAPI_v10_11.h | 134 ++ .../sys/decklink2/linux/DeckLinkAPI_v10_2.h | 68 + .../sys/decklink2/linux/DeckLinkAPI_v10_4.h | 58 + .../sys/decklink2/linux/DeckLinkAPI_v10_5.h | 59 + .../sys/decklink2/linux/DeckLinkAPI_v10_6.h | 63 + .../sys/decklink2/linux/DeckLinkAPI_v10_9.h | 58 + .../sys/decklink2/linux/DeckLinkAPI_v11_5.h | 113 ++ .../sys/decklink2/linux/DeckLinkAPI_v11_5_1.h | 57 + .../sys/decklink2/linux/DeckLinkAPI_v7_1.h | 212 +++ .../sys/decklink2/linux/DeckLinkAPI_v7_3.h | 187 +++ .../sys/decklink2/linux/DeckLinkAPI_v7_6.h | 418 +++++ .../sys/decklink2/linux/DeckLinkAPI_v7_9.h | 101 ++ .../sys/decklink2/linux/DeckLinkAPI_v8_0.h | 76 + .../sys/decklink2/linux/DeckLinkAPI_v8_1.h | 124 ++ .../sys/decklink2/linux/DeckLinkAPI_v9_2.h | 96 ++ .../sys/decklink2/linux/DeckLinkAPI_v9_9.h | 112 ++ .../sys/decklink2/linux/LinuxCOM.h | 116 ++ .../sys/decklink2/mac/DeckLinkAPI.h | 1332 ++++++++++++++++ .../decklink2/mac/DeckLinkAPIConfiguration.h | 269 ++++ .../mac/DeckLinkAPIConfiguration_v10_11.h | 84 + .../mac/DeckLinkAPIConfiguration_v10_2.h | 73 + .../mac/DeckLinkAPIConfiguration_v10_4.h | 75 + .../mac/DeckLinkAPIConfiguration_v10_5.h | 73 + .../mac/DeckLinkAPIConfiguration_v10_9.h | 75 + .../decklink2/mac/DeckLinkAPIDeckControl.h | 223 +++ .../sys/decklink2/mac/DeckLinkAPIDiscovery.h | 79 + .../sys/decklink2/mac/DeckLinkAPIDispatch.cpp | 245 +++ .../mac/DeckLinkAPIDispatch_v10_11.cpp | 219 +++ .../mac/DeckLinkAPIDispatch_v10_8.cpp | 206 +++ .../mac/DeckLinkAPIDispatch_v7_6.cpp | 118 ++ .../mac/DeckLinkAPIDispatch_v8_0.cpp | 144 ++ .../sys/decklink2/mac/DeckLinkAPIModes.h | 289 ++++ .../sys/decklink2/mac/DeckLinkAPIStreaming.h | 383 +++++ .../mac/DeckLinkAPIStreaming_v10_11.h | 59 + .../sys/decklink2/mac/DeckLinkAPITypes.h | 132 ++ .../sys/decklink2/mac/DeckLinkAPIVersion.h | 50 + .../mac/DeckLinkAPIVideoEncoderInput_v10_11.h | 88 ++ .../mac/DeckLinkAPIVideoInput_v10_11.h | 91 ++ .../mac/DeckLinkAPIVideoInput_v11_4.h | 90 ++ .../mac/DeckLinkAPIVideoInput_v11_5_1.h | 102 ++ .../mac/DeckLinkAPIVideoOutput_v10_11.h | 108 ++ .../mac/DeckLinkAPIVideoOutput_v11_4.h | 101 ++ .../sys/decklink2/mac/DeckLinkAPI_v10_11.h | 135 ++ .../sys/decklink2/mac/DeckLinkAPI_v10_2.h | 68 + .../sys/decklink2/mac/DeckLinkAPI_v10_4.h | 58 + .../sys/decklink2/mac/DeckLinkAPI_v10_5.h | 59 + .../sys/decklink2/mac/DeckLinkAPI_v10_6.h | 64 + .../sys/decklink2/mac/DeckLinkAPI_v10_9.h | 58 + .../sys/decklink2/mac/DeckLinkAPI_v11_5.h | 113 ++ .../sys/decklink2/mac/DeckLinkAPI_v11_5_1.h | 57 + .../sys/decklink2/mac/DeckLinkAPI_v7_1.h | 212 +++ .../sys/decklink2/mac/DeckLinkAPI_v7_3.h | 186 +++ .../sys/decklink2/mac/DeckLinkAPI_v7_6.h | 435 ++++++ .../sys/decklink2/mac/DeckLinkAPI_v7_9.h | 104 ++ .../sys/decklink2/mac/DeckLinkAPI_v8_0.h | 76 + .../sys/decklink2/mac/DeckLinkAPI_v8_1.h | 124 ++ .../sys/decklink2/mac/DeckLinkAPI_v9_2.h | 96 ++ .../sys/decklink2/mac/DeckLinkAPI_v9_9.h | 115 ++ .../sys/decklink2/win/DeckLinkAPI.idl | 1376 +++++++++++++++++ .../win/DeckLinkAPIConfiguration.idl | 252 +++ .../decklink2/win/DeckLinkAPIDeckControl.idl | 204 +++ .../decklink2/win/DeckLinkAPIDiscovery.idl | 63 + .../sys/decklink2/win/DeckLinkAPIModes.idl | 270 ++++ .../decklink2/win/DeckLinkAPIStreaming.idl | 362 +++++ .../win/DeckLinkAPIStreaming_v10_8.idl | 53 + .../sys/decklink2/win/DeckLinkAPITypes.idl | 114 ++ .../sys/decklink2/win/DeckLinkAPIVersion.h | 50 + .../sys/decklink2/win/DeckLinkAPI_v10_11.idl | 302 ++++ .../sys/decklink2/win/DeckLinkAPI_v10_2.idl | 86 ++ .../sys/decklink2/win/DeckLinkAPI_v10_4.idl | 74 + .../sys/decklink2/win/DeckLinkAPI_v10_5.idl | 74 + .../sys/decklink2/win/DeckLinkAPI_v10_6.idl | 54 + .../sys/decklink2/win/DeckLinkAPI_v10_8.idl | 59 + .../sys/decklink2/win/DeckLinkAPI_v10_9.idl | 74 + .../sys/decklink2/win/DeckLinkAPI_v11_4.idl | 133 ++ .../sys/decklink2/win/DeckLinkAPI_v11_5.idl | 112 ++ .../sys/decklink2/win/DeckLinkAPI_v11_5_1.idl | 104 ++ .../sys/decklink2/win/DeckLinkAPI_v7_1.idl | 173 +++ .../sys/decklink2/win/DeckLinkAPI_v7_3.idl | 170 ++ .../sys/decklink2/win/DeckLinkAPI_v7_6.idl | 409 +++++ .../sys/decklink2/win/DeckLinkAPI_v7_9.idl | 82 + .../sys/decklink2/win/DeckLinkAPI_v8_0.idl | 75 + .../sys/decklink2/win/DeckLinkAPI_v8_1.idl | 114 ++ .../sys/decklink2/win/DeckLinkAPI_v9_2.idl | 81 + .../sys/decklink2/win/DeckLinkAPI_v9_9.idl | 100 ++ 108 files changed, 17825 insertions(+) create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_2.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_5.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDeckControl.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDiscovery.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIModes.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPITypes.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVersion.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoEncoderInput_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_5_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v11_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_2.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_5.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_6.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_3.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_6.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_0.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_2.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/linux/LinuxCOM.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_2.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_5.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDeckControl.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDiscovery.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_11.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_8.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v7_6.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v8_0.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIModes.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPITypes.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVersion.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoEncoderInput_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_5_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v11_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_11.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_2.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_4.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_5.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_6.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_3.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_6.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_0.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_1.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_2.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_9.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIConfiguration.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDeckControl.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDiscovery.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIModes.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming_v10_8.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPITypes.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIVersion.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_11.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_2.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_4.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_5.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_6.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_8.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_9.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_4.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5_1.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_1.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_3.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_6.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_9.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_0.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_1.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_2.idl create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_9.idl diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI.h new file mode 100644 index 0000000000..84f201c7ad --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI.h @@ -0,0 +1,1299 @@ +/* -LICENSE-START- + ** Copyright (c) 2022 Blackmagic Design + ** + ** Permission is hereby granted, free of charge, to any person or organization + ** obtaining a copy of the software and accompanying documentation (the + ** "Software") to use, reproduce, display, distribute, sub-license, execute, + ** and transmit the Software, and to prepare derivative works of the Software, + ** and to permit third-parties to whom the Software is furnished to do so, in + ** accordance with: + ** + ** (1) if the Software is obtained from Blackmagic Design, the End User License + ** Agreement for the Software Development Kit ("EULA") available at + ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + ** + ** (2) if the Software is obtained from any third party, such licensing terms + ** as notified by that third party, + ** + ** and all subject to the following: + ** + ** (3) the copyright notices in the Software and this entire statement, + ** including the above license grant, this restriction and the following + ** disclaimer, must be included in all copies of the Software, in whole or in + ** part, and all derivative works of the Software, unless such copies or + ** derivative works are solely in the form of machine-executable object code + ** generated by a source language processor. + ** + ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + ** DEALINGS IN THE SOFTWARE. + ** + ** A copy of the Software is available free of charge at + ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + ** + ** -LICENSE-END- + */ + + +#ifndef BMD_DECKLINKAPI_H +#define BMD_DECKLINKAPI_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +/* DeckLink API */ + +#include +#include "LinuxCOM.h" + +#include "DeckLinkAPITypes.h" +#include "DeckLinkAPIModes.h" +#include "DeckLinkAPIDiscovery.h" +#include "DeckLinkAPIConfiguration.h" +#include "DeckLinkAPIDeckControl.h" + +#define BLACKMAGIC_DECKLINK_API_MAGIC 1 + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkVideoOutputCallback = /* 20AA5225-1958-47CB-820B-80A8D521A6EE */ { 0x20,0xAA,0x52,0x25,0x19,0x58,0x47,0xCB,0x82,0x0B,0x80,0xA8,0xD5,0x21,0xA6,0xEE }; +BMD_CONST REFIID IID_IDeckLinkInputCallback = /* C6FCE4C9-C4E4-4047-82FB-5D238232A902 */ { 0xC6,0xFC,0xE4,0xC9,0xC4,0xE4,0x40,0x47,0x82,0xFB,0x5D,0x23,0x82,0x32,0xA9,0x02 }; +BMD_CONST REFIID IID_IDeckLinkEncoderInputCallback = /* ACF13E61-F4A0-4974-A6A7-59AFF6268B31 */ { 0xAC,0xF1,0x3E,0x61,0xF4,0xA0,0x49,0x74,0xA6,0xA7,0x59,0xAF,0xF6,0x26,0x8B,0x31 }; +BMD_CONST REFIID IID_IDeckLinkMemoryAllocator = /* B36EB6E7-9D29-4AA8-92EF-843B87A289E8 */ { 0xB3,0x6E,0xB6,0xE7,0x9D,0x29,0x4A,0xA8,0x92,0xEF,0x84,0x3B,0x87,0xA2,0x89,0xE8 }; +BMD_CONST REFIID IID_IDeckLinkAudioOutputCallback = /* 403C681B-7F46-4A12-B993-2BB127084EE6 */ { 0x40,0x3C,0x68,0x1B,0x7F,0x46,0x4A,0x12,0xB9,0x93,0x2B,0xB1,0x27,0x08,0x4E,0xE6 }; +BMD_CONST REFIID IID_IDeckLinkIterator = /* 50FB36CD-3063-4B73-BDBB-958087F2D8BA */ { 0x50,0xFB,0x36,0xCD,0x30,0x63,0x4B,0x73,0xBD,0xBB,0x95,0x80,0x87,0xF2,0xD8,0xBA }; +BMD_CONST REFIID IID_IDeckLinkAPIInformation = /* 7BEA3C68-730D-4322-AF34-8A7152B532A4 */ { 0x7B,0xEA,0x3C,0x68,0x73,0x0D,0x43,0x22,0xAF,0x34,0x8A,0x71,0x52,0xB5,0x32,0xA4 }; +BMD_CONST REFIID IID_IDeckLinkOutput = /* BE2D9020-461E-442F-84B7-E949CB953B9D */ { 0xBE,0x2D,0x90,0x20,0x46,0x1E,0x44,0x2F,0x84,0xB7,0xE9,0x49,0xCB,0x95,0x3B,0x9D }; +BMD_CONST REFIID IID_IDeckLinkInput = /* C21CDB6E-F414-46E4-A636-80A566E0ED37 */ { 0xC2,0x1C,0xDB,0x6E,0xF4,0x14,0x46,0xE4,0xA6,0x36,0x80,0xA5,0x66,0xE0,0xED,0x37 }; +BMD_CONST REFIID IID_IDeckLinkHDMIInputEDID = /* ABBBACBC-45BC-4665-9D92-ACE6E5A97902 */ { 0xAB,0xBB,0xAC,0xBC,0x45,0xBC,0x46,0x65,0x9D,0x92,0xAC,0xE6,0xE5,0xA9,0x79,0x02 }; +BMD_CONST REFIID IID_IDeckLinkEncoderInput = /* F222551D-13DF-4FD8-B587-9D4F19EC12C9 */ { 0xF2,0x22,0x55,0x1D,0x13,0xDF,0x4F,0xD8,0xB5,0x87,0x9D,0x4F,0x19,0xEC,0x12,0xC9 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrame = /* 3F716FE0-F023-4111-BE5D-EF4414C05B17 */ { 0x3F,0x71,0x6F,0xE0,0xF0,0x23,0x41,0x11,0xBE,0x5D,0xEF,0x44,0x14,0xC0,0x5B,0x17 }; +BMD_CONST REFIID IID_IDeckLinkMutableVideoFrame = /* 69E2639F-40DA-4E19-B6F2-20ACE815C390 */ { 0x69,0xE2,0x63,0x9F,0x40,0xDA,0x4E,0x19,0xB6,0xF2,0x20,0xAC,0xE8,0x15,0xC3,0x90 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrame3DExtensions = /* DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7 */ { 0xDA,0x0F,0x7E,0x4A,0xED,0xC7,0x48,0xA8,0x9C,0xDD,0x2D,0xB5,0x1C,0x72,0x9C,0xD7 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrameMetadataExtensions = /* E232A5B7-4DB4-44C9-9152-F47C12E5F051 */ { 0xE2,0x32,0xA5,0xB7,0x4D,0xB4,0x44,0xC9,0x91,0x52,0xF4,0x7C,0x12,0xE5,0xF0,0x51 }; +BMD_CONST REFIID IID_IDeckLinkVideoInputFrame = /* 05CFE374-537C-4094-9A57-680525118F44 */ { 0x05,0xCF,0xE3,0x74,0x53,0x7C,0x40,0x94,0x9A,0x57,0x68,0x05,0x25,0x11,0x8F,0x44 }; +BMD_CONST REFIID IID_IDeckLinkAncillaryPacket = /* CC5BBF7E-029C-4D3B-9158-6000EF5E3670 */ { 0xCC,0x5B,0xBF,0x7E,0x02,0x9C,0x4D,0x3B,0x91,0x58,0x60,0x00,0xEF,0x5E,0x36,0x70 }; +BMD_CONST REFIID IID_IDeckLinkAncillaryPacketIterator = /* 3FC8994B-88FB-4C17-968F-9AAB69D964A7 */ { 0x3F,0xC8,0x99,0x4B,0x88,0xFB,0x4C,0x17,0x96,0x8F,0x9A,0xAB,0x69,0xD9,0x64,0xA7 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrameAncillaryPackets = /* 6C186C0F-459E-41D8-AEE2-4812D81AEE68 */ { 0x6C,0x18,0x6C,0x0F,0x45,0x9E,0x41,0xD8,0xAE,0xE2,0x48,0x12,0xD8,0x1A,0xEE,0x68 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrameAncillary = /* 732E723C-D1A4-4E29-9E8E-4A88797A0004 */ { 0x73,0x2E,0x72,0x3C,0xD1,0xA4,0x4E,0x29,0x9E,0x8E,0x4A,0x88,0x79,0x7A,0x00,0x04 }; +BMD_CONST REFIID IID_IDeckLinkEncoderPacket = /* B693F36C-316E-4AF1-B6C2-F389A4BCA620 */ { 0xB6,0x93,0xF3,0x6C,0x31,0x6E,0x4A,0xF1,0xB6,0xC2,0xF3,0x89,0xA4,0xBC,0xA6,0x20 }; +BMD_CONST REFIID IID_IDeckLinkEncoderVideoPacket = /* 4E7FD944-E8C7-4EAC-B8C0-7B77F80F5AE0 */ { 0x4E,0x7F,0xD9,0x44,0xE8,0xC7,0x4E,0xAC,0xB8,0xC0,0x7B,0x77,0xF8,0x0F,0x5A,0xE0 }; +BMD_CONST REFIID IID_IDeckLinkEncoderAudioPacket = /* 49E8EDC8-693B-4E14-8EF6-12C658F5A07A */ { 0x49,0xE8,0xED,0xC8,0x69,0x3B,0x4E,0x14,0x8E,0xF6,0x12,0xC6,0x58,0xF5,0xA0,0x7A }; +BMD_CONST REFIID IID_IDeckLinkH265NALPacket = /* 639C8E0B-68D5-4BDE-A6D4-95F3AEAFF2E7 */ { 0x63,0x9C,0x8E,0x0B,0x68,0xD5,0x4B,0xDE,0xA6,0xD4,0x95,0xF3,0xAE,0xAF,0xF2,0xE7 }; +BMD_CONST REFIID IID_IDeckLinkAudioInputPacket = /* E43D5870-2894-11DE-8C30-0800200C9A66 */ { 0xE4,0x3D,0x58,0x70,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66 }; +BMD_CONST REFIID IID_IDeckLinkScreenPreviewCallback = /* B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438 */ { 0xB1,0xD3,0xF4,0x9A,0x85,0xFE,0x4C,0x5D,0x95,0xC8,0x0B,0x5D,0x5D,0xCC,0xD4,0x38 }; +BMD_CONST REFIID IID_IDeckLinkGLScreenPreviewHelper = /* 504E2209-CAC7-4C1A-9FB4-C5BB6274D22F */ { 0x50,0x4E,0x22,0x09,0xCA,0xC7,0x4C,0x1A,0x9F,0xB4,0xC5,0xBB,0x62,0x74,0xD2,0x2F }; +BMD_CONST REFIID IID_IDeckLinkNotificationCallback = /* B002A1EC-070D-4288-8289-BD5D36E5FF0D */ { 0xB0,0x02,0xA1,0xEC,0x07,0x0D,0x42,0x88,0x82,0x89,0xBD,0x5D,0x36,0xE5,0xFF,0x0D }; +BMD_CONST REFIID IID_IDeckLinkNotification = /* B85DF4C8-BDF5-47C1-8064-28162EBDD4EB */ { 0xB8,0x5D,0xF4,0xC8,0xBD,0xF5,0x47,0xC1,0x80,0x64,0x28,0x16,0x2E,0xBD,0xD4,0xEB }; +BMD_CONST REFIID IID_IDeckLinkProfileAttributes = /* 17D4BF8E-4911-473A-80A0-731CF6FF345B */ { 0x17,0xD4,0xBF,0x8E,0x49,0x11,0x47,0x3A,0x80,0xA0,0x73,0x1C,0xF6,0xFF,0x34,0x5B }; +BMD_CONST REFIID IID_IDeckLinkProfileIterator = /* 29E5A8C0-8BE4-46EB-93AC-31DAAB5B7BF2 */ { 0x29,0xE5,0xA8,0xC0,0x8B,0xE4,0x46,0xEB,0x93,0xAC,0x31,0xDA,0xAB,0x5B,0x7B,0xF2 }; +BMD_CONST REFIID IID_IDeckLinkProfile = /* 16093466-674A-432B-9DA0-1AC2C5A8241C */ { 0x16,0x09,0x34,0x66,0x67,0x4A,0x43,0x2B,0x9D,0xA0,0x1A,0xC2,0xC5,0xA8,0x24,0x1C }; +BMD_CONST REFIID IID_IDeckLinkProfileCallback = /* A4F9341E-97AA-4E04-8935-15F809898CEA */ { 0xA4,0xF9,0x34,0x1E,0x97,0xAA,0x4E,0x04,0x89,0x35,0x15,0xF8,0x09,0x89,0x8C,0xEA }; +BMD_CONST REFIID IID_IDeckLinkProfileManager = /* 30D41429-3998-4B6D-84F8-78C94A797C6E */ { 0x30,0xD4,0x14,0x29,0x39,0x98,0x4B,0x6D,0x84,0xF8,0x78,0xC9,0x4A,0x79,0x7C,0x6E }; +BMD_CONST REFIID IID_IDeckLinkStatus = /* 5F558200-4028-49BC-BEAC-DB3FA4A96E46 */ { 0x5F,0x55,0x82,0x00,0x40,0x28,0x49,0xBC,0xBE,0xAC,0xDB,0x3F,0xA4,0xA9,0x6E,0x46 }; +BMD_CONST REFIID IID_IDeckLinkKeyer = /* 89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3 */ { 0x89,0xAF,0xCA,0xF5,0x65,0xF8,0x42,0x1E,0x98,0xF7,0x96,0xFE,0x5F,0x5B,0xFB,0xA3 }; +BMD_CONST REFIID IID_IDeckLinkVideoConversion = /* 3BBCB8A2-DA2C-42D9-B5D8-88083644E99A */ { 0x3B,0xBC,0xB8,0xA2,0xDA,0x2C,0x42,0xD9,0xB5,0xD8,0x88,0x08,0x36,0x44,0xE9,0x9A }; +BMD_CONST REFIID IID_IDeckLinkDeviceNotificationCallback = /* 4997053B-0ADF-4CC8-AC70-7A50C4BE728F */ { 0x49,0x97,0x05,0x3B,0x0A,0xDF,0x4C,0xC8,0xAC,0x70,0x7A,0x50,0xC4,0xBE,0x72,0x8F }; +BMD_CONST REFIID IID_IDeckLinkDiscovery = /* CDBF631C-BC76-45FA-B44D-C55059BC6101 */ { 0xCD,0xBF,0x63,0x1C,0xBC,0x76,0x45,0xFA,0xB4,0x4D,0xC5,0x50,0x59,0xBC,0x61,0x01 }; + +/* Enum BMDVideoOutputFlags - Flags to control the output of ancillary data along with video. */ + +typedef uint32_t BMDVideoOutputFlags; +enum _BMDVideoOutputFlags { + bmdVideoOutputFlagDefault = 0, + bmdVideoOutputVANC = 1 << 0, + bmdVideoOutputVITC = 1 << 1, + bmdVideoOutputRP188 = 1 << 2, + bmdVideoOutputDualStream3D = 1 << 4, + bmdVideoOutputSynchronizeToPlaybackGroup = 1 << 6 +}; + +/* Enum BMDSupportedVideoModeFlags - Flags to describe supported video modes */ + +typedef uint32_t BMDSupportedVideoModeFlags; +enum _BMDSupportedVideoModeFlags { + bmdSupportedVideoModeDefault = 0, + bmdSupportedVideoModeKeying = 1 << 0, + bmdSupportedVideoModeDualStream3D = 1 << 1, + bmdSupportedVideoModeSDISingleLink = 1 << 2, + bmdSupportedVideoModeSDIDualLink = 1 << 3, + bmdSupportedVideoModeSDIQuadLink = 1 << 4, + bmdSupportedVideoModeInAnyProfile = 1 << 5 +}; + +/* Enum BMDPacketType - Type of packet */ + +typedef uint32_t BMDPacketType; +enum _BMDPacketType { + bmdPacketTypeStreamInterruptedMarker = /* 'sint' */ 0x73696E74, // A packet of this type marks the time when a video stream was interrupted, for example by a disconnected cable + bmdPacketTypeStreamData = /* 'sdat' */ 0x73646174 // Regular stream data +}; + +/* Enum BMDFrameFlags - Frame flags */ + +typedef uint32_t BMDFrameFlags; +enum _BMDFrameFlags { + bmdFrameFlagDefault = 0, + bmdFrameFlagFlipVertical = 1 << 0, + bmdFrameContainsHDRMetadata = 1 << 1, + + /* Flags that are applicable only to instances of IDeckLinkVideoInputFrame */ + + bmdFrameCapturedAsPsF = 1 << 30, + bmdFrameHasNoInputSource = 1 << 31 +}; + +/* Enum BMDVideoInputFlags - Flags applicable to video input */ + +typedef uint32_t BMDVideoInputFlags; +enum _BMDVideoInputFlags { + bmdVideoInputFlagDefault = 0, + bmdVideoInputEnableFormatDetection = 1 << 0, + bmdVideoInputDualStream3D = 1 << 1, + bmdVideoInputSynchronizeToCaptureGroup = 1 << 2 +}; + +/* Enum BMDVideoInputFormatChangedEvents - Bitmask passed to the VideoInputFormatChanged notification to identify the properties of the input signal that have changed */ + +typedef uint32_t BMDVideoInputFormatChangedEvents; +enum _BMDVideoInputFormatChangedEvents { + bmdVideoInputDisplayModeChanged = 1 << 0, + bmdVideoInputFieldDominanceChanged = 1 << 1, + bmdVideoInputColorspaceChanged = 1 << 2 +}; + +/* Enum BMDDetectedVideoInputFormatFlags - Flags passed to the VideoInputFormatChanged notification to describe the detected video input signal */ + +typedef uint32_t BMDDetectedVideoInputFormatFlags; +enum _BMDDetectedVideoInputFormatFlags { + bmdDetectedVideoInputYCbCr422 = 1 << 0, + bmdDetectedVideoInputRGB444 = 1 << 1, + bmdDetectedVideoInputDualStream3D = 1 << 2, + bmdDetectedVideoInput12BitDepth = 1 << 3, + bmdDetectedVideoInput10BitDepth = 1 << 4, + bmdDetectedVideoInput8BitDepth = 1 << 5 +}; + +/* Enum BMDDeckLinkCapturePassthroughMode - Enumerates whether the video output is electrically connected to the video input or if the clean switching mode is enabled */ + +typedef uint32_t BMDDeckLinkCapturePassthroughMode; +enum _BMDDeckLinkCapturePassthroughMode { + bmdDeckLinkCapturePassthroughModeDisabled = /* 'pdis' */ 0x70646973, + bmdDeckLinkCapturePassthroughModeDirect = /* 'pdir' */ 0x70646972, + bmdDeckLinkCapturePassthroughModeCleanSwitch = /* 'pcln' */ 0x70636C6E +}; + +/* Enum BMDOutputFrameCompletionResult - Frame Completion Callback */ + +typedef uint32_t BMDOutputFrameCompletionResult; +enum _BMDOutputFrameCompletionResult { + bmdOutputFrameCompleted, + bmdOutputFrameDisplayedLate, + bmdOutputFrameDropped, + bmdOutputFrameFlushed +}; + +/* Enum BMDReferenceStatus - GenLock input status */ + +typedef uint32_t BMDReferenceStatus; +enum _BMDReferenceStatus { + bmdReferenceUnlocked = 0, + bmdReferenceNotSupportedByHardware = 1 << 0, + bmdReferenceLocked = 1 << 1 +}; + +/* Enum BMDAudioFormat - Audio Format */ + +typedef uint32_t BMDAudioFormat; +enum _BMDAudioFormat { + bmdAudioFormatPCM = /* 'lpcm' */ 0x6C70636D // Linear signed PCM samples +}; + +/* Enum BMDAudioSampleRate - Audio sample rates supported for output/input */ + +typedef uint32_t BMDAudioSampleRate; +enum _BMDAudioSampleRate { + bmdAudioSampleRate48kHz = 48000 +}; + +/* Enum BMDAudioSampleType - Audio sample sizes supported for output/input */ + +typedef uint32_t BMDAudioSampleType; +enum _BMDAudioSampleType { + bmdAudioSampleType16bitInteger = 16, + bmdAudioSampleType32bitInteger = 32 +}; + +/* Enum BMDAudioOutputStreamType - Audio output stream type */ + +typedef uint32_t BMDAudioOutputStreamType; +enum _BMDAudioOutputStreamType { + bmdAudioOutputStreamContinuous, + bmdAudioOutputStreamContinuousDontResample, + bmdAudioOutputStreamTimestamped +}; + +/* Enum BMDAncillaryPacketFormat - Ancillary packet format */ + +typedef uint32_t BMDAncillaryPacketFormat; +enum _BMDAncillaryPacketFormat { + bmdAncillaryPacketFormatUInt8 = /* 'ui08' */ 0x75693038, + bmdAncillaryPacketFormatUInt16 = /* 'ui16' */ 0x75693136, + bmdAncillaryPacketFormatYCbCr10 = /* 'v210' */ 0x76323130 +}; + +/* Enum BMDTimecodeFormat - Timecode formats for frame metadata */ + +typedef uint32_t BMDTimecodeFormat; +enum _BMDTimecodeFormat { + bmdTimecodeRP188VITC1 = /* 'rpv1' */ 0x72707631, // RP188 timecode where DBB1 equals VITC1 (line 9) + bmdTimecodeRP188VITC2 = /* 'rp12' */ 0x72703132, // RP188 timecode where DBB1 equals VITC2 (line 9 for progressive or line 571 for interlaced/PsF) + bmdTimecodeRP188LTC = /* 'rplt' */ 0x72706C74, // RP188 timecode where DBB1 equals LTC (line 10) + bmdTimecodeRP188HighFrameRate = /* 'rphr' */ 0x72706872, // RP188 timecode where DBB1 is an HFRTC (SMPTE ST 12-3), the only timecode allowing the frame value to go above 30 + bmdTimecodeRP188Any = /* 'rp18' */ 0x72703138, // Convenience for capture, returning the first valid timecode in {HFRTC (if supported), VITC1, VITC2, LTC } + bmdTimecodeVITC = /* 'vitc' */ 0x76697463, + bmdTimecodeVITCField2 = /* 'vit2' */ 0x76697432, + bmdTimecodeSerial = /* 'seri' */ 0x73657269 +}; + +/* Enum BMDAnalogVideoFlags - Analog video display flags */ + +typedef uint32_t BMDAnalogVideoFlags; +enum _BMDAnalogVideoFlags { + bmdAnalogVideoFlagCompositeSetup75 = 1 << 0, + bmdAnalogVideoFlagComponentBetacamLevels = 1 << 1 +}; + +/* Enum BMDAudioOutputAnalogAESSwitch - Audio output Analog/AESEBU switch */ + +typedef uint32_t BMDAudioOutputAnalogAESSwitch; +enum _BMDAudioOutputAnalogAESSwitch { + bmdAudioOutputSwitchAESEBU = /* 'aes ' */ 0x61657320, + bmdAudioOutputSwitchAnalog = /* 'anlg' */ 0x616E6C67 +}; + +/* Enum BMDVideoOutputConversionMode - Video/audio conversion mode */ + +typedef uint32_t BMDVideoOutputConversionMode; +enum _BMDVideoOutputConversionMode { + bmdNoVideoOutputConversion = /* 'none' */ 0x6E6F6E65, + bmdVideoOutputLetterboxDownconversion = /* 'ltbx' */ 0x6C746278, + bmdVideoOutputAnamorphicDownconversion = /* 'amph' */ 0x616D7068, + bmdVideoOutputHD720toHD1080Conversion = /* '720c' */ 0x37323063, + bmdVideoOutputHardwareLetterboxDownconversion = /* 'HWlb' */ 0x48576C62, + bmdVideoOutputHardwareAnamorphicDownconversion = /* 'HWam' */ 0x4857616D, + bmdVideoOutputHardwareCenterCutDownconversion = /* 'HWcc' */ 0x48576363, + bmdVideoOutputHardware720p1080pCrossconversion = /* 'xcap' */ 0x78636170, + bmdVideoOutputHardwareAnamorphic720pUpconversion = /* 'ua7p' */ 0x75613770, + bmdVideoOutputHardwareAnamorphic1080iUpconversion = /* 'ua1i' */ 0x75613169, + bmdVideoOutputHardwareAnamorphic149To720pUpconversion = /* 'u47p' */ 0x75343770, + bmdVideoOutputHardwareAnamorphic149To1080iUpconversion = /* 'u41i' */ 0x75343169, + bmdVideoOutputHardwarePillarbox720pUpconversion = /* 'up7p' */ 0x75703770, + bmdVideoOutputHardwarePillarbox1080iUpconversion = /* 'up1i' */ 0x75703169 +}; + +/* Enum BMDVideoInputConversionMode - Video input conversion mode */ + +typedef uint32_t BMDVideoInputConversionMode; +enum _BMDVideoInputConversionMode { + bmdNoVideoInputConversion = /* 'none' */ 0x6E6F6E65, + bmdVideoInputLetterboxDownconversionFromHD1080 = /* '10lb' */ 0x31306C62, + bmdVideoInputAnamorphicDownconversionFromHD1080 = /* '10am' */ 0x3130616D, + bmdVideoInputLetterboxDownconversionFromHD720 = /* '72lb' */ 0x37326C62, + bmdVideoInputAnamorphicDownconversionFromHD720 = /* '72am' */ 0x3732616D, + bmdVideoInputLetterboxUpconversion = /* 'lbup' */ 0x6C627570, + bmdVideoInputAnamorphicUpconversion = /* 'amup' */ 0x616D7570 +}; + +/* Enum BMDVideo3DPackingFormat - Video 3D packing format */ + +typedef uint32_t BMDVideo3DPackingFormat; +enum _BMDVideo3DPackingFormat { + bmdVideo3DPackingSidebySideHalf = /* 'sbsh' */ 0x73627368, + bmdVideo3DPackingLinebyLine = /* 'lbyl' */ 0x6C62796C, + bmdVideo3DPackingTopAndBottom = /* 'tabo' */ 0x7461626F, + bmdVideo3DPackingFramePacking = /* 'frpk' */ 0x6672706B, + bmdVideo3DPackingLeftOnly = /* 'left' */ 0x6C656674, + bmdVideo3DPackingRightOnly = /* 'righ' */ 0x72696768 +}; + +/* Enum BMDIdleVideoOutputOperation - Video output operation when not playing video */ + +typedef uint32_t BMDIdleVideoOutputOperation; +enum _BMDIdleVideoOutputOperation { + bmdIdleVideoOutputBlack = /* 'blac' */ 0x626C6163, + bmdIdleVideoOutputLastFrame = /* 'lafa' */ 0x6C616661 +}; + +/* Enum BMDVideoEncoderFrameCodingMode - Video frame coding mode */ + +typedef uint32_t BMDVideoEncoderFrameCodingMode; +enum _BMDVideoEncoderFrameCodingMode { + bmdVideoEncoderFrameCodingModeInter = /* 'inte' */ 0x696E7465, + bmdVideoEncoderFrameCodingModeIntra = /* 'intr' */ 0x696E7472 +}; + +/* Enum BMDDNxHRLevel - DNxHR Levels */ + +typedef uint32_t BMDDNxHRLevel; +enum _BMDDNxHRLevel { + bmdDNxHRLevelSQ = /* 'dnsq' */ 0x646E7371, + bmdDNxHRLevelLB = /* 'dnlb' */ 0x646E6C62, + bmdDNxHRLevelHQ = /* 'dnhq' */ 0x646E6871, + bmdDNxHRLevelHQX = /* 'dhqx' */ 0x64687178, + bmdDNxHRLevel444 = /* 'd444' */ 0x64343434 +}; + +/* Enum BMDLinkConfiguration - Video link configuration */ + +typedef uint32_t BMDLinkConfiguration; +enum _BMDLinkConfiguration { + bmdLinkConfigurationSingleLink = /* 'lcsl' */ 0x6C63736C, + bmdLinkConfigurationDualLink = /* 'lcdl' */ 0x6C63646C, + bmdLinkConfigurationQuadLink = /* 'lcql' */ 0x6C63716C +}; + +/* Enum BMDDeviceInterface - Device interface type */ + +typedef uint32_t BMDDeviceInterface; +enum _BMDDeviceInterface { + bmdDeviceInterfacePCI = /* 'pci ' */ 0x70636920, + bmdDeviceInterfaceUSB = /* 'usb ' */ 0x75736220, + bmdDeviceInterfaceThunderbolt = /* 'thun' */ 0x7468756E +}; + +/* Enum BMDColorspace - Colorspace */ + +typedef uint32_t BMDColorspace; +enum _BMDColorspace { + bmdColorspaceRec601 = /* 'r601' */ 0x72363031, + bmdColorspaceRec709 = /* 'r709' */ 0x72373039, + bmdColorspaceRec2020 = /* '2020' */ 0x32303230 +}; + +/* Enum BMDDynamicRange - SDR or HDR */ + +typedef uint32_t BMDDynamicRange; +enum _BMDDynamicRange { + bmdDynamicRangeSDR = 0, // Standard Dynamic Range in accordance with SMPTE ST 2036-1 + bmdDynamicRangeHDRStaticPQ = 1 << 29, // High Dynamic Range PQ in accordance with SMPTE ST 2084 + bmdDynamicRangeHDRStaticHLG = 1 << 30 // High Dynamic Range HLG in accordance with ITU-R BT.2100-0 +}; + +/* Enum BMDDeckLinkHDMIInputEDIDID - DeckLink HDMI Input EDID ID */ + +typedef uint32_t BMDDeckLinkHDMIInputEDIDID; +enum _BMDDeckLinkHDMIInputEDIDID { + + /* Integers */ + + bmdDeckLinkHDMIInputEDIDDynamicRange = /* 'HIDy' */ 0x48494479 // Parameter is of type BMDDynamicRange. Default is (bmdDynamicRangeSDR|bmdDynamicRangeHDRStaticPQ) +}; + +/* Enum BMDDeckLinkFrameMetadataID - DeckLink Frame Metadata ID */ + +typedef uint32_t BMDDeckLinkFrameMetadataID; +enum _BMDDeckLinkFrameMetadataID { + + /* Colorspace Metadata - Integers */ + + bmdDeckLinkFrameMetadataColorspace = /* 'cspc' */ 0x63737063, // Colorspace of video frame (see BMDColorspace) + + /* HDR Metadata - Integers */ + + bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc = /* 'eotf' */ 0x656F7466, // EOTF in range 0-7 as per CEA 861.3 + + /* HDR Metadata - Floats */ + + bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX = /* 'hdrx' */ 0x68647278, // Red display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY = /* 'hdry' */ 0x68647279, // Red display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX = /* 'hdgx' */ 0x68646778, // Green display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY = /* 'hdgy' */ 0x68646779, // Green display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX = /* 'hdbx' */ 0x68646278, // Blue display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY = /* 'hdby' */ 0x68646279, // Blue display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRWhitePointX = /* 'hdwx' */ 0x68647778, // White point in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRWhitePointY = /* 'hdwy' */ 0x68647779, // White point in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance = /* 'hdml' */ 0x68646D6C, // Max display mastering luminance in range 1 cd/m2 - 65535 cd/m2 + bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance = /* 'hmil' */ 0x686D696C, // Min display mastering luminance in range 0.0001 cd/m2 - 6.5535 cd/m2 + bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel = /* 'mcll' */ 0x6D636C6C, // Maximum Content Light Level in range 1 cd/m2 - 65535 cd/m2 + bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel = /* 'fall' */ 0x66616C6C // Maximum Frame Average Light Level in range 1 cd/m2 - 65535 cd/m2 +}; + +/* Enum BMDProfileID - Identifies a profile */ + +typedef uint32_t BMDProfileID; +enum _BMDProfileID { + bmdProfileOneSubDeviceFullDuplex = /* '1dfd' */ 0x31646664, + bmdProfileOneSubDeviceHalfDuplex = /* '1dhd' */ 0x31646864, + bmdProfileTwoSubDevicesFullDuplex = /* '2dfd' */ 0x32646664, + bmdProfileTwoSubDevicesHalfDuplex = /* '2dhd' */ 0x32646864, + bmdProfileFourSubDevicesHalfDuplex = /* '4dhd' */ 0x34646864 +}; + +/* Enum BMDHDMITimecodePacking - Packing form of timecode on HDMI */ + +typedef uint32_t BMDHDMITimecodePacking; +enum _BMDHDMITimecodePacking { + bmdHDMITimecodePackingIEEEOUI000085 = 0x00008500, + bmdHDMITimecodePackingIEEEOUI080046 = 0x08004601, + bmdHDMITimecodePackingIEEEOUI5CF9F0 = 0x5CF9F003 +}; + +/* Enum BMDInternalKeyingAncillaryDataSource - Source for VANC and timecode data when performing internal keying */ + +typedef uint32_t BMDInternalKeyingAncillaryDataSource; +enum _BMDInternalKeyingAncillaryDataSource { + bmdInternalKeyingUsesAncillaryDataFromInputSignal = /* 'ikai' */ 0x696B6169, + bmdInternalKeyingUsesAncillaryDataFromKeyFrame = /* 'ikak' */ 0x696B616B +}; + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkAttributeID; +enum _BMDDeckLinkAttributeID { + + /* Flags */ + + BMDDeckLinkSupportsInternalKeying = /* 'keyi' */ 0x6B657969, + BMDDeckLinkSupportsExternalKeying = /* 'keye' */ 0x6B657965, + BMDDeckLinkSupportsInputFormatDetection = /* 'infd' */ 0x696E6664, + BMDDeckLinkHasReferenceInput = /* 'hrin' */ 0x6872696E, + BMDDeckLinkHasSerialPort = /* 'hspt' */ 0x68737074, + BMDDeckLinkHasAnalogVideoOutputGain = /* 'avog' */ 0x61766F67, + BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain = /* 'ovog' */ 0x6F766F67, + BMDDeckLinkHasVideoInputAntiAliasingFilter = /* 'aafl' */ 0x6161666C, + BMDDeckLinkHasBypass = /* 'byps' */ 0x62797073, + BMDDeckLinkSupportsClockTimingAdjustment = /* 'ctad' */ 0x63746164, + BMDDeckLinkSupportsFullFrameReferenceInputTimingOffset = /* 'frin' */ 0x6672696E, + BMDDeckLinkSupportsSMPTELevelAOutput = /* 'lvla' */ 0x6C766C61, + BMDDeckLinkSupportsAutoSwitchingPPsFOnInput = /* 'apsf' */ 0x61707366, + BMDDeckLinkSupportsDualLinkSDI = /* 'sdls' */ 0x73646C73, + BMDDeckLinkSupportsQuadLinkSDI = /* 'sqls' */ 0x73716C73, + BMDDeckLinkSupportsIdleOutput = /* 'idou' */ 0x69646F75, + BMDDeckLinkVANCRequires10BitYUVVideoFrames = /* 'vioY' */ 0x76696F59, // Legacy product requires v210 active picture for IDeckLinkVideoFrameAncillaryPackets or 10-bit VANC + BMDDeckLinkHasLTCTimecodeInput = /* 'hltc' */ 0x686C7463, + BMDDeckLinkSupportsHDRMetadata = /* 'hdrm' */ 0x6864726D, + BMDDeckLinkSupportsColorspaceMetadata = /* 'cmet' */ 0x636D6574, + BMDDeckLinkSupportsHDMITimecode = /* 'htim' */ 0x6874696D, + BMDDeckLinkSupportsHighFrameRateTimecode = /* 'HFRT' */ 0x48465254, + BMDDeckLinkSupportsSynchronizeToCaptureGroup = /* 'stcg' */ 0x73746367, + BMDDeckLinkSupportsSynchronizeToPlaybackGroup = /* 'stpg' */ 0x73747067, + + /* Integers */ + + BMDDeckLinkMaximumAudioChannels = /* 'mach' */ 0x6D616368, + BMDDeckLinkMaximumAnalogAudioInputChannels = /* 'iach' */ 0x69616368, + BMDDeckLinkMaximumAnalogAudioOutputChannels = /* 'aach' */ 0x61616368, + BMDDeckLinkNumberOfSubDevices = /* 'nsbd' */ 0x6E736264, + BMDDeckLinkSubDeviceIndex = /* 'subi' */ 0x73756269, + BMDDeckLinkPersistentID = /* 'peid' */ 0x70656964, + BMDDeckLinkDeviceGroupID = /* 'dgid' */ 0x64676964, + BMDDeckLinkTopologicalID = /* 'toid' */ 0x746F6964, + BMDDeckLinkVideoOutputConnections = /* 'vocn' */ 0x766F636E, // Returns a BMDVideoConnection bit field + BMDDeckLinkVideoInputConnections = /* 'vicn' */ 0x7669636E, // Returns a BMDVideoConnection bit field + BMDDeckLinkAudioOutputConnections = /* 'aocn' */ 0x616F636E, // Returns a BMDAudioConnection bit field + BMDDeckLinkAudioInputConnections = /* 'aicn' */ 0x6169636E, // Returns a BMDAudioConnection bit field + BMDDeckLinkVideoIOSupport = /* 'vios' */ 0x76696F73, // Returns a BMDVideoIOSupport bit field + BMDDeckLinkDeckControlConnections = /* 'dccn' */ 0x6463636E, // Returns a BMDDeckControlConnection bit field + BMDDeckLinkDeviceInterface = /* 'dbus' */ 0x64627573, // Returns a BMDDeviceInterface + BMDDeckLinkAudioInputRCAChannelCount = /* 'airc' */ 0x61697263, + BMDDeckLinkAudioInputXLRChannelCount = /* 'aixc' */ 0x61697863, + BMDDeckLinkAudioOutputRCAChannelCount = /* 'aorc' */ 0x616F7263, + BMDDeckLinkAudioOutputXLRChannelCount = /* 'aoxc' */ 0x616F7863, + BMDDeckLinkProfileID = /* 'prid' */ 0x70726964, // Returns a BMDProfileID + BMDDeckLinkDuplex = /* 'dupx' */ 0x64757078, + BMDDeckLinkMinimumPrerollFrames = /* 'mprf' */ 0x6D707266, + BMDDeckLinkSupportedDynamicRange = /* 'sudr' */ 0x73756472, + + /* Floats */ + + BMDDeckLinkVideoInputGainMinimum = /* 'vigm' */ 0x7669676D, + BMDDeckLinkVideoInputGainMaximum = /* 'vigx' */ 0x76696778, + BMDDeckLinkVideoOutputGainMinimum = /* 'vogm' */ 0x766F676D, + BMDDeckLinkVideoOutputGainMaximum = /* 'vogx' */ 0x766F6778, + BMDDeckLinkMicrophoneInputGainMinimum = /* 'migm' */ 0x6D69676D, + BMDDeckLinkMicrophoneInputGainMaximum = /* 'migx' */ 0x6D696778, + + /* Strings */ + + BMDDeckLinkSerialPortDeviceName = /* 'slpn' */ 0x736C706E, + BMDDeckLinkVendorName = /* 'vndr' */ 0x766E6472, + BMDDeckLinkDisplayName = /* 'dspn' */ 0x6473706E, + BMDDeckLinkModelName = /* 'mdln' */ 0x6D646C6E, + BMDDeckLinkDeviceHandle = /* 'devh' */ 0x64657668 +}; + +/* Enum BMDDeckLinkAPIInformationID - DeckLinkAPI information ID */ + +typedef uint32_t BMDDeckLinkAPIInformationID; +enum _BMDDeckLinkAPIInformationID { + + /* Integer or String */ + + BMDDeckLinkAPIVersion = /* 'vers' */ 0x76657273 +}; + +/* Enum BMDDeckLinkStatusID - DeckLink Status ID */ + +typedef uint32_t BMDDeckLinkStatusID; +enum _BMDDeckLinkStatusID { + + /* Integers */ + + bmdDeckLinkStatusDetectedVideoInputMode = /* 'dvim' */ 0x6476696D, + bmdDeckLinkStatusDetectedVideoInputFormatFlags = /* 'dvff' */ 0x64766666, + bmdDeckLinkStatusDetectedVideoInputFieldDominance = /* 'dvfd' */ 0x64766664, + bmdDeckLinkStatusDetectedVideoInputColorspace = /* 'dscl' */ 0x6473636C, + bmdDeckLinkStatusDetectedVideoInputDynamicRange = /* 'dsdr' */ 0x64736472, + bmdDeckLinkStatusDetectedSDILinkConfiguration = /* 'dslc' */ 0x64736C63, + bmdDeckLinkStatusCurrentVideoInputMode = /* 'cvim' */ 0x6376696D, + bmdDeckLinkStatusCurrentVideoInputPixelFormat = /* 'cvip' */ 0x63766970, + bmdDeckLinkStatusCurrentVideoInputFlags = /* 'cvif' */ 0x63766966, + bmdDeckLinkStatusCurrentVideoOutputMode = /* 'cvom' */ 0x63766F6D, + bmdDeckLinkStatusCurrentVideoOutputFlags = /* 'cvof' */ 0x63766F66, + bmdDeckLinkStatusPCIExpressLinkWidth = /* 'pwid' */ 0x70776964, + bmdDeckLinkStatusPCIExpressLinkSpeed = /* 'plnk' */ 0x706C6E6B, + bmdDeckLinkStatusLastVideoOutputPixelFormat = /* 'opix' */ 0x6F706978, + bmdDeckLinkStatusReferenceSignalMode = /* 'refm' */ 0x7265666D, + bmdDeckLinkStatusReferenceSignalFlags = /* 'reff' */ 0x72656666, + bmdDeckLinkStatusBusy = /* 'busy' */ 0x62757379, + bmdDeckLinkStatusInterchangeablePanelType = /* 'icpt' */ 0x69637074, + bmdDeckLinkStatusDeviceTemperature = /* 'dtmp' */ 0x64746D70, + + /* Flags */ + + bmdDeckLinkStatusVideoInputSignalLocked = /* 'visl' */ 0x7669736C, + bmdDeckLinkStatusReferenceSignalLocked = /* 'refl' */ 0x7265666C, + + /* Bytes */ + + bmdDeckLinkStatusReceivedEDID = /* 'edid' */ 0x65646964 +}; + +/* Enum BMDDeckLinkVideoStatusFlags - */ + +typedef uint32_t BMDDeckLinkVideoStatusFlags; +enum _BMDDeckLinkVideoStatusFlags { + bmdDeckLinkVideoStatusPsF = 1 << 0, + bmdDeckLinkVideoStatusDualStream3D = 1 << 1 +}; + +/* Enum BMDDuplexMode - Duplex of the device */ + +typedef uint32_t BMDDuplexMode; +enum _BMDDuplexMode { + bmdDuplexFull = /* 'dxfu' */ 0x64786675, + bmdDuplexHalf = /* 'dxha' */ 0x64786861, + bmdDuplexSimplex = /* 'dxsp' */ 0x64787370, + bmdDuplexInactive = /* 'dxin' */ 0x6478696E +}; + +/* Enum BMDPanelType - The type of interchangeable panel */ + +typedef uint32_t BMDPanelType; +enum _BMDPanelType { + bmdPanelNotDetected = /* 'npnl' */ 0x6E706E6C, + bmdPanelTeranexMiniSmartPanel = /* 'tmsm' */ 0x746D736D +}; + +/* Enum BMDDeviceBusyState - Current device busy state */ + +typedef uint32_t BMDDeviceBusyState; +enum _BMDDeviceBusyState { + bmdDeviceCaptureBusy = 1 << 0, + bmdDevicePlaybackBusy = 1 << 1, + bmdDeviceSerialPortBusy = 1 << 2 +}; + +/* Enum BMDVideoIOSupport - Device video input/output support */ + +typedef uint32_t BMDVideoIOSupport; +enum _BMDVideoIOSupport { + bmdDeviceSupportsCapture = 1 << 0, + bmdDeviceSupportsPlayback = 1 << 1 +}; + +/* Enum BMD3DPreviewFormat - Linked Frame preview format */ + +typedef uint32_t BMD3DPreviewFormat; +enum _BMD3DPreviewFormat { + bmd3DPreviewFormatDefault = /* 'defa' */ 0x64656661, + bmd3DPreviewFormatLeftOnly = /* 'left' */ 0x6C656674, + bmd3DPreviewFormatRightOnly = /* 'righ' */ 0x72696768, + bmd3DPreviewFormatSideBySide = /* 'side' */ 0x73696465, + bmd3DPreviewFormatTopBottom = /* 'topb' */ 0x746F7062 +}; + +/* Enum BMDNotifications - Events that can be subscribed through IDeckLinkNotification */ + +typedef uint32_t BMDNotifications; +enum _BMDNotifications { + bmdPreferencesChanged = /* 'pref' */ 0x70726566, + bmdStatusChanged = /* 'stat' */ 0x73746174 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkVideoOutputCallback; +class IDeckLinkInputCallback; +class IDeckLinkEncoderInputCallback; +class IDeckLinkMemoryAllocator; +class IDeckLinkAudioOutputCallback; +class IDeckLinkIterator; +class IDeckLinkAPIInformation; +class IDeckLinkOutput; +class IDeckLinkInput; +class IDeckLinkHDMIInputEDID; +class IDeckLinkEncoderInput; +class IDeckLinkVideoFrame; +class IDeckLinkMutableVideoFrame; +class IDeckLinkVideoFrame3DExtensions; +class IDeckLinkVideoFrameMetadataExtensions; +class IDeckLinkVideoInputFrame; +class IDeckLinkAncillaryPacket; +class IDeckLinkAncillaryPacketIterator; +class IDeckLinkVideoFrameAncillaryPackets; +class IDeckLinkVideoFrameAncillary; +class IDeckLinkEncoderPacket; +class IDeckLinkEncoderVideoPacket; +class IDeckLinkEncoderAudioPacket; +class IDeckLinkH265NALPacket; +class IDeckLinkAudioInputPacket; +class IDeckLinkScreenPreviewCallback; +class IDeckLinkGLScreenPreviewHelper; +class IDeckLinkNotificationCallback; +class IDeckLinkNotification; +class IDeckLinkProfileAttributes; +class IDeckLinkProfileIterator; +class IDeckLinkProfile; +class IDeckLinkProfileCallback; +class IDeckLinkProfileManager; +class IDeckLinkStatus; +class IDeckLinkKeyer; +class IDeckLinkVideoConversion; +class IDeckLinkDeviceNotificationCallback; +class IDeckLinkDiscovery; + +/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */ + +class BMD_PUBLIC IDeckLinkVideoOutputCallback : public IUnknown +{ +public: + virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame* completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0; + virtual HRESULT ScheduledPlaybackHasStopped (void) = 0; + +protected: + virtual ~IDeckLinkVideoOutputCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkInputCallback : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderInputCallback - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkEncoderInputCallback : public IUnknown +{ +public: + virtual HRESULT VideoInputSignalChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoPacketArrived (/* in */ IDeckLinkEncoderVideoPacket* videoPacket) = 0; + virtual HRESULT AudioPacketArrived (/* in */ IDeckLinkEncoderAudioPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkEncoderInputCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkMemoryAllocator - Memory allocator for video frames. */ + +class BMD_PUBLIC IDeckLinkMemoryAllocator : public IUnknown +{ +public: + virtual HRESULT AllocateBuffer (/* in */ uint32_t bufferSize, /* out */ void** allocatedBuffer) = 0; + virtual HRESULT ReleaseBuffer (/* in */ void* buffer) = 0; + virtual HRESULT Commit (void) = 0; + virtual HRESULT Decommit (void) = 0; +}; + +/* Interface IDeckLinkAudioOutputCallback - Optional callback to allow audio samples to be pulled as required. */ + +class BMD_PUBLIC IDeckLinkAudioOutputCallback : public IUnknown +{ +public: + virtual HRESULT RenderAudioSamples (/* in */ bool preroll) = 0; +}; + +/* Interface IDeckLinkIterator - Enumerates installed DeckLink hardware */ + +class BMD_PUBLIC IDeckLinkIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLink** deckLinkInstance) = 0; +}; + +/* Interface IDeckLinkAPIInformation - DeckLinkAPI attribute interface */ + +class BMD_PUBLIC IDeckLinkAPIInformation : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ bool* value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ double* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ const char** value) = 0; + +protected: + virtual ~IDeckLinkAPIInformation () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkOutput : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoOutputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame** outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary** outBuffer) = 0; // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback* theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t* bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + virtual HRESULT WriteAudioSamplesSync (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t* bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback* theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue* actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool* active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* streamTime, /* out */ double* playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus* referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* frameCompletionTimestamp) = 0; + +protected: + virtual ~IDeckLinkOutput () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoInputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkHDMIInputEDID - Created by QueryInterface from IDeckLink. Releasing all references will restore EDID to default */ + +class BMD_PUBLIC IDeckLinkHDMIInputEDID : public IUnknown +{ +public: + virtual HRESULT SetInt (/* in */ BMDDeckLinkHDMIInputEDIDID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkHDMIInputEDIDID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT WriteToEDID (void) = 0; + +protected: + virtual ~IDeckLinkHDMIInputEDID () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderInput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkEncoderInput : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedCodec, /* in */ uint32_t requestedCodecProfile, /* in */ BMDSupportedVideoModeFlags flags, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailablePacketsCount (/* out */ uint32_t* availablePacketsCount) = 0; + virtual HRESULT SetMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioFormat audioFormat, /* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkEncoderInputCallback* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkEncoderInput () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */ + +class BMD_PUBLIC IDeckLinkVideoFrame : public IUnknown +{ +public: + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual long GetRowBytes (void) = 0; + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual BMDFrameFlags GetFlags (void) = 0; + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) = 0; + virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary** ancillary) = 0; // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + +protected: + virtual ~IDeckLinkVideoFrame () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */ + +class BMD_PUBLIC IDeckLinkMutableVideoFrame : public IDeckLinkVideoFrame +{ +public: + virtual HRESULT SetFlags (/* in */ BMDFrameFlags newFlags) = 0; + virtual HRESULT SetTimecode (/* in */ BMDTimecodeFormat format, /* in */ IDeckLinkTimecode* timecode) = 0; + virtual HRESULT SetTimecodeFromComponents (/* in */ BMDTimecodeFormat format, /* in */ uint8_t hours, /* in */ uint8_t minutes, /* in */ uint8_t seconds, /* in */ uint8_t frames, /* in */ BMDTimecodeFlags flags) = 0; + virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary* ancillary) = 0; + virtual HRESULT SetTimecodeUserBits (/* in */ BMDTimecodeFormat format, /* in */ BMDTimecodeUserBits userBits) = 0; + +protected: + virtual ~IDeckLinkMutableVideoFrame () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrame3DExtensions - Optional interface implemented on IDeckLinkVideoFrame to support 3D frames */ + +class BMD_PUBLIC IDeckLinkVideoFrame3DExtensions : public IUnknown +{ +public: + virtual BMDVideo3DPackingFormat Get3DPackingFormat (void) = 0; + virtual HRESULT GetFrameForRightEye (/* out */ IDeckLinkVideoFrame** rightEyeFrame) = 0; + +protected: + virtual ~IDeckLinkVideoFrame3DExtensions () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrameMetadataExtensions - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDR information */ + +class BMD_PUBLIC IDeckLinkVideoFrameMetadataExtensions : public IUnknown +{ +public: + virtual HRESULT GetInt (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ double* value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ bool* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ const char** value) = 0; + virtual HRESULT GetBytes (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ void* buffer /* optional */, /* in, out */ uint32_t* bufferSize) = 0; + +protected: + virtual ~IDeckLinkVideoFrameMetadataExtensions () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkVideoInputFrame : public IDeckLinkVideoFrame +{ +public: + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration) = 0; + +protected: + virtual ~IDeckLinkVideoInputFrame () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkAncillaryPacket - On output, user needs to implement this interface */ + +class BMD_PUBLIC IDeckLinkAncillaryPacket : public IUnknown +{ +public: + virtual HRESULT GetBytes (/* in */ BMDAncillaryPacketFormat format /* For output, only one format need be offered */, /* out */ const void** data /* Optional */, /* out */ uint32_t* size /* Optional */) = 0; + virtual uint8_t GetDID (void) = 0; + virtual uint8_t GetSDID (void) = 0; + virtual uint32_t GetLineNumber (void) = 0; // On output, zero is auto + virtual uint8_t GetDataStreamIndex (void) = 0; // Usually zero. Can only be 1 if non-SD and the first data stream is completely full + +protected: + virtual ~IDeckLinkAncillaryPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkAncillaryPacketIterator - Enumerates ancillary packets */ + +class BMD_PUBLIC IDeckLinkAncillaryPacketIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkAncillaryPacket** packet) = 0; + +protected: + virtual ~IDeckLinkAncillaryPacketIterator () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrameAncillaryPackets - Obtained through QueryInterface on an IDeckLinkVideoFrame object. */ + +class BMD_PUBLIC IDeckLinkVideoFrameAncillaryPackets : public IUnknown +{ +public: + virtual HRESULT GetPacketIterator (/* out */ IDeckLinkAncillaryPacketIterator** iterator) = 0; + virtual HRESULT GetFirstPacketByID (/* in */ uint8_t DID, /* in */ uint8_t SDID, /* out */ IDeckLinkAncillaryPacket** packet) = 0; + virtual HRESULT AttachPacket (/* in */ IDeckLinkAncillaryPacket* packet) = 0; // Implement IDeckLinkAncillaryPacket to output your own + virtual HRESULT DetachPacket (/* in */ IDeckLinkAncillaryPacket* packet) = 0; + virtual HRESULT DetachAllPackets (void) = 0; + +protected: + virtual ~IDeckLinkVideoFrameAncillaryPackets () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrameAncillary - Use of IDeckLinkVideoFrameAncillaryPackets is preferred. Obtained through QueryInterface on an IDeckLinkVideoFrame object. */ + +class BMD_PUBLIC IDeckLinkVideoFrameAncillary : public IUnknown +{ +public: + virtual HRESULT GetBufferForVerticalBlankingLine (/* in */ uint32_t lineNumber, /* out */ void** buffer) = 0; // Pixels/rowbytes is same as display mode, except for above HD where it's 1920 pixels for UHD modes and 2048 pixels for DCI modes + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual BMDDisplayMode GetDisplayMode (void) = 0; + +protected: + virtual ~IDeckLinkVideoFrameAncillary () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderPacket - Interface to encapsulate an encoded packet. */ + +class BMD_PUBLIC IDeckLinkEncoderPacket : public IUnknown +{ +public: + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual long GetSize (void) = 0; + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue* frameTime, /* in */ BMDTimeScale timeScale) = 0; + virtual BMDPacketType GetPacketType (void) = 0; + +protected: + virtual ~IDeckLinkEncoderPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderVideoPacket - Provided by the IDeckLinkEncoderInput video packet arrival callback. */ + +class BMD_PUBLIC IDeckLinkEncoderVideoPacket : public IDeckLinkEncoderPacket +{ +public: + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration) = 0; + virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) = 0; + +protected: + virtual ~IDeckLinkEncoderVideoPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderAudioPacket - Provided by the IDeckLinkEncoderInput audio packet arrival callback. */ + +class BMD_PUBLIC IDeckLinkEncoderAudioPacket : public IDeckLinkEncoderPacket +{ +public: + virtual BMDAudioFormat GetAudioFormat (void) = 0; + +protected: + virtual ~IDeckLinkEncoderAudioPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkH265NALPacket - Obtained through QueryInterface on an IDeckLinkEncoderVideoPacket object */ + +class BMD_PUBLIC IDeckLinkH265NALPacket : public IDeckLinkEncoderVideoPacket +{ +public: + virtual HRESULT GetUnitType (/* out */ uint8_t* unitType) = 0; + virtual HRESULT GetBytesNoPrefix (/* out */ void** buffer) = 0; + virtual long GetSizeNoPrefix (void) = 0; + +protected: + virtual ~IDeckLinkH265NALPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkAudioInputPacket - Provided by the IDeckLinkInput callback. */ + +class BMD_PUBLIC IDeckLinkAudioInputPacket : public IUnknown +{ +public: + virtual long GetSampleFrameCount (void) = 0; + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual HRESULT GetPacketTime (/* out */ BMDTimeValue* packetTime, /* in */ BMDTimeScale timeScale) = 0; + +protected: + virtual ~IDeckLinkAudioInputPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */ + +class BMD_PUBLIC IDeckLinkScreenPreviewCallback : public IUnknown +{ +public: + virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + +protected: + virtual ~IDeckLinkScreenPreviewCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance on platforms with native COM support or from CreateOpenGLScreenPreviewHelper/CreateOpenGL3ScreenPreviewHelper on other platforms. */ + +class BMD_PUBLIC IDeckLinkGLScreenPreviewHelper : public IUnknown +{ +public: + + /* Methods must be called with OpenGL context set */ + + virtual HRESULT InitializeGL (void) = 0; + virtual HRESULT PaintGL (void) = 0; + virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + virtual HRESULT Set3DPreviewFormat (/* in */ BMD3DPreviewFormat previewFormat) = 0; + +protected: + virtual ~IDeckLinkGLScreenPreviewHelper () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkNotificationCallback - DeckLink Notification Callback Interface */ + +class BMD_PUBLIC IDeckLinkNotificationCallback : public IUnknown +{ +public: + virtual HRESULT Notify (/* in */ BMDNotifications topic, /* in */ uint64_t param1, /* in */ uint64_t param2) = 0; +}; + +/* Interface IDeckLinkNotification - DeckLink Notification interface */ + +class BMD_PUBLIC IDeckLinkNotification : public IUnknown +{ +public: + virtual HRESULT Subscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback* theCallback) = 0; + virtual HRESULT Unsubscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback* theCallback) = 0; + +protected: + virtual ~IDeckLinkNotification () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileAttributes - Created by QueryInterface from an IDeckLinkProfile, or from IDeckLink. When queried from IDeckLink, interrogates the active profile */ + +class BMD_PUBLIC IDeckLinkProfileAttributes : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool* value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ const char** value) = 0; + +protected: + virtual ~IDeckLinkProfileAttributes () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileIterator - Enumerates IDeckLinkProfile interfaces */ + +class BMD_PUBLIC IDeckLinkProfileIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkProfile** profile) = 0; + +protected: + virtual ~IDeckLinkProfileIterator () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfile - Represents the active profile when queried from IDeckLink */ + +class BMD_PUBLIC IDeckLinkProfile : public IUnknown +{ +public: + virtual HRESULT GetDevice (/* out */ IDeckLink** device) = 0; // Device affected when this profile becomes active + virtual HRESULT IsActive (/* out */ bool* isActive) = 0; + virtual HRESULT SetActive (void) = 0; // Activating a profile will also change the profile on all devices enumerated by GetPeers. Activation is not complete until IDeckLinkProfileCallback::ProfileActivated is called + virtual HRESULT GetPeers (/* out */ IDeckLinkProfileIterator** profileIterator) = 0; // Profiles of other devices activated with this profile + +protected: + virtual ~IDeckLinkProfile () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileCallback - Receive notifications about profiles related to this device */ + +class BMD_PUBLIC IDeckLinkProfileCallback : public IUnknown +{ +public: + virtual HRESULT ProfileChanging (/* in */ IDeckLinkProfile* profileToBeActivated, /* in */ bool streamsWillBeForcedToStop) = 0; // Called before this device changes profile. User has an opportunity for teardown if streamsWillBeForcedToStop + virtual HRESULT ProfileActivated (/* in */ IDeckLinkProfile* activatedProfile) = 0; // Called after this device has been activated with a new profile + +protected: + virtual ~IDeckLinkProfileCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileManager - Created by QueryInterface from IDeckLink when a device has multiple optional profiles */ + +class BMD_PUBLIC IDeckLinkProfileManager : public IUnknown +{ +public: + virtual HRESULT GetProfiles (/* out */ IDeckLinkProfileIterator** profileIterator) = 0; // All available profiles for this device + virtual HRESULT GetProfile (/* in */ BMDProfileID profileID, /* out */ IDeckLinkProfile** profile) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkProfileCallback* callback) = 0; + +protected: + virtual ~IDeckLinkProfileManager () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkStatus - DeckLink Status interface */ + +class BMD_PUBLIC IDeckLinkStatus : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkStatusID statusID, /* out */ bool* value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkStatusID statusID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkStatusID statusID, /* out */ double* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkStatusID statusID, /* out */ const char** value) = 0; + virtual HRESULT GetBytes (/* in */ BMDDeckLinkStatusID statusID, /* out */ void* buffer, /* in, out */ uint32_t* bufferSize) = 0; + +protected: + virtual ~IDeckLinkStatus () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkKeyer - DeckLink Keyer interface */ + +class BMD_PUBLIC IDeckLinkKeyer : public IUnknown +{ +public: + virtual HRESULT Enable (/* in */ bool isExternal) = 0; + virtual HRESULT SetLevel (/* in */ uint8_t level) = 0; + virtual HRESULT RampUp (/* in */ uint32_t numberOfFrames) = 0; + virtual HRESULT RampDown (/* in */ uint32_t numberOfFrames) = 0; + virtual HRESULT Disable (void) = 0; + +protected: + virtual ~IDeckLinkKeyer () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance. */ + +class BMD_PUBLIC IDeckLinkVideoConversion : public IUnknown +{ +public: + virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame* srcFrame, /* in */ IDeckLinkVideoFrame* dstFrame) = 0; + +protected: + virtual ~IDeckLinkVideoConversion () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDeviceNotificationCallback - DeckLink device arrival/removal notification callbacks */ + +class BMD_PUBLIC IDeckLinkDeviceNotificationCallback : public IUnknown +{ +public: + virtual HRESULT DeckLinkDeviceArrived (/* in */ IDeckLink* deckLinkDevice) = 0; + virtual HRESULT DeckLinkDeviceRemoved (/* in */ IDeckLink* deckLinkDevice) = 0; + +protected: + virtual ~IDeckLinkDeviceNotificationCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDiscovery - DeckLink device discovery */ + +class BMD_PUBLIC IDeckLinkDiscovery : public IUnknown +{ +public: + virtual HRESULT InstallDeviceNotifications (/* in */ IDeckLinkDeviceNotificationCallback* deviceNotificationCallback) = 0; + virtual HRESULT UninstallDeviceNotifications (void) = 0; + +protected: + virtual ~IDeckLinkDiscovery () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + BMD_PUBLIC IDeckLinkIterator* CreateDeckLinkIteratorInstance(void); + BMD_PUBLIC IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance(void); + BMD_PUBLIC IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance(void); + BMD_PUBLIC IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper(void); + BMD_PUBLIC IDeckLinkGLScreenPreviewHelper* CreateOpenGL3ScreenPreviewHelper(void); // Requires OpenGL 3.2 support and provides improved performance and color handling + BMD_PUBLIC IDeckLinkVideoConversion* CreateVideoConversionInstance(void); + BMD_PUBLIC IDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance(void); // For use when creating a custom IDeckLinkVideoFrame without wrapping IDeckLinkOutput::CreateVideoFrame + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPI_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration.h new file mode 100644 index 0000000000..42e2441357 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration.h @@ -0,0 +1,269 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_H +#define BMD_DECKLINKAPICONFIGURATION_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration = /* 912F634B-2D4E-40A4-8AAB-8D80B73F1289 */ { 0x91,0x2F,0x63,0x4B,0x2D,0x4E,0x40,0xA4,0x8A,0xAB,0x8D,0x80,0xB7,0x3F,0x12,0x89 }; +BMD_CONST REFIID IID_IDeckLinkEncoderConfiguration = /* 138050E5-C60A-4552-BF3F-0F358049327E */ { 0x13,0x80,0x50,0xE5,0xC6,0x0A,0x45,0x52,0xBF,0x3F,0x0F,0x35,0x80,0x49,0x32,0x7E }; + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID; +enum _BMDDeckLinkConfigurationID { + + /* Serial port Flags */ + + bmdDeckLinkConfigSwapSerialRxTx = /* 'ssrt' */ 0x73737274, + + /* Video Input/Output Integers */ + + bmdDeckLinkConfigHDMI3DPackingFormat = /* '3dpf' */ 0x33647066, + bmdDeckLinkConfigBypass = /* 'byps' */ 0x62797073, + bmdDeckLinkConfigClockTimingAdjustment = /* 'ctad' */ 0x63746164, + + /* Audio Input/Output Flags */ + + bmdDeckLinkConfigAnalogAudioConsumerLevels = /* 'aacl' */ 0x6161636C, + bmdDeckLinkConfigSwapHDMICh3AndCh4OnInput = /* 'hi34' */ 0x68693334, + bmdDeckLinkConfigSwapHDMICh3AndCh4OnOutput = /* 'ho34' */ 0x686F3334, + + /* Video Output Flags */ + + bmdDeckLinkConfigFieldFlickerRemoval = /* 'fdfr' */ 0x66646672, + bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion = /* 'to59' */ 0x746F3539, + bmdDeckLinkConfig444SDIVideoOutput = /* '444o' */ 0x3434346F, + bmdDeckLinkConfigBlackVideoOutputDuringCapture = /* 'bvoc' */ 0x62766F63, + bmdDeckLinkConfigLowLatencyVideoOutput = /* 'llvo' */ 0x6C6C766F, + bmdDeckLinkConfigDownConversionOnAllAnalogOutput = /* 'caao' */ 0x6361616F, + bmdDeckLinkConfigSMPTELevelAOutput = /* 'smta' */ 0x736D7461, + bmdDeckLinkConfigRec2020Output = /* 'rec2' */ 0x72656332, // Ensure output is Rec.2020 colorspace + bmdDeckLinkConfigQuadLinkSDIVideoOutputSquareDivisionSplit = /* 'SDQS' */ 0x53445153, + bmdDeckLinkConfigOutput1080pAsPsF = /* 'pfpr' */ 0x70667072, + + /* Video Output Integers */ + + bmdDeckLinkConfigVideoOutputConnection = /* 'vocn' */ 0x766F636E, + bmdDeckLinkConfigVideoOutputConversionMode = /* 'vocm' */ 0x766F636D, + bmdDeckLinkConfigAnalogVideoOutputFlags = /* 'avof' */ 0x61766F66, + bmdDeckLinkConfigReferenceInputTimingOffset = /* 'glot' */ 0x676C6F74, + bmdDeckLinkConfigVideoOutputIdleOperation = /* 'voio' */ 0x766F696F, + bmdDeckLinkConfigDefaultVideoOutputMode = /* 'dvom' */ 0x64766F6D, + bmdDeckLinkConfigDefaultVideoOutputModeFlags = /* 'dvof' */ 0x64766F66, + bmdDeckLinkConfigSDIOutputLinkConfiguration = /* 'solc' */ 0x736F6C63, + bmdDeckLinkConfigHDMITimecodePacking = /* 'htpk' */ 0x6874706B, + bmdDeckLinkConfigPlaybackGroup = /* 'plgr' */ 0x706C6772, + + /* Video Output Floats */ + + bmdDeckLinkConfigVideoOutputComponentLumaGain = /* 'oclg' */ 0x6F636C67, + bmdDeckLinkConfigVideoOutputComponentChromaBlueGain = /* 'occb' */ 0x6F636362, + bmdDeckLinkConfigVideoOutputComponentChromaRedGain = /* 'occr' */ 0x6F636372, + bmdDeckLinkConfigVideoOutputCompositeLumaGain = /* 'oilg' */ 0x6F696C67, + bmdDeckLinkConfigVideoOutputCompositeChromaGain = /* 'oicg' */ 0x6F696367, + bmdDeckLinkConfigVideoOutputSVideoLumaGain = /* 'oslg' */ 0x6F736C67, + bmdDeckLinkConfigVideoOutputSVideoChromaGain = /* 'oscg' */ 0x6F736367, + + /* Video Input Flags */ + + bmdDeckLinkConfigVideoInputScanning = /* 'visc' */ 0x76697363, // Applicable to H264 Pro Recorder only + bmdDeckLinkConfigUseDedicatedLTCInput = /* 'dltc' */ 0x646C7463, // Use timecode from LTC input instead of SDI stream + bmdDeckLinkConfigSDIInput3DPayloadOverride = /* '3dds' */ 0x33646473, + bmdDeckLinkConfigCapture1080pAsPsF = /* 'cfpr' */ 0x63667072, + + /* Video Input Integers */ + + bmdDeckLinkConfigVideoInputConnection = /* 'vicn' */ 0x7669636E, + bmdDeckLinkConfigAnalogVideoInputFlags = /* 'avif' */ 0x61766966, + bmdDeckLinkConfigVideoInputConversionMode = /* 'vicm' */ 0x7669636D, + bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame = /* 'pdif' */ 0x70646966, + bmdDeckLinkConfigVANCSourceLine1Mapping = /* 'vsl1' */ 0x76736C31, + bmdDeckLinkConfigVANCSourceLine2Mapping = /* 'vsl2' */ 0x76736C32, + bmdDeckLinkConfigVANCSourceLine3Mapping = /* 'vsl3' */ 0x76736C33, + bmdDeckLinkConfigCapturePassThroughMode = /* 'cptm' */ 0x6370746D, + bmdDeckLinkConfigCaptureGroup = /* 'cpgr' */ 0x63706772, + + /* Video Input Floats */ + + bmdDeckLinkConfigVideoInputComponentLumaGain = /* 'iclg' */ 0x69636C67, + bmdDeckLinkConfigVideoInputComponentChromaBlueGain = /* 'iccb' */ 0x69636362, + bmdDeckLinkConfigVideoInputComponentChromaRedGain = /* 'iccr' */ 0x69636372, + bmdDeckLinkConfigVideoInputCompositeLumaGain = /* 'iilg' */ 0x69696C67, + bmdDeckLinkConfigVideoInputCompositeChromaGain = /* 'iicg' */ 0x69696367, + bmdDeckLinkConfigVideoInputSVideoLumaGain = /* 'islg' */ 0x69736C67, + bmdDeckLinkConfigVideoInputSVideoChromaGain = /* 'iscg' */ 0x69736367, + + /* Keying Integers */ + + bmdDeckLinkConfigInternalKeyingAncillaryDataSource = /* 'ikas' */ 0x696B6173, + + /* Audio Input Flags */ + + bmdDeckLinkConfigMicrophonePhantomPower = /* 'mphp' */ 0x6D706870, + + /* Audio Input Integers */ + + bmdDeckLinkConfigAudioInputConnection = /* 'aicn' */ 0x6169636E, + + /* Audio Input Floats */ + + bmdDeckLinkConfigAnalogAudioInputScaleChannel1 = /* 'ais1' */ 0x61697331, + bmdDeckLinkConfigAnalogAudioInputScaleChannel2 = /* 'ais2' */ 0x61697332, + bmdDeckLinkConfigAnalogAudioInputScaleChannel3 = /* 'ais3' */ 0x61697333, + bmdDeckLinkConfigAnalogAudioInputScaleChannel4 = /* 'ais4' */ 0x61697334, + bmdDeckLinkConfigDigitalAudioInputScale = /* 'dais' */ 0x64616973, + bmdDeckLinkConfigMicrophoneInputGain = /* 'micg' */ 0x6D696367, + + /* Audio Output Integers */ + + bmdDeckLinkConfigAudioOutputAESAnalogSwitch = /* 'aoaa' */ 0x616F6161, + + /* Audio Output Floats */ + + bmdDeckLinkConfigAnalogAudioOutputScaleChannel1 = /* 'aos1' */ 0x616F7331, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel2 = /* 'aos2' */ 0x616F7332, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel3 = /* 'aos3' */ 0x616F7333, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel4 = /* 'aos4' */ 0x616F7334, + bmdDeckLinkConfigDigitalAudioOutputScale = /* 'daos' */ 0x64616F73, + bmdDeckLinkConfigHeadphoneVolume = /* 'hvol' */ 0x68766F6C, + + /* Device Information Strings */ + + bmdDeckLinkConfigDeviceInformationLabel = /* 'dila' */ 0x64696C61, + bmdDeckLinkConfigDeviceInformationSerialNumber = /* 'disn' */ 0x6469736E, + bmdDeckLinkConfigDeviceInformationCompany = /* 'dico' */ 0x6469636F, + bmdDeckLinkConfigDeviceInformationPhone = /* 'diph' */ 0x64697068, + bmdDeckLinkConfigDeviceInformationEmail = /* 'diem' */ 0x6469656D, + bmdDeckLinkConfigDeviceInformationDate = /* 'dida' */ 0x64696461, + + /* Deck Control Integers */ + + bmdDeckLinkConfigDeckControlConnection = /* 'dcco' */ 0x6463636F +}; + +/* Enum BMDDeckLinkEncoderConfigurationID - DeckLink Encoder Configuration ID */ + +typedef uint32_t BMDDeckLinkEncoderConfigurationID; +enum _BMDDeckLinkEncoderConfigurationID { + + /* Video Encoder Integers */ + + bmdDeckLinkEncoderConfigPreferredBitDepth = /* 'epbr' */ 0x65706272, + bmdDeckLinkEncoderConfigFrameCodingMode = /* 'efcm' */ 0x6566636D, + + /* HEVC/H.265 Encoder Integers */ + + bmdDeckLinkEncoderConfigH265TargetBitrate = /* 'htbr' */ 0x68746272, + + /* DNxHR/DNxHD Compression ID */ + + bmdDeckLinkEncoderConfigDNxHRCompressionID = /* 'dcid' */ 0x64636964, + + /* DNxHR/DNxHD Level */ + + bmdDeckLinkEncoderConfigDNxHRLevel = /* 'dlev' */ 0x646C6576, + + /* Encoded Sample Decriptions */ + + bmdDeckLinkEncoderConfigMPEG4SampleDescription = /* 'stsE' */ 0x73747345, // Full MPEG4 sample description (aka SampleEntry of an 'stsd' atom-box). Useful for MediaFoundation, QuickTime, MKV and more + bmdDeckLinkEncoderConfigMPEG4CodecSpecificDesc = /* 'esds' */ 0x65736473 // Sample description extensions only (atom stream, each with size and fourCC header). Useful for AVFoundation, VideoToolbox, MKV and more +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkConfiguration; +class IDeckLinkEncoderConfiguration; + +/* Interface IDeckLinkConfiguration - DeckLink Configuration interface */ + +class BMD_PUBLIC IDeckLinkConfiguration : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool* value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double* value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char** value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderConfiguration - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */ + +class BMD_PUBLIC IDeckLinkEncoderConfiguration : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ bool* value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ double* value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ const char* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ const char** value) = 0; + virtual HRESULT GetBytes (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ void* buffer /* optional */, /* in, out */ uint32_t* bufferSize) = 0; + +protected: + virtual ~IDeckLinkEncoderConfiguration () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_11.h new file mode 100644 index 0000000000..9fe70ffca4 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_11.h @@ -0,0 +1,84 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_11_H +#define BMD_DECKLINKAPICONFIGURATION_v10_11_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_11 = /* EF90380B-4AE5-4346-9077-E288E149F129 */ {0xEF,0x90,0x38,0x0B,0x4A,0xE5,0x43,0x46,0x90,0x77,0xE2,0x88,0xE1,0x49,0xF1,0x29}; + +/* Enum BMDDeckLinkConfigurationID_v10_11 - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_11; +enum _BMDDeckLinkConfigurationID_v10_11 { + + /* Video Input/Output Integers */ + + bmdDeckLinkConfigDuplexMode_v10_11 = /* 'dupx' */ 0x64757078, +}; + +// Forward Declarations + +class IDeckLinkConfiguration_v10_11; + +/* Interface IDeckLinkConfiguration_v10_11 - DeckLink Configuration interface */ + +class BMD_PUBLIC IDeckLinkConfiguration_v10_11 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_11 () {} // call Release method to drop reference count +}; + + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_2.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_2.h new file mode 100644 index 0000000000..a75821923b --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_2.h @@ -0,0 +1,73 @@ +/* -LICENSE-START- +** Copyright (c) 2014 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_2_H +#define BMD_DECKLINKAPICONFIGURATION_v10_2_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_2 = /* C679A35B-610C-4D09-B748-1D0478100FC0 */ {0xC6,0x79,0xA3,0x5B,0x61,0x0C,0x4D,0x09,0xB7,0x48,0x1D,0x04,0x78,0x10,0x0F,0xC0}; + +// Forward Declarations + +class IDeckLinkConfiguration_v10_2; + +/* Interface IDeckLinkConfiguration_v10_2 - DeckLink Configuration interface */ + +class BMD_PUBLIC IDeckLinkConfiguration_v10_2 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_2 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_2_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_4.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_4.h new file mode 100644 index 0000000000..eabb917cc0 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_4.h @@ -0,0 +1,76 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_4_H +#define BMD_DECKLINKAPICONFIGURATION_v10_4_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_4 = /* 1E69FCF6-4203-4936-8076-2A9F4CFD50CB */ {0x1E,0x69,0xFC,0xF6,0x42,0x03,0x49,0x36,0x80,0x76,0x2A,0x9F,0x4C,0xFD,0x50,0xCB}; + + +// +// Forward Declarations + +class IDeckLinkConfiguration_v10_4; + +/* Interface IDeckLinkConfiguration_v10_4 - DeckLink Configuration interface */ + +class BMD_PUBLIC IDeckLinkConfiguration_v10_4 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_4 () {} // call Release method to drop reference count +}; + + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_5.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_5.h new file mode 100644 index 0000000000..fd8ef772e1 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_5.h @@ -0,0 +1,73 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_5_H +#define BMD_DECKLINKAPICONFIGURATION_v10_5_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkEncoderConfiguration_v10_5 = /* 67455668-0848-45DF-8D8E-350A77C9A028 */ {0x67,0x45,0x56,0x68,0x08,0x48,0x45,0xDF,0x8D,0x8E,0x35,0x0A,0x77,0xC9,0xA0,0x28}; + +// Forward Declarations + +class IDeckLinkEncoderConfiguration_v10_5; + +/* Interface IDeckLinkEncoderConfiguration_v10_5 - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */ + +class BMD_PUBLIC IDeckLinkEncoderConfiguration_v10_5 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ const char *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ const char **value) = 0; + virtual HRESULT GetDecoderConfigurationInfo (/* out */ void *buffer, /* in */ long bufferSize, /* out */ long *returnedSize) = 0; + +protected: + virtual ~IDeckLinkEncoderConfiguration_v10_5 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_5_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_9.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_9.h new file mode 100644 index 0000000000..84ad1d681b --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIConfiguration_v10_9.h @@ -0,0 +1,75 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_9_H +#define BMD_DECKLINKAPICONFIGURATION_v10_9_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_9 = /* CB71734A-FE37-4E8D-8E13-802133A1C3F2 */ {0xCB,0x71,0x73,0x4A,0xFE,0x37,0x4E,0x8D,0x8E,0x13,0x80,0x21,0x33,0xA1,0xC3,0xF2}; + +// +// Forward Declarations + +class IDeckLinkConfiguration_v10_9; + +/* Interface IDeckLinkConfiguration_v10_9 - DeckLink Configuration interface */ + +class BMD_PUBLIC IDeckLinkConfiguration_v10_9 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_9 () {} // call Release method to drop reference count +}; + + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_9_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDeckControl.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDeckControl.h new file mode 100644 index 0000000000..7ae9bd9798 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDeckControl.h @@ -0,0 +1,223 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIDECKCONTROL_H +#define BMD_DECKLINKAPIDECKCONTROL_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkDeckControlStatusCallback = /* 53436FFB-B434-4906-BADC-AE3060FFE8EF */ { 0x53,0x43,0x6F,0xFB,0xB4,0x34,0x49,0x06,0xBA,0xDC,0xAE,0x30,0x60,0xFF,0xE8,0xEF }; +BMD_CONST REFIID IID_IDeckLinkDeckControl = /* 8E1C3ACE-19C7-4E00-8B92-D80431D958BE */ { 0x8E,0x1C,0x3A,0xCE,0x19,0xC7,0x4E,0x00,0x8B,0x92,0xD8,0x04,0x31,0xD9,0x58,0xBE }; + +/* Enum BMDDeckControlMode - DeckControl mode */ + +typedef uint32_t BMDDeckControlMode; +enum _BMDDeckControlMode { + bmdDeckControlNotOpened = /* 'ntop' */ 0x6E746F70, + bmdDeckControlVTRControlMode = /* 'vtrc' */ 0x76747263, + bmdDeckControlExportMode = /* 'expm' */ 0x6578706D, + bmdDeckControlCaptureMode = /* 'capm' */ 0x6361706D +}; + +/* Enum BMDDeckControlEvent - DeckControl event */ + +typedef uint32_t BMDDeckControlEvent; +enum _BMDDeckControlEvent { + bmdDeckControlAbortedEvent = /* 'abte' */ 0x61627465, // This event is triggered when a capture or edit-to-tape operation is aborted. + + /* Export-To-Tape events */ + + bmdDeckControlPrepareForExportEvent = /* 'pfee' */ 0x70666565, // This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback should be called at this point. + bmdDeckControlExportCompleteEvent = /* 'exce' */ 0x65786365, // This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode. + + /* Capture events */ + + bmdDeckControlPrepareForCaptureEvent = /* 'pfce' */ 0x70666365, // This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid. + bmdDeckControlCaptureCompleteEvent = /* 'ccev' */ 0x63636576 // This event is triggered a few frames after reaching the out-point. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode. +}; + +/* Enum BMDDeckControlVTRControlState - VTR Control state */ + +typedef uint32_t BMDDeckControlVTRControlState; +enum _BMDDeckControlVTRControlState { + bmdDeckControlNotInVTRControlMode = /* 'nvcm' */ 0x6E76636D, + bmdDeckControlVTRControlPlaying = /* 'vtrp' */ 0x76747270, + bmdDeckControlVTRControlRecording = /* 'vtrr' */ 0x76747272, + bmdDeckControlVTRControlStill = /* 'vtra' */ 0x76747261, + bmdDeckControlVTRControlShuttleForward = /* 'vtsf' */ 0x76747366, + bmdDeckControlVTRControlShuttleReverse = /* 'vtsr' */ 0x76747372, + bmdDeckControlVTRControlJogForward = /* 'vtjf' */ 0x76746A66, + bmdDeckControlVTRControlJogReverse = /* 'vtjr' */ 0x76746A72, + bmdDeckControlVTRControlStopped = /* 'vtro' */ 0x7674726F +}; + +/* Enum BMDDeckControlStatusFlags - Deck Control status flags */ + +typedef uint32_t BMDDeckControlStatusFlags; +enum _BMDDeckControlStatusFlags { + bmdDeckControlStatusDeckConnected = 1 << 0, + bmdDeckControlStatusRemoteMode = 1 << 1, + bmdDeckControlStatusRecordInhibited = 1 << 2, + bmdDeckControlStatusCassetteOut = 1 << 3 +}; + +/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */ + +typedef uint32_t BMDDeckControlExportModeOpsFlags; +enum _BMDDeckControlExportModeOpsFlags { + bmdDeckControlExportModeInsertVideo = 1 << 0, + bmdDeckControlExportModeInsertAudio1 = 1 << 1, + bmdDeckControlExportModeInsertAudio2 = 1 << 2, + bmdDeckControlExportModeInsertAudio3 = 1 << 3, + bmdDeckControlExportModeInsertAudio4 = 1 << 4, + bmdDeckControlExportModeInsertAudio5 = 1 << 5, + bmdDeckControlExportModeInsertAudio6 = 1 << 6, + bmdDeckControlExportModeInsertAudio7 = 1 << 7, + bmdDeckControlExportModeInsertAudio8 = 1 << 8, + bmdDeckControlExportModeInsertAudio9 = 1 << 9, + bmdDeckControlExportModeInsertAudio10 = 1 << 10, + bmdDeckControlExportModeInsertAudio11 = 1 << 11, + bmdDeckControlExportModeInsertAudio12 = 1 << 12, + bmdDeckControlExportModeInsertTimeCode = 1 << 13, + bmdDeckControlExportModeInsertAssemble = 1 << 14, + bmdDeckControlExportModeInsertPreview = 1 << 15, + bmdDeckControlUseManualExport = 1 << 16 +}; + +/* Enum BMDDeckControlError - Deck Control error */ + +typedef uint32_t BMDDeckControlError; +enum _BMDDeckControlError { + bmdDeckControlNoError = /* 'noer' */ 0x6E6F6572, + bmdDeckControlModeError = /* 'moer' */ 0x6D6F6572, + bmdDeckControlMissedInPointError = /* 'mier' */ 0x6D696572, + bmdDeckControlDeckTimeoutError = /* 'dter' */ 0x64746572, + bmdDeckControlCommandFailedError = /* 'cfer' */ 0x63666572, + bmdDeckControlDeviceAlreadyOpenedError = /* 'dalo' */ 0x64616C6F, + bmdDeckControlFailedToOpenDeviceError = /* 'fder' */ 0x66646572, + bmdDeckControlInLocalModeError = /* 'lmer' */ 0x6C6D6572, + bmdDeckControlEndOfTapeError = /* 'eter' */ 0x65746572, + bmdDeckControlUserAbortError = /* 'uaer' */ 0x75616572, + bmdDeckControlNoTapeInDeckError = /* 'nter' */ 0x6E746572, + bmdDeckControlNoVideoFromCardError = /* 'nvfc' */ 0x6E766663, + bmdDeckControlNoCommunicationError = /* 'ncom' */ 0x6E636F6D, + bmdDeckControlBufferTooSmallError = /* 'btsm' */ 0x6274736D, + bmdDeckControlBadChecksumError = /* 'chks' */ 0x63686B73, + bmdDeckControlUnknownError = /* 'uner' */ 0x756E6572 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkDeckControlStatusCallback; +class IDeckLinkDeckControl; + +/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */ + +class BMD_PUBLIC IDeckLinkDeckControlStatusCallback : public IUnknown +{ +public: + virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0; + virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState newState, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0; + +protected: + virtual ~IDeckLinkDeckControlStatusCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDeckControl - Deck Control main interface */ + +class BMD_PUBLIC IDeckLinkDeckControl : public IUnknown +{ +public: + virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Close (/* in */ bool standbyOn) = 0; + virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode* mode, /* out */ BMDDeckControlVTRControlState* vtrControlState, /* out */ BMDDeckControlStatusFlags* flags) = 0; + virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0; + virtual HRESULT SendCommand (/* in */ uint8_t* inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t* outBuffer, /* out */ uint32_t* outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Play (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Stop (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Eject (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT StepForward (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT StepBack (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetTimecodeString (/* out */ const char** currentTimeCode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode** currentTimecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD* currentTimecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0; + virtual HRESULT GetPreroll (/* out */ uint32_t* prerollSeconds) = 0; + virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0; + virtual HRESULT GetExportOffset (/* out */ int32_t* exportOffsetFields) = 0; + virtual HRESULT GetManualExportOffset (/* out */ int32_t* deckManualExportOffsetFields) = 0; + virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0; + virtual HRESULT GetCaptureOffset (/* out */ int32_t* captureOffsetFields) = 0; + virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetDeviceID (/* out */ uint16_t* deviceId, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Abort (void) = 0; + virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback* callback) = 0; + +protected: + virtual ~IDeckLinkDeckControl () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPIDECKCONTROL_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDiscovery.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDiscovery.h new file mode 100644 index 0000000000..02bbca4ea4 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDiscovery.h @@ -0,0 +1,79 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIDISCOVERY_H +#define BMD_DECKLINKAPIDISCOVERY_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLink = /* C418FBDD-0587-48ED-8FE5-640F0A14AF91 */ { 0xC4,0x18,0xFB,0xDD,0x05,0x87,0x48,0xED,0x8F,0xE5,0x64,0x0F,0x0A,0x14,0xAF,0x91 }; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLink; + +/* Interface IDeckLink - Represents a DeckLink device */ + +class BMD_PUBLIC IDeckLink : public IUnknown +{ +public: + virtual HRESULT GetModelName (/* out */ const char** modelName) = 0; + virtual HRESULT GetDisplayName (/* out */ const char** displayName) = 0; + +protected: + virtual ~IDeckLink () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPIDISCOVERY_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch.cpp new file mode 100644 index 0000000000..fd57c2eeb2 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch.cpp @@ -0,0 +1,188 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +**/ + +#include +#include +#include + +#include "DeckLinkAPI.h" + +#define kDeckLinkAPI_Name "libDeckLinkAPI.so" +#define KDeckLinkPreviewAPI_Name "libDeckLinkPreviewAPI.so" + +typedef IDeckLinkIterator* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGL3ScreenPreviewHelperFunc)(void); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); +typedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void); +typedef IDeckLinkVideoFrameAncillaryPackets* (*CreateVideoFrameAncillaryPacketsInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static pthread_once_t gPreviewOnceControl = PTHREAD_ONCE_INIT; + +static bool gLoadedDeckLinkAPI = false; + +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateOpenGL3ScreenPreviewHelperFunc gCreateOpenGL3PreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; +static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc = NULL; +static CreateVideoFrameAncillaryPacketsInstanceFunc gCreateVideoFrameAncillaryPacketsFunc = NULL; + +static void InitDeckLinkAPI (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + + gLoadedDeckLinkAPI = true; + + gCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, "CreateDeckLinkIteratorInstance_0004"); + if (!gCreateIteratorFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, "CreateDeckLinkAPIInformationInstance_0001"); + if (!gCreateAPIInformationFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, "CreateVideoConversionInstance_0001"); + if (!gCreateVideoConversionFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)dlsym(libraryHandle, "CreateDeckLinkDiscoveryInstance_0003"); + if (!gCreateDeckLinkDiscoveryFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateVideoFrameAncillaryPacketsFunc = (CreateVideoFrameAncillaryPacketsInstanceFunc)dlsym(libraryHandle, "CreateVideoFrameAncillaryPacketsInstance_0001"); + if (!gCreateVideoFrameAncillaryPacketsFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +static void InitDeckLinkPreviewAPI (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, "CreateOpenGLScreenPreviewHelper_0001"); + if (!gCreateOpenGLPreviewFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateOpenGL3PreviewFunc = (CreateOpenGL3ScreenPreviewHelperFunc)dlsym(libraryHandle, "CreateOpenGL3ScreenPreviewHelper_0001"); + if (!gCreateOpenGL3PreviewFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +bool IsDeckLinkAPIPresent (void) +{ + // If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller + return gLoadedDeckLinkAPI; +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGL3ScreenPreviewHelper (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI); + + if (gCreateOpenGL3PreviewFunc == NULL) + return NULL; + return gCreateOpenGL3PreviewFunc(); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + return gCreateVideoConversionFunc(); +} + +IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateDeckLinkDiscoveryFunc == NULL) + return NULL; + return gCreateDeckLinkDiscoveryFunc(); +} + +IDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoFrameAncillaryPacketsFunc == NULL) + return NULL; + return gCreateVideoFrameAncillaryPacketsFunc(); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp new file mode 100644 index 0000000000..4ea27bb4a5 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp @@ -0,0 +1,173 @@ +/* -LICENSE-START- +** Copyright (c) 2019 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +**/ + +#include +#include +#include + +#include "DeckLinkAPI_v10_11.h" + +#define kDeckLinkAPI_Name "libDeckLinkAPI.so" +#define KDeckLinkPreviewAPI_Name "libDeckLinkPreviewAPI.so" + +typedef IDeckLinkIterator* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); +typedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void); +typedef IDeckLinkVideoFrameAncillaryPackets* (*CreateVideoFrameAncillaryPacketsInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static pthread_once_t gPreviewOnceControl = PTHREAD_ONCE_INIT; + +static bool gLoadedDeckLinkAPI = false; + +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; +static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc = NULL; +static CreateVideoFrameAncillaryPacketsInstanceFunc gCreateVideoFrameAncillaryPacketsFunc = NULL; + +static void InitDeckLinkAPI (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + + gLoadedDeckLinkAPI = true; + + gCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, "CreateDeckLinkIteratorInstance_0003"); + if (!gCreateIteratorFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, "CreateDeckLinkAPIInformationInstance_0001"); + if (!gCreateAPIInformationFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, "CreateVideoConversionInstance_0001"); + if (!gCreateVideoConversionFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)dlsym(libraryHandle, "CreateDeckLinkDiscoveryInstance_0002"); + if (!gCreateDeckLinkDiscoveryFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateVideoFrameAncillaryPacketsFunc = (CreateVideoFrameAncillaryPacketsInstanceFunc)dlsym(libraryHandle, "CreateVideoFrameAncillaryPacketsInstance_0001"); + if (!gCreateVideoFrameAncillaryPacketsFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +static void InitDeckLinkPreviewAPI (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, "CreateOpenGLScreenPreviewHelper_0001"); + if (!gCreateOpenGLPreviewFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +bool IsDeckLinkAPIPresent_v10_11 (void) +{ + // If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller + return gLoadedDeckLinkAPI; +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + return gCreateVideoConversionFunc(); +} + +IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateDeckLinkDiscoveryFunc == NULL) + return NULL; + return gCreateDeckLinkDiscoveryFunc(); +} + +IDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoFrameAncillaryPacketsFunc == NULL) + return NULL; + return gCreateVideoFrameAncillaryPacketsFunc(); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp new file mode 100644 index 0000000000..a1236fe560 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp @@ -0,0 +1,159 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +**/ + +#include +#include +#include + +#include "DeckLinkAPI.h" + +#define kDeckLinkAPI_Name "libDeckLinkAPI.so" +#define KDeckLinkPreviewAPI_Name "libDeckLinkPreviewAPI.so" + +typedef IDeckLinkIterator* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); +typedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static pthread_once_t gPreviewOnceControl = PTHREAD_ONCE_INIT; + +static bool gLoadedDeckLinkAPI = false; + +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; +static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc = NULL; + +static void InitDeckLinkAPI(void) +{ + void *libraryHandle; + + libraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW | RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + + gLoadedDeckLinkAPI = true; + + gCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, "CreateDeckLinkIteratorInstance_0002"); + if (!gCreateIteratorFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, "CreateDeckLinkAPIInformationInstance_0001"); + if (!gCreateAPIInformationFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, "CreateVideoConversionInstance_0001"); + if (!gCreateVideoConversionFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)dlsym(libraryHandle, "CreateDeckLinkDiscoveryInstance_0001"); + if (!gCreateDeckLinkDiscoveryFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +static void InitDeckLinkPreviewAPI(void) +{ + void *libraryHandle; + + libraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW | RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, "CreateOpenGLScreenPreviewHelper_0001"); + if (!gCreateOpenGLPreviewFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +bool IsDeckLinkAPIPresent(void) +{ + // If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller + return gLoadedDeckLinkAPI; +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + return gCreateVideoConversionFunc(); +} + +IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateDeckLinkDiscoveryFunc == NULL) + return NULL; + return gCreateDeckLinkDiscoveryFunc(); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp new file mode 100644 index 0000000000..a454fda8da --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp @@ -0,0 +1,122 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +**/ + +#include +#include +#include + +#include "DeckLinkAPI_v7_6.h" + +#define kDeckLinkAPI_Name "libDeckLinkAPI.so" +#define KDeckLinkPreviewAPI_Name "libDeckLinkPreviewAPI.so" + +typedef IDeckLinkIterator* (*CreateIteratorFunc_v7_6)(void); +typedef IDeckLinkGLScreenPreviewHelper_v7_6* (*CreateOpenGLScreenPreviewHelperFunc_v7_6)(void); +typedef IDeckLinkVideoConversion_v7_6* (*CreateVideoConversionInstanceFunc_v7_6)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static pthread_once_t gPreviewOnceControl = PTHREAD_ONCE_INIT; + +static CreateIteratorFunc_v7_6 gCreateIteratorFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc_v7_6 gCreateOpenGLPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc_v7_6 gCreateVideoConversionFunc = NULL; + +static void InitDeckLinkAPI_v7_6 (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + + gCreateIteratorFunc = (CreateIteratorFunc_v7_6)dlsym(libraryHandle, "CreateDeckLinkIteratorInstance"); + if (!gCreateIteratorFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc_v7_6)dlsym(libraryHandle, "CreateVideoConversionInstance"); + if (!gCreateVideoConversionFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +static void InitDeckLinkPreviewAPI_v7_6 (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc_v7_6)dlsym(libraryHandle, "CreateOpenGLScreenPreviewHelper"); + if (!gCreateOpenGLPreviewFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance_v7_6 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6); + + if (gCreateIteratorFunc == NULL) + return NULL; + return gCreateIteratorFunc(); +} + +IDeckLinkGLScreenPreviewHelper_v7_6* CreateOpenGLScreenPreviewHelper_v7_6 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6); + pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI_v7_6); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkVideoConversion_v7_6* CreateVideoConversionInstance_v7_6 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + return gCreateVideoConversionFunc(); +} + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp new file mode 100644 index 0000000000..22f2a71a0c --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp @@ -0,0 +1,146 @@ +/* -LICENSE-START- +** Copyright (c) 2011 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +**/ + +#include +#include +#include + +#include "DeckLinkAPI_v8_0.h" + +#define kDeckLinkAPI_Name "libDeckLinkAPI.so" +#define KDeckLinkPreviewAPI_Name "libDeckLinkPreviewAPI.so" + +typedef IDeckLinkIterator_v8_0* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static pthread_once_t gPreviewOnceControl = PTHREAD_ONCE_INIT; + +static bool gLoadedDeckLinkAPI = false; + +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; + +static void InitDeckLinkAPI (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + + gLoadedDeckLinkAPI = true; + + gCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, "CreateDeckLinkIteratorInstance_0001"); + if (!gCreateIteratorFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, "CreateDeckLinkAPIInformationInstance_0001"); + if (!gCreateAPIInformationFunc) + fprintf(stderr, "%s\n", dlerror()); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, "CreateVideoConversionInstance_0001"); + if (!gCreateVideoConversionFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +static void InitDeckLinkPreviewAPI (void) +{ + void *libraryHandle; + + libraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL); + if (!libraryHandle) + { + fprintf(stderr, "%s\n", dlerror()); + return; + } + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, "CreateOpenGLScreenPreviewHelper_0001"); + if (!gCreateOpenGLPreviewFunc) + fprintf(stderr, "%s\n", dlerror()); +} + +bool IsDeckLinkAPIPresent (void) +{ + // If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller + return gLoadedDeckLinkAPI; +} + +IDeckLinkIterator_v8_0* CreateDeckLinkIteratorInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + return gCreateVideoConversionFunc(); +} + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIModes.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIModes.h new file mode 100644 index 0000000000..0a54dca4cc --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIModes.h @@ -0,0 +1,289 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIMODES_H +#define BMD_DECKLINKAPIMODES_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkDisplayModeIterator = /* 9C88499F-F601-4021-B80B-032E4EB41C35 */ { 0x9C,0x88,0x49,0x9F,0xF6,0x01,0x40,0x21,0xB8,0x0B,0x03,0x2E,0x4E,0xB4,0x1C,0x35 }; +BMD_CONST REFIID IID_IDeckLinkDisplayMode = /* 3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78 */ { 0x3E,0xB2,0xC1,0xAB,0x0A,0x3D,0x45,0x23,0xA3,0xAD,0xF4,0x0D,0x7F,0xB1,0x4E,0x78 }; + +/* Enum BMDDisplayMode - BMDDisplayMode enumerates the video modes supported. */ + +typedef uint32_t BMDDisplayMode; +enum _BMDDisplayMode { + + /* SD Modes */ + + bmdModeNTSC = /* 'ntsc' */ 0x6E747363, + bmdModeNTSC2398 = /* 'nt23' */ 0x6E743233, // 3:2 pulldown + bmdModePAL = /* 'pal ' */ 0x70616C20, + bmdModeNTSCp = /* 'ntsp' */ 0x6E747370, + bmdModePALp = /* 'palp' */ 0x70616C70, + + /* HD 1080 Modes */ + + bmdModeHD1080p2398 = /* '23ps' */ 0x32337073, + bmdModeHD1080p24 = /* '24ps' */ 0x32347073, + bmdModeHD1080p25 = /* 'Hp25' */ 0x48703235, + bmdModeHD1080p2997 = /* 'Hp29' */ 0x48703239, + bmdModeHD1080p30 = /* 'Hp30' */ 0x48703330, + bmdModeHD1080p4795 = /* 'Hp47' */ 0x48703437, + bmdModeHD1080p48 = /* 'Hp48' */ 0x48703438, + bmdModeHD1080p50 = /* 'Hp50' */ 0x48703530, + bmdModeHD1080p5994 = /* 'Hp59' */ 0x48703539, + bmdModeHD1080p6000 = /* 'Hp60' */ 0x48703630, // N.B. This _really_ is 60.00 Hz. + bmdModeHD1080p9590 = /* 'Hp95' */ 0x48703935, + bmdModeHD1080p96 = /* 'Hp96' */ 0x48703936, + bmdModeHD1080p100 = /* 'Hp10' */ 0x48703130, + bmdModeHD1080p11988 = /* 'Hp11' */ 0x48703131, + bmdModeHD1080p120 = /* 'Hp12' */ 0x48703132, + bmdModeHD1080i50 = /* 'Hi50' */ 0x48693530, + bmdModeHD1080i5994 = /* 'Hi59' */ 0x48693539, + bmdModeHD1080i6000 = /* 'Hi60' */ 0x48693630, // N.B. This _really_ is 60.00 Hz. + + /* HD 720 Modes */ + + bmdModeHD720p50 = /* 'hp50' */ 0x68703530, + bmdModeHD720p5994 = /* 'hp59' */ 0x68703539, + bmdModeHD720p60 = /* 'hp60' */ 0x68703630, + + /* 2K Modes */ + + bmdMode2k2398 = /* '2k23' */ 0x326B3233, + bmdMode2k24 = /* '2k24' */ 0x326B3234, + bmdMode2k25 = /* '2k25' */ 0x326B3235, + + /* 2K DCI Modes */ + + bmdMode2kDCI2398 = /* '2d23' */ 0x32643233, + bmdMode2kDCI24 = /* '2d24' */ 0x32643234, + bmdMode2kDCI25 = /* '2d25' */ 0x32643235, + bmdMode2kDCI2997 = /* '2d29' */ 0x32643239, + bmdMode2kDCI30 = /* '2d30' */ 0x32643330, + bmdMode2kDCI4795 = /* '2d47' */ 0x32643437, + bmdMode2kDCI48 = /* '2d48' */ 0x32643438, + bmdMode2kDCI50 = /* '2d50' */ 0x32643530, + bmdMode2kDCI5994 = /* '2d59' */ 0x32643539, + bmdMode2kDCI60 = /* '2d60' */ 0x32643630, + bmdMode2kDCI9590 = /* '2d95' */ 0x32643935, + bmdMode2kDCI96 = /* '2d96' */ 0x32643936, + bmdMode2kDCI100 = /* '2d10' */ 0x32643130, + bmdMode2kDCI11988 = /* '2d11' */ 0x32643131, + bmdMode2kDCI120 = /* '2d12' */ 0x32643132, + + /* 4K UHD Modes */ + + bmdMode4K2160p2398 = /* '4k23' */ 0x346B3233, + bmdMode4K2160p24 = /* '4k24' */ 0x346B3234, + bmdMode4K2160p25 = /* '4k25' */ 0x346B3235, + bmdMode4K2160p2997 = /* '4k29' */ 0x346B3239, + bmdMode4K2160p30 = /* '4k30' */ 0x346B3330, + bmdMode4K2160p4795 = /* '4k47' */ 0x346B3437, + bmdMode4K2160p48 = /* '4k48' */ 0x346B3438, + bmdMode4K2160p50 = /* '4k50' */ 0x346B3530, + bmdMode4K2160p5994 = /* '4k59' */ 0x346B3539, + bmdMode4K2160p60 = /* '4k60' */ 0x346B3630, + bmdMode4K2160p9590 = /* '4k95' */ 0x346B3935, + bmdMode4K2160p96 = /* '4k96' */ 0x346B3936, + bmdMode4K2160p100 = /* '4k10' */ 0x346B3130, + bmdMode4K2160p11988 = /* '4k11' */ 0x346B3131, + bmdMode4K2160p120 = /* '4k12' */ 0x346B3132, + + /* 4K DCI Modes */ + + bmdMode4kDCI2398 = /* '4d23' */ 0x34643233, + bmdMode4kDCI24 = /* '4d24' */ 0x34643234, + bmdMode4kDCI25 = /* '4d25' */ 0x34643235, + bmdMode4kDCI2997 = /* '4d29' */ 0x34643239, + bmdMode4kDCI30 = /* '4d30' */ 0x34643330, + bmdMode4kDCI4795 = /* '4d47' */ 0x34643437, + bmdMode4kDCI48 = /* '4d48' */ 0x34643438, + bmdMode4kDCI50 = /* '4d50' */ 0x34643530, + bmdMode4kDCI5994 = /* '4d59' */ 0x34643539, + bmdMode4kDCI60 = /* '4d60' */ 0x34643630, + bmdMode4kDCI9590 = /* '4d95' */ 0x34643935, + bmdMode4kDCI96 = /* '4d96' */ 0x34643936, + bmdMode4kDCI100 = /* '4d10' */ 0x34643130, + bmdMode4kDCI11988 = /* '4d11' */ 0x34643131, + bmdMode4kDCI120 = /* '4d12' */ 0x34643132, + + /* 8K UHD Modes */ + + bmdMode8K4320p2398 = /* '8k23' */ 0x386B3233, + bmdMode8K4320p24 = /* '8k24' */ 0x386B3234, + bmdMode8K4320p25 = /* '8k25' */ 0x386B3235, + bmdMode8K4320p2997 = /* '8k29' */ 0x386B3239, + bmdMode8K4320p30 = /* '8k30' */ 0x386B3330, + bmdMode8K4320p4795 = /* '8k47' */ 0x386B3437, + bmdMode8K4320p48 = /* '8k48' */ 0x386B3438, + bmdMode8K4320p50 = /* '8k50' */ 0x386B3530, + bmdMode8K4320p5994 = /* '8k59' */ 0x386B3539, + bmdMode8K4320p60 = /* '8k60' */ 0x386B3630, + + /* 8K DCI Modes */ + + bmdMode8kDCI2398 = /* '8d23' */ 0x38643233, + bmdMode8kDCI24 = /* '8d24' */ 0x38643234, + bmdMode8kDCI25 = /* '8d25' */ 0x38643235, + bmdMode8kDCI2997 = /* '8d29' */ 0x38643239, + bmdMode8kDCI30 = /* '8d30' */ 0x38643330, + bmdMode8kDCI4795 = /* '8d47' */ 0x38643437, + bmdMode8kDCI48 = /* '8d48' */ 0x38643438, + bmdMode8kDCI50 = /* '8d50' */ 0x38643530, + bmdMode8kDCI5994 = /* '8d59' */ 0x38643539, + bmdMode8kDCI60 = /* '8d60' */ 0x38643630, + + /* PC Modes */ + + bmdMode640x480p60 = /* 'vga6' */ 0x76676136, + bmdMode800x600p60 = /* 'svg6' */ 0x73766736, + bmdMode1440x900p50 = /* 'wxg5' */ 0x77786735, + bmdMode1440x900p60 = /* 'wxg6' */ 0x77786736, + bmdMode1440x1080p50 = /* 'sxg5' */ 0x73786735, + bmdMode1440x1080p60 = /* 'sxg6' */ 0x73786736, + bmdMode1600x1200p50 = /* 'uxg5' */ 0x75786735, + bmdMode1600x1200p60 = /* 'uxg6' */ 0x75786736, + bmdMode1920x1200p50 = /* 'wux5' */ 0x77757835, + bmdMode1920x1200p60 = /* 'wux6' */ 0x77757836, + bmdMode1920x1440p50 = /* '1945' */ 0x31393435, + bmdMode1920x1440p60 = /* '1946' */ 0x31393436, + bmdMode2560x1440p50 = /* 'wqh5' */ 0x77716835, + bmdMode2560x1440p60 = /* 'wqh6' */ 0x77716836, + bmdMode2560x1600p50 = /* 'wqx5' */ 0x77717835, + bmdMode2560x1600p60 = /* 'wqx6' */ 0x77717836, + + /* Special Modes */ + + bmdModeUnknown = /* 'iunk' */ 0x69756E6B +}; + +/* Enum BMDFieldDominance - BMDFieldDominance enumerates settings applicable to video fields. */ + +typedef uint32_t BMDFieldDominance; +enum _BMDFieldDominance { + bmdUnknownFieldDominance = 0, + bmdLowerFieldFirst = /* 'lowr' */ 0x6C6F7772, + bmdUpperFieldFirst = /* 'uppr' */ 0x75707072, + bmdProgressiveFrame = /* 'prog' */ 0x70726F67, + bmdProgressiveSegmentedFrame = /* 'psf ' */ 0x70736620 +}; + +/* Enum BMDPixelFormat - Video pixel formats supported for output/input */ + +typedef uint32_t BMDPixelFormat; +enum _BMDPixelFormat { + bmdFormatUnspecified = 0, + bmdFormat8BitYUV = /* '2vuy' */ 0x32767579, + bmdFormat10BitYUV = /* 'v210' */ 0x76323130, + bmdFormat8BitARGB = 32, + bmdFormat8BitBGRA = /* 'BGRA' */ 0x42475241, + bmdFormat10BitRGB = /* 'r210' */ 0x72323130, // Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10 + bmdFormat12BitRGB = /* 'R12B' */ 0x52313242, // Big-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component + bmdFormat12BitRGBLE = /* 'R12L' */ 0x5231324C, // Little-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component + bmdFormat10BitRGBXLE = /* 'R10l' */ 0x5231306C, // Little-endian 10-bit RGB with SMPTE video levels (64-940) + bmdFormat10BitRGBX = /* 'R10b' */ 0x52313062, // Big-endian 10-bit RGB with SMPTE video levels (64-940) + bmdFormatH265 = /* 'hev1' */ 0x68657631, // High Efficiency Video Coding (HEVC/h.265) + + /* AVID DNxHR */ + + bmdFormatDNxHR = /* 'AVdh' */ 0x41566468 +}; + +/* Enum BMDDisplayModeFlags - Flags to describe the characteristics of an IDeckLinkDisplayMode. */ + +typedef uint32_t BMDDisplayModeFlags; +enum _BMDDisplayModeFlags { + bmdDisplayModeSupports3D = 1 << 0, + bmdDisplayModeColorspaceRec601 = 1 << 1, + bmdDisplayModeColorspaceRec709 = 1 << 2, + bmdDisplayModeColorspaceRec2020 = 1 << 3 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkDisplayModeIterator; +class IDeckLinkDisplayMode; + +/* Interface IDeckLinkDisplayModeIterator - Enumerates over supported input/output display modes. */ + +class BMD_PUBLIC IDeckLinkDisplayModeIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkDisplayMode** deckLinkDisplayMode) = 0; + +protected: + virtual ~IDeckLinkDisplayModeIterator () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDisplayMode - Represents a display mode */ + +class BMD_PUBLIC IDeckLinkDisplayMode : public IUnknown +{ +public: + virtual HRESULT GetName (/* out */ const char** name) = 0; + virtual BMDDisplayMode GetDisplayMode (void) = 0; + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual HRESULT GetFrameRate (/* out */ BMDTimeValue* frameDuration, /* out */ BMDTimeScale* timeScale) = 0; + virtual BMDFieldDominance GetFieldDominance (void) = 0; + virtual BMDDisplayModeFlags GetFlags (void) = 0; + +protected: + virtual ~IDeckLinkDisplayMode () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPIMODES_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPITypes.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPITypes.h new file mode 100644 index 0000000000..893c3c92e4 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPITypes.h @@ -0,0 +1,132 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPITYPES_H +#define BMD_DECKLINKAPITYPES_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + +typedef int64_t BMDTimeValue; +typedef int64_t BMDTimeScale; +typedef uint32_t BMDTimecodeBCD; +typedef uint32_t BMDTimecodeUserBits; + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkTimecode = /* BC6CFBD3-8317-4325-AC1C-1216391E9340 */ { 0xBC,0x6C,0xFB,0xD3,0x83,0x17,0x43,0x25,0xAC,0x1C,0x12,0x16,0x39,0x1E,0x93,0x40 }; + +/* Enum BMDTimecodeFlags - Timecode flags */ + +typedef uint32_t BMDTimecodeFlags; +enum _BMDTimecodeFlags { + bmdTimecodeFlagDefault = 0, + bmdTimecodeIsDropFrame = 1 << 0, + bmdTimecodeFieldMark = 1 << 1, + bmdTimecodeColorFrame = 1 << 2, + bmdTimecodeEmbedRecordingTrigger = 1 << 3, // On SDI recording trigger utilises a user-bit. + bmdTimecodeRecordingTriggered = 1 << 4 +}; + +/* Enum BMDVideoConnection - Video connection types */ + +typedef uint32_t BMDVideoConnection; +enum _BMDVideoConnection { + bmdVideoConnectionUnspecified = 0, + bmdVideoConnectionSDI = 1 << 0, + bmdVideoConnectionHDMI = 1 << 1, + bmdVideoConnectionOpticalSDI = 1 << 2, + bmdVideoConnectionComponent = 1 << 3, + bmdVideoConnectionComposite = 1 << 4, + bmdVideoConnectionSVideo = 1 << 5 +}; + +/* Enum BMDAudioConnection - Audio connection types */ + +typedef uint32_t BMDAudioConnection; +enum _BMDAudioConnection { + bmdAudioConnectionEmbedded = 1 << 0, + bmdAudioConnectionAESEBU = 1 << 1, + bmdAudioConnectionAnalog = 1 << 2, + bmdAudioConnectionAnalogXLR = 1 << 3, + bmdAudioConnectionAnalogRCA = 1 << 4, + bmdAudioConnectionMicrophone = 1 << 5, + bmdAudioConnectionHeadphones = 1 << 6 +}; + +/* Enum BMDDeckControlConnection - Deck control connections */ + +typedef uint32_t BMDDeckControlConnection; +enum _BMDDeckControlConnection { + bmdDeckControlConnectionRS422Remote1 = 1 << 0, + bmdDeckControlConnectionRS422Remote2 = 1 << 1 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkTimecode; + +/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */ + +class BMD_PUBLIC IDeckLinkTimecode : public IUnknown +{ +public: + virtual BMDTimecodeBCD GetBCD (void) = 0; + virtual HRESULT GetComponents (/* out */ uint8_t* hours, /* out */ uint8_t* minutes, /* out */ uint8_t* seconds, /* out */ uint8_t* frames) = 0; + virtual HRESULT GetString (/* out */ const char** timecode) = 0; + virtual BMDTimecodeFlags GetFlags (void) = 0; + virtual HRESULT GetTimecodeUserBits (/* out */ BMDTimecodeUserBits* userBits) = 0; + +protected: + virtual ~IDeckLinkTimecode () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPITYPES_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVersion.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVersion.h new file mode 100644 index 0000000000..679ef92584 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVersion.h @@ -0,0 +1,50 @@ +/* -LICENSE-START- + * ** Copyright (c) 2014 Blackmagic Design + * ** + * ** Permission is hereby granted, free of charge, to any person or organization + * ** obtaining a copy of the software and accompanying documentation (the + * ** "Software") to use, reproduce, display, distribute, sub-license, execute, + * ** and transmit the Software, and to prepare derivative works of the Software, + * ** and to permit third-parties to whom the Software is furnished to do so, in + * ** accordance with: + * ** + * ** (1) if the Software is obtained from Blackmagic Design, the End User License + * ** Agreement for the Software Development Kit (“EULA”) available at + * ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + * ** + * ** (2) if the Software is obtained from any third party, such licensing terms + * ** as notified by that third party, + * ** + * ** and all subject to the following: + * ** + * ** (3) the copyright notices in the Software and this entire statement, + * ** including the above license grant, this restriction and the following + * ** disclaimer, must be included in all copies of the Software, in whole or in + * ** part, and all derivative works of the Software, unless such copies or + * ** derivative works are solely in the form of machine-executable object code + * ** generated by a source language processor. + * ** + * ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * ** DEALINGS IN THE SOFTWARE. + * ** + * ** A copy of the Software is available free of charge at + * ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + * ** + * ** -LICENSE-END- + * */ + +/* DeckLinkAPIVersion.h */ + +#ifndef __DeckLink_API_Version_h__ +#define __DeckLink_API_Version_h__ + +#define BLACKMAGIC_DECKLINK_API_VERSION 0x0c040200 +#define BLACKMAGIC_DECKLINK_API_VERSION_STRING "12.4.2" + +#endif // __DeckLink_API_Version_h__ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoEncoderInput_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoEncoderInput_v10_11.h new file mode 100644 index 0000000000..590a485588 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoEncoderInput_v10_11.h @@ -0,0 +1,87 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H +#define BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// Type Declarations +BMD_CONST REFIID IID_IDeckLinkEncoderInput_v10_11 = /* 270587DA-6B7D-42E7-A1F0-6D853F581185 */ {0x27,0x05,0x87,0xDA,0x6B,0x7D,0x42,0xE7,0xA1,0xF0,0x6D,0x85,0x3F,0x58,0x11,0x85}; + +/* Interface IDeckLinkEncoderInput_v10_11 - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkEncoderInput_v10_11 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailablePacketsCount (/* out */ uint32_t *availablePacketsCount) = 0; + virtual HRESULT SetMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioFormat audioFormat, /* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkEncoderInputCallback *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkEncoderInput_v10_11 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v10_11.h new file mode 100644 index 0000000000..c4c3d70ef8 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v10_11.h @@ -0,0 +1,90 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOINPUT_v10_11_H +#define BMD_DECKLINKAPIVIDEOINPUT_v10_11_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" +#include "DeckLinkAPIVideoInput_v11_5_1.h" + +// Type Declarations +BMD_CONST REFIID IID_IDeckLinkInput_v10_11 = /* AF22762B-DFAC-4846-AA79-FA8883560995 */ {0xAF,0x22,0x76,0x2B,0xDF,0xAC,0x48,0x46,0xAA,0x79,0xFA,0x88,0x83,0x56,0x09,0x95}; + +/* Interface IDeckLinkInput_v10_11 - DeckLink input interface. */ + +class IDeckLinkInput_v10_11 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v10_11 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_4.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_4.h new file mode 100644 index 0000000000..ade2250676 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_4.h @@ -0,0 +1,89 @@ +/* -LICENSE-START- +** Copyright (c) 2019 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOINPUT_v11_4_H +#define BMD_DECKLINKAPIVIDEOINPUT_v11_4_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPIVideoInput_v11_5_1.h" + +// Type Declarations +BMD_CONST REFIID IID_IDeckLinkInput_v11_4 = /* 2A88CF76-F494-4216-A7EF-DC74EEB83882 */ { 0x2A,0x88,0xCF,0x76,0xF4,0x94,0x42,0x16,0xA7,0xEF,0xDC,0x74,0xEE,0xB8,0x38,0x82 }; + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput_v11_4 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDSupportedVideoModeFlags flags, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v11_4 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v11_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_5_1.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_5_1.h new file mode 100644 index 0000000000..51fb5172ac --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoInput_v11_5_1.h @@ -0,0 +1,102 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H +#define BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +BMD_CONST REFIID IID_IDeckLinkInputCallback_v11_5_1 = /* DD04E5EC-7415-42AB-AE4A-E80C4DFC044A */ { 0xDD, 0x04, 0xE5, 0xEC, 0x74, 0x15, 0x42, 0xAB, 0xAE, 0x4A, 0xE8, 0x0C, 0x4D, 0xFC, 0x04, 0x4A }; +BMD_CONST REFIID IID_IDeckLinkInput_v11_5_1 = /* 9434C6E4-B15D-4B1C-979E-661E3DDCB4B9 */ { 0x94, 0x34, 0xC6, 0xE4, 0xB1, 0x5D, 0x4B, 0x1C, 0x97, 0x9E, 0x66, 0x1E, 0x3D, 0xDC, 0xB4, 0xB9 }; + +/* Interface IDeckLinkInputCallback_v11_5_1 - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkInputCallback_v11_5_1 : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback_v11_5_1 () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkInput_v11_5_1 - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput_v11_5_1 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoInputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v11_5_1 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v10_11.h new file mode 100644 index 0000000000..21d3d150d3 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v10_11.h @@ -0,0 +1,107 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H +#define BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// Type Declarations +BMD_CONST REFIID IID_IDeckLinkOutput_v10_11 = /* CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564 */ {0xCC,0x5C,0x8A,0x6E,0x3F,0x2F,0x4B,0x3A,0x87,0xEA,0xFD,0x78,0xAF,0x30,0x05,0x64}; + +/* Interface IDeckLinkOutput_v10_11 - DeckLink output interface. */ + +class IDeckLinkOutput_v10_11 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *frameCompletionTimestamp) = 0; + +protected: + virtual ~IDeckLinkOutput_v10_11 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v11_4.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v11_4.h new file mode 100644 index 0000000000..ba4b01f9ac --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIVideoOutput_v11_4.h @@ -0,0 +1,100 @@ +/* -LICENSE-START- +** Copyright (c) 2019 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H +#define BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H + +#include "DeckLinkAPI.h" + +// Type Declarations +BMD_CONST REFIID IID_IDeckLinkOutput_v11_4 = /* 065A0F6C-C508-4D0D-B919-F5EB0EBFC96B */ { 0x06,0x5A,0x0F,0x6C,0xC5,0x08,0x4D,0x0D,0xB9,0x19,0xF5,0xEB,0x0E,0xBF,0xC9,0x6B }; + +/* Interface IDeckLinkOutput_v11_4 - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkOutput_v11_4 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame** outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary** outBuffer) = 0; // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback* theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t* bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + virtual HRESULT WriteAudioSamplesSync (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t* bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback* theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue* actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool* active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* streamTime, /* out */ double* playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus* referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* frameCompletionTimestamp) = 0; + +protected: + virtual ~IDeckLinkOutput_v11_4 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_11.h new file mode 100644 index 0000000000..26d5117187 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_11.h @@ -0,0 +1,134 @@ +/* -LICENSE-START- +** Copyright (c) 2018 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_11_H +#define BMD_DECKLINKAPI_v10_11_H + +#include "DeckLinkAPI.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkAttributes_v10_11 = /* ABC11843-D966-44CB-96E2-A1CB5D3135C4 */ {0xAB,0xC1,0x18,0x43,0xD9,0x66,0x44,0xCB,0x96,0xE2,0xA1,0xCB,0x5D,0x31,0x35,0xC4}; +BMD_CONST REFIID IID_IDeckLinkNotification_v10_11 = /* 0A1FB207-E215-441B-9B19-6FA1575946C5 */ {0x0A,0x1F,0xB2,0x07,0xE2,0x15,0x44,0x1B,0x9B,0x19,0x6F,0xA1,0x57,0x59,0x46,0xC5}; + +/* Enum BMDDisplayModeSupport_v10_11 - Output mode supported flags */ + +typedef uint32_t BMDDisplayModeSupport_v10_11; +enum _BMDDisplayModeSupport_v10_11 { + bmdDisplayModeNotSupported_v10_11 = 0, + bmdDisplayModeSupported_v10_11, + bmdDisplayModeSupportedWithConversion_v10_11 +}; + +/* Enum BMDDuplexMode_v10_11 - Duplex for configurable ports */ + +typedef uint32_t BMDDuplexMode_v10_11; +enum _BMDDuplexMode_v10_11 { + bmdDuplexModeFull_v10_11 = /* 'fdup' */ 0x66647570, + bmdDuplexModeHalf_v10_11 = /* 'hdup' */ 0x68647570 +}; + +/* Enum BMDDeckLinkAttributeID_v10_11 - DeckLink Attribute ID */ + +enum _BMDDeckLinkAttributeID_v10_11 { + + /* Flags */ + + BMDDeckLinkSupportsDuplexModeConfiguration_v10_11 = 'dupx', + BMDDeckLinkSupportsHDKeying_v10_11 = 'keyh', + + /* Integers */ + + BMDDeckLinkPairedDevicePersistentID_v10_11 = 'ppid', + BMDDeckLinkSupportsFullDuplex_v10_11 = 'fdup', +}; + +enum _BMDDeckLinkStatusID_v10_11 { + bmdDeckLinkStatusDuplexMode_v10_11 = 'dupx', +}; + +typedef uint32_t BMDDuplexStatus_v10_11; +enum _BMDDuplexStatus_v10_11 { + bmdDuplexFullDuplex_v10_11 = 'fdup', + bmdDuplexHalfDuplex_v10_11 = 'hdup', + bmdDuplexSimplex_v10_11 = 'splx', + bmdDuplexInactive_v10_11 = 'inac', +}; + +#if defined(__cplusplus) + +/* Interface IDeckLinkAttributes_v10_11 - DeckLink Attribute interface */ + +class BMD_PUBLIC IDeckLinkAttributes_v10_11 : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool *value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ const char **value) = 0; + +protected: + virtual ~IDeckLinkAttributes_v10_11 () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkNotification_v10_11 - DeckLink Notification interface */ + +class BMD_PUBLIC IDeckLinkNotification_v10_11 : public IUnknown +{ +public: + virtual HRESULT Subscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0; + virtual HRESULT Unsubscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0; +}; + +/* Functions */ + +extern "C" { + + BMD_PUBLIC IDeckLinkIterator* CreateDeckLinkIteratorInstance_v10_11 (void); + BMD_PUBLIC IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance_v10_11 (void); + BMD_PUBLIC IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance_v10_11 (void); + BMD_PUBLIC IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper_v10_11 (void); + BMD_PUBLIC IDeckLinkVideoConversion* CreateVideoConversionInstance_v10_11 (void); + BMD_PUBLIC IDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance_v10_11 (void); // For use when creating a custom IDeckLinkVideoFrame without wrapping IDeckLinkOutput::CreateVideoFrame + +} + +#endif // defined(__cplusplus) +#endif /* defined(BMD_DECKLINKAPI_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_2.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_2.h new file mode 100644 index 0000000000..d1633a01e8 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_2.h @@ -0,0 +1,68 @@ +/* -LICENSE-START- +** Copyright (c) 2014 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_2_H +#define BMD_DECKLINKAPI_v10_2_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_2; +enum _BMDDeckLinkConfigurationID_v10_2 { + /* Video output flags */ + + bmdDeckLinkConfig3GBpsVideoOutput_v10_2 = '3gbs', +}; + +/* Enum BMDAudioConnection_v10_2 - Audio connection types */ + +typedef uint32_t BMDAudioConnection_v10_2; +enum _BMDAudioConnection_v10_2 { + bmdAudioConnectionEmbedded_v10_2 = /* 'embd' */ 0x656D6264, + bmdAudioConnectionAESEBU_v10_2 = /* 'aes ' */ 0x61657320, + bmdAudioConnectionAnalog_v10_2 = /* 'anlg' */ 0x616E6C67, + bmdAudioConnectionAnalogXLR_v10_2 = /* 'axlr' */ 0x61786C72, + bmdAudioConnectionAnalogRCA_v10_2 = /* 'arca' */ 0x61726361 +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_2_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_4.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_4.h new file mode 100644 index 0000000000..fa5892dd0a --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_4.h @@ -0,0 +1,58 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_4_H +#define BMD_DECKLINKAPI_v10_4_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_4; +enum _BMDDeckLinkConfigurationID_v10_4 { + + /* Video output flags */ + + bmdDeckLinkConfigSingleLinkVideoOutput_v10_4 = /* 'sglo' */ 0x73676C6F, +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_5.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_5.h new file mode 100644 index 0000000000..40ce330f09 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_5.h @@ -0,0 +1,59 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_5_H +#define BMD_DECKLINKAPI_v10_5_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkAttributeID_v10_5; +enum _BMDDeckLinkAttributeID_v10_5 { + + /* Integers */ + + BMDDeckLinkDeviceBusyState_v10_5 = /* 'dbst' */ 0x64627374, +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_5_H) */ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_6.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_6.h new file mode 100644 index 0000000000..2bc306c6b7 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_6.h @@ -0,0 +1,63 @@ +/* -LICENSE-START- +** Copyright (c) 2016 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_6_H +#define BMD_DECKLINKAPI_v10_6_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkAttributeID_c10_6; +enum _BMDDeckLinkAttributeID_v10_6 { + + /* Flags */ + + BMDDeckLinkSupportsDesktopDisplay_v10_6 = /* 'extd' */ 0x65787464, +}; + +typedef uint32_t BMDIdleVideoOutputOperation_v10_6; +enum _BMDIdleVideoOutputOperation_v10_6 { + bmdIdleVideoOutputDesktop_v10_6 = /* 'desk' */ 0x6465736B +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_6_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_9.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_9.h new file mode 100644 index 0000000000..8b6b4b208f --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v10_9.h @@ -0,0 +1,58 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_9_H +#define BMD_DECKLINKAPI_v10_9_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_9; +enum _BMDDeckLinkConfigurationID_v10_9 { + + /* Flags */ + + bmdDeckLinkConfig1080pNotPsF_v10_9 = 'fpro', +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_9_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5.h new file mode 100644 index 0000000000..30578e5df1 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5.h @@ -0,0 +1,113 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v11_5_H +#define BMD_DECKLINKAPI_v11_5_H + +#include "DeckLinkAPI.h" + +BMD_CONST REFIID IID_IDeckLinkVideoFrameMetadataExtensions_v11_5 = /* D5973DC9-6432-46D0-8F0B-2496F8A1238F */ {0xD5,0x97,0x3D,0xC9,0x64,0x32,0x46,0xD0,0x8F,0x0B,0x24,0x96,0xF8,0xA1,0x23,0x8F}; + +/* Enum BMDDeckLinkFrameMetadataID - DeckLink Frame Metadata ID */ + +typedef uint32_t BMDDeckLinkFrameMetadataID_v11_5; +enum _BMDDeckLinkFrameMetadataID_v11_5 { + bmdDeckLinkFrameMetadataCintelFilmType_v11_5 = /* 'cfty' */ 0x63667479, // Current film type + bmdDeckLinkFrameMetadataCintelFilmGauge_v11_5 = /* 'cfga' */ 0x63666761, // Current film gauge + bmdDeckLinkFrameMetadataCintelKeykodeLow_v11_5 = /* 'ckkl' */ 0x636B6B6C, // Raw keykode value - low 64 bits + bmdDeckLinkFrameMetadataCintelKeykodeHigh_v11_5 = /* 'ckkh' */ 0x636B6B68, // Raw keykode value - high 64 bits + bmdDeckLinkFrameMetadataCintelTile1Size_v11_5 = /* 'ct1s' */ 0x63743173, // Size in bytes of compressed raw tile 1 + bmdDeckLinkFrameMetadataCintelTile2Size_v11_5 = /* 'ct2s' */ 0x63743273, // Size in bytes of compressed raw tile 2 + bmdDeckLinkFrameMetadataCintelTile3Size_v11_5 = /* 'ct3s' */ 0x63743373, // Size in bytes of compressed raw tile 3 + bmdDeckLinkFrameMetadataCintelTile4Size_v11_5 = /* 'ct4s' */ 0x63743473, // Size in bytes of compressed raw tile 4 + bmdDeckLinkFrameMetadataCintelImageWidth_v11_5 = /* 'IWPx' */ 0x49575078, // Width in pixels of image + bmdDeckLinkFrameMetadataCintelImageHeight_v11_5 = /* 'IHPx' */ 0x49485078, // Height in pixels of image + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInRed_v11_5 = /* 'mrir' */ 0x6D726972, // Red in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInRed_v11_5 = /* 'mgir' */ 0x6D676972, // Green in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInRed_v11_5 = /* 'mbir' */ 0x6D626972, // Blue in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInGreen_v11_5 = /* 'mrig' */ 0x6D726967, // Red in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInGreen_v11_5 = /* 'mgig' */ 0x6D676967, // Green in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInGreen_v11_5 = /* 'mbig' */ 0x6D626967, // Blue in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInBlue_v11_5 = /* 'mrib' */ 0x6D726962, // Red in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInBlue_v11_5 = /* 'mgib' */ 0x6D676962, // Green in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInBlue_v11_5 = /* 'mbib' */ 0x6D626962, // Blue in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInRed_v11_5 = /* 'mlrr' */ 0x6D6C7272, // Red in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInRed_v11_5 = /* 'mlgr' */ 0x6D6C6772, // Green in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInRed_v11_5 = /* 'mlbr' */ 0x6D6C6272, // Blue in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInGreen_v11_5 = /* 'mlrg' */ 0x6D6C7267, // Red in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInGreen_v11_5 = /* 'mlgg' */ 0x6D6C6767, // Green in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInGreen_v11_5 = /* 'mlbg' */ 0x6D6C6267, // Blue in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInBlue_v11_5 = /* 'mlrb' */ 0x6D6C7262, // Red in blue log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInBlue_v11_5 = /* 'mlgb' */ 0x6D6C6762, // Green in blue log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInBlue_v11_5 = /* 'mlbb' */ 0x6D6C6262, // Blue in blue log masking parameter + bmdDeckLinkFrameMetadataCintelFilmFrameRate_v11_5 = /* 'cffr' */ 0x63666672, // Film frame rate + bmdDeckLinkFrameMetadataCintelOffsetToApplyHorizontal_v11_5 = /* 'otah' */ 0x6F746168, // Horizontal offset (pixels) to be applied to image + bmdDeckLinkFrameMetadataCintelOffsetToApplyVertical_v11_5 = /* 'otav' */ 0x6F746176, // Vertical offset (pixels) to be applied to image + bmdDeckLinkFrameMetadataCintelGainRed_v11_5 = /* 'LfRd' */ 0x4C665264, // Red gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelGainGreen_v11_5 = /* 'LfGr' */ 0x4C664772, // Green gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelGainBlue_v11_5 = /* 'LfBl' */ 0x4C66426C, // Blue gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelLiftRed_v11_5 = /* 'GnRd' */ 0x476E5264, // Red lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelLiftGreen_v11_5 = /* 'GnGr' */ 0x476E4772, // Green lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelLiftBlue_v11_5 = /* 'GnBl' */ 0x476E426C, // Blue lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelHDRGainRed_v11_5 = /* 'HGRd' */ 0x48475264, // Red gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintelHDRGainGreen_v11_5 = /* 'HGGr' */ 0x48474772, // Green gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintelHDRGainBlue_v11_5 = /* 'HGBl' */ 0x4847426C, // Blue gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintel16mmCropRequired_v11_5 = /* 'c16c' */ 0x63313663, // The image should be cropped to 16mm size + bmdDeckLinkFrameMetadataCintelInversionRequired_v11_5 = /* 'cinv' */ 0x63696E76, // The image should be colour inverted + bmdDeckLinkFrameMetadataCintelFlipRequired_v11_5 = /* 'cflr' */ 0x63666C72, // The image should be flipped horizontally + bmdDeckLinkFrameMetadataCintelFocusAssistEnabled_v11_5 = /* 'cfae' */ 0x63666165, // Focus Assist is currently enabled + bmdDeckLinkFrameMetadataCintelKeykodeIsInterpolated_v11_5 = /* 'kkii' */ 0x6B6B6969 // The keykode for this frame is interpolated from nearby keykodes +}; + +/* Interface IDeckLinkVideoFrameMetadataExtensions - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDMI HDR information */ + +class BMD_PUBLIC IDeckLinkVideoFrameMetadataExtensions_v11_5 : public IUnknown +{ +public: + virtual HRESULT GetInt (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ int64_t *value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ double *value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ bool* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ const char **value) = 0; + +protected: + virtual ~IDeckLinkVideoFrameMetadataExtensions_v11_5 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPI_v11_5_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5_1.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5_1.h new file mode 100644 index 0000000000..42bc74fcc2 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v11_5_1.h @@ -0,0 +1,57 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v11_5_1_H +#define BMD_DECKLINKAPI_v11_5_1_H + +#include "DeckLinkAPI.h" + +/* Enum BMDDeckLinkStatusID - DeckLink Status ID */ + +typedef uint32_t BMDDeckLinkStatusID_v11_5_1; +enum _BMDDeckLinkStatusID_v11_5_1 { + + /* Video output flags */ + + bmdDeckLinkStatusDetectedVideoInputFlags_v11_5_1 = /* 'dvif' */ 0x64766966, + +}; + +#endif /* defined(BMD_DECKLINKAPI_v11_5_1_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_1.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_1.h new file mode 100644 index 0000000000..3c59736c2a --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_1.h @@ -0,0 +1,212 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v7_1.h */ + +#ifndef __DeckLink_API_v7_1_h__ +#define __DeckLink_API_v7_1_h__ + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// "B28131B6-59AC-4857-B5AC-CD75D5883E2F" +#define IID_IDeckLinkDisplayModeIterator_v7_1 (REFIID){0xB2,0x81,0x31,0xB6,0x59,0xAC,0x48,0x57,0xB5,0xAC,0xCD,0x75,0xD5,0x88,0x3E,0x2F} + +// "AF0CD6D5-8376-435E-8433-54F9DD530AC3" +#define IID_IDeckLinkDisplayMode_v7_1 (REFIID){0xAF,0x0C,0xD6,0xD5,0x83,0x76,0x43,0x5E,0x84,0x33,0x54,0xF9,0xDD,0x53,0x0A,0xC3} + +// "EBD01AFA-E4B0-49C6-A01D-EDB9D1B55FD9" +#define IID_IDeckLinkVideoOutputCallback_v7_1 (REFIID){0xEB,0xD0,0x1A,0xFA,0xE4,0xB0,0x49,0xC6,0xA0,0x1D,0xED,0xB9,0xD1,0xB5,0x5F,0xD9} + +// "7F94F328-5ED4-4E9F-9729-76A86BDC99CC" +#define IID_IDeckLinkInputCallback_v7_1 (REFIID){0x7F,0x94,0xF3,0x28,0x5E,0xD4,0x4E,0x9F,0x97,0x29,0x76,0xA8,0x6B,0xDC,0x99,0xCC} + +// "AE5B3E9B-4E1E-4535-B6E8-480FF52F6CE5" +#define IID_IDeckLinkOutput_v7_1 (REFIID){0xAE,0x5B,0x3E,0x9B,0x4E,0x1E,0x45,0x35,0xB6,0xE8,0x48,0x0F,0xF5,0x2F,0x6C,0xE5} + +// "2B54EDEF-5B32-429F-BA11-BB990596EACD" +#define IID_IDeckLinkInput_v7_1 (REFIID){0x2B,0x54,0xED,0xEF,0x5B,0x32,0x42,0x9F,0xBA,0x11,0xBB,0x99,0x05,0x96,0xEA,0xCD} + +// "333F3A10-8C2D-43CF-B79D-46560FEEA1CE" +#define IID_IDeckLinkVideoFrame_v7_1 (REFIID){0x33,0x3F,0x3A,0x10,0x8C,0x2D,0x43,0xCF,0xB7,0x9D,0x46,0x56,0x0F,0xEE,0xA1,0xCE} + +// "C8B41D95-8848-40EE-9B37-6E3417FB114B" +#define IID_IDeckLinkVideoInputFrame_v7_1 (REFIID){0xC8,0xB4,0x1D,0x95,0x88,0x48,0x40,0xEE,0x9B,0x37,0x6E,0x34,0x17,0xFB,0x11,0x4B} + +// "C86DE4F6-A29F-42E3-AB3A-1363E29F0788" +#define IID_IDeckLinkAudioInputPacket_v7_1 (REFIID){0xC8,0x6D,0xE4,0xF6,0xA2,0x9F,0x42,0xE3,0xAB,0x3A,0x13,0x63,0xE2,0x9F,0x07,0x88} + +#if defined(__cplusplus) + +class IDeckLinkDisplayModeIterator_v7_1; +class IDeckLinkDisplayMode_v7_1; +class IDeckLinkVideoFrame_v7_1; +class IDeckLinkVideoInputFrame_v7_1; +class IDeckLinkAudioInputPacket_v7_1; + +class BMD_PUBLIC IDeckLinkDisplayModeIterator_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Next (IDeckLinkDisplayMode_v7_1* *deckLinkDisplayMode) = 0; +}; + + +class BMD_PUBLIC IDeckLinkDisplayMode_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetName (const char **name) = 0; + virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode () = 0; + virtual long STDMETHODCALLTYPE GetWidth () = 0; + virtual long STDMETHODCALLTYPE GetHeight () = 0; + virtual HRESULT STDMETHODCALLTYPE GetFrameRate (BMDTimeValue *frameDuration, BMDTimeScale *timeScale) = 0; +}; + +class BMD_PUBLIC IDeckLinkVideoOutputCallback_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted (IDeckLinkVideoFrame_v7_1* completedFrame, BMDOutputFrameCompletionResult result) = 0; +}; + +class BMD_PUBLIC IDeckLinkInputCallback_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived (IDeckLinkVideoInputFrame_v7_1* videoFrame, IDeckLinkAudioInputPacket_v7_1* audioPacket) = 0; +}; + +// IDeckLinkOutput_v7_1. Created by QueryInterface from IDeckLink. +class BMD_PUBLIC IDeckLinkOutput_v7_1 : public IUnknown +{ +public: + // Display mode predicates + virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator (IDeckLinkDisplayModeIterator_v7_1* *iterator) = 0; + + + // Video output + virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput (BMDDisplayMode displayMode) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput () = 0; + + virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator (IDeckLinkMemoryAllocator* theAllocator) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame (int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1* *outFrame) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateVideoFrameFromBuffer (void* buffer, int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1* *outFrame) = 0; + + virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync (IDeckLinkVideoFrame_v7_1* theFrame) = 0; + virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame (IDeckLinkVideoFrame_v7_1* theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale) = 0; + virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback (IDeckLinkVideoOutputCallback_v7_1* theCallback) = 0; + + + // Audio output + virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput () = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync (void* buffer, uint32_t sampleFrameCount, uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll () = 0; + virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll () = 0; + virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples (void* buffer, uint32_t sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount (uint32_t *bufferedSampleCount) = 0; + virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples () = 0; + + virtual HRESULT STDMETHODCALLTYPE SetAudioCallback (IDeckLinkAudioOutputCallback* theCallback) = 0; + + + // Output control + virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed) = 0; + virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, BMDTimeValue *actualStopTime, BMDTimeScale timeScale) = 0; + virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock (BMDTimeScale desiredTimeScale, BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0; +}; + +// IDeckLinkInput_v7_1. Created by QueryInterface from IDeckLink. +class BMD_PUBLIC IDeckLinkInput_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator (IDeckLinkDisplayModeIterator_v7_1 **iterator) = 0; + + // Video input + virtual HRESULT STDMETHODCALLTYPE EnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableVideoInput () = 0; + + // Audio input + virtual HRESULT STDMETHODCALLTYPE EnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableAudioInput () = 0; + virtual HRESULT STDMETHODCALLTYPE ReadAudioSamples (void* buffer, uint32_t sampleFrameCount, uint32_t *sampleFramesRead, BMDTimeValue *audioPacketTime, BMDTimeScale timeScale) = 0; + virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount (uint32_t *bufferedSampleCount) = 0; + + + virtual HRESULT STDMETHODCALLTYPE StartStreams () = 0; + virtual HRESULT STDMETHODCALLTYPE StopStreams () = 0; + virtual HRESULT STDMETHODCALLTYPE PauseStreams () = 0; + virtual HRESULT STDMETHODCALLTYPE SetCallback (IDeckLinkInputCallback_v7_1* theCallback) = 0; +}; + +// IDeckLinkVideoFrame_v7_1. Created by IDeckLinkOutput::CreateVideoFrame. +class BMD_PUBLIC IDeckLinkVideoFrame_v7_1 : public IUnknown +{ +public: + virtual long STDMETHODCALLTYPE GetWidth () = 0; + virtual long STDMETHODCALLTYPE GetHeight () = 0; + virtual long STDMETHODCALLTYPE GetRowBytes () = 0; + virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat () = 0; + virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags () = 0; + virtual HRESULT STDMETHODCALLTYPE GetBytes (void* *buffer) = 0; +}; + +// IDeckLinkVideoInputFrame_v7_1. Provided by the IDeckLinkInput_v7_1 frame arrival callback. +class BMD_PUBLIC IDeckLinkVideoInputFrame_v7_1 : public IDeckLinkVideoFrame_v7_1 +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetFrameTime (BMDTimeValue *frameTime, BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0; +}; + +// IDeckLinkAudioInputPacket_v7_1. Provided by the IDeckLinkInput_v7_1 callback. +class BMD_PUBLIC IDeckLinkAudioInputPacket_v7_1 : public IUnknown +{ +public: + virtual long STDMETHODCALLTYPE GetSampleCount () = 0; + virtual HRESULT STDMETHODCALLTYPE GetBytes (void* *buffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAudioPacketTime (BMDTimeValue *packetTime, BMDTimeScale timeScale) = 0; +}; + +#endif // defined(__cplusplus) + +#endif // __DeckLink_API_v7_1_h__ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_3.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_3.h new file mode 100644 index 0000000000..37e0464db5 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_3.h @@ -0,0 +1,187 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v7_3.h */ + +#ifndef __DeckLink_API_v7_3_h__ +#define __DeckLink_API_v7_3_h__ + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v7_6.h" +#include "DeckLinkAPI_v10_11.h" + +/* Interface ID Declarations */ + +#define IID_IDeckLinkInputCallback_v7_3 /* FD6F311D-4D00-444B-9ED4-1F25B5730AD0 */ (REFIID){0xFD,0x6F,0x31,0x1D,0x4D,0x00,0x44,0x4B,0x9E,0xD4,0x1F,0x25,0xB5,0x73,0x0A,0xD0} +#define IID_IDeckLinkOutput_v7_3 /* 271C65E3-C323-4344-A30F-D908BCB20AA3 */ (REFIID){0x27,0x1C,0x65,0xE3,0xC3,0x23,0x43,0x44,0xA3,0x0F,0xD9,0x08,0xBC,0xB2,0x0A,0xA3} +#define IID_IDeckLinkInput_v7_3 /* 4973F012-9925-458C-871C-18774CDBBECB */ (REFIID){0x49,0x73,0xF0,0x12,0x99,0x25,0x45,0x8C,0x87,0x1C,0x18,0x77,0x4C,0xDB,0xBE,0xCB} +#define IID_IDeckLinkVideoInputFrame_v7_3 /* CF317790-2894-11DE-8C30-0800200C9A66 */ (REFIID){0xCF,0x31,0x77,0x90,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66} + +/* End Interface ID Declarations */ + +#if defined(__cplusplus) + +/* Forward Declarations */ + +class IDeckLinkVideoInputFrame_v7_3; + +/* End Forward Declarations */ + + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkOutput_v7_3 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (BMDDisplayMode displayMode, BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0; + virtual HRESULT CreateAncillaryData (BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount, BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, uint32_t sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetHardwareReferenceClock (BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0; + +protected: + virtual ~IDeckLinkOutput_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkOutput */ + + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkInputCallback_v7_3 : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode_v7_6 *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame_v7_3 *videoFrame, /* in */ IDeckLinkAudioInputPacket *audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkInputCallback */ + + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput_v7_3 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v7_3 *theCallback) = 0; + +protected: + virtual ~IDeckLinkInput_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkInput */ + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkVideoInputFrame_v7_3 : public IDeckLinkVideoFrame_v7_6 +{ +public: + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0; + +protected: + virtual ~IDeckLinkVideoInputFrame_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkVideoInputFrame */ + +#endif // defined(__cplusplus) +#endif // __DeckLink_API_v7_3_h__ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_6.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_6.h new file mode 100644 index 0000000000..2920e45e20 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_6.h @@ -0,0 +1,418 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v7_6.h */ + +#ifndef __DeckLink_API_v7_6_h__ +#define __DeckLink_API_v7_6_h__ + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// Interface ID Declarations + +#define IID_IDeckLinkVideoOutputCallback_v7_6 /* E763A626-4A3C-49D1-BF13-E7AD3692AE52 */ (REFIID){0xE7,0x63,0xA6,0x26,0x4A,0x3C,0x49,0xD1,0xBF,0x13,0xE7,0xAD,0x36,0x92,0xAE,0x52} +#define IID_IDeckLinkInputCallback_v7_6 /* 31D28EE7-88B6-4CB1-897A-CDBF79A26414 */ (REFIID){0x31,0xD2,0x8E,0xE7,0x88,0xB6,0x4C,0xB1,0x89,0x7A,0xCD,0xBF,0x79,0xA2,0x64,0x14} +#define IID_IDeckLinkDisplayModeIterator_v7_6 /* 455D741F-1779-4800-86F5-0B5D13D79751 */ (REFIID){0x45,0x5D,0x74,0x1F,0x17,0x79,0x48,0x00,0x86,0xF5,0x0B,0x5D,0x13,0xD7,0x97,0x51} +#define IID_IDeckLinkDisplayMode_v7_6 /* 87451E84-2B7E-439E-A629-4393EA4A8550 */ (REFIID){0x87,0x45,0x1E,0x84,0x2B,0x7E,0x43,0x9E,0xA6,0x29,0x43,0x93,0xEA,0x4A,0x85,0x50} +#define IID_IDeckLinkOutput_v7_6 /* 29228142-EB8C-4141-A621-F74026450955 */ (REFIID){0x29,0x22,0x81,0x42,0xEB,0x8C,0x41,0x41,0xA6,0x21,0xF7,0x40,0x26,0x45,0x09,0x55} +#define IID_IDeckLinkInput_v7_6 /* 300C135A-9F43-48E2-9906-6D7911D93CF1 */ (REFIID){0x30,0x0C,0x13,0x5A,0x9F,0x43,0x48,0xE2,0x99,0x06,0x6D,0x79,0x11,0xD9,0x3C,0xF1} +#define IID_IDeckLinkTimecode_v7_6 /* EFB9BCA6-A521-44F7-BD69-2332F24D9EE6 */ (REFIID){0xEF,0xB9,0xBC,0xA6,0xA5,0x21,0x44,0xF7,0xBD,0x69,0x23,0x32,0xF2,0x4D,0x9E,0xE6} +#define IID_IDeckLinkVideoFrame_v7_6 /* A8D8238E-6B18-4196-99E1-5AF717B83D32 */ (REFIID){0xA8,0xD8,0x23,0x8E,0x6B,0x18,0x41,0x96,0x99,0xE1,0x5A,0xF7,0x17,0xB8,0x3D,0x32} +#define IID_IDeckLinkMutableVideoFrame_v7_6 /* 46FCEE00-B4E6-43D0-91C0-023A7FCEB34F */ (REFIID){0x46,0xFC,0xEE,0x00,0xB4,0xE6,0x43,0xD0,0x91,0xC0,0x02,0x3A,0x7F,0xCE,0xB3,0x4F} +#define IID_IDeckLinkVideoInputFrame_v7_6 /* 9A74FA41-AE9F-47AC-8CF4-01F42DD59965 */ (REFIID){0x9A,0x74,0xFA,0x41,0xAE,0x9F,0x47,0xAC,0x8C,0xF4,0x01,0xF4,0x2D,0xD5,0x99,0x65} +#define IID_IDeckLinkScreenPreviewCallback_v7_6 /* 373F499D-4B4D-4518-AD22-6354E5A5825E */ (REFIID){0x37,0x3F,0x49,0x9D,0x4B,0x4D,0x45,0x18,0xAD,0x22,0x63,0x54,0xE5,0xA5,0x82,0x5E} +#define IID_IDeckLinkGLScreenPreviewHelper_v7_6 /* BA575CD9-A15E-497B-B2C2-F9AFE7BE4EBA */ (REFIID){0xBA,0x57,0x5C,0xD9,0xA1,0x5E,0x49,0x7B,0xB2,0xC2,0xF9,0xAF,0xE7,0xBE,0x4E,0xBA} +#define IID_IDeckLinkVideoConversion_v7_6 /* 3EB504C9-F97D-40FE-A158-D407D48CB53B */ (REFIID){0x3E,0xB5,0x04,0xC9,0xF9,0x7D,0x40,0xFE,0xA1,0x58,0xD4,0x07,0xD4,0x8C,0xB5,0x3B} +#define IID_IDeckLinkConfiguration_v7_6 /* B8EAD569-B764-47F0-A73F-AE40DF6CBF10 */ (REFIID){0xB8,0xEA,0xD5,0x69,0xB7,0x64,0x47,0xF0,0xA7,0x3F,0xAE,0x40,0xDF,0x6C,0xBF,0x10} + + +#if defined(__cplusplus) + +/* Enum BMDVideoConnection - Video connection types */ + +typedef uint32_t BMDVideoConnection_v7_6; +enum _BMDVideoConnection_v7_6 { + bmdVideoConnectionSDI_v7_6 = 'sdi ', + bmdVideoConnectionHDMI_v7_6 = 'hdmi', + bmdVideoConnectionOpticalSDI_v7_6 = 'opti', + bmdVideoConnectionComponent_v7_6 = 'cpnt', + bmdVideoConnectionComposite_v7_6 = 'cmst', + bmdVideoConnectionSVideo_v7_6 = 'svid' +}; + +// Forward Declarations + +class IDeckLinkVideoOutputCallback_v7_6; +class IDeckLinkInputCallback_v7_6; +class IDeckLinkDisplayModeIterator_v7_6; +class IDeckLinkDisplayMode_v7_6; +class IDeckLinkOutput_v7_6; +class IDeckLinkInput_v7_6; +class IDeckLinkTimecode_v7_6; +class IDeckLinkVideoFrame_v7_6; +class IDeckLinkMutableVideoFrame_v7_6; +class IDeckLinkVideoInputFrame_v7_6; +class IDeckLinkScreenPreviewCallback_v7_6; +class IDeckLinkGLScreenPreviewHelper_v7_6; +class IDeckLinkVideoConversion_v7_6; + + +/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */ + +class BMD_PUBLIC IDeckLinkVideoOutputCallback_v7_6 : public IUnknown +{ +public: + virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame_v7_6 *completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0; + virtual HRESULT ScheduledPlaybackHasStopped (void) = 0; + +protected: + virtual ~IDeckLinkVideoOutputCallback_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkInputCallback_v7_6 : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode_v7_6 *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame_v7_6* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */ + +class BMD_PUBLIC IDeckLinkDisplayModeIterator_v7_6 : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode) = 0; + +protected: + virtual ~IDeckLinkDisplayModeIterator_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkDisplayMode - represents a display mode */ + +class BMD_PUBLIC IDeckLinkDisplayMode_v7_6 : public IUnknown +{ +public: + virtual HRESULT GetName (/* out */ const char **name) = 0; + virtual BMDDisplayMode GetDisplayMode (void) = 0; + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual HRESULT GetFrameRate (/* out */ BMDTimeValue *frameDuration, /* out */ BMDTimeScale *timeScale) = 0; + virtual BMDFieldDominance GetFieldDominance (void) = 0; + +protected: + virtual ~IDeckLinkDisplayMode_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkOutput_v7_6 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback_v7_6 *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkOutput_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkInput_v7_6 - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput_v7_6 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v7_6 *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */ + +class BMD_PUBLIC IDeckLinkTimecode_v7_6 : public IUnknown +{ +public: + virtual BMDTimecodeBCD GetBCD (void) = 0; + virtual HRESULT GetComponents (/* out */ uint8_t *hours, /* out */ uint8_t *minutes, /* out */ uint8_t *seconds, /* out */ uint8_t *frames) = 0; + virtual HRESULT GetString (/* out */ const char **timecode) = 0; + virtual BMDTimecodeFlags GetFlags (void) = 0; + +protected: + virtual ~IDeckLinkTimecode_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */ + +class BMD_PUBLIC IDeckLinkVideoFrame_v7_6 : public IUnknown +{ +public: + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual long GetRowBytes (void) = 0; + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual BMDFrameFlags GetFlags (void) = 0; + virtual HRESULT GetBytes (/* out */ void **buffer) = 0; + + virtual HRESULT GetTimecode (BMDTimecodeFormat format, /* out */ IDeckLinkTimecode_v7_6 **timecode) = 0; + virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary **ancillary) = 0; + +protected: + virtual ~IDeckLinkVideoFrame_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */ + +class BMD_PUBLIC IDeckLinkMutableVideoFrame_v7_6 : public IDeckLinkVideoFrame_v7_6 +{ +public: + virtual HRESULT SetFlags (BMDFrameFlags newFlags) = 0; + + virtual HRESULT SetTimecode (BMDTimecodeFormat format, /* in */ IDeckLinkTimecode_v7_6 *timecode) = 0; + virtual HRESULT SetTimecodeFromComponents (BMDTimecodeFormat format, uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t frames, BMDTimecodeFlags flags) = 0; + virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary *ancillary) = 0; + +protected: + virtual ~IDeckLinkMutableVideoFrame_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkVideoInputFrame_v7_6 : public IDeckLinkVideoFrame_v7_6 +{ +public: + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0; + virtual HRESULT GetHardwareReferenceTimestamp (BMDTimeScale timeScale, /* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration) = 0; + +protected: + virtual ~IDeckLinkVideoInputFrame_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */ + +class BMD_PUBLIC IDeckLinkScreenPreviewCallback_v7_6 : public IUnknown +{ +public: + virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + +protected: + virtual ~IDeckLinkScreenPreviewCallback_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */ + +class BMD_PUBLIC IDeckLinkGLScreenPreviewHelper_v7_6 : public IUnknown +{ +public: + + /* Methods must be called with OpenGL context set */ + + virtual HRESULT InitializeGL (void) = 0; + virtual HRESULT PaintGL (void) = 0; + virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + +protected: + virtual ~IDeckLinkGLScreenPreviewHelper_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */ + +class BMD_PUBLIC IDeckLinkVideoConversion_v7_6 : public IUnknown +{ +public: + virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame_v7_6* srcFrame, /* in */ IDeckLinkVideoFrame_v7_6* dstFrame) = 0; + +protected: + virtual ~IDeckLinkVideoConversion_v7_6 () {}; // call Release method to drop reference count +}; + +/* Interface IDeckLinkConfiguration - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkConfiguration_v7_6 : public IUnknown +{ +public: + virtual HRESULT GetConfigurationValidator (/* out */ IDeckLinkConfiguration_v7_6 **configObject) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + + /* Video Output Configuration */ + + virtual HRESULT SetVideoOutputFormat (/* in */ BMDVideoConnection_v7_6 videoOutputConnection) = 0; + virtual HRESULT IsVideoOutputActive (/* in */ BMDVideoConnection_v7_6 videoOutputConnection, /* out */ bool *active) = 0; + + virtual HRESULT SetAnalogVideoOutputFlags (/* in */ BMDAnalogVideoFlags analogVideoFlags) = 0; + virtual HRESULT GetAnalogVideoOutputFlags (/* out */ BMDAnalogVideoFlags *analogVideoFlags) = 0; + + virtual HRESULT EnableFieldFlickerRemovalWhenPaused (/* in */ bool enable) = 0; + virtual HRESULT IsEnabledFieldFlickerRemovalWhenPaused (/* out */ bool *enabled) = 0; + + virtual HRESULT Set444And3GBpsVideoOutput (/* in */ bool enable444VideoOutput, /* in */ bool enable3GbsOutput) = 0; + virtual HRESULT Get444And3GBpsVideoOutput (/* out */ bool *is444VideoOutputEnabled, /* out */ bool *threeGbsOutputEnabled) = 0; + + virtual HRESULT SetVideoOutputConversionMode (/* in */ BMDVideoOutputConversionMode conversionMode) = 0; + virtual HRESULT GetVideoOutputConversionMode (/* out */ BMDVideoOutputConversionMode *conversionMode) = 0; + + virtual HRESULT Set_HD1080p24_to_HD1080i5994_Conversion (/* in */ bool enable) = 0; + virtual HRESULT Get_HD1080p24_to_HD1080i5994_Conversion (/* out */ bool *enabled) = 0; + + /* Video Input Configuration */ + + virtual HRESULT SetVideoInputFormat (/* in */ BMDVideoConnection_v7_6 videoInputFormat) = 0; + virtual HRESULT GetVideoInputFormat (/* out */ BMDVideoConnection_v7_6 *videoInputFormat) = 0; + + virtual HRESULT SetAnalogVideoInputFlags (/* in */ BMDAnalogVideoFlags analogVideoFlags) = 0; + virtual HRESULT GetAnalogVideoInputFlags (/* out */ BMDAnalogVideoFlags *analogVideoFlags) = 0; + + virtual HRESULT SetVideoInputConversionMode (/* in */ BMDVideoInputConversionMode conversionMode) = 0; + virtual HRESULT GetVideoInputConversionMode (/* out */ BMDVideoInputConversionMode *conversionMode) = 0; + + virtual HRESULT SetBlackVideoOutputDuringCapture (/* in */ bool blackOutInCapture) = 0; + virtual HRESULT GetBlackVideoOutputDuringCapture (/* out */ bool *blackOutInCapture) = 0; + + virtual HRESULT Set32PulldownSequenceInitialTimecodeFrame (/* in */ uint32_t aFrameTimecode) = 0; + virtual HRESULT Get32PulldownSequenceInitialTimecodeFrame (/* out */ uint32_t *aFrameTimecode) = 0; + + virtual HRESULT SetVancSourceLineMapping (/* in */ uint32_t activeLine1VANCsource, /* in */ uint32_t activeLine2VANCsource, /* in */ uint32_t activeLine3VANCsource) = 0; + virtual HRESULT GetVancSourceLineMapping (/* out */ uint32_t *activeLine1VANCsource, /* out */ uint32_t *activeLine2VANCsource, /* out */ uint32_t *activeLine3VANCsource) = 0; + + /* Audio Input Configuration */ + + virtual HRESULT SetAudioInputFormat (/* in */ BMDAudioConnection audioInputFormat) = 0; + virtual HRESULT GetAudioInputFormat (/* out */ BMDAudioConnection *audioInputFormat) = 0; +}; + +/* Functions */ + +extern "C" { + + BMD_PUBLIC IDeckLinkIterator* CreateDeckLinkIteratorInstance_v7_6 (void); + BMD_PUBLIC IDeckLinkGLScreenPreviewHelper_v7_6* CreateOpenGLScreenPreviewHelper_v7_6 (void); + BMD_PUBLIC IDeckLinkVideoConversion_v7_6* CreateVideoConversionInstance_v7_6 (void); + +}; + + +#endif // defined(__cplusplus) +#endif // __DeckLink_API_v7_6_h__ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_9.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_9.h new file mode 100644 index 0000000000..54c92f1745 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v7_9.h @@ -0,0 +1,101 @@ +/* -LICENSE-START- +** Copyright (c) 2010 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v7_9.h */ + +#ifndef __DeckLink_API_v7_9_h__ +#define __DeckLink_API_v7_9_h__ + +#include "DeckLinkAPI.h" + +// Interface ID Declarations +#define IID_IDeckLinkDeckControl_v7_9 /* A4D81043-0619-42B7-8ED6-602D29041DF7 */ (REFIID){0xA4,0xD8,0x10,0x43,0x06,0x19,0x42,0xB7,0x8E,0xD6,0x60,0x2D,0x29,0x04,0x1D,0xF7} + +#if defined(__cplusplus) + + +// Forward Declarations +class IDeckLinkDeckControl_v7_9; + +/* Interface IDeckLinkDeckControl_v7_9 - Deck Control main interface */ +class BMD_PUBLIC IDeckLinkDeckControl_v7_9 : public IUnknown +{ +public: + virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Close (/* in */ bool standbyOn) = 0; + virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0; + virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0; + virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeString (/* out */ const char **currentTimeCode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0; + virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0; + virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0; + virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0; + virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0; + virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0; + virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0; + virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Abort (void) = 0; + virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback *callback) = 0; + +protected: + virtual ~IDeckLinkDeckControl_v7_9 () {}; // call Release method to drop reference count +}; + + + +#endif // defined(__cplusplus) +#endif // __DeckLink_API_v7_9_h__ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_0.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_0.h new file mode 100644 index 0000000000..32e7b93670 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_0.h @@ -0,0 +1,76 @@ +/* -LICENSE-START- +** Copyright (c) 2011 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v8_0_H +#define BMD_DECKLINKAPI_v8_0_H + +#include "DeckLinkAPI.h" + +// Interface ID Declarations + +#define IID_IDeckLink_v8_0 /* 62BFF75D-6569-4E55-8D4D-66AA03829ABC */ (REFIID){0x62,0xBF,0xF7,0x5D,0x65,0x69,0x4E,0x55,0x8D,0x4D,0x66,0xAA,0x03,0x82,0x9A,0xBC} +#define IID_IDeckLinkIterator_v8_0 /* 74E936FC-CC28-4A67-81A0-1E94E52D4E69 */ (REFIID){0x74,0xE9,0x36,0xFC,0xCC,0x28,0x4A,0x67,0x81,0xA0,0x1E,0x94,0xE5,0x2D,0x4E,0x69} + +#if defined (__cplusplus) + +/* Interface IDeckLink_v8_0 - represents a DeckLink device */ + +class BMD_PUBLIC IDeckLink_v8_0 : public IUnknown +{ +public: + virtual HRESULT GetModelName (/* out */ const char **modelName) = 0; +}; + +/* Interface IDeckLinkIterator_v8_0 - enumerates installed DeckLink hardware */ + +class BMD_PUBLIC IDeckLinkIterator_v8_0 : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLink_v8_0 **deckLinkInstance) = 0; +}; + +extern "C" { + BMD_PUBLIC IDeckLinkIterator_v8_0* CreateDeckLinkIteratorInstance_v8_0 (void); +}; + +#endif // defined __cplusplus + +#endif /* defined(BMD_DECKLINKAPI_v8_0_H) */ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_1.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_1.h new file mode 100644 index 0000000000..5bc67de2ab --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v8_1.h @@ -0,0 +1,124 @@ +/* -LICENSE-START- + ** Copyright (c) 2011 Blackmagic Design + ** + ** Permission is hereby granted, free of charge, to any person or organization + ** obtaining a copy of the software and accompanying documentation (the + ** "Software") to use, reproduce, display, distribute, sub-license, execute, + ** and transmit the Software, and to prepare derivative works of the Software, + ** and to permit third-parties to whom the Software is furnished to do so, in + ** accordance with: + ** + ** (1) if the Software is obtained from Blackmagic Design, the End User License + ** Agreement for the Software Development Kit (“EULA”) available at + ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + ** + ** (2) if the Software is obtained from any third party, such licensing terms + ** as notified by that third party, + ** + ** and all subject to the following: + ** + ** (3) the copyright notices in the Software and this entire statement, + ** including the above license grant, this restriction and the following + ** disclaimer, must be included in all copies of the Software, in whole or in + ** part, and all derivative works of the Software, unless such copies or + ** derivative works are solely in the form of machine-executable object code + ** generated by a source language processor. + ** + ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + ** DEALINGS IN THE SOFTWARE. + ** + ** A copy of the Software is available free of charge at + ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + ** + ** -LICENSE-END- + */ + +#ifndef BMD_DECKLINKAPI_v8_1_H +#define BMD_DECKLINKAPI_v8_1_H + +#include "DeckLinkAPI.h" + + +// Interface ID Declarations + +#define IID_IDeckLinkDeckControlStatusCallback_v8_1 /* E5F693C1-4283-4716-B18F-C1431521955B */ (REFIID){0xE5,0xF6,0x93,0xC1,0x42,0x83,0x47,0x16,0xB1,0x8F,0xC1,0x43,0x15,0x21,0x95,0x5B} +#define IID_IDeckLinkDeckControl_v8_1 /* 522A9E39-0F3C-4742-94EE-D80DE335DA1D */ (REFIID){0x52,0x2A,0x9E,0x39,0x0F,0x3C,0x47,0x42,0x94,0xEE,0xD8,0x0D,0xE3,0x35,0xDA,0x1D} + + +/* Enum BMDDeckControlVTRControlState_v8_1 - VTR Control state */ + +typedef uint32_t BMDDeckControlVTRControlState_v8_1; +enum _BMDDeckControlVTRControlState_v8_1 { + bmdDeckControlNotInVTRControlMode_v8_1 = 'nvcm', + bmdDeckControlVTRControlPlaying_v8_1 = 'vtrp', + bmdDeckControlVTRControlRecording_v8_1 = 'vtrr', + bmdDeckControlVTRControlStill_v8_1 = 'vtra', + bmdDeckControlVTRControlSeeking_v8_1 = 'vtrs', + bmdDeckControlVTRControlStopped_v8_1 = 'vtro' +}; + + +/* Interface IDeckLinkDeckControlStatusCallback_v8_1 - Deck control state change callback. */ + +class BMD_PUBLIC IDeckLinkDeckControlStatusCallback_v8_1 : public IUnknown +{ +public: + virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0; + virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState_v8_1 newState, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0; + +protected: + virtual ~IDeckLinkDeckControlStatusCallback_v8_1 () {}; // call Release method to drop reference count +}; + +/* Interface IDeckLinkDeckControl_v8_1 - Deck Control main interface */ + +class BMD_PUBLIC IDeckLinkDeckControl_v8_1 : public IUnknown +{ +public: + virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Close (/* in */ bool standbyOn) = 0; + virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState_v8_1 *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0; + virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0; + virtual HRESULT SendCommand (/* in */ uint8_t *inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t *outBuffer, /* out */ uint32_t *outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeString (/* out */ const char **currentTimeCode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0; + virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0; + virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0; + virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0; + virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0; + virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0; + virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0; + virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Abort (void) = 0; + virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback_v8_1 *callback) = 0; + +protected: + virtual ~IDeckLinkDeckControl_v8_1 () {}; // call Release method to drop reference count +}; + + +#endif // BMD_DECKLINKAPI_v8_1_H diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_2.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_2.h new file mode 100644 index 0000000000..c11c801292 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_2.h @@ -0,0 +1,96 @@ +/* -LICENSE-START- +** Copyright (c) 2012 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v9_2_H +#define BMD_DECKLINKAPI_v9_2_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" +#include "DeckLinkAPIVideoInput_v11_5_1.h" + + +// Interface ID Declarations + +#define IID_IDeckLinkInput_v9_2 /* 6D40EF78-28B9-4E21-990D-95BB7750A04F */ (REFIID){0x6D,0x40,0xEF,0x78,0x28,0xB9,0x4E,0x21,0x99,0x0D,0x95,0xBB,0x77,0x50,0xA0,0x4F} + + +#if defined(__cplusplus) + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput_v9_2 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v9_2 () {}; // call Release method to drop reference count +}; + + +#endif // defined(__cplusplus) +#endif // BMD_DECKLINKAPI_v9_2_H diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_9.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_9.h new file mode 100644 index 0000000000..16dc671344 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPI_v9_9.h @@ -0,0 +1,112 @@ +/* -LICENSE-START- +** Copyright (c) 2013 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v9_9_H +#define BMD_DECKLINKAPI_v9_9_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + + +// Interface ID Declarations + +#define IID_IDeckLinkOutput_v9_9 /* A3EF0963-0862-44ED-92A9-EE89ABF431C7 */ (REFIID){0xA3,0xEF,0x09,0x63,0x08,0x62,0x44,0xED,0x92,0xA9,0xEE,0x89,0xAB,0xF4,0x31,0xC7} + + +#if defined(__cplusplus) + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkOutput_v9_9 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkOutput_v9_9 () {}; // call Release method to drop reference count +}; + +#endif // defined(__cplusplus) +#endif // BMD_DECKLINKAPI_v9_9_H diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/LinuxCOM.h b/subprojects/gst-plugins-bad/sys/decklink2/linux/LinuxCOM.h new file mode 100644 index 0000000000..cad638c234 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/LinuxCOM.h @@ -0,0 +1,116 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef __LINUX_COM_H_ +#define __LINUX_COM_H_ + +struct REFIID +{ + unsigned char byte0; + unsigned char byte1; + unsigned char byte2; + unsigned char byte3; + unsigned char byte4; + unsigned char byte5; + unsigned char byte6; + unsigned char byte7; + unsigned char byte8; + unsigned char byte9; + unsigned char byte10; + unsigned char byte11; + unsigned char byte12; + unsigned char byte13; + unsigned char byte14; + unsigned char byte15; +}; + +typedef REFIID CFUUIDBytes; +#define CFUUIDGetUUIDBytes(x) x + +typedef int HRESULT; +typedef unsigned long ULONG; +typedef void *LPVOID; + +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) +#define FAILED(Status) ((HRESULT)(Status)<0) + +#define IS_ERROR(Status) ((unsigned long)(Status) >> 31 == SEVERITY_ERROR) +#define HRESULT_CODE(hr) ((hr) & 0xFFFF) +#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) +#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) +#define SEVERITY_SUCCESS 0 +#define SEVERITY_ERROR 1 + +#define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) +#define E_UNEXPECTED ((HRESULT)0x8000FFFFL) +#define E_NOTIMPL ((HRESULT)0x80000001L) +#define E_OUTOFMEMORY ((HRESULT)0x80000002L) +#define E_INVALIDARG ((HRESULT)0x80000003L) +#define E_NOINTERFACE ((HRESULT)0x80000004L) +#define E_POINTER ((HRESULT)0x80000005L) +#define E_HANDLE ((HRESULT)0x80000006L) +#define E_ABORT ((HRESULT)0x80000007L) +#define E_FAIL ((HRESULT)0x80000008L) +#define E_ACCESSDENIED ((HRESULT)0x80000009L) + +#define STDMETHODCALLTYPE + +#define IID_IUnknown (REFIID){0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} +#define IUnknownUUID IID_IUnknown + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +#ifdef __cplusplus +class BMD_PUBLIC IUnknown +{ + public: + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) = 0; + virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; + virtual ULONG STDMETHODCALLTYPE Release(void) = 0; +}; +#endif + +#endif + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI.h new file mode 100644 index 0000000000..e9070c88dc --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI.h @@ -0,0 +1,1332 @@ +/* -LICENSE-START- + ** Copyright (c) 2022 Blackmagic Design + ** + ** Permission is hereby granted, free of charge, to any person or organization + ** obtaining a copy of the software and accompanying documentation (the + ** "Software") to use, reproduce, display, distribute, sub-license, execute, + ** and transmit the Software, and to prepare derivative works of the Software, + ** and to permit third-parties to whom the Software is furnished to do so, in + ** accordance with: + ** + ** (1) if the Software is obtained from Blackmagic Design, the End User License + ** Agreement for the Software Development Kit ("EULA") available at + ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + ** + ** (2) if the Software is obtained from any third party, such licensing terms + ** as notified by that third party, + ** + ** and all subject to the following: + ** + ** (3) the copyright notices in the Software and this entire statement, + ** including the above license grant, this restriction and the following + ** disclaimer, must be included in all copies of the Software, in whole or in + ** part, and all derivative works of the Software, unless such copies or + ** derivative works are solely in the form of machine-executable object code + ** generated by a source language processor. + ** + ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + ** DEALINGS IN THE SOFTWARE. + ** + ** A copy of the Software is available free of charge at + ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + ** + ** -LICENSE-END- + */ + + +#ifndef BMD_DECKLINKAPI_H +#define BMD_DECKLINKAPI_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +/* DeckLink API */ + +#include +#include +#include + +#include "DeckLinkAPITypes.h" +#include "DeckLinkAPIModes.h" +#include "DeckLinkAPIDiscovery.h" +#include "DeckLinkAPIConfiguration.h" +#include "DeckLinkAPIDeckControl.h" + +#include "DeckLinkAPIStreaming.h" + +#define BLACKMAGIC_DECKLINK_API_MAGIC 1 + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkVideoOutputCallback = /* 20AA5225-1958-47CB-820B-80A8D521A6EE */ { 0x20,0xAA,0x52,0x25,0x19,0x58,0x47,0xCB,0x82,0x0B,0x80,0xA8,0xD5,0x21,0xA6,0xEE }; +BMD_CONST REFIID IID_IDeckLinkInputCallback = /* C6FCE4C9-C4E4-4047-82FB-5D238232A902 */ { 0xC6,0xFC,0xE4,0xC9,0xC4,0xE4,0x40,0x47,0x82,0xFB,0x5D,0x23,0x82,0x32,0xA9,0x02 }; +BMD_CONST REFIID IID_IDeckLinkEncoderInputCallback = /* ACF13E61-F4A0-4974-A6A7-59AFF6268B31 */ { 0xAC,0xF1,0x3E,0x61,0xF4,0xA0,0x49,0x74,0xA6,0xA7,0x59,0xAF,0xF6,0x26,0x8B,0x31 }; +BMD_CONST REFIID IID_IDeckLinkMemoryAllocator = /* B36EB6E7-9D29-4AA8-92EF-843B87A289E8 */ { 0xB3,0x6E,0xB6,0xE7,0x9D,0x29,0x4A,0xA8,0x92,0xEF,0x84,0x3B,0x87,0xA2,0x89,0xE8 }; +BMD_CONST REFIID IID_IDeckLinkAudioOutputCallback = /* 403C681B-7F46-4A12-B993-2BB127084EE6 */ { 0x40,0x3C,0x68,0x1B,0x7F,0x46,0x4A,0x12,0xB9,0x93,0x2B,0xB1,0x27,0x08,0x4E,0xE6 }; +BMD_CONST REFIID IID_IDeckLinkIterator = /* 50FB36CD-3063-4B73-BDBB-958087F2D8BA */ { 0x50,0xFB,0x36,0xCD,0x30,0x63,0x4B,0x73,0xBD,0xBB,0x95,0x80,0x87,0xF2,0xD8,0xBA }; +BMD_CONST REFIID IID_IDeckLinkAPIInformation = /* 7BEA3C68-730D-4322-AF34-8A7152B532A4 */ { 0x7B,0xEA,0x3C,0x68,0x73,0x0D,0x43,0x22,0xAF,0x34,0x8A,0x71,0x52,0xB5,0x32,0xA4 }; +BMD_CONST REFIID IID_IDeckLinkOutput = /* BE2D9020-461E-442F-84B7-E949CB953B9D */ { 0xBE,0x2D,0x90,0x20,0x46,0x1E,0x44,0x2F,0x84,0xB7,0xE9,0x49,0xCB,0x95,0x3B,0x9D }; +BMD_CONST REFIID IID_IDeckLinkInput = /* C21CDB6E-F414-46E4-A636-80A566E0ED37 */ { 0xC2,0x1C,0xDB,0x6E,0xF4,0x14,0x46,0xE4,0xA6,0x36,0x80,0xA5,0x66,0xE0,0xED,0x37 }; +BMD_CONST REFIID IID_IDeckLinkHDMIInputEDID = /* ABBBACBC-45BC-4665-9D92-ACE6E5A97902 */ { 0xAB,0xBB,0xAC,0xBC,0x45,0xBC,0x46,0x65,0x9D,0x92,0xAC,0xE6,0xE5,0xA9,0x79,0x02 }; +BMD_CONST REFIID IID_IDeckLinkEncoderInput = /* F222551D-13DF-4FD8-B587-9D4F19EC12C9 */ { 0xF2,0x22,0x55,0x1D,0x13,0xDF,0x4F,0xD8,0xB5,0x87,0x9D,0x4F,0x19,0xEC,0x12,0xC9 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrame = /* 3F716FE0-F023-4111-BE5D-EF4414C05B17 */ { 0x3F,0x71,0x6F,0xE0,0xF0,0x23,0x41,0x11,0xBE,0x5D,0xEF,0x44,0x14,0xC0,0x5B,0x17 }; +BMD_CONST REFIID IID_IDeckLinkMutableVideoFrame = /* 69E2639F-40DA-4E19-B6F2-20ACE815C390 */ { 0x69,0xE2,0x63,0x9F,0x40,0xDA,0x4E,0x19,0xB6,0xF2,0x20,0xAC,0xE8,0x15,0xC3,0x90 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrame3DExtensions = /* DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7 */ { 0xDA,0x0F,0x7E,0x4A,0xED,0xC7,0x48,0xA8,0x9C,0xDD,0x2D,0xB5,0x1C,0x72,0x9C,0xD7 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrameMetadataExtensions = /* E232A5B7-4DB4-44C9-9152-F47C12E5F051 */ { 0xE2,0x32,0xA5,0xB7,0x4D,0xB4,0x44,0xC9,0x91,0x52,0xF4,0x7C,0x12,0xE5,0xF0,0x51 }; +BMD_CONST REFIID IID_IDeckLinkVideoInputFrame = /* 05CFE374-537C-4094-9A57-680525118F44 */ { 0x05,0xCF,0xE3,0x74,0x53,0x7C,0x40,0x94,0x9A,0x57,0x68,0x05,0x25,0x11,0x8F,0x44 }; +BMD_CONST REFIID IID_IDeckLinkAncillaryPacket = /* CC5BBF7E-029C-4D3B-9158-6000EF5E3670 */ { 0xCC,0x5B,0xBF,0x7E,0x02,0x9C,0x4D,0x3B,0x91,0x58,0x60,0x00,0xEF,0x5E,0x36,0x70 }; +BMD_CONST REFIID IID_IDeckLinkAncillaryPacketIterator = /* 3FC8994B-88FB-4C17-968F-9AAB69D964A7 */ { 0x3F,0xC8,0x99,0x4B,0x88,0xFB,0x4C,0x17,0x96,0x8F,0x9A,0xAB,0x69,0xD9,0x64,0xA7 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrameAncillaryPackets = /* 6C186C0F-459E-41D8-AEE2-4812D81AEE68 */ { 0x6C,0x18,0x6C,0x0F,0x45,0x9E,0x41,0xD8,0xAE,0xE2,0x48,0x12,0xD8,0x1A,0xEE,0x68 }; +BMD_CONST REFIID IID_IDeckLinkVideoFrameAncillary = /* 732E723C-D1A4-4E29-9E8E-4A88797A0004 */ { 0x73,0x2E,0x72,0x3C,0xD1,0xA4,0x4E,0x29,0x9E,0x8E,0x4A,0x88,0x79,0x7A,0x00,0x04 }; +BMD_CONST REFIID IID_IDeckLinkEncoderPacket = /* B693F36C-316E-4AF1-B6C2-F389A4BCA620 */ { 0xB6,0x93,0xF3,0x6C,0x31,0x6E,0x4A,0xF1,0xB6,0xC2,0xF3,0x89,0xA4,0xBC,0xA6,0x20 }; +BMD_CONST REFIID IID_IDeckLinkEncoderVideoPacket = /* 4E7FD944-E8C7-4EAC-B8C0-7B77F80F5AE0 */ { 0x4E,0x7F,0xD9,0x44,0xE8,0xC7,0x4E,0xAC,0xB8,0xC0,0x7B,0x77,0xF8,0x0F,0x5A,0xE0 }; +BMD_CONST REFIID IID_IDeckLinkEncoderAudioPacket = /* 49E8EDC8-693B-4E14-8EF6-12C658F5A07A */ { 0x49,0xE8,0xED,0xC8,0x69,0x3B,0x4E,0x14,0x8E,0xF6,0x12,0xC6,0x58,0xF5,0xA0,0x7A }; +BMD_CONST REFIID IID_IDeckLinkH265NALPacket = /* 639C8E0B-68D5-4BDE-A6D4-95F3AEAFF2E7 */ { 0x63,0x9C,0x8E,0x0B,0x68,0xD5,0x4B,0xDE,0xA6,0xD4,0x95,0xF3,0xAE,0xAF,0xF2,0xE7 }; +BMD_CONST REFIID IID_IDeckLinkAudioInputPacket = /* E43D5870-2894-11DE-8C30-0800200C9A66 */ { 0xE4,0x3D,0x58,0x70,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66 }; +BMD_CONST REFIID IID_IDeckLinkScreenPreviewCallback = /* B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438 */ { 0xB1,0xD3,0xF4,0x9A,0x85,0xFE,0x4C,0x5D,0x95,0xC8,0x0B,0x5D,0x5D,0xCC,0xD4,0x38 }; +BMD_CONST REFIID IID_IDeckLinkCocoaScreenPreviewCallback = /* D174152F-8F96-4C07-83A5-DD5F5AF0A2AA */ { 0xD1,0x74,0x15,0x2F,0x8F,0x96,0x4C,0x07,0x83,0xA5,0xDD,0x5F,0x5A,0xF0,0xA2,0xAA }; +BMD_CONST REFIID IID_IDeckLinkGLScreenPreviewHelper = /* 504E2209-CAC7-4C1A-9FB4-C5BB6274D22F */ { 0x50,0x4E,0x22,0x09,0xCA,0xC7,0x4C,0x1A,0x9F,0xB4,0xC5,0xBB,0x62,0x74,0xD2,0x2F }; +BMD_CONST REFIID IID_IDeckLinkMetalScreenPreviewHelper = /* 1AB252C5-DACB-4AE8-A58B-5320DE9CE373 */ { 0x1A,0xB2,0x52,0xC5,0xDA,0xCB,0x4A,0xE8,0xA5,0x8B,0x53,0x20,0xDE,0x9C,0xE3,0x73 }; +BMD_CONST REFIID IID_IDeckLinkNotificationCallback = /* B002A1EC-070D-4288-8289-BD5D36E5FF0D */ { 0xB0,0x02,0xA1,0xEC,0x07,0x0D,0x42,0x88,0x82,0x89,0xBD,0x5D,0x36,0xE5,0xFF,0x0D }; +BMD_CONST REFIID IID_IDeckLinkNotification = /* B85DF4C8-BDF5-47C1-8064-28162EBDD4EB */ { 0xB8,0x5D,0xF4,0xC8,0xBD,0xF5,0x47,0xC1,0x80,0x64,0x28,0x16,0x2E,0xBD,0xD4,0xEB }; +BMD_CONST REFIID IID_IDeckLinkProfileAttributes = /* 17D4BF8E-4911-473A-80A0-731CF6FF345B */ { 0x17,0xD4,0xBF,0x8E,0x49,0x11,0x47,0x3A,0x80,0xA0,0x73,0x1C,0xF6,0xFF,0x34,0x5B }; +BMD_CONST REFIID IID_IDeckLinkProfileIterator = /* 29E5A8C0-8BE4-46EB-93AC-31DAAB5B7BF2 */ { 0x29,0xE5,0xA8,0xC0,0x8B,0xE4,0x46,0xEB,0x93,0xAC,0x31,0xDA,0xAB,0x5B,0x7B,0xF2 }; +BMD_CONST REFIID IID_IDeckLinkProfile = /* 16093466-674A-432B-9DA0-1AC2C5A8241C */ { 0x16,0x09,0x34,0x66,0x67,0x4A,0x43,0x2B,0x9D,0xA0,0x1A,0xC2,0xC5,0xA8,0x24,0x1C }; +BMD_CONST REFIID IID_IDeckLinkProfileCallback = /* A4F9341E-97AA-4E04-8935-15F809898CEA */ { 0xA4,0xF9,0x34,0x1E,0x97,0xAA,0x4E,0x04,0x89,0x35,0x15,0xF8,0x09,0x89,0x8C,0xEA }; +BMD_CONST REFIID IID_IDeckLinkProfileManager = /* 30D41429-3998-4B6D-84F8-78C94A797C6E */ { 0x30,0xD4,0x14,0x29,0x39,0x98,0x4B,0x6D,0x84,0xF8,0x78,0xC9,0x4A,0x79,0x7C,0x6E }; +BMD_CONST REFIID IID_IDeckLinkStatus = /* 5F558200-4028-49BC-BEAC-DB3FA4A96E46 */ { 0x5F,0x55,0x82,0x00,0x40,0x28,0x49,0xBC,0xBE,0xAC,0xDB,0x3F,0xA4,0xA9,0x6E,0x46 }; +BMD_CONST REFIID IID_IDeckLinkKeyer = /* 89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3 */ { 0x89,0xAF,0xCA,0xF5,0x65,0xF8,0x42,0x1E,0x98,0xF7,0x96,0xFE,0x5F,0x5B,0xFB,0xA3 }; +BMD_CONST REFIID IID_IDeckLinkVideoConversion = /* 3BBCB8A2-DA2C-42D9-B5D8-88083644E99A */ { 0x3B,0xBC,0xB8,0xA2,0xDA,0x2C,0x42,0xD9,0xB5,0xD8,0x88,0x08,0x36,0x44,0xE9,0x9A }; +BMD_CONST REFIID IID_IDeckLinkDeviceNotificationCallback = /* 4997053B-0ADF-4CC8-AC70-7A50C4BE728F */ { 0x49,0x97,0x05,0x3B,0x0A,0xDF,0x4C,0xC8,0xAC,0x70,0x7A,0x50,0xC4,0xBE,0x72,0x8F }; +BMD_CONST REFIID IID_IDeckLinkDiscovery = /* CDBF631C-BC76-45FA-B44D-C55059BC6101 */ { 0xCD,0xBF,0x63,0x1C,0xBC,0x76,0x45,0xFA,0xB4,0x4D,0xC5,0x50,0x59,0xBC,0x61,0x01 }; + +/* Enum BMDVideoOutputFlags - Flags to control the output of ancillary data along with video. */ + +typedef uint32_t BMDVideoOutputFlags; +enum _BMDVideoOutputFlags { + bmdVideoOutputFlagDefault = 0, + bmdVideoOutputVANC = 1 << 0, + bmdVideoOutputVITC = 1 << 1, + bmdVideoOutputRP188 = 1 << 2, + bmdVideoOutputDualStream3D = 1 << 4, + bmdVideoOutputSynchronizeToPlaybackGroup = 1 << 6 +}; + +/* Enum BMDSupportedVideoModeFlags - Flags to describe supported video modes */ + +typedef uint32_t BMDSupportedVideoModeFlags; +enum _BMDSupportedVideoModeFlags { + bmdSupportedVideoModeDefault = 0, + bmdSupportedVideoModeKeying = 1 << 0, + bmdSupportedVideoModeDualStream3D = 1 << 1, + bmdSupportedVideoModeSDISingleLink = 1 << 2, + bmdSupportedVideoModeSDIDualLink = 1 << 3, + bmdSupportedVideoModeSDIQuadLink = 1 << 4, + bmdSupportedVideoModeInAnyProfile = 1 << 5 +}; + +/* Enum BMDPacketType - Type of packet */ + +typedef uint32_t BMDPacketType; +enum _BMDPacketType { + bmdPacketTypeStreamInterruptedMarker = /* 'sint' */ 0x73696E74, // A packet of this type marks the time when a video stream was interrupted, for example by a disconnected cable + bmdPacketTypeStreamData = /* 'sdat' */ 0x73646174 // Regular stream data +}; + +/* Enum BMDFrameFlags - Frame flags */ + +typedef uint32_t BMDFrameFlags; +enum _BMDFrameFlags { + bmdFrameFlagDefault = 0, + bmdFrameFlagFlipVertical = 1 << 0, + bmdFrameContainsHDRMetadata = 1 << 1, + + /* Flags that are applicable only to instances of IDeckLinkVideoInputFrame */ + + bmdFrameCapturedAsPsF = 1 << 30, + bmdFrameHasNoInputSource = 1 << 31 +}; + +/* Enum BMDVideoInputFlags - Flags applicable to video input */ + +typedef uint32_t BMDVideoInputFlags; +enum _BMDVideoInputFlags { + bmdVideoInputFlagDefault = 0, + bmdVideoInputEnableFormatDetection = 1 << 0, + bmdVideoInputDualStream3D = 1 << 1, + bmdVideoInputSynchronizeToCaptureGroup = 1 << 2 +}; + +/* Enum BMDVideoInputFormatChangedEvents - Bitmask passed to the VideoInputFormatChanged notification to identify the properties of the input signal that have changed */ + +typedef uint32_t BMDVideoInputFormatChangedEvents; +enum _BMDVideoInputFormatChangedEvents { + bmdVideoInputDisplayModeChanged = 1 << 0, + bmdVideoInputFieldDominanceChanged = 1 << 1, + bmdVideoInputColorspaceChanged = 1 << 2 +}; + +/* Enum BMDDetectedVideoInputFormatFlags - Flags passed to the VideoInputFormatChanged notification to describe the detected video input signal */ + +typedef uint32_t BMDDetectedVideoInputFormatFlags; +enum _BMDDetectedVideoInputFormatFlags { + bmdDetectedVideoInputYCbCr422 = 1 << 0, + bmdDetectedVideoInputRGB444 = 1 << 1, + bmdDetectedVideoInputDualStream3D = 1 << 2, + bmdDetectedVideoInput12BitDepth = 1 << 3, + bmdDetectedVideoInput10BitDepth = 1 << 4, + bmdDetectedVideoInput8BitDepth = 1 << 5 +}; + +/* Enum BMDDeckLinkCapturePassthroughMode - Enumerates whether the video output is electrically connected to the video input or if the clean switching mode is enabled */ + +typedef uint32_t BMDDeckLinkCapturePassthroughMode; +enum _BMDDeckLinkCapturePassthroughMode { + bmdDeckLinkCapturePassthroughModeDisabled = /* 'pdis' */ 0x70646973, + bmdDeckLinkCapturePassthroughModeDirect = /* 'pdir' */ 0x70646972, + bmdDeckLinkCapturePassthroughModeCleanSwitch = /* 'pcln' */ 0x70636C6E +}; + +/* Enum BMDOutputFrameCompletionResult - Frame Completion Callback */ + +typedef uint32_t BMDOutputFrameCompletionResult; +enum _BMDOutputFrameCompletionResult { + bmdOutputFrameCompleted, + bmdOutputFrameDisplayedLate, + bmdOutputFrameDropped, + bmdOutputFrameFlushed +}; + +/* Enum BMDReferenceStatus - GenLock input status */ + +typedef uint32_t BMDReferenceStatus; +enum _BMDReferenceStatus { + bmdReferenceUnlocked = 0, + bmdReferenceNotSupportedByHardware = 1 << 0, + bmdReferenceLocked = 1 << 1 +}; + +/* Enum BMDAudioFormat - Audio Format */ + +typedef uint32_t BMDAudioFormat; +enum _BMDAudioFormat { + bmdAudioFormatPCM = /* 'lpcm' */ 0x6C70636D // Linear signed PCM samples +}; + +/* Enum BMDAudioSampleRate - Audio sample rates supported for output/input */ + +typedef uint32_t BMDAudioSampleRate; +enum _BMDAudioSampleRate { + bmdAudioSampleRate48kHz = 48000 +}; + +/* Enum BMDAudioSampleType - Audio sample sizes supported for output/input */ + +typedef uint32_t BMDAudioSampleType; +enum _BMDAudioSampleType { + bmdAudioSampleType16bitInteger = 16, + bmdAudioSampleType32bitInteger = 32 +}; + +/* Enum BMDAudioOutputStreamType - Audio output stream type */ + +typedef uint32_t BMDAudioOutputStreamType; +enum _BMDAudioOutputStreamType { + bmdAudioOutputStreamContinuous, + bmdAudioOutputStreamContinuousDontResample, + bmdAudioOutputStreamTimestamped +}; + +/* Enum BMDAncillaryPacketFormat - Ancillary packet format */ + +typedef uint32_t BMDAncillaryPacketFormat; +enum _BMDAncillaryPacketFormat { + bmdAncillaryPacketFormatUInt8 = /* 'ui08' */ 0x75693038, + bmdAncillaryPacketFormatUInt16 = /* 'ui16' */ 0x75693136, + bmdAncillaryPacketFormatYCbCr10 = /* 'v210' */ 0x76323130 +}; + +/* Enum BMDTimecodeFormat - Timecode formats for frame metadata */ + +typedef uint32_t BMDTimecodeFormat; +enum _BMDTimecodeFormat { + bmdTimecodeRP188VITC1 = /* 'rpv1' */ 0x72707631, // RP188 timecode where DBB1 equals VITC1 (line 9) + bmdTimecodeRP188VITC2 = /* 'rp12' */ 0x72703132, // RP188 timecode where DBB1 equals VITC2 (line 9 for progressive or line 571 for interlaced/PsF) + bmdTimecodeRP188LTC = /* 'rplt' */ 0x72706C74, // RP188 timecode where DBB1 equals LTC (line 10) + bmdTimecodeRP188HighFrameRate = /* 'rphr' */ 0x72706872, // RP188 timecode where DBB1 is an HFRTC (SMPTE ST 12-3), the only timecode allowing the frame value to go above 30 + bmdTimecodeRP188Any = /* 'rp18' */ 0x72703138, // Convenience for capture, returning the first valid timecode in {HFRTC (if supported), VITC1, VITC2, LTC } + bmdTimecodeVITC = /* 'vitc' */ 0x76697463, + bmdTimecodeVITCField2 = /* 'vit2' */ 0x76697432, + bmdTimecodeSerial = /* 'seri' */ 0x73657269 +}; + +/* Enum BMDAnalogVideoFlags - Analog video display flags */ + +typedef uint32_t BMDAnalogVideoFlags; +enum _BMDAnalogVideoFlags { + bmdAnalogVideoFlagCompositeSetup75 = 1 << 0, + bmdAnalogVideoFlagComponentBetacamLevels = 1 << 1 +}; + +/* Enum BMDAudioOutputAnalogAESSwitch - Audio output Analog/AESEBU switch */ + +typedef uint32_t BMDAudioOutputAnalogAESSwitch; +enum _BMDAudioOutputAnalogAESSwitch { + bmdAudioOutputSwitchAESEBU = /* 'aes ' */ 0x61657320, + bmdAudioOutputSwitchAnalog = /* 'anlg' */ 0x616E6C67 +}; + +/* Enum BMDVideoOutputConversionMode - Video/audio conversion mode */ + +typedef uint32_t BMDVideoOutputConversionMode; +enum _BMDVideoOutputConversionMode { + bmdNoVideoOutputConversion = /* 'none' */ 0x6E6F6E65, + bmdVideoOutputLetterboxDownconversion = /* 'ltbx' */ 0x6C746278, + bmdVideoOutputAnamorphicDownconversion = /* 'amph' */ 0x616D7068, + bmdVideoOutputHD720toHD1080Conversion = /* '720c' */ 0x37323063, + bmdVideoOutputHardwareLetterboxDownconversion = /* 'HWlb' */ 0x48576C62, + bmdVideoOutputHardwareAnamorphicDownconversion = /* 'HWam' */ 0x4857616D, + bmdVideoOutputHardwareCenterCutDownconversion = /* 'HWcc' */ 0x48576363, + bmdVideoOutputHardware720p1080pCrossconversion = /* 'xcap' */ 0x78636170, + bmdVideoOutputHardwareAnamorphic720pUpconversion = /* 'ua7p' */ 0x75613770, + bmdVideoOutputHardwareAnamorphic1080iUpconversion = /* 'ua1i' */ 0x75613169, + bmdVideoOutputHardwareAnamorphic149To720pUpconversion = /* 'u47p' */ 0x75343770, + bmdVideoOutputHardwareAnamorphic149To1080iUpconversion = /* 'u41i' */ 0x75343169, + bmdVideoOutputHardwarePillarbox720pUpconversion = /* 'up7p' */ 0x75703770, + bmdVideoOutputHardwarePillarbox1080iUpconversion = /* 'up1i' */ 0x75703169 +}; + +/* Enum BMDVideoInputConversionMode - Video input conversion mode */ + +typedef uint32_t BMDVideoInputConversionMode; +enum _BMDVideoInputConversionMode { + bmdNoVideoInputConversion = /* 'none' */ 0x6E6F6E65, + bmdVideoInputLetterboxDownconversionFromHD1080 = /* '10lb' */ 0x31306C62, + bmdVideoInputAnamorphicDownconversionFromHD1080 = /* '10am' */ 0x3130616D, + bmdVideoInputLetterboxDownconversionFromHD720 = /* '72lb' */ 0x37326C62, + bmdVideoInputAnamorphicDownconversionFromHD720 = /* '72am' */ 0x3732616D, + bmdVideoInputLetterboxUpconversion = /* 'lbup' */ 0x6C627570, + bmdVideoInputAnamorphicUpconversion = /* 'amup' */ 0x616D7570 +}; + +/* Enum BMDVideo3DPackingFormat - Video 3D packing format */ + +typedef uint32_t BMDVideo3DPackingFormat; +enum _BMDVideo3DPackingFormat { + bmdVideo3DPackingSidebySideHalf = /* 'sbsh' */ 0x73627368, + bmdVideo3DPackingLinebyLine = /* 'lbyl' */ 0x6C62796C, + bmdVideo3DPackingTopAndBottom = /* 'tabo' */ 0x7461626F, + bmdVideo3DPackingFramePacking = /* 'frpk' */ 0x6672706B, + bmdVideo3DPackingLeftOnly = /* 'left' */ 0x6C656674, + bmdVideo3DPackingRightOnly = /* 'righ' */ 0x72696768 +}; + +/* Enum BMDIdleVideoOutputOperation - Video output operation when not playing video */ + +typedef uint32_t BMDIdleVideoOutputOperation; +enum _BMDIdleVideoOutputOperation { + bmdIdleVideoOutputBlack = /* 'blac' */ 0x626C6163, + bmdIdleVideoOutputLastFrame = /* 'lafa' */ 0x6C616661 +}; + +/* Enum BMDVideoEncoderFrameCodingMode - Video frame coding mode */ + +typedef uint32_t BMDVideoEncoderFrameCodingMode; +enum _BMDVideoEncoderFrameCodingMode { + bmdVideoEncoderFrameCodingModeInter = /* 'inte' */ 0x696E7465, + bmdVideoEncoderFrameCodingModeIntra = /* 'intr' */ 0x696E7472 +}; + +/* Enum BMDDNxHRLevel - DNxHR Levels */ + +typedef uint32_t BMDDNxHRLevel; +enum _BMDDNxHRLevel { + bmdDNxHRLevelSQ = /* 'dnsq' */ 0x646E7371, + bmdDNxHRLevelLB = /* 'dnlb' */ 0x646E6C62, + bmdDNxHRLevelHQ = /* 'dnhq' */ 0x646E6871, + bmdDNxHRLevelHQX = /* 'dhqx' */ 0x64687178, + bmdDNxHRLevel444 = /* 'd444' */ 0x64343434 +}; + +/* Enum BMDLinkConfiguration - Video link configuration */ + +typedef uint32_t BMDLinkConfiguration; +enum _BMDLinkConfiguration { + bmdLinkConfigurationSingleLink = /* 'lcsl' */ 0x6C63736C, + bmdLinkConfigurationDualLink = /* 'lcdl' */ 0x6C63646C, + bmdLinkConfigurationQuadLink = /* 'lcql' */ 0x6C63716C +}; + +/* Enum BMDDeviceInterface - Device interface type */ + +typedef uint32_t BMDDeviceInterface; +enum _BMDDeviceInterface { + bmdDeviceInterfacePCI = /* 'pci ' */ 0x70636920, + bmdDeviceInterfaceUSB = /* 'usb ' */ 0x75736220, + bmdDeviceInterfaceThunderbolt = /* 'thun' */ 0x7468756E +}; + +/* Enum BMDColorspace - Colorspace */ + +typedef uint32_t BMDColorspace; +enum _BMDColorspace { + bmdColorspaceRec601 = /* 'r601' */ 0x72363031, + bmdColorspaceRec709 = /* 'r709' */ 0x72373039, + bmdColorspaceRec2020 = /* '2020' */ 0x32303230 +}; + +/* Enum BMDDynamicRange - SDR or HDR */ + +typedef uint32_t BMDDynamicRange; +enum _BMDDynamicRange { + bmdDynamicRangeSDR = 0, // Standard Dynamic Range in accordance with SMPTE ST 2036-1 + bmdDynamicRangeHDRStaticPQ = 1 << 29, // High Dynamic Range PQ in accordance with SMPTE ST 2084 + bmdDynamicRangeHDRStaticHLG = 1 << 30 // High Dynamic Range HLG in accordance with ITU-R BT.2100-0 +}; + +/* Enum BMDDeckLinkHDMIInputEDIDID - DeckLink HDMI Input EDID ID */ + +typedef uint32_t BMDDeckLinkHDMIInputEDIDID; +enum _BMDDeckLinkHDMIInputEDIDID { + + /* Integers */ + + bmdDeckLinkHDMIInputEDIDDynamicRange = /* 'HIDy' */ 0x48494479 // Parameter is of type BMDDynamicRange. Default is (bmdDynamicRangeSDR|bmdDynamicRangeHDRStaticPQ) +}; + +/* Enum BMDDeckLinkFrameMetadataID - DeckLink Frame Metadata ID */ + +typedef uint32_t BMDDeckLinkFrameMetadataID; +enum _BMDDeckLinkFrameMetadataID { + + /* Colorspace Metadata - Integers */ + + bmdDeckLinkFrameMetadataColorspace = /* 'cspc' */ 0x63737063, // Colorspace of video frame (see BMDColorspace) + + /* HDR Metadata - Integers */ + + bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc = /* 'eotf' */ 0x656F7466, // EOTF in range 0-7 as per CEA 861.3 + + /* HDR Metadata - Floats */ + + bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX = /* 'hdrx' */ 0x68647278, // Red display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY = /* 'hdry' */ 0x68647279, // Red display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX = /* 'hdgx' */ 0x68646778, // Green display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY = /* 'hdgy' */ 0x68646779, // Green display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX = /* 'hdbx' */ 0x68646278, // Blue display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY = /* 'hdby' */ 0x68646279, // Blue display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRWhitePointX = /* 'hdwx' */ 0x68647778, // White point in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRWhitePointY = /* 'hdwy' */ 0x68647779, // White point in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance = /* 'hdml' */ 0x68646D6C, // Max display mastering luminance in range 1 cd/m2 - 65535 cd/m2 + bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance = /* 'hmil' */ 0x686D696C, // Min display mastering luminance in range 0.0001 cd/m2 - 6.5535 cd/m2 + bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel = /* 'mcll' */ 0x6D636C6C, // Maximum Content Light Level in range 1 cd/m2 - 65535 cd/m2 + bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel = /* 'fall' */ 0x66616C6C // Maximum Frame Average Light Level in range 1 cd/m2 - 65535 cd/m2 +}; + +/* Enum BMDProfileID - Identifies a profile */ + +typedef uint32_t BMDProfileID; +enum _BMDProfileID { + bmdProfileOneSubDeviceFullDuplex = /* '1dfd' */ 0x31646664, + bmdProfileOneSubDeviceHalfDuplex = /* '1dhd' */ 0x31646864, + bmdProfileTwoSubDevicesFullDuplex = /* '2dfd' */ 0x32646664, + bmdProfileTwoSubDevicesHalfDuplex = /* '2dhd' */ 0x32646864, + bmdProfileFourSubDevicesHalfDuplex = /* '4dhd' */ 0x34646864 +}; + +/* Enum BMDHDMITimecodePacking - Packing form of timecode on HDMI */ + +typedef uint32_t BMDHDMITimecodePacking; +enum _BMDHDMITimecodePacking { + bmdHDMITimecodePackingIEEEOUI000085 = 0x00008500, + bmdHDMITimecodePackingIEEEOUI080046 = 0x08004601, + bmdHDMITimecodePackingIEEEOUI5CF9F0 = 0x5CF9F003 +}; + +/* Enum BMDInternalKeyingAncillaryDataSource - Source for VANC and timecode data when performing internal keying */ + +typedef uint32_t BMDInternalKeyingAncillaryDataSource; +enum _BMDInternalKeyingAncillaryDataSource { + bmdInternalKeyingUsesAncillaryDataFromInputSignal = /* 'ikai' */ 0x696B6169, + bmdInternalKeyingUsesAncillaryDataFromKeyFrame = /* 'ikak' */ 0x696B616B +}; + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkAttributeID; +enum _BMDDeckLinkAttributeID { + + /* Flags */ + + BMDDeckLinkSupportsInternalKeying = /* 'keyi' */ 0x6B657969, + BMDDeckLinkSupportsExternalKeying = /* 'keye' */ 0x6B657965, + BMDDeckLinkSupportsInputFormatDetection = /* 'infd' */ 0x696E6664, + BMDDeckLinkHasReferenceInput = /* 'hrin' */ 0x6872696E, + BMDDeckLinkHasSerialPort = /* 'hspt' */ 0x68737074, + BMDDeckLinkHasAnalogVideoOutputGain = /* 'avog' */ 0x61766F67, + BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain = /* 'ovog' */ 0x6F766F67, + BMDDeckLinkHasVideoInputAntiAliasingFilter = /* 'aafl' */ 0x6161666C, + BMDDeckLinkHasBypass = /* 'byps' */ 0x62797073, + BMDDeckLinkSupportsClockTimingAdjustment = /* 'ctad' */ 0x63746164, + BMDDeckLinkSupportsFullFrameReferenceInputTimingOffset = /* 'frin' */ 0x6672696E, + BMDDeckLinkSupportsSMPTELevelAOutput = /* 'lvla' */ 0x6C766C61, + BMDDeckLinkSupportsAutoSwitchingPPsFOnInput = /* 'apsf' */ 0x61707366, + BMDDeckLinkSupportsDualLinkSDI = /* 'sdls' */ 0x73646C73, + BMDDeckLinkSupportsQuadLinkSDI = /* 'sqls' */ 0x73716C73, + BMDDeckLinkSupportsIdleOutput = /* 'idou' */ 0x69646F75, + BMDDeckLinkVANCRequires10BitYUVVideoFrames = /* 'vioY' */ 0x76696F59, // Legacy product requires v210 active picture for IDeckLinkVideoFrameAncillaryPackets or 10-bit VANC + BMDDeckLinkHasLTCTimecodeInput = /* 'hltc' */ 0x686C7463, + BMDDeckLinkSupportsHDRMetadata = /* 'hdrm' */ 0x6864726D, + BMDDeckLinkSupportsColorspaceMetadata = /* 'cmet' */ 0x636D6574, + BMDDeckLinkSupportsHDMITimecode = /* 'htim' */ 0x6874696D, + BMDDeckLinkSupportsHighFrameRateTimecode = /* 'HFRT' */ 0x48465254, + BMDDeckLinkSupportsSynchronizeToCaptureGroup = /* 'stcg' */ 0x73746367, + BMDDeckLinkSupportsSynchronizeToPlaybackGroup = /* 'stpg' */ 0x73747067, + + /* Integers */ + + BMDDeckLinkMaximumAudioChannels = /* 'mach' */ 0x6D616368, + BMDDeckLinkMaximumAnalogAudioInputChannels = /* 'iach' */ 0x69616368, + BMDDeckLinkMaximumAnalogAudioOutputChannels = /* 'aach' */ 0x61616368, + BMDDeckLinkNumberOfSubDevices = /* 'nsbd' */ 0x6E736264, + BMDDeckLinkSubDeviceIndex = /* 'subi' */ 0x73756269, + BMDDeckLinkPersistentID = /* 'peid' */ 0x70656964, + BMDDeckLinkDeviceGroupID = /* 'dgid' */ 0x64676964, + BMDDeckLinkTopologicalID = /* 'toid' */ 0x746F6964, + BMDDeckLinkVideoOutputConnections = /* 'vocn' */ 0x766F636E, // Returns a BMDVideoConnection bit field + BMDDeckLinkVideoInputConnections = /* 'vicn' */ 0x7669636E, // Returns a BMDVideoConnection bit field + BMDDeckLinkAudioOutputConnections = /* 'aocn' */ 0x616F636E, // Returns a BMDAudioConnection bit field + BMDDeckLinkAudioInputConnections = /* 'aicn' */ 0x6169636E, // Returns a BMDAudioConnection bit field + BMDDeckLinkVideoIOSupport = /* 'vios' */ 0x76696F73, // Returns a BMDVideoIOSupport bit field + BMDDeckLinkDeckControlConnections = /* 'dccn' */ 0x6463636E, // Returns a BMDDeckControlConnection bit field + BMDDeckLinkDeviceInterface = /* 'dbus' */ 0x64627573, // Returns a BMDDeviceInterface + BMDDeckLinkAudioInputRCAChannelCount = /* 'airc' */ 0x61697263, + BMDDeckLinkAudioInputXLRChannelCount = /* 'aixc' */ 0x61697863, + BMDDeckLinkAudioOutputRCAChannelCount = /* 'aorc' */ 0x616F7263, + BMDDeckLinkAudioOutputXLRChannelCount = /* 'aoxc' */ 0x616F7863, + BMDDeckLinkProfileID = /* 'prid' */ 0x70726964, // Returns a BMDProfileID + BMDDeckLinkDuplex = /* 'dupx' */ 0x64757078, + BMDDeckLinkMinimumPrerollFrames = /* 'mprf' */ 0x6D707266, + BMDDeckLinkSupportedDynamicRange = /* 'sudr' */ 0x73756472, + + /* Floats */ + + BMDDeckLinkVideoInputGainMinimum = /* 'vigm' */ 0x7669676D, + BMDDeckLinkVideoInputGainMaximum = /* 'vigx' */ 0x76696778, + BMDDeckLinkVideoOutputGainMinimum = /* 'vogm' */ 0x766F676D, + BMDDeckLinkVideoOutputGainMaximum = /* 'vogx' */ 0x766F6778, + BMDDeckLinkMicrophoneInputGainMinimum = /* 'migm' */ 0x6D69676D, + BMDDeckLinkMicrophoneInputGainMaximum = /* 'migx' */ 0x6D696778, + + /* Strings */ + + BMDDeckLinkSerialPortDeviceName = /* 'slpn' */ 0x736C706E, + BMDDeckLinkVendorName = /* 'vndr' */ 0x766E6472, + BMDDeckLinkDisplayName = /* 'dspn' */ 0x6473706E, + BMDDeckLinkModelName = /* 'mdln' */ 0x6D646C6E, + BMDDeckLinkDeviceHandle = /* 'devh' */ 0x64657668 +}; + +/* Enum BMDDeckLinkAPIInformationID - DeckLinkAPI information ID */ + +typedef uint32_t BMDDeckLinkAPIInformationID; +enum _BMDDeckLinkAPIInformationID { + + /* Integer or String */ + + BMDDeckLinkAPIVersion = /* 'vers' */ 0x76657273 +}; + +/* Enum BMDDeckLinkStatusID - DeckLink Status ID */ + +typedef uint32_t BMDDeckLinkStatusID; +enum _BMDDeckLinkStatusID { + + /* Integers */ + + bmdDeckLinkStatusDetectedVideoInputMode = /* 'dvim' */ 0x6476696D, + bmdDeckLinkStatusDetectedVideoInputFormatFlags = /* 'dvff' */ 0x64766666, + bmdDeckLinkStatusDetectedVideoInputFieldDominance = /* 'dvfd' */ 0x64766664, + bmdDeckLinkStatusDetectedVideoInputColorspace = /* 'dscl' */ 0x6473636C, + bmdDeckLinkStatusDetectedVideoInputDynamicRange = /* 'dsdr' */ 0x64736472, + bmdDeckLinkStatusDetectedSDILinkConfiguration = /* 'dslc' */ 0x64736C63, + bmdDeckLinkStatusCurrentVideoInputMode = /* 'cvim' */ 0x6376696D, + bmdDeckLinkStatusCurrentVideoInputPixelFormat = /* 'cvip' */ 0x63766970, + bmdDeckLinkStatusCurrentVideoInputFlags = /* 'cvif' */ 0x63766966, + bmdDeckLinkStatusCurrentVideoOutputMode = /* 'cvom' */ 0x63766F6D, + bmdDeckLinkStatusCurrentVideoOutputFlags = /* 'cvof' */ 0x63766F66, + bmdDeckLinkStatusPCIExpressLinkWidth = /* 'pwid' */ 0x70776964, + bmdDeckLinkStatusPCIExpressLinkSpeed = /* 'plnk' */ 0x706C6E6B, + bmdDeckLinkStatusLastVideoOutputPixelFormat = /* 'opix' */ 0x6F706978, + bmdDeckLinkStatusReferenceSignalMode = /* 'refm' */ 0x7265666D, + bmdDeckLinkStatusReferenceSignalFlags = /* 'reff' */ 0x72656666, + bmdDeckLinkStatusBusy = /* 'busy' */ 0x62757379, + bmdDeckLinkStatusInterchangeablePanelType = /* 'icpt' */ 0x69637074, + bmdDeckLinkStatusDeviceTemperature = /* 'dtmp' */ 0x64746D70, + + /* Flags */ + + bmdDeckLinkStatusVideoInputSignalLocked = /* 'visl' */ 0x7669736C, + bmdDeckLinkStatusReferenceSignalLocked = /* 'refl' */ 0x7265666C, + + /* Bytes */ + + bmdDeckLinkStatusReceivedEDID = /* 'edid' */ 0x65646964 +}; + +/* Enum BMDDeckLinkVideoStatusFlags - */ + +typedef uint32_t BMDDeckLinkVideoStatusFlags; +enum _BMDDeckLinkVideoStatusFlags { + bmdDeckLinkVideoStatusPsF = 1 << 0, + bmdDeckLinkVideoStatusDualStream3D = 1 << 1 +}; + +/* Enum BMDDuplexMode - Duplex of the device */ + +typedef uint32_t BMDDuplexMode; +enum _BMDDuplexMode { + bmdDuplexFull = /* 'dxfu' */ 0x64786675, + bmdDuplexHalf = /* 'dxha' */ 0x64786861, + bmdDuplexSimplex = /* 'dxsp' */ 0x64787370, + bmdDuplexInactive = /* 'dxin' */ 0x6478696E +}; + +/* Enum BMDPanelType - The type of interchangeable panel */ + +typedef uint32_t BMDPanelType; +enum _BMDPanelType { + bmdPanelNotDetected = /* 'npnl' */ 0x6E706E6C, + bmdPanelTeranexMiniSmartPanel = /* 'tmsm' */ 0x746D736D +}; + +/* Enum BMDDeviceBusyState - Current device busy state */ + +typedef uint32_t BMDDeviceBusyState; +enum _BMDDeviceBusyState { + bmdDeviceCaptureBusy = 1 << 0, + bmdDevicePlaybackBusy = 1 << 1, + bmdDeviceSerialPortBusy = 1 << 2 +}; + +/* Enum BMDVideoIOSupport - Device video input/output support */ + +typedef uint32_t BMDVideoIOSupport; +enum _BMDVideoIOSupport { + bmdDeviceSupportsCapture = 1 << 0, + bmdDeviceSupportsPlayback = 1 << 1 +}; + +/* Enum BMD3DPreviewFormat - Linked Frame preview format */ + +typedef uint32_t BMD3DPreviewFormat; +enum _BMD3DPreviewFormat { + bmd3DPreviewFormatDefault = /* 'defa' */ 0x64656661, + bmd3DPreviewFormatLeftOnly = /* 'left' */ 0x6C656674, + bmd3DPreviewFormatRightOnly = /* 'righ' */ 0x72696768, + bmd3DPreviewFormatSideBySide = /* 'side' */ 0x73696465, + bmd3DPreviewFormatTopBottom = /* 'topb' */ 0x746F7062 +}; + +/* Enum BMDNotifications - Events that can be subscribed through IDeckLinkNotification */ + +typedef uint32_t BMDNotifications; +enum _BMDNotifications { + bmdPreferencesChanged = /* 'pref' */ 0x70726566, + bmdStatusChanged = /* 'stat' */ 0x73746174 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkVideoOutputCallback; +class IDeckLinkInputCallback; +class IDeckLinkEncoderInputCallback; +class IDeckLinkMemoryAllocator; +class IDeckLinkAudioOutputCallback; +class IDeckLinkIterator; +class IDeckLinkAPIInformation; +class IDeckLinkOutput; +class IDeckLinkInput; +class IDeckLinkHDMIInputEDID; +class IDeckLinkEncoderInput; +class IDeckLinkVideoFrame; +class IDeckLinkMutableVideoFrame; +class IDeckLinkVideoFrame3DExtensions; +class IDeckLinkVideoFrameMetadataExtensions; +class IDeckLinkVideoInputFrame; +class IDeckLinkAncillaryPacket; +class IDeckLinkAncillaryPacketIterator; +class IDeckLinkVideoFrameAncillaryPackets; +class IDeckLinkVideoFrameAncillary; +class IDeckLinkEncoderPacket; +class IDeckLinkEncoderVideoPacket; +class IDeckLinkEncoderAudioPacket; +class IDeckLinkH265NALPacket; +class IDeckLinkAudioInputPacket; +class IDeckLinkScreenPreviewCallback; +class IDeckLinkCocoaScreenPreviewCallback; +class IDeckLinkGLScreenPreviewHelper; +class IDeckLinkMetalScreenPreviewHelper; +class IDeckLinkNotificationCallback; +class IDeckLinkNotification; +class IDeckLinkProfileAttributes; +class IDeckLinkProfileIterator; +class IDeckLinkProfile; +class IDeckLinkProfileCallback; +class IDeckLinkProfileManager; +class IDeckLinkStatus; +class IDeckLinkKeyer; +class IDeckLinkVideoConversion; +class IDeckLinkDeviceNotificationCallback; +class IDeckLinkDiscovery; + +/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */ + +class BMD_PUBLIC IDeckLinkVideoOutputCallback : public IUnknown +{ +public: + virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame* completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0; + virtual HRESULT ScheduledPlaybackHasStopped (void) = 0; + +protected: + virtual ~IDeckLinkVideoOutputCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkInputCallback : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderInputCallback - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkEncoderInputCallback : public IUnknown +{ +public: + virtual HRESULT VideoInputSignalChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoPacketArrived (/* in */ IDeckLinkEncoderVideoPacket* videoPacket) = 0; + virtual HRESULT AudioPacketArrived (/* in */ IDeckLinkEncoderAudioPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkEncoderInputCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkMemoryAllocator - Memory allocator for video frames. */ + +class BMD_PUBLIC IDeckLinkMemoryAllocator : public IUnknown +{ +public: + virtual HRESULT AllocateBuffer (/* in */ uint32_t bufferSize, /* out */ void** allocatedBuffer) = 0; + virtual HRESULT ReleaseBuffer (/* in */ void* buffer) = 0; + virtual HRESULT Commit (void) = 0; + virtual HRESULT Decommit (void) = 0; +}; + +/* Interface IDeckLinkAudioOutputCallback - Optional callback to allow audio samples to be pulled as required. */ + +class BMD_PUBLIC IDeckLinkAudioOutputCallback : public IUnknown +{ +public: + virtual HRESULT RenderAudioSamples (/* in */ bool preroll) = 0; +}; + +/* Interface IDeckLinkIterator - Enumerates installed DeckLink hardware */ + +class BMD_PUBLIC IDeckLinkIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLink** deckLinkInstance) = 0; +}; + +/* Interface IDeckLinkAPIInformation - DeckLinkAPI attribute interface */ + +class BMD_PUBLIC IDeckLinkAPIInformation : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ bool* value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ double* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ CFStringRef* value) = 0; + +protected: + virtual ~IDeckLinkAPIInformation () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkOutput : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoOutputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame** outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary** outBuffer) = 0; // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback* theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t* bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + virtual HRESULT WriteAudioSamplesSync (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t* bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback* theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue* actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool* active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* streamTime, /* out */ double* playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus* referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* frameCompletionTimestamp) = 0; + +protected: + virtual ~IDeckLinkOutput () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoInputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkHDMIInputEDID - Created by QueryInterface from IDeckLink. Releasing all references will restore EDID to default */ + +class BMD_PUBLIC IDeckLinkHDMIInputEDID : public IUnknown +{ +public: + virtual HRESULT SetInt (/* in */ BMDDeckLinkHDMIInputEDIDID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkHDMIInputEDIDID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT WriteToEDID (void) = 0; + +protected: + virtual ~IDeckLinkHDMIInputEDID () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderInput - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkEncoderInput : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedCodec, /* in */ uint32_t requestedCodecProfile, /* in */ BMDSupportedVideoModeFlags flags, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailablePacketsCount (/* out */ uint32_t* availablePacketsCount) = 0; + virtual HRESULT SetMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioFormat audioFormat, /* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkEncoderInputCallback* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkEncoderInput () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */ + +class BMD_PUBLIC IDeckLinkVideoFrame : public IUnknown +{ +public: + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual long GetRowBytes (void) = 0; + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual BMDFrameFlags GetFlags (void) = 0; + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) = 0; + virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary** ancillary) = 0; // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + +protected: + virtual ~IDeckLinkVideoFrame () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */ + +class BMD_PUBLIC IDeckLinkMutableVideoFrame : public IDeckLinkVideoFrame +{ +public: + virtual HRESULT SetFlags (/* in */ BMDFrameFlags newFlags) = 0; + virtual HRESULT SetTimecode (/* in */ BMDTimecodeFormat format, /* in */ IDeckLinkTimecode* timecode) = 0; + virtual HRESULT SetTimecodeFromComponents (/* in */ BMDTimecodeFormat format, /* in */ uint8_t hours, /* in */ uint8_t minutes, /* in */ uint8_t seconds, /* in */ uint8_t frames, /* in */ BMDTimecodeFlags flags) = 0; + virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary* ancillary) = 0; + virtual HRESULT SetTimecodeUserBits (/* in */ BMDTimecodeFormat format, /* in */ BMDTimecodeUserBits userBits) = 0; + +protected: + virtual ~IDeckLinkMutableVideoFrame () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrame3DExtensions - Optional interface implemented on IDeckLinkVideoFrame to support 3D frames */ + +class BMD_PUBLIC IDeckLinkVideoFrame3DExtensions : public IUnknown +{ +public: + virtual BMDVideo3DPackingFormat Get3DPackingFormat (void) = 0; + virtual HRESULT GetFrameForRightEye (/* out */ IDeckLinkVideoFrame** rightEyeFrame) = 0; + +protected: + virtual ~IDeckLinkVideoFrame3DExtensions () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrameMetadataExtensions - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDR information */ + +class BMD_PUBLIC IDeckLinkVideoFrameMetadataExtensions : public IUnknown +{ +public: + virtual HRESULT GetInt (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ double* value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ bool* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ CFStringRef* value) = 0; + virtual HRESULT GetBytes (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ void* buffer /* optional */, /* in, out */ uint32_t* bufferSize) = 0; + +protected: + virtual ~IDeckLinkVideoFrameMetadataExtensions () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkVideoInputFrame : public IDeckLinkVideoFrame +{ +public: + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration) = 0; + +protected: + virtual ~IDeckLinkVideoInputFrame () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkAncillaryPacket - On output, user needs to implement this interface */ + +class BMD_PUBLIC IDeckLinkAncillaryPacket : public IUnknown +{ +public: + virtual HRESULT GetBytes (/* in */ BMDAncillaryPacketFormat format /* For output, only one format need be offered */, /* out */ const void** data /* Optional */, /* out */ uint32_t* size /* Optional */) = 0; + virtual uint8_t GetDID (void) = 0; + virtual uint8_t GetSDID (void) = 0; + virtual uint32_t GetLineNumber (void) = 0; // On output, zero is auto + virtual uint8_t GetDataStreamIndex (void) = 0; // Usually zero. Can only be 1 if non-SD and the first data stream is completely full + +protected: + virtual ~IDeckLinkAncillaryPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkAncillaryPacketIterator - Enumerates ancillary packets */ + +class BMD_PUBLIC IDeckLinkAncillaryPacketIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkAncillaryPacket** packet) = 0; + +protected: + virtual ~IDeckLinkAncillaryPacketIterator () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrameAncillaryPackets - Obtained through QueryInterface on an IDeckLinkVideoFrame object. */ + +class BMD_PUBLIC IDeckLinkVideoFrameAncillaryPackets : public IUnknown +{ +public: + virtual HRESULT GetPacketIterator (/* out */ IDeckLinkAncillaryPacketIterator** iterator) = 0; + virtual HRESULT GetFirstPacketByID (/* in */ uint8_t DID, /* in */ uint8_t SDID, /* out */ IDeckLinkAncillaryPacket** packet) = 0; + virtual HRESULT AttachPacket (/* in */ IDeckLinkAncillaryPacket* packet) = 0; // Implement IDeckLinkAncillaryPacket to output your own + virtual HRESULT DetachPacket (/* in */ IDeckLinkAncillaryPacket* packet) = 0; + virtual HRESULT DetachAllPackets (void) = 0; + +protected: + virtual ~IDeckLinkVideoFrameAncillaryPackets () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoFrameAncillary - Use of IDeckLinkVideoFrameAncillaryPackets is preferred. Obtained through QueryInterface on an IDeckLinkVideoFrame object. */ + +class BMD_PUBLIC IDeckLinkVideoFrameAncillary : public IUnknown +{ +public: + virtual HRESULT GetBufferForVerticalBlankingLine (/* in */ uint32_t lineNumber, /* out */ void** buffer) = 0; // Pixels/rowbytes is same as display mode, except for above HD where it's 1920 pixels for UHD modes and 2048 pixels for DCI modes + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual BMDDisplayMode GetDisplayMode (void) = 0; + +protected: + virtual ~IDeckLinkVideoFrameAncillary () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderPacket - Interface to encapsulate an encoded packet. */ + +class BMD_PUBLIC IDeckLinkEncoderPacket : public IUnknown +{ +public: + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual long GetSize (void) = 0; + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue* frameTime, /* in */ BMDTimeScale timeScale) = 0; + virtual BMDPacketType GetPacketType (void) = 0; + +protected: + virtual ~IDeckLinkEncoderPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderVideoPacket - Provided by the IDeckLinkEncoderInput video packet arrival callback. */ + +class BMD_PUBLIC IDeckLinkEncoderVideoPacket : public IDeckLinkEncoderPacket +{ +public: + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration) = 0; + virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) = 0; + +protected: + virtual ~IDeckLinkEncoderVideoPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderAudioPacket - Provided by the IDeckLinkEncoderInput audio packet arrival callback. */ + +class BMD_PUBLIC IDeckLinkEncoderAudioPacket : public IDeckLinkEncoderPacket +{ +public: + virtual BMDAudioFormat GetAudioFormat (void) = 0; + +protected: + virtual ~IDeckLinkEncoderAudioPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkH265NALPacket - Obtained through QueryInterface on an IDeckLinkEncoderVideoPacket object */ + +class BMD_PUBLIC IDeckLinkH265NALPacket : public IDeckLinkEncoderVideoPacket +{ +public: + virtual HRESULT GetUnitType (/* out */ uint8_t* unitType) = 0; + virtual HRESULT GetBytesNoPrefix (/* out */ void** buffer) = 0; + virtual long GetSizeNoPrefix (void) = 0; + +protected: + virtual ~IDeckLinkH265NALPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkAudioInputPacket - Provided by the IDeckLinkInput callback. */ + +class BMD_PUBLIC IDeckLinkAudioInputPacket : public IUnknown +{ +public: + virtual long GetSampleFrameCount (void) = 0; + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual HRESULT GetPacketTime (/* out */ BMDTimeValue* packetTime, /* in */ BMDTimeScale timeScale) = 0; + +protected: + virtual ~IDeckLinkAudioInputPacket () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */ + +class BMD_PUBLIC IDeckLinkScreenPreviewCallback : public IUnknown +{ +public: + virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + +protected: + virtual ~IDeckLinkScreenPreviewCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkCocoaScreenPreviewCallback - Screen preview callback for Cocoa-based applications. Created with CreateCocoaScreenPreview */ + +class BMD_PUBLIC IDeckLinkCocoaScreenPreviewCallback : public IDeckLinkScreenPreviewCallback +{ +public: + +protected: + virtual ~IDeckLinkCocoaScreenPreviewCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance on platforms with native COM support or from CreateOpenGLScreenPreviewHelper/CreateOpenGL3ScreenPreviewHelper on other platforms. */ + +class BMD_PUBLIC IDeckLinkGLScreenPreviewHelper : public IUnknown +{ +public: + + /* Methods must be called with OpenGL context set */ + + virtual HRESULT InitializeGL (void) = 0; + virtual HRESULT PaintGL (void) = 0; + virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + virtual HRESULT Set3DPreviewFormat (/* in */ BMD3DPreviewFormat previewFormat) = 0; + +protected: + virtual ~IDeckLinkGLScreenPreviewHelper () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkMetalScreenPreviewHelper - Created with CreateMetalScreenPreviewHelper(). */ + +class BMD_PUBLIC IDeckLinkMetalScreenPreviewHelper : public IUnknown +{ +public: + virtual HRESULT Initialize (/* in */ void* device) = 0; + virtual HRESULT Draw (/* in */ void* cmdBuffer, /* in */ void* renderPassDescriptor, /* in */ void* viewport) = 0; + virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + virtual HRESULT Set3DPreviewFormat (/* in */ BMD3DPreviewFormat previewFormat) = 0; + +protected: + virtual ~IDeckLinkMetalScreenPreviewHelper () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkNotificationCallback - DeckLink Notification Callback Interface */ + +class BMD_PUBLIC IDeckLinkNotificationCallback : public IUnknown +{ +public: + virtual HRESULT Notify (/* in */ BMDNotifications topic, /* in */ uint64_t param1, /* in */ uint64_t param2) = 0; +}; + +/* Interface IDeckLinkNotification - DeckLink Notification interface */ + +class BMD_PUBLIC IDeckLinkNotification : public IUnknown +{ +public: + virtual HRESULT Subscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback* theCallback) = 0; + virtual HRESULT Unsubscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback* theCallback) = 0; + +protected: + virtual ~IDeckLinkNotification () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileAttributes - Created by QueryInterface from an IDeckLinkProfile, or from IDeckLink. When queried from IDeckLink, interrogates the active profile */ + +class BMD_PUBLIC IDeckLinkProfileAttributes : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool* value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ CFStringRef* value) = 0; + +protected: + virtual ~IDeckLinkProfileAttributes () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileIterator - Enumerates IDeckLinkProfile interfaces */ + +class BMD_PUBLIC IDeckLinkProfileIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkProfile** profile) = 0; + +protected: + virtual ~IDeckLinkProfileIterator () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfile - Represents the active profile when queried from IDeckLink */ + +class BMD_PUBLIC IDeckLinkProfile : public IUnknown +{ +public: + virtual HRESULT GetDevice (/* out */ IDeckLink** device) = 0; // Device affected when this profile becomes active + virtual HRESULT IsActive (/* out */ bool* isActive) = 0; + virtual HRESULT SetActive (void) = 0; // Activating a profile will also change the profile on all devices enumerated by GetPeers. Activation is not complete until IDeckLinkProfileCallback::ProfileActivated is called + virtual HRESULT GetPeers (/* out */ IDeckLinkProfileIterator** profileIterator) = 0; // Profiles of other devices activated with this profile + +protected: + virtual ~IDeckLinkProfile () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileCallback - Receive notifications about profiles related to this device */ + +class BMD_PUBLIC IDeckLinkProfileCallback : public IUnknown +{ +public: + virtual HRESULT ProfileChanging (/* in */ IDeckLinkProfile* profileToBeActivated, /* in */ bool streamsWillBeForcedToStop) = 0; // Called before this device changes profile. User has an opportunity for teardown if streamsWillBeForcedToStop + virtual HRESULT ProfileActivated (/* in */ IDeckLinkProfile* activatedProfile) = 0; // Called after this device has been activated with a new profile + +protected: + virtual ~IDeckLinkProfileCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkProfileManager - Created by QueryInterface from IDeckLink when a device has multiple optional profiles */ + +class BMD_PUBLIC IDeckLinkProfileManager : public IUnknown +{ +public: + virtual HRESULT GetProfiles (/* out */ IDeckLinkProfileIterator** profileIterator) = 0; // All available profiles for this device + virtual HRESULT GetProfile (/* in */ BMDProfileID profileID, /* out */ IDeckLinkProfile** profile) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkProfileCallback* callback) = 0; + +protected: + virtual ~IDeckLinkProfileManager () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkStatus - DeckLink Status interface */ + +class BMD_PUBLIC IDeckLinkStatus : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkStatusID statusID, /* out */ bool* value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkStatusID statusID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkStatusID statusID, /* out */ double* value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkStatusID statusID, /* out */ CFStringRef* value) = 0; + virtual HRESULT GetBytes (/* in */ BMDDeckLinkStatusID statusID, /* out */ void* buffer, /* in, out */ uint32_t* bufferSize) = 0; + +protected: + virtual ~IDeckLinkStatus () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkKeyer - DeckLink Keyer interface */ + +class BMD_PUBLIC IDeckLinkKeyer : public IUnknown +{ +public: + virtual HRESULT Enable (/* in */ bool isExternal) = 0; + virtual HRESULT SetLevel (/* in */ uint8_t level) = 0; + virtual HRESULT RampUp (/* in */ uint32_t numberOfFrames) = 0; + virtual HRESULT RampDown (/* in */ uint32_t numberOfFrames) = 0; + virtual HRESULT Disable (void) = 0; + +protected: + virtual ~IDeckLinkKeyer () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance. */ + +class BMD_PUBLIC IDeckLinkVideoConversion : public IUnknown +{ +public: + virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame* srcFrame, /* in */ IDeckLinkVideoFrame* dstFrame) = 0; + +protected: + virtual ~IDeckLinkVideoConversion () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDeviceNotificationCallback - DeckLink device arrival/removal notification callbacks */ + +class BMD_PUBLIC IDeckLinkDeviceNotificationCallback : public IUnknown +{ +public: + virtual HRESULT DeckLinkDeviceArrived (/* in */ IDeckLink* deckLinkDevice) = 0; + virtual HRESULT DeckLinkDeviceRemoved (/* in */ IDeckLink* deckLinkDevice) = 0; + +protected: + virtual ~IDeckLinkDeviceNotificationCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDiscovery - DeckLink device discovery */ + +class BMD_PUBLIC IDeckLinkDiscovery : public IUnknown +{ +public: + virtual HRESULT InstallDeviceNotifications (/* in */ IDeckLinkDeviceNotificationCallback* deviceNotificationCallback) = 0; + virtual HRESULT UninstallDeviceNotifications (void) = 0; + +protected: + virtual ~IDeckLinkDiscovery () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + BMD_PUBLIC IDeckLinkIterator* CreateDeckLinkIteratorInstance(void); + BMD_PUBLIC IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance(void); + BMD_PUBLIC IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance(void); + BMD_PUBLIC IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper(void); + BMD_PUBLIC IDeckLinkGLScreenPreviewHelper* CreateOpenGL3ScreenPreviewHelper(void); // Requires OpenGL 3.2 support and provides improved performance and color handling + BMD_PUBLIC IDeckLinkCocoaScreenPreviewCallback* CreateCocoaScreenPreview(/* in */ void* /* (NSView*)*/ parentView); + BMD_PUBLIC IDeckLinkMetalScreenPreviewHelper* CreateMetalScreenPreviewHelper(void); + BMD_PUBLIC IDeckLinkVideoConversion* CreateVideoConversionInstance(void); + BMD_PUBLIC IDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance(void); // For use when creating a custom IDeckLinkVideoFrame without wrapping IDeckLinkOutput::CreateVideoFrame + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPI_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration.h new file mode 100644 index 0000000000..9f2a145307 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration.h @@ -0,0 +1,269 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_H +#define BMD_DECKLINKAPICONFIGURATION_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration = /* 912F634B-2D4E-40A4-8AAB-8D80B73F1289 */ { 0x91,0x2F,0x63,0x4B,0x2D,0x4E,0x40,0xA4,0x8A,0xAB,0x8D,0x80,0xB7,0x3F,0x12,0x89 }; +BMD_CONST REFIID IID_IDeckLinkEncoderConfiguration = /* 138050E5-C60A-4552-BF3F-0F358049327E */ { 0x13,0x80,0x50,0xE5,0xC6,0x0A,0x45,0x52,0xBF,0x3F,0x0F,0x35,0x80,0x49,0x32,0x7E }; + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID; +enum _BMDDeckLinkConfigurationID { + + /* Serial port Flags */ + + bmdDeckLinkConfigSwapSerialRxTx = /* 'ssrt' */ 0x73737274, + + /* Video Input/Output Integers */ + + bmdDeckLinkConfigHDMI3DPackingFormat = /* '3dpf' */ 0x33647066, + bmdDeckLinkConfigBypass = /* 'byps' */ 0x62797073, + bmdDeckLinkConfigClockTimingAdjustment = /* 'ctad' */ 0x63746164, + + /* Audio Input/Output Flags */ + + bmdDeckLinkConfigAnalogAudioConsumerLevels = /* 'aacl' */ 0x6161636C, + bmdDeckLinkConfigSwapHDMICh3AndCh4OnInput = /* 'hi34' */ 0x68693334, + bmdDeckLinkConfigSwapHDMICh3AndCh4OnOutput = /* 'ho34' */ 0x686F3334, + + /* Video Output Flags */ + + bmdDeckLinkConfigFieldFlickerRemoval = /* 'fdfr' */ 0x66646672, + bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion = /* 'to59' */ 0x746F3539, + bmdDeckLinkConfig444SDIVideoOutput = /* '444o' */ 0x3434346F, + bmdDeckLinkConfigBlackVideoOutputDuringCapture = /* 'bvoc' */ 0x62766F63, + bmdDeckLinkConfigLowLatencyVideoOutput = /* 'llvo' */ 0x6C6C766F, + bmdDeckLinkConfigDownConversionOnAllAnalogOutput = /* 'caao' */ 0x6361616F, + bmdDeckLinkConfigSMPTELevelAOutput = /* 'smta' */ 0x736D7461, + bmdDeckLinkConfigRec2020Output = /* 'rec2' */ 0x72656332, // Ensure output is Rec.2020 colorspace + bmdDeckLinkConfigQuadLinkSDIVideoOutputSquareDivisionSplit = /* 'SDQS' */ 0x53445153, + bmdDeckLinkConfigOutput1080pAsPsF = /* 'pfpr' */ 0x70667072, + + /* Video Output Integers */ + + bmdDeckLinkConfigVideoOutputConnection = /* 'vocn' */ 0x766F636E, + bmdDeckLinkConfigVideoOutputConversionMode = /* 'vocm' */ 0x766F636D, + bmdDeckLinkConfigAnalogVideoOutputFlags = /* 'avof' */ 0x61766F66, + bmdDeckLinkConfigReferenceInputTimingOffset = /* 'glot' */ 0x676C6F74, + bmdDeckLinkConfigVideoOutputIdleOperation = /* 'voio' */ 0x766F696F, + bmdDeckLinkConfigDefaultVideoOutputMode = /* 'dvom' */ 0x64766F6D, + bmdDeckLinkConfigDefaultVideoOutputModeFlags = /* 'dvof' */ 0x64766F66, + bmdDeckLinkConfigSDIOutputLinkConfiguration = /* 'solc' */ 0x736F6C63, + bmdDeckLinkConfigHDMITimecodePacking = /* 'htpk' */ 0x6874706B, + bmdDeckLinkConfigPlaybackGroup = /* 'plgr' */ 0x706C6772, + + /* Video Output Floats */ + + bmdDeckLinkConfigVideoOutputComponentLumaGain = /* 'oclg' */ 0x6F636C67, + bmdDeckLinkConfigVideoOutputComponentChromaBlueGain = /* 'occb' */ 0x6F636362, + bmdDeckLinkConfigVideoOutputComponentChromaRedGain = /* 'occr' */ 0x6F636372, + bmdDeckLinkConfigVideoOutputCompositeLumaGain = /* 'oilg' */ 0x6F696C67, + bmdDeckLinkConfigVideoOutputCompositeChromaGain = /* 'oicg' */ 0x6F696367, + bmdDeckLinkConfigVideoOutputSVideoLumaGain = /* 'oslg' */ 0x6F736C67, + bmdDeckLinkConfigVideoOutputSVideoChromaGain = /* 'oscg' */ 0x6F736367, + + /* Video Input Flags */ + + bmdDeckLinkConfigVideoInputScanning = /* 'visc' */ 0x76697363, // Applicable to H264 Pro Recorder only + bmdDeckLinkConfigUseDedicatedLTCInput = /* 'dltc' */ 0x646C7463, // Use timecode from LTC input instead of SDI stream + bmdDeckLinkConfigSDIInput3DPayloadOverride = /* '3dds' */ 0x33646473, + bmdDeckLinkConfigCapture1080pAsPsF = /* 'cfpr' */ 0x63667072, + + /* Video Input Integers */ + + bmdDeckLinkConfigVideoInputConnection = /* 'vicn' */ 0x7669636E, + bmdDeckLinkConfigAnalogVideoInputFlags = /* 'avif' */ 0x61766966, + bmdDeckLinkConfigVideoInputConversionMode = /* 'vicm' */ 0x7669636D, + bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame = /* 'pdif' */ 0x70646966, + bmdDeckLinkConfigVANCSourceLine1Mapping = /* 'vsl1' */ 0x76736C31, + bmdDeckLinkConfigVANCSourceLine2Mapping = /* 'vsl2' */ 0x76736C32, + bmdDeckLinkConfigVANCSourceLine3Mapping = /* 'vsl3' */ 0x76736C33, + bmdDeckLinkConfigCapturePassThroughMode = /* 'cptm' */ 0x6370746D, + bmdDeckLinkConfigCaptureGroup = /* 'cpgr' */ 0x63706772, + + /* Video Input Floats */ + + bmdDeckLinkConfigVideoInputComponentLumaGain = /* 'iclg' */ 0x69636C67, + bmdDeckLinkConfigVideoInputComponentChromaBlueGain = /* 'iccb' */ 0x69636362, + bmdDeckLinkConfigVideoInputComponentChromaRedGain = /* 'iccr' */ 0x69636372, + bmdDeckLinkConfigVideoInputCompositeLumaGain = /* 'iilg' */ 0x69696C67, + bmdDeckLinkConfigVideoInputCompositeChromaGain = /* 'iicg' */ 0x69696367, + bmdDeckLinkConfigVideoInputSVideoLumaGain = /* 'islg' */ 0x69736C67, + bmdDeckLinkConfigVideoInputSVideoChromaGain = /* 'iscg' */ 0x69736367, + + /* Keying Integers */ + + bmdDeckLinkConfigInternalKeyingAncillaryDataSource = /* 'ikas' */ 0x696B6173, + + /* Audio Input Flags */ + + bmdDeckLinkConfigMicrophonePhantomPower = /* 'mphp' */ 0x6D706870, + + /* Audio Input Integers */ + + bmdDeckLinkConfigAudioInputConnection = /* 'aicn' */ 0x6169636E, + + /* Audio Input Floats */ + + bmdDeckLinkConfigAnalogAudioInputScaleChannel1 = /* 'ais1' */ 0x61697331, + bmdDeckLinkConfigAnalogAudioInputScaleChannel2 = /* 'ais2' */ 0x61697332, + bmdDeckLinkConfigAnalogAudioInputScaleChannel3 = /* 'ais3' */ 0x61697333, + bmdDeckLinkConfigAnalogAudioInputScaleChannel4 = /* 'ais4' */ 0x61697334, + bmdDeckLinkConfigDigitalAudioInputScale = /* 'dais' */ 0x64616973, + bmdDeckLinkConfigMicrophoneInputGain = /* 'micg' */ 0x6D696367, + + /* Audio Output Integers */ + + bmdDeckLinkConfigAudioOutputAESAnalogSwitch = /* 'aoaa' */ 0x616F6161, + + /* Audio Output Floats */ + + bmdDeckLinkConfigAnalogAudioOutputScaleChannel1 = /* 'aos1' */ 0x616F7331, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel2 = /* 'aos2' */ 0x616F7332, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel3 = /* 'aos3' */ 0x616F7333, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel4 = /* 'aos4' */ 0x616F7334, + bmdDeckLinkConfigDigitalAudioOutputScale = /* 'daos' */ 0x64616F73, + bmdDeckLinkConfigHeadphoneVolume = /* 'hvol' */ 0x68766F6C, + + /* Device Information Strings */ + + bmdDeckLinkConfigDeviceInformationLabel = /* 'dila' */ 0x64696C61, + bmdDeckLinkConfigDeviceInformationSerialNumber = /* 'disn' */ 0x6469736E, + bmdDeckLinkConfigDeviceInformationCompany = /* 'dico' */ 0x6469636F, + bmdDeckLinkConfigDeviceInformationPhone = /* 'diph' */ 0x64697068, + bmdDeckLinkConfigDeviceInformationEmail = /* 'diem' */ 0x6469656D, + bmdDeckLinkConfigDeviceInformationDate = /* 'dida' */ 0x64696461, + + /* Deck Control Integers */ + + bmdDeckLinkConfigDeckControlConnection = /* 'dcco' */ 0x6463636F +}; + +/* Enum BMDDeckLinkEncoderConfigurationID - DeckLink Encoder Configuration ID */ + +typedef uint32_t BMDDeckLinkEncoderConfigurationID; +enum _BMDDeckLinkEncoderConfigurationID { + + /* Video Encoder Integers */ + + bmdDeckLinkEncoderConfigPreferredBitDepth = /* 'epbr' */ 0x65706272, + bmdDeckLinkEncoderConfigFrameCodingMode = /* 'efcm' */ 0x6566636D, + + /* HEVC/H.265 Encoder Integers */ + + bmdDeckLinkEncoderConfigH265TargetBitrate = /* 'htbr' */ 0x68746272, + + /* DNxHR/DNxHD Compression ID */ + + bmdDeckLinkEncoderConfigDNxHRCompressionID = /* 'dcid' */ 0x64636964, + + /* DNxHR/DNxHD Level */ + + bmdDeckLinkEncoderConfigDNxHRLevel = /* 'dlev' */ 0x646C6576, + + /* Encoded Sample Decriptions */ + + bmdDeckLinkEncoderConfigMPEG4SampleDescription = /* 'stsE' */ 0x73747345, // Full MPEG4 sample description (aka SampleEntry of an 'stsd' atom-box). Useful for MediaFoundation, QuickTime, MKV and more + bmdDeckLinkEncoderConfigMPEG4CodecSpecificDesc = /* 'esds' */ 0x65736473 // Sample description extensions only (atom stream, each with size and fourCC header). Useful for AVFoundation, VideoToolbox, MKV and more +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkConfiguration; +class IDeckLinkEncoderConfiguration; + +/* Interface IDeckLinkConfiguration - DeckLink Configuration interface */ + +class BMD_PUBLIC IDeckLinkConfiguration : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool* value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double* value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ CFStringRef value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ CFStringRef* value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkEncoderConfiguration - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */ + +class BMD_PUBLIC IDeckLinkEncoderConfiguration : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ bool* value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ double* value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ CFStringRef value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ CFStringRef* value) = 0; + virtual HRESULT GetBytes (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ void* buffer /* optional */, /* in, out */ uint32_t* bufferSize) = 0; + +protected: + virtual ~IDeckLinkEncoderConfiguration () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_11.h new file mode 100644 index 0000000000..ea19f8db24 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_11.h @@ -0,0 +1,84 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_11_H +#define BMD_DECKLINKAPICONFIGURATION_v10_11_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_11 = /* EF90380B-4AE5-4346-9077-E288E149F129 */ {0xEF,0x90,0x38,0x0B,0x4A,0xE5,0x43,0x46,0x90,0x77,0xE2,0x88,0xE1,0x49,0xF1,0x29}; + +/* Enum BMDDeckLinkConfigurationID_v10_11 - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_11; +enum _BMDDeckLinkConfigurationID_v10_11 { + + /* Video Input/Output Integers */ + + bmdDeckLinkConfigDuplexMode_v10_11 = 'dupx', +}; + +// Forward Declarations + +class IDeckLinkConfiguration_v10_11; + +/* Interface IDeckLinkConfiguration_v10_11 - DeckLink Configuration interface */ + +class IDeckLinkConfiguration_v10_11 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ CFStringRef value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ CFStringRef *value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_11 () {} // call Release method to drop reference count +}; + + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_2.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_2.h new file mode 100644 index 0000000000..b0e0dbc9e8 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_2.h @@ -0,0 +1,73 @@ +/* -LICENSE-START- +** Copyright (c) 2014 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_2_H +#define BMD_DECKLINKAPICONFIGURATION_v10_2_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_2 = /* C679A35B-610C-4D09-B748-1D0478100FC0 */ {0xC6,0x79,0xA3,0x5B,0x61,0x0C,0x4D,0x09,0xB7,0x48,0x1D,0x04,0x78,0x10,0x0F,0xC0}; + +// Forward Declarations + +class IDeckLinkConfiguration_v10_2; + +/* Interface IDeckLinkConfiguration_v10_2 - DeckLink Configuration interface */ + +class IDeckLinkConfiguration_v10_2 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ CFStringRef value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ CFStringRef *value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_2 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_2_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_4.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_4.h new file mode 100644 index 0000000000..7d3215de90 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_4.h @@ -0,0 +1,75 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_4_H +#define BMD_DECKLINKAPICONFIGURATION_v10_4_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_4 = /* 1E69FCF6-4203-4936-8076-2A9F4CFD50CB */ {0x1E,0x69,0xFC,0xF6,0x42,0x03,0x49,0x36,0x80,0x76,0x2A,0x9F,0x4C,0xFD,0x50,0xCB}; + +// +// Forward Declarations + +class IDeckLinkConfiguration_v10_4; + +/* Interface IDeckLinkConfiguration_v10_4 - DeckLink Configuration interface */ + +class IDeckLinkConfiguration_v10_4 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ CFStringRef value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ CFStringRef *value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_4 () {} // call Release method to drop reference count +}; + + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_5.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_5.h new file mode 100644 index 0000000000..b67572d4d9 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_5.h @@ -0,0 +1,73 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_5_H +#define BMD_DECKLINKAPICONFIGURATION_v10_5_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkEncoderConfiguration_v10_5 = /* 67455668-0848-45DF-8D8E-350A77C9A028 */ {0x67,0x45,0x56,0x68,0x08,0x48,0x45,0xDF,0x8D,0x8E,0x35,0x0A,0x77,0xC9,0xA0,0x28}; + +// Forward Declarations + +class IDeckLinkConfiguration_v10_5; + +/* Interface IDeckLinkEncoderConfiguration_v10_5 - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */ + +class IDeckLinkEncoderConfiguration_v10_5 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ CFStringRef value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ CFStringRef *value) = 0; + virtual HRESULT GetDecoderConfigurationInfo (/* out */ void *buffer, /* in */ long bufferSize, /* out */ long *returnedSize) = 0; + +protected: + virtual ~IDeckLinkEncoderConfiguration_v10_5 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_5_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_9.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_9.h new file mode 100644 index 0000000000..04a6a45ce8 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIConfiguration_v10_9.h @@ -0,0 +1,75 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPICONFIGURATION_v10_9_H +#define BMD_DECKLINKAPICONFIGURATION_v10_9_H + +#include "DeckLinkAPIConfiguration.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkConfiguration_v10_9 = /* CB71734A-FE37-4E8D-8E13-802133A1C3F2 */ {0xCB,0x71,0x73,0x4A,0xFE,0x37,0x4E,0x8D,0x8E,0x13,0x80,0x21,0x33,0xA1,0xC3,0xF2}; + +// +// Forward Declarations + +class IDeckLinkConfiguration_v10_9; + +/* Interface IDeckLinkConfiguration_v10_9 - DeckLink Configuration interface */ + +class IDeckLinkConfiguration_v10_9 : public IUnknown +{ +public: + virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0; + virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0; + virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ CFStringRef value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ CFStringRef *value) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + +protected: + virtual ~IDeckLinkConfiguration_v10_9 () {} // call Release method to drop reference count +}; + + +#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_9_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDeckControl.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDeckControl.h new file mode 100644 index 0000000000..f946af20dc --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDeckControl.h @@ -0,0 +1,223 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIDECKCONTROL_H +#define BMD_DECKLINKAPIDECKCONTROL_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkDeckControlStatusCallback = /* 53436FFB-B434-4906-BADC-AE3060FFE8EF */ { 0x53,0x43,0x6F,0xFB,0xB4,0x34,0x49,0x06,0xBA,0xDC,0xAE,0x30,0x60,0xFF,0xE8,0xEF }; +BMD_CONST REFIID IID_IDeckLinkDeckControl = /* 8E1C3ACE-19C7-4E00-8B92-D80431D958BE */ { 0x8E,0x1C,0x3A,0xCE,0x19,0xC7,0x4E,0x00,0x8B,0x92,0xD8,0x04,0x31,0xD9,0x58,0xBE }; + +/* Enum BMDDeckControlMode - DeckControl mode */ + +typedef uint32_t BMDDeckControlMode; +enum _BMDDeckControlMode { + bmdDeckControlNotOpened = /* 'ntop' */ 0x6E746F70, + bmdDeckControlVTRControlMode = /* 'vtrc' */ 0x76747263, + bmdDeckControlExportMode = /* 'expm' */ 0x6578706D, + bmdDeckControlCaptureMode = /* 'capm' */ 0x6361706D +}; + +/* Enum BMDDeckControlEvent - DeckControl event */ + +typedef uint32_t BMDDeckControlEvent; +enum _BMDDeckControlEvent { + bmdDeckControlAbortedEvent = /* 'abte' */ 0x61627465, // This event is triggered when a capture or edit-to-tape operation is aborted. + + /* Export-To-Tape events */ + + bmdDeckControlPrepareForExportEvent = /* 'pfee' */ 0x70666565, // This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback should be called at this point. + bmdDeckControlExportCompleteEvent = /* 'exce' */ 0x65786365, // This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode. + + /* Capture events */ + + bmdDeckControlPrepareForCaptureEvent = /* 'pfce' */ 0x70666365, // This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid. + bmdDeckControlCaptureCompleteEvent = /* 'ccev' */ 0x63636576 // This event is triggered a few frames after reaching the out-point. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode. +}; + +/* Enum BMDDeckControlVTRControlState - VTR Control state */ + +typedef uint32_t BMDDeckControlVTRControlState; +enum _BMDDeckControlVTRControlState { + bmdDeckControlNotInVTRControlMode = /* 'nvcm' */ 0x6E76636D, + bmdDeckControlVTRControlPlaying = /* 'vtrp' */ 0x76747270, + bmdDeckControlVTRControlRecording = /* 'vtrr' */ 0x76747272, + bmdDeckControlVTRControlStill = /* 'vtra' */ 0x76747261, + bmdDeckControlVTRControlShuttleForward = /* 'vtsf' */ 0x76747366, + bmdDeckControlVTRControlShuttleReverse = /* 'vtsr' */ 0x76747372, + bmdDeckControlVTRControlJogForward = /* 'vtjf' */ 0x76746A66, + bmdDeckControlVTRControlJogReverse = /* 'vtjr' */ 0x76746A72, + bmdDeckControlVTRControlStopped = /* 'vtro' */ 0x7674726F +}; + +/* Enum BMDDeckControlStatusFlags - Deck Control status flags */ + +typedef uint32_t BMDDeckControlStatusFlags; +enum _BMDDeckControlStatusFlags { + bmdDeckControlStatusDeckConnected = 1 << 0, + bmdDeckControlStatusRemoteMode = 1 << 1, + bmdDeckControlStatusRecordInhibited = 1 << 2, + bmdDeckControlStatusCassetteOut = 1 << 3 +}; + +/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */ + +typedef uint32_t BMDDeckControlExportModeOpsFlags; +enum _BMDDeckControlExportModeOpsFlags { + bmdDeckControlExportModeInsertVideo = 1 << 0, + bmdDeckControlExportModeInsertAudio1 = 1 << 1, + bmdDeckControlExportModeInsertAudio2 = 1 << 2, + bmdDeckControlExportModeInsertAudio3 = 1 << 3, + bmdDeckControlExportModeInsertAudio4 = 1 << 4, + bmdDeckControlExportModeInsertAudio5 = 1 << 5, + bmdDeckControlExportModeInsertAudio6 = 1 << 6, + bmdDeckControlExportModeInsertAudio7 = 1 << 7, + bmdDeckControlExportModeInsertAudio8 = 1 << 8, + bmdDeckControlExportModeInsertAudio9 = 1 << 9, + bmdDeckControlExportModeInsertAudio10 = 1 << 10, + bmdDeckControlExportModeInsertAudio11 = 1 << 11, + bmdDeckControlExportModeInsertAudio12 = 1 << 12, + bmdDeckControlExportModeInsertTimeCode = 1 << 13, + bmdDeckControlExportModeInsertAssemble = 1 << 14, + bmdDeckControlExportModeInsertPreview = 1 << 15, + bmdDeckControlUseManualExport = 1 << 16 +}; + +/* Enum BMDDeckControlError - Deck Control error */ + +typedef uint32_t BMDDeckControlError; +enum _BMDDeckControlError { + bmdDeckControlNoError = /* 'noer' */ 0x6E6F6572, + bmdDeckControlModeError = /* 'moer' */ 0x6D6F6572, + bmdDeckControlMissedInPointError = /* 'mier' */ 0x6D696572, + bmdDeckControlDeckTimeoutError = /* 'dter' */ 0x64746572, + bmdDeckControlCommandFailedError = /* 'cfer' */ 0x63666572, + bmdDeckControlDeviceAlreadyOpenedError = /* 'dalo' */ 0x64616C6F, + bmdDeckControlFailedToOpenDeviceError = /* 'fder' */ 0x66646572, + bmdDeckControlInLocalModeError = /* 'lmer' */ 0x6C6D6572, + bmdDeckControlEndOfTapeError = /* 'eter' */ 0x65746572, + bmdDeckControlUserAbortError = /* 'uaer' */ 0x75616572, + bmdDeckControlNoTapeInDeckError = /* 'nter' */ 0x6E746572, + bmdDeckControlNoVideoFromCardError = /* 'nvfc' */ 0x6E766663, + bmdDeckControlNoCommunicationError = /* 'ncom' */ 0x6E636F6D, + bmdDeckControlBufferTooSmallError = /* 'btsm' */ 0x6274736D, + bmdDeckControlBadChecksumError = /* 'chks' */ 0x63686B73, + bmdDeckControlUnknownError = /* 'uner' */ 0x756E6572 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkDeckControlStatusCallback; +class IDeckLinkDeckControl; + +/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */ + +class BMD_PUBLIC IDeckLinkDeckControlStatusCallback : public IUnknown +{ +public: + virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0; + virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState newState, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0; + +protected: + virtual ~IDeckLinkDeckControlStatusCallback () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDeckControl - Deck Control main interface */ + +class BMD_PUBLIC IDeckLinkDeckControl : public IUnknown +{ +public: + virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Close (/* in */ bool standbyOn) = 0; + virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode* mode, /* out */ BMDDeckControlVTRControlState* vtrControlState, /* out */ BMDDeckControlStatusFlags* flags) = 0; + virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0; + virtual HRESULT SendCommand (/* in */ uint8_t* inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t* outBuffer, /* out */ uint32_t* outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Play (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Stop (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Eject (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT StepForward (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT StepBack (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetTimecodeString (/* out */ CFStringRef* currentTimeCode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode** currentTimecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD* currentTimecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0; + virtual HRESULT GetPreroll (/* out */ uint32_t* prerollSeconds) = 0; + virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0; + virtual HRESULT GetExportOffset (/* out */ int32_t* exportOffsetFields) = 0; + virtual HRESULT GetManualExportOffset (/* out */ int32_t* deckManualExportOffsetFields) = 0; + virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0; + virtual HRESULT GetCaptureOffset (/* out */ int32_t* captureOffsetFields) = 0; + virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT GetDeviceID (/* out */ uint16_t* deviceId, /* out */ BMDDeckControlError* error) = 0; + virtual HRESULT Abort (void) = 0; + virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError* error) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback* callback) = 0; + +protected: + virtual ~IDeckLinkDeckControl () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPIDECKCONTROL_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDiscovery.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDiscovery.h new file mode 100644 index 0000000000..d0ac6ddf1f --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDiscovery.h @@ -0,0 +1,79 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIDISCOVERY_H +#define BMD_DECKLINKAPIDISCOVERY_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLink = /* C418FBDD-0587-48ED-8FE5-640F0A14AF91 */ { 0xC4,0x18,0xFB,0xDD,0x05,0x87,0x48,0xED,0x8F,0xE5,0x64,0x0F,0x0A,0x14,0xAF,0x91 }; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLink; + +/* Interface IDeckLink - Represents a DeckLink device */ + +class BMD_PUBLIC IDeckLink : public IUnknown +{ +public: + virtual HRESULT GetModelName (/* out */ CFStringRef* modelName) = 0; + virtual HRESULT GetDisplayName (/* out */ CFStringRef* displayName) = 0; + +protected: + virtual ~IDeckLink () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPIDISCOVERY_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch.cpp b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch.cpp new file mode 100644 index 0000000000..abb03ac215 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch.cpp @@ -0,0 +1,245 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPIDispatch.cpp */ + +#include "DeckLinkAPI.h" +#include + +#if BLACKMAGIC_DECKLINK_API_MAGIC != 1 + #error The DeckLink API version of DeckLinkAPIDispatch.cpp is not the same version as DeckLinkAPI.h +#endif + +#define kDeckLinkAPI_BundlePath "/Library/Frameworks/DeckLinkAPI.framework" + + +typedef IDeckLinkIterator* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGL3ScreenPreviewHelperFunc)(void); +typedef IDeckLinkMetalScreenPreviewHelper* (*CreateMetalScreenPreviewHelperFunc)(void); +typedef IDeckLinkCocoaScreenPreviewCallback* (*CreateCocoaScreenPreviewFunc)(void*); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); +typedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void); +typedef IDeckLinkVideoFrameAncillaryPackets* (*CreateVideoFrameAncillaryPacketsInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gDeckLinkAPIBundleRef = NULL; +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateOpenGL3ScreenPreviewHelperFunc gCreateOpenGL3PreviewFunc = NULL; +static CreateMetalScreenPreviewHelperFunc gCreateMetalPreviewFunc = NULL; +static CreateCocoaScreenPreviewFunc gCreateCocoaPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; +static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc= NULL; +static CreateVideoFrameAncillaryPacketsInstanceFunc gCreateVideoFrameAncillaryPacketsFunc = NULL; + + +static void InitDeckLinkAPI (void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gDeckLinkAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gDeckLinkAPIBundleRef != NULL) + { + gCreateIteratorFunc = (CreateIteratorFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkIteratorInstance_0004")); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkAPIInformationInstance_0001")); + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper_0001")); + gCreateOpenGL3PreviewFunc = (CreateOpenGL3ScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateOpenGL3ScreenPreviewHelper_0001")); + gCreateMetalPreviewFunc = (CreateMetalScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateMetalScreenPreviewHelper_0001")); + gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateCocoaScreenPreview_0001")); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoConversionInstance_0001")); + gCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkDiscoveryInstance_0003")); + gCreateVideoFrameAncillaryPacketsFunc = (CreateVideoFrameAncillaryPacketsInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoFrameAncillaryPacketsInstance_0001")); + } + CFRelease(bundleURL); + } +} + +bool IsDeckLinkAPIPresent (void) +{ + // If the DeckLink API bundle was successfully loaded, return this knowledge to the caller + if (gDeckLinkAPIBundleRef != NULL) + return true; + + return false; +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGL3ScreenPreviewHelper (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateOpenGL3PreviewFunc == NULL) + return NULL; + + return gCreateOpenGL3PreviewFunc(); +} + +IDeckLinkMetalScreenPreviewHelper* CreateMetalScreenPreviewHelper (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateMetalPreviewFunc == NULL) + return NULL; + + return gCreateMetalPreviewFunc(); +} + +IDeckLinkCocoaScreenPreviewCallback* CreateCocoaScreenPreview (void* parentView) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateCocoaPreviewFunc == NULL) + return NULL; + + return gCreateCocoaPreviewFunc(parentView); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + + return gCreateVideoConversionFunc(); +} + +IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateDeckLinkDiscoveryFunc == NULL) + return NULL; + + return gCreateDeckLinkDiscoveryFunc(); +} + +IDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoFrameAncillaryPacketsFunc == NULL) + return NULL; + + return gCreateVideoFrameAncillaryPacketsFunc(); +} + + +#define kBMDStreamingAPI_BundlePath "/Library/Application Support/Blackmagic Design/Streaming/BMDStreamingAPI.bundle" + +typedef IBMDStreamingDiscovery* (*CreateDiscoveryFunc)(void); +typedef IBMDStreamingH264NALParser* (*CreateNALParserFunc)(void); + +static pthread_once_t gBMDStreamingOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gBMDStreamingAPIBundleRef = NULL; +static CreateDiscoveryFunc gCreateDiscoveryFunc = NULL; +static CreateNALParserFunc gCreateNALParserFunc = NULL; + +static void InitBMDStreamingAPI(void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kBMDStreamingAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gBMDStreamingAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gBMDStreamingAPIBundleRef != NULL) + { + gCreateDiscoveryFunc = (CreateDiscoveryFunc)CFBundleGetFunctionPointerForName(gBMDStreamingAPIBundleRef, CFSTR("CreateBMDStreamingDiscoveryInstance_0002")); + gCreateNALParserFunc = (CreateNALParserFunc)CFBundleGetFunctionPointerForName(gBMDStreamingAPIBundleRef, CFSTR("CreateBMDStreamingH264NALParser_0001")); + } + + CFRelease(bundleURL); + } +} + +IBMDStreamingDiscovery* CreateBMDStreamingDiscoveryInstance() +{ + pthread_once(&gBMDStreamingOnceControl, InitBMDStreamingAPI); + + if (gCreateDiscoveryFunc == NULL) + return NULL; + + return gCreateDiscoveryFunc(); +} + +IBMDStreamingH264NALParser* CreateBMDStreamingH264NALParser() +{ + pthread_once(&gBMDStreamingOnceControl, InitBMDStreamingAPI); + + if (gCreateNALParserFunc == NULL) + return NULL; + + return gCreateNALParserFunc(); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_11.cpp b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_11.cpp new file mode 100644 index 0000000000..b7afbeb4eb --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_11.cpp @@ -0,0 +1,219 @@ +/* -LICENSE-START- +** Copyright (c) 2019 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPIDispatch.cpp */ + +#include "DeckLinkAPI_v10_11.h" +#include + +#if BLACKMAGIC_DECKLINK_API_MAGIC != 1 + #error The DeckLink API version of DeckLinkAPIDispatch.cpp is not the same version as DeckLinkAPI.h +#endif + +#define kDeckLinkAPI_BundlePath "/Library/Frameworks/DeckLinkAPI.framework" + + +typedef IDeckLinkIterator* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkCocoaScreenPreviewCallback* (*CreateCocoaScreenPreviewFunc)(void*); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); +typedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void); +typedef IDeckLinkVideoFrameAncillaryPackets* (*CreateVideoFrameAncillaryPacketsInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gDeckLinkAPIBundleRef = NULL; +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateCocoaScreenPreviewFunc gCreateCocoaPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; +static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc= NULL; +static CreateVideoFrameAncillaryPacketsInstanceFunc gCreateVideoFrameAncillaryPacketsFunc = NULL; + + +static void InitDeckLinkAPI (void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gDeckLinkAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gDeckLinkAPIBundleRef != NULL) + { + gCreateIteratorFunc = (CreateIteratorFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkIteratorInstance_0003")); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkAPIInformationInstance_0001")); + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper_0001")); + gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateCocoaScreenPreview_0001")); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoConversionInstance_0001")); + gCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkDiscoveryInstance_0002")); + gCreateVideoFrameAncillaryPacketsFunc = (CreateVideoFrameAncillaryPacketsInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoFrameAncillaryPacketsInstance_0001")); + } + CFRelease(bundleURL); + } +} + +bool IsDeckLinkAPIPresent_v10_11 (void) +{ + // If the DeckLink API bundle was successfully loaded, return this knowledge to the caller + if (gDeckLinkAPIBundleRef != NULL) + return true; + + return false; +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkCocoaScreenPreviewCallback* CreateCocoaScreenPreview_v10_11 (void* parentView) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateCocoaPreviewFunc == NULL) + return NULL; + + return gCreateCocoaPreviewFunc(parentView); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + + return gCreateVideoConversionFunc(); +} + +IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateDeckLinkDiscoveryFunc == NULL) + return NULL; + + return gCreateDeckLinkDiscoveryFunc(); +} + +IDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance_v10_11 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoFrameAncillaryPacketsFunc == NULL) + return NULL; + + return gCreateVideoFrameAncillaryPacketsFunc(); +} + + +#define kBMDStreamingAPI_BundlePath "/Library/Application Support/Blackmagic Design/Streaming/BMDStreamingAPI.bundle" + +typedef IBMDStreamingDiscovery* (*CreateDiscoveryFunc)(void); +typedef IBMDStreamingH264NALParser* (*CreateNALParserFunc)(void); + +static pthread_once_t gBMDStreamingOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gBMDStreamingAPIBundleRef = NULL; +static CreateDiscoveryFunc gCreateDiscoveryFunc = NULL; +static CreateNALParserFunc gCreateNALParserFunc = NULL; + +static void InitBMDStreamingAPI(void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kBMDStreamingAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gBMDStreamingAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gBMDStreamingAPIBundleRef != NULL) + { + gCreateDiscoveryFunc = (CreateDiscoveryFunc)CFBundleGetFunctionPointerForName(gBMDStreamingAPIBundleRef, CFSTR("CreateBMDStreamingDiscoveryInstance_0002")); + gCreateNALParserFunc = (CreateNALParserFunc)CFBundleGetFunctionPointerForName(gBMDStreamingAPIBundleRef, CFSTR("CreateBMDStreamingH264NALParser_0001")); + } + + CFRelease(bundleURL); + } +} + +IBMDStreamingDiscovery* CreateBMDStreamingDiscoveryInstance_v10_11() +{ + pthread_once(&gBMDStreamingOnceControl, InitBMDStreamingAPI); + + if (gCreateDiscoveryFunc == NULL) + return NULL; + + return gCreateDiscoveryFunc(); +} + +IBMDStreamingH264NALParser* CreateBMDStreamingH264NALParser_v10_11() +{ + pthread_once(&gBMDStreamingOnceControl, InitBMDStreamingAPI); + + if (gCreateNALParserFunc == NULL) + return NULL; + + return gCreateNALParserFunc(); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_8.cpp b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_8.cpp new file mode 100644 index 0000000000..2da795ad41 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v10_8.cpp @@ -0,0 +1,206 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPIDispatch.cpp */ + +#include "DeckLinkAPI.h" +#include + +#if BLACKMAGIC_DECKLINK_API_MAGIC != 1 +#error The DeckLink API version of DeckLinkAPIDispatch.cpp is not the same version as DeckLinkAPI.h +#endif + +#define kDeckLinkAPI_BundlePath "/Library/Frameworks/DeckLinkAPI.framework" + + +typedef IDeckLinkIterator* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkCocoaScreenPreviewCallback* (*CreateCocoaScreenPreviewFunc)(void*); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); +typedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gDeckLinkAPIBundleRef = NULL; +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateCocoaScreenPreviewFunc gCreateCocoaPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; +static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc = NULL; + + +static void InitDeckLinkAPI(void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gDeckLinkAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gDeckLinkAPIBundleRef != NULL) + { + gCreateIteratorFunc = (CreateIteratorFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkIteratorInstance_0002")); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkAPIInformationInstance_0001")); + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper_0001")); + gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateCocoaScreenPreview_0001")); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoConversionInstance_0001")); + gCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkDiscoveryInstance_0001")); + } + CFRelease(bundleURL); + } +} + +bool IsDeckLinkAPIPresent(void) +{ + // If the DeckLink API bundle was successfully loaded, return this knowledge to the caller + if (gDeckLinkAPIBundleRef != NULL) + return true; + + return false; +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkCocoaScreenPreviewCallback* CreateCocoaScreenPreview(void* parentView) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateCocoaPreviewFunc == NULL) + return NULL; + + return gCreateCocoaPreviewFunc(parentView); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + + return gCreateVideoConversionFunc(); +} + +IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance(void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateDeckLinkDiscoveryFunc == NULL) + return NULL; + + return gCreateDeckLinkDiscoveryFunc(); +} + + +#define kBMDStreamingAPI_BundlePath "/Library/Application Support/Blackmagic Design/Streaming/BMDStreamingAPI.bundle" + +typedef IBMDStreamingDiscovery* (*CreateDiscoveryFunc)(void); +typedef IBMDStreamingH264NALParser* (*CreateNALParserFunc)(void); + +static pthread_once_t gBMDStreamingOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gBMDStreamingAPIBundleRef = NULL; +static CreateDiscoveryFunc gCreateDiscoveryFunc = NULL; +static CreateNALParserFunc gCreateNALParserFunc = NULL; + +static void InitBMDStreamingAPI(void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kBMDStreamingAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gBMDStreamingAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gBMDStreamingAPIBundleRef != NULL) + { + gCreateDiscoveryFunc = (CreateDiscoveryFunc)CFBundleGetFunctionPointerForName(gBMDStreamingAPIBundleRef, CFSTR("CreateBMDStreamingDiscoveryInstance_0001")); + gCreateNALParserFunc = (CreateNALParserFunc)CFBundleGetFunctionPointerForName(gBMDStreamingAPIBundleRef, CFSTR("CreateBMDStreamingH264NALParser_0001")); + } + + CFRelease(bundleURL); + } +} + +IBMDStreamingDiscovery* CreateBMDStreamingDiscoveryInstance() +{ + pthread_once(&gBMDStreamingOnceControl, InitBMDStreamingAPI); + + if (gCreateDiscoveryFunc == NULL) + return NULL; + + return gCreateDiscoveryFunc(); +} + +IBMDStreamingH264NALParser* CreateBMDStreamingH264NALParser() +{ + pthread_once(&gBMDStreamingOnceControl, InitBMDStreamingAPI); + + if (gCreateNALParserFunc == NULL) + return NULL; + + return gCreateNALParserFunc(); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v7_6.cpp b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v7_6.cpp new file mode 100644 index 0000000000..0ee2d73ceb --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v7_6.cpp @@ -0,0 +1,118 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPIDispatch_v7_6.cpp */ + +#include "DeckLinkAPI_v7_6.h" +#include + +#define kDeckLinkAPI_BundlePath "/Library/Frameworks/DeckLinkAPI.framework" + +typedef IDeckLinkIterator* (*CreateIteratorFunc_v7_6)(void); +typedef IDeckLinkGLScreenPreviewHelper_v7_6* (*CreateOpenGLScreenPreviewHelperFunc_v7_6)(void); +typedef IDeckLinkCocoaScreenPreviewCallback_v7_6* (*CreateCocoaScreenPreviewFunc_v7_6)(void*); +typedef IDeckLinkVideoConversion_v7_6* (*CreateVideoConversionInstanceFunc_v7_6)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gBundleRef = NULL; +static CreateIteratorFunc_v7_6 gCreateIteratorFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc_v7_6 gCreateOpenGLPreviewFunc = NULL; +static CreateCocoaScreenPreviewFunc_v7_6 gCreateCocoaPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc_v7_6 gCreateVideoConversionFunc = NULL; + + +static void InitDeckLinkAPI_v7_6 (void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gBundleRef != NULL) + { + gCreateIteratorFunc = (CreateIteratorFunc_v7_6)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateDeckLinkIteratorInstance")); + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc_v7_6)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper")); + gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc_v7_6)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateCocoaScreenPreview")); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc_v7_6)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateVideoConversionInstance")); + } + CFRelease(bundleURL); + } +} + +IDeckLinkIterator* CreateDeckLinkIteratorInstance_v7_6 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6); + + if (gCreateIteratorFunc == NULL) + return NULL; + + return gCreateIteratorFunc(); +} + +IDeckLinkGLScreenPreviewHelper_v7_6* CreateOpenGLScreenPreviewHelper_v7_6 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkCocoaScreenPreviewCallback_v7_6* CreateCocoaScreenPreview_v7_6 (void* parentView) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6); + + if (gCreateCocoaPreviewFunc == NULL) + return NULL; + + return gCreateCocoaPreviewFunc(parentView); +} + +IDeckLinkVideoConversion_v7_6* CreateVideoConversionInstance_v7_6 (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + + return gCreateVideoConversionFunc(); +} + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v8_0.cpp b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v8_0.cpp new file mode 100644 index 0000000000..af16c219ae --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIDispatch_v8_0.cpp @@ -0,0 +1,144 @@ +/* -LICENSE-START- +** Copyright (c) 2011 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPIDispatch.cpp */ + +#include "DeckLinkAPI_v8_0.h" +#include + +#if BLACKMAGIC_DECKLINK_API_MAGIC != 1 + #error The DeckLink API version of DeckLinkAPIDispatch.cpp is not the same version as DeckLinkAPI.h +#endif + +#define kDeckLinkAPI_BundlePath "/Library/Frameworks/DeckLinkAPI.framework" + +typedef IDeckLinkIterator_v8_0* (*CreateIteratorFunc)(void); +typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void); +typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void); +typedef IDeckLinkCocoaScreenPreviewCallback* (*CreateCocoaScreenPreviewFunc)(void*); +typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void); + +static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT; +static CFBundleRef gDeckLinkAPIBundleRef = NULL; +static CreateIteratorFunc gCreateIteratorFunc = NULL; +static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; +static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; +static CreateCocoaScreenPreviewFunc gCreateCocoaPreviewFunc = NULL; +static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; + + +static void InitDeckLinkAPI (void) +{ + CFURLRef bundleURL; + + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true); + if (bundleURL != NULL) + { + gDeckLinkAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL); + if (gDeckLinkAPIBundleRef != NULL) + { + gCreateIteratorFunc = (CreateIteratorFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkIteratorInstance_0001")); + gCreateAPIInformationFunc = (CreateAPIInformationFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkAPIInformationInstance_0001")); + gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper_0001")); + gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateCocoaScreenPreview_0001")); + gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoConversionInstance_0001")); + } + CFRelease(bundleURL); + } +} + +bool IsDeckLinkAPIPresent (void) +{ + // If the DeckLink API bundle was successfully loaded, return this knowledge to the caller + if (gDeckLinkAPIBundleRef != NULL) + return true; + + return false; +} + +IDeckLinkIterator_v8_0* CreateDeckLinkIteratorInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateIteratorFunc == NULL) + return NULL; + + return gCreateIteratorFunc(); +} + +IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateAPIInformationFunc == NULL) + return NULL; + + return gCreateAPIInformationFunc(); +} + +IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateOpenGLPreviewFunc == NULL) + return NULL; + + return gCreateOpenGLPreviewFunc(); +} + +IDeckLinkCocoaScreenPreviewCallback* CreateCocoaScreenPreview (void* parentView) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateCocoaPreviewFunc == NULL) + return NULL; + + return gCreateCocoaPreviewFunc(parentView); +} + +IDeckLinkVideoConversion* CreateVideoConversionInstance (void) +{ + pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI); + + if (gCreateVideoConversionFunc == NULL) + return NULL; + + return gCreateVideoConversionFunc(); +} + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIModes.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIModes.h new file mode 100644 index 0000000000..4b0fb1ae1a --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIModes.h @@ -0,0 +1,289 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIMODES_H +#define BMD_DECKLINKAPIMODES_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkDisplayModeIterator = /* 9C88499F-F601-4021-B80B-032E4EB41C35 */ { 0x9C,0x88,0x49,0x9F,0xF6,0x01,0x40,0x21,0xB8,0x0B,0x03,0x2E,0x4E,0xB4,0x1C,0x35 }; +BMD_CONST REFIID IID_IDeckLinkDisplayMode = /* 3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78 */ { 0x3E,0xB2,0xC1,0xAB,0x0A,0x3D,0x45,0x23,0xA3,0xAD,0xF4,0x0D,0x7F,0xB1,0x4E,0x78 }; + +/* Enum BMDDisplayMode - BMDDisplayMode enumerates the video modes supported. */ + +typedef uint32_t BMDDisplayMode; +enum _BMDDisplayMode { + + /* SD Modes */ + + bmdModeNTSC = /* 'ntsc' */ 0x6E747363, + bmdModeNTSC2398 = /* 'nt23' */ 0x6E743233, // 3:2 pulldown + bmdModePAL = /* 'pal ' */ 0x70616C20, + bmdModeNTSCp = /* 'ntsp' */ 0x6E747370, + bmdModePALp = /* 'palp' */ 0x70616C70, + + /* HD 1080 Modes */ + + bmdModeHD1080p2398 = /* '23ps' */ 0x32337073, + bmdModeHD1080p24 = /* '24ps' */ 0x32347073, + bmdModeHD1080p25 = /* 'Hp25' */ 0x48703235, + bmdModeHD1080p2997 = /* 'Hp29' */ 0x48703239, + bmdModeHD1080p30 = /* 'Hp30' */ 0x48703330, + bmdModeHD1080p4795 = /* 'Hp47' */ 0x48703437, + bmdModeHD1080p48 = /* 'Hp48' */ 0x48703438, + bmdModeHD1080p50 = /* 'Hp50' */ 0x48703530, + bmdModeHD1080p5994 = /* 'Hp59' */ 0x48703539, + bmdModeHD1080p6000 = /* 'Hp60' */ 0x48703630, // N.B. This _really_ is 60.00 Hz. + bmdModeHD1080p9590 = /* 'Hp95' */ 0x48703935, + bmdModeHD1080p96 = /* 'Hp96' */ 0x48703936, + bmdModeHD1080p100 = /* 'Hp10' */ 0x48703130, + bmdModeHD1080p11988 = /* 'Hp11' */ 0x48703131, + bmdModeHD1080p120 = /* 'Hp12' */ 0x48703132, + bmdModeHD1080i50 = /* 'Hi50' */ 0x48693530, + bmdModeHD1080i5994 = /* 'Hi59' */ 0x48693539, + bmdModeHD1080i6000 = /* 'Hi60' */ 0x48693630, // N.B. This _really_ is 60.00 Hz. + + /* HD 720 Modes */ + + bmdModeHD720p50 = /* 'hp50' */ 0x68703530, + bmdModeHD720p5994 = /* 'hp59' */ 0x68703539, + bmdModeHD720p60 = /* 'hp60' */ 0x68703630, + + /* 2K Modes */ + + bmdMode2k2398 = /* '2k23' */ 0x326B3233, + bmdMode2k24 = /* '2k24' */ 0x326B3234, + bmdMode2k25 = /* '2k25' */ 0x326B3235, + + /* 2K DCI Modes */ + + bmdMode2kDCI2398 = /* '2d23' */ 0x32643233, + bmdMode2kDCI24 = /* '2d24' */ 0x32643234, + bmdMode2kDCI25 = /* '2d25' */ 0x32643235, + bmdMode2kDCI2997 = /* '2d29' */ 0x32643239, + bmdMode2kDCI30 = /* '2d30' */ 0x32643330, + bmdMode2kDCI4795 = /* '2d47' */ 0x32643437, + bmdMode2kDCI48 = /* '2d48' */ 0x32643438, + bmdMode2kDCI50 = /* '2d50' */ 0x32643530, + bmdMode2kDCI5994 = /* '2d59' */ 0x32643539, + bmdMode2kDCI60 = /* '2d60' */ 0x32643630, + bmdMode2kDCI9590 = /* '2d95' */ 0x32643935, + bmdMode2kDCI96 = /* '2d96' */ 0x32643936, + bmdMode2kDCI100 = /* '2d10' */ 0x32643130, + bmdMode2kDCI11988 = /* '2d11' */ 0x32643131, + bmdMode2kDCI120 = /* '2d12' */ 0x32643132, + + /* 4K UHD Modes */ + + bmdMode4K2160p2398 = /* '4k23' */ 0x346B3233, + bmdMode4K2160p24 = /* '4k24' */ 0x346B3234, + bmdMode4K2160p25 = /* '4k25' */ 0x346B3235, + bmdMode4K2160p2997 = /* '4k29' */ 0x346B3239, + bmdMode4K2160p30 = /* '4k30' */ 0x346B3330, + bmdMode4K2160p4795 = /* '4k47' */ 0x346B3437, + bmdMode4K2160p48 = /* '4k48' */ 0x346B3438, + bmdMode4K2160p50 = /* '4k50' */ 0x346B3530, + bmdMode4K2160p5994 = /* '4k59' */ 0x346B3539, + bmdMode4K2160p60 = /* '4k60' */ 0x346B3630, + bmdMode4K2160p9590 = /* '4k95' */ 0x346B3935, + bmdMode4K2160p96 = /* '4k96' */ 0x346B3936, + bmdMode4K2160p100 = /* '4k10' */ 0x346B3130, + bmdMode4K2160p11988 = /* '4k11' */ 0x346B3131, + bmdMode4K2160p120 = /* '4k12' */ 0x346B3132, + + /* 4K DCI Modes */ + + bmdMode4kDCI2398 = /* '4d23' */ 0x34643233, + bmdMode4kDCI24 = /* '4d24' */ 0x34643234, + bmdMode4kDCI25 = /* '4d25' */ 0x34643235, + bmdMode4kDCI2997 = /* '4d29' */ 0x34643239, + bmdMode4kDCI30 = /* '4d30' */ 0x34643330, + bmdMode4kDCI4795 = /* '4d47' */ 0x34643437, + bmdMode4kDCI48 = /* '4d48' */ 0x34643438, + bmdMode4kDCI50 = /* '4d50' */ 0x34643530, + bmdMode4kDCI5994 = /* '4d59' */ 0x34643539, + bmdMode4kDCI60 = /* '4d60' */ 0x34643630, + bmdMode4kDCI9590 = /* '4d95' */ 0x34643935, + bmdMode4kDCI96 = /* '4d96' */ 0x34643936, + bmdMode4kDCI100 = /* '4d10' */ 0x34643130, + bmdMode4kDCI11988 = /* '4d11' */ 0x34643131, + bmdMode4kDCI120 = /* '4d12' */ 0x34643132, + + /* 8K UHD Modes */ + + bmdMode8K4320p2398 = /* '8k23' */ 0x386B3233, + bmdMode8K4320p24 = /* '8k24' */ 0x386B3234, + bmdMode8K4320p25 = /* '8k25' */ 0x386B3235, + bmdMode8K4320p2997 = /* '8k29' */ 0x386B3239, + bmdMode8K4320p30 = /* '8k30' */ 0x386B3330, + bmdMode8K4320p4795 = /* '8k47' */ 0x386B3437, + bmdMode8K4320p48 = /* '8k48' */ 0x386B3438, + bmdMode8K4320p50 = /* '8k50' */ 0x386B3530, + bmdMode8K4320p5994 = /* '8k59' */ 0x386B3539, + bmdMode8K4320p60 = /* '8k60' */ 0x386B3630, + + /* 8K DCI Modes */ + + bmdMode8kDCI2398 = /* '8d23' */ 0x38643233, + bmdMode8kDCI24 = /* '8d24' */ 0x38643234, + bmdMode8kDCI25 = /* '8d25' */ 0x38643235, + bmdMode8kDCI2997 = /* '8d29' */ 0x38643239, + bmdMode8kDCI30 = /* '8d30' */ 0x38643330, + bmdMode8kDCI4795 = /* '8d47' */ 0x38643437, + bmdMode8kDCI48 = /* '8d48' */ 0x38643438, + bmdMode8kDCI50 = /* '8d50' */ 0x38643530, + bmdMode8kDCI5994 = /* '8d59' */ 0x38643539, + bmdMode8kDCI60 = /* '8d60' */ 0x38643630, + + /* PC Modes */ + + bmdMode640x480p60 = /* 'vga6' */ 0x76676136, + bmdMode800x600p60 = /* 'svg6' */ 0x73766736, + bmdMode1440x900p50 = /* 'wxg5' */ 0x77786735, + bmdMode1440x900p60 = /* 'wxg6' */ 0x77786736, + bmdMode1440x1080p50 = /* 'sxg5' */ 0x73786735, + bmdMode1440x1080p60 = /* 'sxg6' */ 0x73786736, + bmdMode1600x1200p50 = /* 'uxg5' */ 0x75786735, + bmdMode1600x1200p60 = /* 'uxg6' */ 0x75786736, + bmdMode1920x1200p50 = /* 'wux5' */ 0x77757835, + bmdMode1920x1200p60 = /* 'wux6' */ 0x77757836, + bmdMode1920x1440p50 = /* '1945' */ 0x31393435, + bmdMode1920x1440p60 = /* '1946' */ 0x31393436, + bmdMode2560x1440p50 = /* 'wqh5' */ 0x77716835, + bmdMode2560x1440p60 = /* 'wqh6' */ 0x77716836, + bmdMode2560x1600p50 = /* 'wqx5' */ 0x77717835, + bmdMode2560x1600p60 = /* 'wqx6' */ 0x77717836, + + /* Special Modes */ + + bmdModeUnknown = /* 'iunk' */ 0x69756E6B +}; + +/* Enum BMDFieldDominance - BMDFieldDominance enumerates settings applicable to video fields. */ + +typedef uint32_t BMDFieldDominance; +enum _BMDFieldDominance { + bmdUnknownFieldDominance = 0, + bmdLowerFieldFirst = /* 'lowr' */ 0x6C6F7772, + bmdUpperFieldFirst = /* 'uppr' */ 0x75707072, + bmdProgressiveFrame = /* 'prog' */ 0x70726F67, + bmdProgressiveSegmentedFrame = /* 'psf ' */ 0x70736620 +}; + +/* Enum BMDPixelFormat - Video pixel formats supported for output/input */ + +typedef uint32_t BMDPixelFormat; +enum _BMDPixelFormat { + bmdFormatUnspecified = 0, + bmdFormat8BitYUV = /* '2vuy' */ 0x32767579, + bmdFormat10BitYUV = /* 'v210' */ 0x76323130, + bmdFormat8BitARGB = 32, + bmdFormat8BitBGRA = /* 'BGRA' */ 0x42475241, + bmdFormat10BitRGB = /* 'r210' */ 0x72323130, // Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10 + bmdFormat12BitRGB = /* 'R12B' */ 0x52313242, // Big-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component + bmdFormat12BitRGBLE = /* 'R12L' */ 0x5231324C, // Little-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component + bmdFormat10BitRGBXLE = /* 'R10l' */ 0x5231306C, // Little-endian 10-bit RGB with SMPTE video levels (64-940) + bmdFormat10BitRGBX = /* 'R10b' */ 0x52313062, // Big-endian 10-bit RGB with SMPTE video levels (64-940) + bmdFormatH265 = /* 'hev1' */ 0x68657631, // High Efficiency Video Coding (HEVC/h.265) + + /* AVID DNxHR */ + + bmdFormatDNxHR = /* 'AVdh' */ 0x41566468 +}; + +/* Enum BMDDisplayModeFlags - Flags to describe the characteristics of an IDeckLinkDisplayMode. */ + +typedef uint32_t BMDDisplayModeFlags; +enum _BMDDisplayModeFlags { + bmdDisplayModeSupports3D = 1 << 0, + bmdDisplayModeColorspaceRec601 = 1 << 1, + bmdDisplayModeColorspaceRec709 = 1 << 2, + bmdDisplayModeColorspaceRec2020 = 1 << 3 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkDisplayModeIterator; +class IDeckLinkDisplayMode; + +/* Interface IDeckLinkDisplayModeIterator - Enumerates over supported input/output display modes. */ + +class BMD_PUBLIC IDeckLinkDisplayModeIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkDisplayMode** deckLinkDisplayMode) = 0; + +protected: + virtual ~IDeckLinkDisplayModeIterator () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkDisplayMode - Represents a display mode */ + +class BMD_PUBLIC IDeckLinkDisplayMode : public IUnknown +{ +public: + virtual HRESULT GetName (/* out */ CFStringRef* name) = 0; + virtual BMDDisplayMode GetDisplayMode (void) = 0; + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual HRESULT GetFrameRate (/* out */ BMDTimeValue* frameDuration, /* out */ BMDTimeScale* timeScale) = 0; + virtual BMDFieldDominance GetFieldDominance (void) = 0; + virtual BMDDisplayModeFlags GetFlags (void) = 0; + +protected: + virtual ~IDeckLinkDisplayMode () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPIMODES_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming.h new file mode 100644 index 0000000000..5ef156e7d5 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming.h @@ -0,0 +1,383 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPISTREAMING_H +#define BMD_DECKLINKAPISTREAMING_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + + +// Interface ID Declarations + +BMD_CONST REFIID IID_IBMDStreamingDeviceNotificationCallback = /* F9531D64-3305-4B29-A387-7F74BB0D0E84 */ { 0xF9,0x53,0x1D,0x64,0x33,0x05,0x4B,0x29,0xA3,0x87,0x7F,0x74,0xBB,0x0D,0x0E,0x84 }; +BMD_CONST REFIID IID_IBMDStreamingH264InputCallback = /* 823C475F-55AE-46F9-890C-537CC5CEDCCA */ { 0x82,0x3C,0x47,0x5F,0x55,0xAE,0x46,0xF9,0x89,0x0C,0x53,0x7C,0xC5,0xCE,0xDC,0xCA }; +BMD_CONST REFIID IID_IBMDStreamingDiscovery = /* 2C837444-F989-4D87-901A-47C8A36D096D */ { 0x2C,0x83,0x74,0x44,0xF9,0x89,0x4D,0x87,0x90,0x1A,0x47,0xC8,0xA3,0x6D,0x09,0x6D }; +BMD_CONST REFIID IID_IBMDStreamingVideoEncodingMode = /* 1AB8035B-CD13-458D-B6DF-5E8F7C2141D9 */ { 0x1A,0xB8,0x03,0x5B,0xCD,0x13,0x45,0x8D,0xB6,0xDF,0x5E,0x8F,0x7C,0x21,0x41,0xD9 }; +BMD_CONST REFIID IID_IBMDStreamingMutableVideoEncodingMode = /* 19BF7D90-1E0A-400D-B2C6-FFC4E78AD49D */ { 0x19,0xBF,0x7D,0x90,0x1E,0x0A,0x40,0x0D,0xB2,0xC6,0xFF,0xC4,0xE7,0x8A,0xD4,0x9D }; +BMD_CONST REFIID IID_IBMDStreamingVideoEncodingModePresetIterator = /* 7AC731A3-C950-4AD0-804A-8377AA51C6C4 */ { 0x7A,0xC7,0x31,0xA3,0xC9,0x50,0x4A,0xD0,0x80,0x4A,0x83,0x77,0xAA,0x51,0xC6,0xC4 }; +BMD_CONST REFIID IID_IBMDStreamingDeviceInput = /* 24B6B6EC-1727-44BB-9818-34FF086ACF98 */ { 0x24,0xB6,0xB6,0xEC,0x17,0x27,0x44,0xBB,0x98,0x18,0x34,0xFF,0x08,0x6A,0xCF,0x98 }; +BMD_CONST REFIID IID_IBMDStreamingH264NALPacket = /* E260E955-14BE-4395-9775-9F02CC0A9D89 */ { 0xE2,0x60,0xE9,0x55,0x14,0xBE,0x43,0x95,0x97,0x75,0x9F,0x02,0xCC,0x0A,0x9D,0x89 }; +BMD_CONST REFIID IID_IBMDStreamingAudioPacket = /* D9EB5902-1AD2-43F4-9E2C-3CFA50B5EE19 */ { 0xD9,0xEB,0x59,0x02,0x1A,0xD2,0x43,0xF4,0x9E,0x2C,0x3C,0xFA,0x50,0xB5,0xEE,0x19 }; +BMD_CONST REFIID IID_IBMDStreamingMPEG2TSPacket = /* 91810D1C-4FB3-4AAA-AE56-FA301D3DFA4C */ { 0x91,0x81,0x0D,0x1C,0x4F,0xB3,0x4A,0xAA,0xAE,0x56,0xFA,0x30,0x1D,0x3D,0xFA,0x4C }; +BMD_CONST REFIID IID_IBMDStreamingH264NALParser = /* 5867F18C-5BFA-4CCC-B2A7-9DFD140417D2 */ { 0x58,0x67,0xF1,0x8C,0x5B,0xFA,0x4C,0xCC,0xB2,0xA7,0x9D,0xFD,0x14,0x04,0x17,0xD2 }; + +/* Enum BMDStreamingDeviceMode - Device modes */ + +typedef uint32_t BMDStreamingDeviceMode; +enum _BMDStreamingDeviceMode { + bmdStreamingDeviceIdle = /* 'idle' */ 0x69646C65, + bmdStreamingDeviceEncoding = /* 'enco' */ 0x656E636F, + bmdStreamingDeviceStopping = /* 'stop' */ 0x73746F70, + bmdStreamingDeviceUnknown = /* 'munk' */ 0x6D756E6B +}; + +/* Enum BMDStreamingEncodingFrameRate - Encoded frame rates */ + +typedef uint32_t BMDStreamingEncodingFrameRate; +enum _BMDStreamingEncodingFrameRate { + + /* Interlaced rates */ + + bmdStreamingEncodedFrameRate50i = /* 'e50i' */ 0x65353069, + bmdStreamingEncodedFrameRate5994i = /* 'e59i' */ 0x65353969, + bmdStreamingEncodedFrameRate60i = /* 'e60i' */ 0x65363069, + + /* Progressive rates */ + + bmdStreamingEncodedFrameRate2398p = /* 'e23p' */ 0x65323370, + bmdStreamingEncodedFrameRate24p = /* 'e24p' */ 0x65323470, + bmdStreamingEncodedFrameRate25p = /* 'e25p' */ 0x65323570, + bmdStreamingEncodedFrameRate2997p = /* 'e29p' */ 0x65323970, + bmdStreamingEncodedFrameRate30p = /* 'e30p' */ 0x65333070, + bmdStreamingEncodedFrameRate50p = /* 'e50p' */ 0x65353070, + bmdStreamingEncodedFrameRate5994p = /* 'e59p' */ 0x65353970, + bmdStreamingEncodedFrameRate60p = /* 'e60p' */ 0x65363070 +}; + +/* Enum BMDStreamingEncodingSupport - Output encoding mode supported flag */ + +typedef uint32_t BMDStreamingEncodingSupport; +enum _BMDStreamingEncodingSupport { + bmdStreamingEncodingModeNotSupported = 0, + bmdStreamingEncodingModeSupported, + bmdStreamingEncodingModeSupportedWithChanges +}; + +/* Enum BMDStreamingVideoCodec - Video codecs */ + +typedef uint32_t BMDStreamingVideoCodec; +enum _BMDStreamingVideoCodec { + bmdStreamingVideoCodecH264 = /* 'H264' */ 0x48323634 +}; + +/* Enum BMDStreamingH264Profile - H264 encoding profile */ + +typedef uint32_t BMDStreamingH264Profile; +enum _BMDStreamingH264Profile { + bmdStreamingH264ProfileHigh = /* 'high' */ 0x68696768, + bmdStreamingH264ProfileMain = /* 'main' */ 0x6D61696E, + bmdStreamingH264ProfileBaseline = /* 'base' */ 0x62617365 +}; + +/* Enum BMDStreamingH264Level - H264 encoding level */ + +typedef uint32_t BMDStreamingH264Level; +enum _BMDStreamingH264Level { + bmdStreamingH264Level12 = /* 'lv12' */ 0x6C763132, + bmdStreamingH264Level13 = /* 'lv13' */ 0x6C763133, + bmdStreamingH264Level2 = /* 'lv2 ' */ 0x6C763220, + bmdStreamingH264Level21 = /* 'lv21' */ 0x6C763231, + bmdStreamingH264Level22 = /* 'lv22' */ 0x6C763232, + bmdStreamingH264Level3 = /* 'lv3 ' */ 0x6C763320, + bmdStreamingH264Level31 = /* 'lv31' */ 0x6C763331, + bmdStreamingH264Level32 = /* 'lv32' */ 0x6C763332, + bmdStreamingH264Level4 = /* 'lv4 ' */ 0x6C763420, + bmdStreamingH264Level41 = /* 'lv41' */ 0x6C763431, + bmdStreamingH264Level42 = /* 'lv42' */ 0x6C763432 +}; + +/* Enum BMDStreamingH264EntropyCoding - H264 entropy coding */ + +typedef uint32_t BMDStreamingH264EntropyCoding; +enum _BMDStreamingH264EntropyCoding { + bmdStreamingH264EntropyCodingCAVLC = /* 'EVLC' */ 0x45564C43, + bmdStreamingH264EntropyCodingCABAC = /* 'EBAC' */ 0x45424143 +}; + +/* Enum BMDStreamingAudioCodec - Audio codecs */ + +typedef uint32_t BMDStreamingAudioCodec; +enum _BMDStreamingAudioCodec { + bmdStreamingAudioCodecAAC = /* 'AAC ' */ 0x41414320 +}; + +/* Enum BMDStreamingEncodingModePropertyID - Encoding mode properties */ + +typedef uint32_t BMDStreamingEncodingModePropertyID; +enum _BMDStreamingEncodingModePropertyID { + + /* Integers, Video Properties */ + + bmdStreamingEncodingPropertyVideoFrameRate = /* 'vfrt' */ 0x76667274, // Uses values of type BMDStreamingEncodingFrameRate + bmdStreamingEncodingPropertyVideoBitRateKbps = /* 'vbrt' */ 0x76627274, + + /* Integers, H264 Properties */ + + bmdStreamingEncodingPropertyH264Profile = /* 'hprf' */ 0x68707266, + bmdStreamingEncodingPropertyH264Level = /* 'hlvl' */ 0x686C766C, + bmdStreamingEncodingPropertyH264EntropyCoding = /* 'hent' */ 0x68656E74, + + /* Flags, H264 Properties */ + + bmdStreamingEncodingPropertyH264HasBFrames = /* 'hBfr' */ 0x68426672, + + /* Integers, Audio Properties */ + + bmdStreamingEncodingPropertyAudioCodec = /* 'acdc' */ 0x61636463, + bmdStreamingEncodingPropertyAudioSampleRate = /* 'asrt' */ 0x61737274, + bmdStreamingEncodingPropertyAudioChannelCount = /* 'achc' */ 0x61636863, + bmdStreamingEncodingPropertyAudioBitRateKbps = /* 'abrt' */ 0x61627274 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IBMDStreamingDeviceNotificationCallback; +class IBMDStreamingH264InputCallback; +class IBMDStreamingDiscovery; +class IBMDStreamingVideoEncodingMode; +class IBMDStreamingMutableVideoEncodingMode; +class IBMDStreamingVideoEncodingModePresetIterator; +class IBMDStreamingDeviceInput; +class IBMDStreamingH264NALPacket; +class IBMDStreamingAudioPacket; +class IBMDStreamingMPEG2TSPacket; +class IBMDStreamingH264NALParser; + +/* Interface IBMDStreamingDeviceNotificationCallback - Device notification callbacks. */ + +class BMD_PUBLIC IBMDStreamingDeviceNotificationCallback : public IUnknown +{ +public: + virtual HRESULT StreamingDeviceArrived (/* in */ IDeckLink* device) = 0; + virtual HRESULT StreamingDeviceRemoved (/* in */ IDeckLink* device) = 0; + virtual HRESULT StreamingDeviceModeChanged (/* in */ IDeckLink* device, /* in */ BMDStreamingDeviceMode mode) = 0; + +protected: + virtual ~IBMDStreamingDeviceNotificationCallback () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingH264InputCallback - H264 input callbacks. */ + +class BMD_PUBLIC IBMDStreamingH264InputCallback : public IUnknown +{ +public: + virtual HRESULT H264NALPacketArrived (/* in */ IBMDStreamingH264NALPacket* nalPacket) = 0; + virtual HRESULT H264AudioPacketArrived (/* in */ IBMDStreamingAudioPacket* audioPacket) = 0; + virtual HRESULT MPEG2TSPacketArrived (/* in */ IBMDStreamingMPEG2TSPacket* tsPacket) = 0; + virtual HRESULT H264VideoInputConnectorScanningChanged (void) = 0; + virtual HRESULT H264VideoInputConnectorChanged (void) = 0; + virtual HRESULT H264VideoInputModeChanged (void) = 0; + +protected: + virtual ~IBMDStreamingH264InputCallback () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingDiscovery - Installs device notifications */ + +class BMD_PUBLIC IBMDStreamingDiscovery : public IUnknown +{ +public: + virtual HRESULT InstallDeviceNotifications (/* in */ IBMDStreamingDeviceNotificationCallback* theCallback) = 0; + virtual HRESULT UninstallDeviceNotifications (void) = 0; + +protected: + virtual ~IBMDStreamingDiscovery () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingVideoEncodingMode - Represents an encoded video mode. */ + +class BMD_PUBLIC IBMDStreamingVideoEncodingMode : public IUnknown +{ +public: + virtual HRESULT GetName (/* out */ CFStringRef* name) = 0; + virtual unsigned int GetPresetID (void) = 0; + virtual unsigned int GetSourcePositionX (void) = 0; + virtual unsigned int GetSourcePositionY (void) = 0; + virtual unsigned int GetSourceWidth (void) = 0; + virtual unsigned int GetSourceHeight (void) = 0; + virtual unsigned int GetDestWidth (void) = 0; + virtual unsigned int GetDestHeight (void) = 0; + virtual HRESULT GetFlag (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* out */ bool* value) = 0; + virtual HRESULT GetInt (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* out */ int64_t* value) = 0; + virtual HRESULT GetFloat (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* out */ double* value) = 0; + virtual HRESULT GetString (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* out */ CFStringRef* value) = 0; + virtual HRESULT CreateMutableVideoEncodingMode (/* out */ IBMDStreamingMutableVideoEncodingMode** newEncodingMode) = 0; // Creates a mutable copy of the encoding mode + +protected: + virtual ~IBMDStreamingVideoEncodingMode () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingMutableVideoEncodingMode - Represents a mutable encoded video mode. */ + +class BMD_PUBLIC IBMDStreamingMutableVideoEncodingMode : public IBMDStreamingVideoEncodingMode +{ +public: + virtual HRESULT SetSourceRect (/* in */ uint32_t posX, /* in */ uint32_t posY, /* in */ uint32_t width, /* in */ uint32_t height) = 0; + virtual HRESULT SetDestSize (/* in */ uint32_t width, /* in */ uint32_t height) = 0; + virtual HRESULT SetFlag (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* in */ bool value) = 0; + virtual HRESULT SetInt (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* in */ int64_t value) = 0; + virtual HRESULT SetFloat (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* in */ double value) = 0; + virtual HRESULT SetString (/* in */ BMDStreamingEncodingModePropertyID cfgID, /* in */ CFStringRef value) = 0; + +protected: + virtual ~IBMDStreamingMutableVideoEncodingMode () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingVideoEncodingModePresetIterator - Enumerates encoding mode presets */ + +class BMD_PUBLIC IBMDStreamingVideoEncodingModePresetIterator : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IBMDStreamingVideoEncodingMode** videoEncodingMode) = 0; + +protected: + virtual ~IBMDStreamingVideoEncodingModePresetIterator () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingDeviceInput - Created by QueryInterface from IDeckLink */ + +class BMD_PUBLIC IBMDStreamingDeviceInput : public IUnknown +{ +public: + + /* Input modes */ + + virtual HRESULT DoesSupportVideoInputMode (/* in */ BMDDisplayMode inputMode, /* out */ bool* result) = 0; + virtual HRESULT GetVideoInputModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetVideoInputMode (/* in */ BMDDisplayMode inputMode) = 0; + virtual HRESULT GetCurrentDetectedVideoInputMode (/* out */ BMDDisplayMode* detectedMode) = 0; + + /* Capture modes */ + + virtual HRESULT GetVideoEncodingMode (/* out */ IBMDStreamingVideoEncodingMode** encodingMode) = 0; + virtual HRESULT GetVideoEncodingModePresetIterator (/* in */ BMDDisplayMode inputMode, /* out */ IBMDStreamingVideoEncodingModePresetIterator** iterator) = 0; + virtual HRESULT DoesSupportVideoEncodingMode (/* in */ BMDDisplayMode inputMode, /* in */ IBMDStreamingVideoEncodingMode* encodingMode, /* out */ BMDStreamingEncodingSupport* result, /* out */ IBMDStreamingVideoEncodingMode** changedEncodingMode) = 0; + virtual HRESULT SetVideoEncodingMode (/* in */ IBMDStreamingVideoEncodingMode* encodingMode) = 0; + + /* Input control */ + + virtual HRESULT StartCapture (void) = 0; + virtual HRESULT StopCapture (void) = 0; + virtual HRESULT SetCallback (/* in */ IUnknown* theCallback) = 0; + +protected: + virtual ~IBMDStreamingDeviceInput () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingH264NALPacket - Represent an H.264 NAL packet */ + +class BMD_PUBLIC IBMDStreamingH264NALPacket : public IUnknown +{ +public: + virtual long GetPayloadSize (void) = 0; + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual HRESULT GetBytesWithSizePrefix (/* out */ void** buffer) = 0; // Contains a 32-bit unsigned big endian size prefix + virtual HRESULT GetDisplayTime (/* in */ uint64_t requestedTimeScale, /* out */ uint64_t* displayTime) = 0; + virtual HRESULT GetPacketIndex (/* out */ uint32_t* packetIndex) = 0; // Deprecated + +protected: + virtual ~IBMDStreamingH264NALPacket () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingAudioPacket - Represents a chunk of audio data */ + +class BMD_PUBLIC IBMDStreamingAudioPacket : public IUnknown +{ +public: + virtual BMDStreamingAudioCodec GetCodec (void) = 0; + virtual long GetPayloadSize (void) = 0; + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + virtual HRESULT GetPlayTime (/* in */ uint64_t requestedTimeScale, /* out */ uint64_t* playTime) = 0; + virtual HRESULT GetPacketIndex (/* out */ uint32_t* packetIndex) = 0; // Deprecated + +protected: + virtual ~IBMDStreamingAudioPacket () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingMPEG2TSPacket - Represent an MPEG2 Transport Stream packet */ + +class BMD_PUBLIC IBMDStreamingMPEG2TSPacket : public IUnknown +{ +public: + virtual long GetPayloadSize (void) = 0; + virtual HRESULT GetBytes (/* out */ void** buffer) = 0; + +protected: + virtual ~IBMDStreamingMPEG2TSPacket () {} // call Release method to drop reference count +}; + +/* Interface IBMDStreamingH264NALParser - For basic NAL parsing */ + +class BMD_PUBLIC IBMDStreamingH264NALParser : public IUnknown +{ +public: + virtual HRESULT IsNALSequenceParameterSet (/* in */ IBMDStreamingH264NALPacket* nal) = 0; + virtual HRESULT IsNALPictureParameterSet (/* in */ IBMDStreamingH264NALPacket* nal) = 0; + virtual HRESULT GetProfileAndLevelFromSPS (/* in */ IBMDStreamingH264NALPacket* nal, /* out */ uint32_t* profileIdc, /* out */ uint32_t* profileCompatability, /* out */ uint32_t* levelIdc) = 0; + +protected: + virtual ~IBMDStreamingH264NALParser () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + BMD_PUBLIC IBMDStreamingDiscovery* CreateBMDStreamingDiscoveryInstance(void); + BMD_PUBLIC IBMDStreamingH264NALParser* CreateBMDStreamingH264NALParser(void); + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPISTREAMING_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming_v10_11.h new file mode 100644 index 0000000000..9ac9e499d9 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIStreaming_v10_11.h @@ -0,0 +1,59 @@ +/* -LICENSE-START- +** Copyright (c) 2018 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPISTREAMING_H +#define BMD_DECKLINKAPISTREAMING_H + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + + +/* Functions */ + +extern "C" { + + IBMDStreamingDiscovery* BMD_PUBLIC CreateBMDStreamingDiscoveryInstance_v10_11 (void); + IBMDStreamingH264NALParser* BMD_PUBLIC CreateBMDStreamingH264NALParser_v10_11 (void); + +} + + +#endif /* defined(BMD_DECKLINKAPISTREAMING_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPITypes.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPITypes.h new file mode 100644 index 0000000000..8437eb4c2a --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPITypes.h @@ -0,0 +1,132 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPITYPES_H +#define BMD_DECKLINKAPITYPES_H + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +#ifndef BMD_PUBLIC + #define BMD_PUBLIC +#endif + +// Type Declarations + +typedef int64_t BMDTimeValue; +typedef int64_t BMDTimeScale; +typedef uint32_t BMDTimecodeBCD; +typedef uint32_t BMDTimecodeUserBits; + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkTimecode = /* BC6CFBD3-8317-4325-AC1C-1216391E9340 */ { 0xBC,0x6C,0xFB,0xD3,0x83,0x17,0x43,0x25,0xAC,0x1C,0x12,0x16,0x39,0x1E,0x93,0x40 }; + +/* Enum BMDTimecodeFlags - Timecode flags */ + +typedef uint32_t BMDTimecodeFlags; +enum _BMDTimecodeFlags { + bmdTimecodeFlagDefault = 0, + bmdTimecodeIsDropFrame = 1 << 0, + bmdTimecodeFieldMark = 1 << 1, + bmdTimecodeColorFrame = 1 << 2, + bmdTimecodeEmbedRecordingTrigger = 1 << 3, // On SDI recording trigger utilises a user-bit. + bmdTimecodeRecordingTriggered = 1 << 4 +}; + +/* Enum BMDVideoConnection - Video connection types */ + +typedef uint32_t BMDVideoConnection; +enum _BMDVideoConnection { + bmdVideoConnectionUnspecified = 0, + bmdVideoConnectionSDI = 1 << 0, + bmdVideoConnectionHDMI = 1 << 1, + bmdVideoConnectionOpticalSDI = 1 << 2, + bmdVideoConnectionComponent = 1 << 3, + bmdVideoConnectionComposite = 1 << 4, + bmdVideoConnectionSVideo = 1 << 5 +}; + +/* Enum BMDAudioConnection - Audio connection types */ + +typedef uint32_t BMDAudioConnection; +enum _BMDAudioConnection { + bmdAudioConnectionEmbedded = 1 << 0, + bmdAudioConnectionAESEBU = 1 << 1, + bmdAudioConnectionAnalog = 1 << 2, + bmdAudioConnectionAnalogXLR = 1 << 3, + bmdAudioConnectionAnalogRCA = 1 << 4, + bmdAudioConnectionMicrophone = 1 << 5, + bmdAudioConnectionHeadphones = 1 << 6 +}; + +/* Enum BMDDeckControlConnection - Deck control connections */ + +typedef uint32_t BMDDeckControlConnection; +enum _BMDDeckControlConnection { + bmdDeckControlConnectionRS422Remote1 = 1 << 0, + bmdDeckControlConnectionRS422Remote2 = 1 << 1 +}; + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkTimecode; + +/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */ + +class BMD_PUBLIC IDeckLinkTimecode : public IUnknown +{ +public: + virtual BMDTimecodeBCD GetBCD (void) = 0; + virtual HRESULT GetComponents (/* out */ uint8_t* hours, /* out */ uint8_t* minutes, /* out */ uint8_t* seconds, /* out */ uint8_t* frames) = 0; + virtual HRESULT GetString (/* out */ CFStringRef* timecode) = 0; + virtual BMDTimecodeFlags GetFlags (void) = 0; + virtual HRESULT GetTimecodeUserBits (/* out */ BMDTimecodeUserBits* userBits) = 0; + +protected: + virtual ~IDeckLinkTimecode () {} // call Release method to drop reference count +}; + +/* Functions */ + +extern "C" { + + +} + + + +#endif /* defined(__cplusplus) */ +#endif /* defined(BMD_DECKLINKAPITYPES_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVersion.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVersion.h new file mode 100644 index 0000000000..679ef92584 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVersion.h @@ -0,0 +1,50 @@ +/* -LICENSE-START- + * ** Copyright (c) 2014 Blackmagic Design + * ** + * ** Permission is hereby granted, free of charge, to any person or organization + * ** obtaining a copy of the software and accompanying documentation (the + * ** "Software") to use, reproduce, display, distribute, sub-license, execute, + * ** and transmit the Software, and to prepare derivative works of the Software, + * ** and to permit third-parties to whom the Software is furnished to do so, in + * ** accordance with: + * ** + * ** (1) if the Software is obtained from Blackmagic Design, the End User License + * ** Agreement for the Software Development Kit (“EULA”) available at + * ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + * ** + * ** (2) if the Software is obtained from any third party, such licensing terms + * ** as notified by that third party, + * ** + * ** and all subject to the following: + * ** + * ** (3) the copyright notices in the Software and this entire statement, + * ** including the above license grant, this restriction and the following + * ** disclaimer, must be included in all copies of the Software, in whole or in + * ** part, and all derivative works of the Software, unless such copies or + * ** derivative works are solely in the form of machine-executable object code + * ** generated by a source language processor. + * ** + * ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * ** DEALINGS IN THE SOFTWARE. + * ** + * ** A copy of the Software is available free of charge at + * ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + * ** + * ** -LICENSE-END- + * */ + +/* DeckLinkAPIVersion.h */ + +#ifndef __DeckLink_API_Version_h__ +#define __DeckLink_API_Version_h__ + +#define BLACKMAGIC_DECKLINK_API_VERSION 0x0c040200 +#define BLACKMAGIC_DECKLINK_API_VERSION_STRING "12.4.2" + +#endif // __DeckLink_API_Version_h__ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoEncoderInput_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoEncoderInput_v10_11.h new file mode 100644 index 0000000000..8921b35333 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoEncoderInput_v10_11.h @@ -0,0 +1,88 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H +#define BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// Type Declarations + +BMD_CONST REFIID IID_IDeckLinkEncoderInput_v10_11 = /* 270587DA-6B7D-42E7-A1F0-6D853F581185 */ {0x27,0x05,0x87,0xDA,0x6B,0x7D,0x42,0xE7,0xA1,0xF0,0x6D,0x85,0x3F,0x58,0x11,0x85}; + +/* Interface IDeckLinkEncoderInput_v10_11 - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkEncoderInput_v10_11 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailablePacketsCount (/* out */ uint32_t *availablePacketsCount) = 0; + virtual HRESULT SetMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioFormat audioFormat, /* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkEncoderInputCallback *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkEncoderInput_v10_11 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v10_11.h new file mode 100644 index 0000000000..0a287f8cdf --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v10_11.h @@ -0,0 +1,91 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOINPUT_v10_11_H +#define BMD_DECKLINKAPIVIDEOINPUT_v10_11_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" +#include "DeckLinkAPIVideoInput_v11_5_1.h" + +// Type Declarations + +BMD_CONST REFIID IID_IDeckLinkInput_v10_11 = /* AF22762B-DFAC-4846-AA79-FA8883560995 */ {0xAF,0x22,0x76,0x2B,0xDF,0xAC,0x48,0x46,0xAA,0x79,0xFA,0x88,0x83,0x56,0x09,0x95}; + +/* Interface IDeckLinkInput_v10_11 - DeckLink input interface. */ + +class IDeckLinkInput_v10_11 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v10_11 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_4.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_4.h new file mode 100644 index 0000000000..4879fc2a18 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_4.h @@ -0,0 +1,90 @@ +/* -LICENSE-START- +** Copyright (c) 2019 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOINPUT_v11_4_H +#define BMD_DECKLINKAPIVIDEOINPUT_v11_4_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPIVideoInput_v11_5_1.h" + +// Type Declarations + +BMD_CONST REFIID IID_IDeckLinkInput_v11_4 = /* 2A88CF76-F494-4216-A7EF-DC74EEB83882 */ { 0x2A,0x88,0xCF,0x76,0xF4,0x94,0x42,0x16,0xA7,0xEF,0xDC,0x74,0xEE,0xB8,0x38,0x82 }; + +/* Interface IDeckLinkInput_v11_4 - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput_v11_4 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDSupportedVideoModeFlags flags, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v11_4 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v11_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_5_1.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_5_1.h new file mode 100644 index 0000000000..51fb5172ac --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoInput_v11_5_1.h @@ -0,0 +1,102 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H +#define BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +BMD_CONST REFIID IID_IDeckLinkInputCallback_v11_5_1 = /* DD04E5EC-7415-42AB-AE4A-E80C4DFC044A */ { 0xDD, 0x04, 0xE5, 0xEC, 0x74, 0x15, 0x42, 0xAB, 0xAE, 0x4A, 0xE8, 0x0C, 0x4D, 0xFC, 0x04, 0x4A }; +BMD_CONST REFIID IID_IDeckLinkInput_v11_5_1 = /* 9434C6E4-B15D-4B1C-979E-661E3DDCB4B9 */ { 0x94, 0x34, 0xC6, 0xE4, 0xB1, 0x5D, 0x4B, 0x1C, 0x97, 0x9E, 0x66, 0x1E, 0x3D, 0xDC, 0xB4, 0xB9 }; + +/* Interface IDeckLinkInputCallback_v11_5_1 - Frame arrival callback. */ + +class BMD_PUBLIC IDeckLinkInputCallback_v11_5_1 : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback_v11_5_1 () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkInput_v11_5_1 - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkInput_v11_5_1 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoInputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0; + virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1* theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v11_5_1 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v10_11.h new file mode 100644 index 0000000000..22a13a5dcc --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v10_11.h @@ -0,0 +1,108 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H +#define BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// Type Declarations + +BMD_CONST REFIID IID_IDeckLinkOutput_v10_11 = /* CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564 */ {0xCC,0x5C,0x8A,0x6E,0x3F,0x2F,0x4B,0x3A,0x87,0xEA,0xFD,0x78,0xAF,0x30,0x05,0x64}; + +/* Interface IDeckLinkOutput_v10_11 - DeckLink output interface. */ + +class IDeckLinkOutput_v10_11 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *frameCompletionTimestamp) = 0; + +protected: + virtual ~IDeckLinkOutput_v10_11 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v11_4.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v11_4.h new file mode 100644 index 0000000000..14d65ac24c --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPIVideoOutput_v11_4.h @@ -0,0 +1,101 @@ +/* -LICENSE-START- +** Copyright (c) 2019 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H +#define BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +BMD_CONST REFIID IID_IDeckLinkOutput_v11_4 = /* 065A0F6C-C508-4D0D-B919-F5EB0EBFC96B */ { 0x06,0x5A,0x0F,0x6C,0xC5,0x08,0x4D,0x0D,0xB9,0x19,0xF5,0xEB,0x0E,0xBF,0xC9,0x6B }; + +/* Interface IDeckLinkOutput_v11_4 - Created by QueryInterface from IDeckLink. */ + +class BMD_PUBLIC IDeckLinkOutput_v11_4 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0; + virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0; + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame** outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary** outBuffer) = 0; // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame* theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback* theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t* bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + virtual HRESULT WriteAudioSamplesSync (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t* sampleFramesWritten) = 0; + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t* bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback* theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue* actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool* active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* streamTime, /* out */ double* playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus* referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0; + virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* frameCompletionTimestamp) = 0; + +protected: + virtual ~IDeckLinkOutput_v11_4 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_11.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_11.h new file mode 100644 index 0000000000..d9ef54e525 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_11.h @@ -0,0 +1,135 @@ +/* -LICENSE-START- +** Copyright (c) 2018 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_11_H +#define BMD_DECKLINKAPI_v10_11_H + +#include "DeckLinkAPI.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkAttributes_v10_11 = /* ABC11843-D966-44CB-96E2-A1CB5D3135C4 */ {0xAB,0xC1,0x18,0x43,0xD9,0x66,0x44,0xCB,0x96,0xE2,0xA1,0xCB,0x5D,0x31,0x35,0xC4}; +BMD_CONST REFIID IID_IDeckLinkNotification_v10_11 = /* 0A1FB207-E215-441B-9B19-6FA1575946C5 */ {0x0A,0x1F,0xB2,0x07,0xE2,0x15,0x44,0x1B,0x9B,0x19,0x6F,0xA1,0x57,0x59,0x46,0xC5}; + +/* Enum BMDDisplayModeSupport_v10_11 - Output mode supported flags */ + +typedef uint32_t BMDDisplayModeSupport_v10_11; +enum _BMDDisplayModeSupport_v10_11 { + bmdDisplayModeNotSupported_v10_11 = 0, + bmdDisplayModeSupported_v10_11, + bmdDisplayModeSupportedWithConversion_v10_11 +}; + +/* Enum BMDDuplexMode_v10_11 - Duplex for configurable ports */ + +typedef uint32_t BMDDuplexMode_v10_11; +enum _BMDDuplexMode_v10_11 { + bmdDuplexModeFull_v10_11 = 'fdup', + bmdDuplexModeHalf_v10_11 = 'hdup' +}; + +/* Enum BMDDeckLinkAttributeID_v10_11 - DeckLink Attribute ID */ + +enum _BMDDeckLinkAttributeID_v10_11 { + + /* Flags */ + + BMDDeckLinkSupportsDuplexModeConfiguration_v10_11 = 'dupx', + BMDDeckLinkSupportsHDKeying_v10_11 = 'keyh', + + /* Integers */ + + BMDDeckLinkPairedDevicePersistentID_v10_11 = 'ppid', + BMDDeckLinkSupportsFullDuplex_v10_11 = 'fdup', +}; + +enum _BMDDeckLinkStatusID_v10_11 { + bmdDeckLinkStatusDuplexMode_v10_11 = 'dupx', +}; + +typedef uint32_t BMDDuplexStatus_v10_11; +enum _BMDDuplexStatus_v10_11 { + bmdDuplexFullDuplex_v10_11 = 'fdup', + bmdDuplexHalfDuplex_v10_11 = 'hdup', + bmdDuplexSimplex_v10_11 = 'splx', + bmdDuplexInactive_v10_11 = 'inac', +}; + +#if defined(__cplusplus) + +/* Interface IDeckLinkAttributes_v10_11 - DeckLink Attribute interface */ + +class BMD_PUBLIC IDeckLinkAttributes_v10_11 : public IUnknown +{ +public: + virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool *value) = 0; + virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t *value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ CFStringRef *value) = 0; + +protected: + virtual ~IDeckLinkAttributes_v10_11 () {} // call Release method to drop reference count +}; + +/* Interface IDeckLinkNotification_v10_11 - DeckLink Notification interface */ + +class BMD_PUBLIC IDeckLinkNotification_v10_11 : public IUnknown +{ +public: + virtual HRESULT Subscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0; + virtual HRESULT Unsubscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0; +}; + +/* Functions */ + +extern "C" { + + IDeckLinkIterator* BMD_PUBLIC CreateDeckLinkIteratorInstance_v10_11 (void); + IDeckLinkDiscovery* BMD_PUBLIC CreateDeckLinkDiscoveryInstance_v10_11 (void); + IDeckLinkAPIInformation* BMD_PUBLIC CreateDeckLinkAPIInformationInstance_v10_11 (void); + IDeckLinkGLScreenPreviewHelper* BMD_PUBLIC CreateOpenGLScreenPreviewHelper_v10_11 (void); + IDeckLinkCocoaScreenPreviewCallback* BMD_PUBLIC CreateCocoaScreenPreview_v10_11 (void* /* (NSView*) */ parentView); + IDeckLinkVideoConversion* BMD_PUBLIC CreateVideoConversionInstance_v10_11 (void); + IDeckLinkVideoFrameAncillaryPackets* BMD_PUBLIC CreateVideoFrameAncillaryPacketsInstance_v10_11 (void); // For use when creating a custom IDeckLinkVideoFrame without wrapping IDeckLinkOutput::CreateVideoFrame + +} + +#endif // defined(__cplusplus) +#endif /* defined(BMD_DECKLINKAPI_v10_11_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_2.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_2.h new file mode 100644 index 0000000000..20eedd28cd --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_2.h @@ -0,0 +1,68 @@ +/* -LICENSE-START- +** Copyright (c) 2014 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_2_H +#define BMD_DECKLINKAPI_v10_2_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_2; +enum _BMDDeckLinkConfigurationID_v10_2 { + /* Video output flags */ + + bmdDeckLinkConfig3GBpsVideoOutput_v10_2 = '3gbs', +}; + +/* Enum BMDAudioConnection_v10_2 - Audio connection types */ + +typedef uint32_t BMDAudioConnection_v10_2; +enum _BMDAudioConnection_v10_2 { + bmdAudioConnectionEmbedded_v10_2 = 'embd', + bmdAudioConnectionAESEBU_v10_2 = 'aes ', + bmdAudioConnectionAnalog_v10_2 = 'anlg', + bmdAudioConnectionAnalogXLR_v10_2 = 'axlr', + bmdAudioConnectionAnalogRCA_v10_2 = 'arca' +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_2_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_4.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_4.h new file mode 100644 index 0000000000..fa5892dd0a --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_4.h @@ -0,0 +1,58 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_4_H +#define BMD_DECKLINKAPI_v10_4_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_4; +enum _BMDDeckLinkConfigurationID_v10_4 { + + /* Video output flags */ + + bmdDeckLinkConfigSingleLinkVideoOutput_v10_4 = /* 'sglo' */ 0x73676C6F, +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_4_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_5.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_5.h new file mode 100644 index 0000000000..40ce330f09 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_5.h @@ -0,0 +1,59 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_5_H +#define BMD_DECKLINKAPI_v10_5_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkAttributeID_v10_5; +enum _BMDDeckLinkAttributeID_v10_5 { + + /* Integers */ + + BMDDeckLinkDeviceBusyState_v10_5 = /* 'dbst' */ 0x64627374, +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_5_H) */ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_6.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_6.h new file mode 100644 index 0000000000..67082779d9 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_6.h @@ -0,0 +1,64 @@ +/* -LICENSE-START- +** Copyright (c) 2016 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_6_H +#define BMD_DECKLINKAPI_v10_6_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkAttributeID_c10_6; +enum _BMDDeckLinkAttributeID_v10_6 { + + /* Flags */ + + BMDDeckLinkSupportsDesktopDisplay_v10_6 = 'extd', +}; + +typedef uint32_t BMDIdleVideoOutputOperation_v10_6; +enum _BMDIdleVideoOutputOperation_v10_6 { + bmdIdleVideoOutputDesktop_v10_6 = 'desk' +}; + + +#endif /* defined(BMD_DECKLINKAPI_v10_6_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_9.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_9.h new file mode 100644 index 0000000000..8b6b4b208f --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v10_9.h @@ -0,0 +1,58 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v10_9_H +#define BMD_DECKLINKAPI_v10_9_H + +#include "DeckLinkAPI.h" + +// Type Declarations + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef uint32_t BMDDeckLinkConfigurationID_v10_9; +enum _BMDDeckLinkConfigurationID_v10_9 { + + /* Flags */ + + bmdDeckLinkConfig1080pNotPsF_v10_9 = 'fpro', +}; + +#endif /* defined(BMD_DECKLINKAPI_v10_9_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5.h new file mode 100644 index 0000000000..a7115ae336 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5.h @@ -0,0 +1,113 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v11_5_H +#define BMD_DECKLINKAPI_v11_5_H + +#include "DeckLinkAPI.h" + +BMD_CONST REFIID IID_IDeckLinkVideoFrameMetadataExtensions_v11_5 = /* D5973DC9-6432-46D0-8F0B-2496F8A1238F */ {0xD5,0x97,0x3D,0xC9,0x64,0x32,0x46,0xD0,0x8F,0x0B,0x24,0x96,0xF8,0xA1,0x23,0x8F}; + +/* Enum BMDDeckLinkFrameMetadataID - DeckLink Frame Metadata ID */ + +typedef uint32_t BMDDeckLinkFrameMetadataID_v11_5; +enum _BMDDeckLinkFrameMetadataID_v11_5 { + bmdDeckLinkFrameMetadataCintelFilmType_v11_5 = /* 'cfty' */ 0x63667479, // Current film type + bmdDeckLinkFrameMetadataCintelFilmGauge_v11_5 = /* 'cfga' */ 0x63666761, // Current film gauge + bmdDeckLinkFrameMetadataCintelKeykodeLow_v11_5 = /* 'ckkl' */ 0x636B6B6C, // Raw keykode value - low 64 bits + bmdDeckLinkFrameMetadataCintelKeykodeHigh_v11_5 = /* 'ckkh' */ 0x636B6B68, // Raw keykode value - high 64 bits + bmdDeckLinkFrameMetadataCintelTile1Size_v11_5 = /* 'ct1s' */ 0x63743173, // Size in bytes of compressed raw tile 1 + bmdDeckLinkFrameMetadataCintelTile2Size_v11_5 = /* 'ct2s' */ 0x63743273, // Size in bytes of compressed raw tile 2 + bmdDeckLinkFrameMetadataCintelTile3Size_v11_5 = /* 'ct3s' */ 0x63743373, // Size in bytes of compressed raw tile 3 + bmdDeckLinkFrameMetadataCintelTile4Size_v11_5 = /* 'ct4s' */ 0x63743473, // Size in bytes of compressed raw tile 4 + bmdDeckLinkFrameMetadataCintelImageWidth_v11_5 = /* 'IWPx' */ 0x49575078, // Width in pixels of image + bmdDeckLinkFrameMetadataCintelImageHeight_v11_5 = /* 'IHPx' */ 0x49485078, // Height in pixels of image + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInRed_v11_5 = /* 'mrir' */ 0x6D726972, // Red in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInRed_v11_5 = /* 'mgir' */ 0x6D676972, // Green in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInRed_v11_5 = /* 'mbir' */ 0x6D626972, // Blue in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInGreen_v11_5 = /* 'mrig' */ 0x6D726967, // Red in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInGreen_v11_5 = /* 'mgig' */ 0x6D676967, // Green in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInGreen_v11_5 = /* 'mbig' */ 0x6D626967, // Blue in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInBlue_v11_5 = /* 'mrib' */ 0x6D726962, // Red in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInBlue_v11_5 = /* 'mgib' */ 0x6D676962, // Green in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInBlue_v11_5 = /* 'mbib' */ 0x6D626962, // Blue in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInRed_v11_5 = /* 'mlrr' */ 0x6D6C7272, // Red in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInRed_v11_5 = /* 'mlgr' */ 0x6D6C6772, // Green in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInRed_v11_5 = /* 'mlbr' */ 0x6D6C6272, // Blue in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInGreen_v11_5 = /* 'mlrg' */ 0x6D6C7267, // Red in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInGreen_v11_5 = /* 'mlgg' */ 0x6D6C6767, // Green in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInGreen_v11_5 = /* 'mlbg' */ 0x6D6C6267, // Blue in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInBlue_v11_5 = /* 'mlrb' */ 0x6D6C7262, // Red in blue log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInBlue_v11_5 = /* 'mlgb' */ 0x6D6C6762, // Green in blue log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInBlue_v11_5 = /* 'mlbb' */ 0x6D6C6262, // Blue in blue log masking parameter + bmdDeckLinkFrameMetadataCintelFilmFrameRate_v11_5 = /* 'cffr' */ 0x63666672, // Film frame rate + bmdDeckLinkFrameMetadataCintelOffsetToApplyHorizontal_v11_5 = /* 'otah' */ 0x6F746168, // Horizontal offset (pixels) to be applied to image + bmdDeckLinkFrameMetadataCintelOffsetToApplyVertical_v11_5 = /* 'otav' */ 0x6F746176, // Vertical offset (pixels) to be applied to image + bmdDeckLinkFrameMetadataCintelGainRed_v11_5 = /* 'LfRd' */ 0x4C665264, // Red gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelGainGreen_v11_5 = /* 'LfGr' */ 0x4C664772, // Green gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelGainBlue_v11_5 = /* 'LfBl' */ 0x4C66426C, // Blue gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelLiftRed_v11_5 = /* 'GnRd' */ 0x476E5264, // Red lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelLiftGreen_v11_5 = /* 'GnGr' */ 0x476E4772, // Green lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelLiftBlue_v11_5 = /* 'GnBl' */ 0x476E426C, // Blue lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelHDRGainRed_v11_5 = /* 'HGRd' */ 0x48475264, // Red gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintelHDRGainGreen_v11_5 = /* 'HGGr' */ 0x48474772, // Green gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintelHDRGainBlue_v11_5 = /* 'HGBl' */ 0x4847426C, // Blue gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintel16mmCropRequired_v11_5 = /* 'c16c' */ 0x63313663, // The image should be cropped to 16mm size + bmdDeckLinkFrameMetadataCintelInversionRequired_v11_5 = /* 'cinv' */ 0x63696E76, // The image should be colour inverted + bmdDeckLinkFrameMetadataCintelFlipRequired_v11_5 = /* 'cflr' */ 0x63666C72, // The image should be flipped horizontally + bmdDeckLinkFrameMetadataCintelFocusAssistEnabled_v11_5 = /* 'cfae' */ 0x63666165, // Focus Assist is currently enabled + bmdDeckLinkFrameMetadataCintelKeykodeIsInterpolated_v11_5 = /* 'kkii' */ 0x6B6B6969 // The keykode for this frame is interpolated from nearby keykodes +}; + +/* Interface IDeckLinkVideoFrameMetadataExtensions - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDMI HDR information */ + +class BMD_PUBLIC IDeckLinkVideoFrameMetadataExtensions_v11_5 : public IUnknown +{ +public: + virtual HRESULT GetInt (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ int64_t *value) = 0; + virtual HRESULT GetFloat (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ double *value) = 0; + virtual HRESULT GetFlag (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ bool *value) = 0; + virtual HRESULT GetString (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ CFStringRef *value) = 0; + +protected: + virtual ~IDeckLinkVideoFrameMetadataExtensions_v11_5 () {} // call Release method to drop reference count +}; + +#endif /* defined(BMD_DECKLINKAPI_v11_5_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5_1.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5_1.h new file mode 100644 index 0000000000..a406f000e1 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v11_5_1.h @@ -0,0 +1,57 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v11_5_1_H +#define BMD_DECKLINKAPI_v11_5_1_H + +#include "DeckLinkAPI.h" + +/* Enum BMDDeckLinkStatusID - DeckLink Status ID */ + +typedef uint32_t BMDDeckLinkStatusID_v11_5_1; +enum _BMDDeckLinkStatusID_v11_5_1 { + + /* Video output flags */ + + bmdDeckLinkStatusDetectedVideoInputFlags_v11_5_1 = /* 'dvif' */ 0x64766966, + +}; + +#endif /* defined(BMD_DECKLINKAPI_v11_5_1_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_1.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_1.h new file mode 100644 index 0000000000..5f4f135331 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_1.h @@ -0,0 +1,212 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v7_1.h */ + +#ifndef __DeckLink_API_v7_1_h__ +#define __DeckLink_API_v7_1_h__ + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// "B28131B6-59AC-4857-B5AC-CD75D5883E2F" +#define IID_IDeckLinkDisplayModeIterator_v7_1 (REFIID){0xB2,0x81,0x31,0xB6,0x59,0xAC,0x48,0x57,0xB5,0xAC,0xCD,0x75,0xD5,0x88,0x3E,0x2F} + +// "AF0CD6D5-8376-435E-8433-54F9DD530AC3" +#define IID_IDeckLinkDisplayMode_v7_1 (REFIID){0xAF,0x0C,0xD6,0xD5,0x83,0x76,0x43,0x5E,0x84,0x33,0x54,0xF9,0xDD,0x53,0x0A,0xC3} + +// "EBD01AFA-E4B0-49C6-A01D-EDB9D1B55FD9" +#define IID_IDeckLinkVideoOutputCallback_v7_1 (REFIID){0xEB,0xD0,0x1A,0xFA,0xE4,0xB0,0x49,0xC6,0xA0,0x1D,0xED,0xB9,0xD1,0xB5,0x5F,0xD9} + +// "7F94F328-5ED4-4E9F-9729-76A86BDC99CC" +#define IID_IDeckLinkInputCallback_v7_1 (REFIID){0x7F,0x94,0xF3,0x28,0x5E,0xD4,0x4E,0x9F,0x97,0x29,0x76,0xA8,0x6B,0xDC,0x99,0xCC} + +// "AE5B3E9B-4E1E-4535-B6E8-480FF52F6CE5" +#define IID_IDeckLinkOutput_v7_1 (REFIID){0xAE,0x5B,0x3E,0x9B,0x4E,0x1E,0x45,0x35,0xB6,0xE8,0x48,0x0F,0xF5,0x2F,0x6C,0xE5} + +// "2B54EDEF-5B32-429F-BA11-BB990596EACD" +#define IID_IDeckLinkInput_v7_1 (REFIID){0x2B,0x54,0xED,0xEF,0x5B,0x32,0x42,0x9F,0xBA,0x11,0xBB,0x99,0x05,0x96,0xEA,0xCD} + +// "333F3A10-8C2D-43CF-B79D-46560FEEA1CE" +#define IID_IDeckLinkVideoFrame_v7_1 (REFIID){0x33,0x3F,0x3A,0x10,0x8C,0x2D,0x43,0xCF,0xB7,0x9D,0x46,0x56,0x0F,0xEE,0xA1,0xCE} + +// "C8B41D95-8848-40EE-9B37-6E3417FB114B" +#define IID_IDeckLinkVideoInputFrame_v7_1 (REFIID){0xC8,0xB4,0x1D,0x95,0x88,0x48,0x40,0xEE,0x9B,0x37,0x6E,0x34,0x17,0xFB,0x11,0x4B} + +// "C86DE4F6-A29F-42E3-AB3A-1363E29F0788" +#define IID_IDeckLinkAudioInputPacket_v7_1 (REFIID){0xC8,0x6D,0xE4,0xF6,0xA2,0x9F,0x42,0xE3,0xAB,0x3A,0x13,0x63,0xE2,0x9F,0x07,0x88} + +#if defined(__cplusplus) + +class IDeckLinkVideoFrame_v7_1; +class IDeckLinkDisplayModeIterator_v7_1; +class IDeckLinkDisplayMode_v7_1; +class IDeckLinkVideoInputFrame_v7_1; +class IDeckLinkAudioInputPacket_v7_1; + +class IDeckLinkDisplayModeIterator_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Next (IDeckLinkDisplayMode_v7_1* *deckLinkDisplayMode) = 0; +}; + + +class IDeckLinkDisplayMode_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetName (CFStringRef* name) = 0; + virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode () = 0; + virtual long STDMETHODCALLTYPE GetWidth () = 0; + virtual long STDMETHODCALLTYPE GetHeight () = 0; + virtual HRESULT STDMETHODCALLTYPE GetFrameRate (BMDTimeValue *frameDuration, BMDTimeScale *timeScale) = 0; +}; + +class IDeckLinkVideoOutputCallback_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted (IDeckLinkVideoFrame_v7_1* completedFrame, BMDOutputFrameCompletionResult result) = 0; +}; + +class IDeckLinkInputCallback_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived (IDeckLinkVideoInputFrame_v7_1* videoFrame, IDeckLinkAudioInputPacket_v7_1* audioPacket) = 0; +}; + +// IDeckLinkOutput_v7_1. Created by QueryInterface from IDeckLink. +class IDeckLinkOutput_v7_1 : public IUnknown +{ +public: + // Display mode predicates + virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator (IDeckLinkDisplayModeIterator_v7_1* *iterator) = 0; + + + // Video output + virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput (BMDDisplayMode displayMode) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput () = 0; + + virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator (IDeckLinkMemoryAllocator* theAllocator) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame (int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1* *outFrame) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateVideoFrameFromBuffer (void* buffer, int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1* *outFrame) = 0; + + virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync (IDeckLinkVideoFrame_v7_1* theFrame) = 0; + virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame (IDeckLinkVideoFrame_v7_1* theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale) = 0; + virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback (IDeckLinkVideoOutputCallback_v7_1* theCallback) = 0; + + + // Audio output + virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput () = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync (void* buffer, uint32_t sampleFrameCount, uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll () = 0; + virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll () = 0; + virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples (void* buffer, uint32_t sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount (uint32_t *bufferedSampleCount) = 0; + virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples () = 0; + + virtual HRESULT STDMETHODCALLTYPE SetAudioCallback (IDeckLinkAudioOutputCallback* theCallback) = 0; + + + // Output control + virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed) = 0; + virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, BMDTimeValue *actualStopTime, BMDTimeScale timeScale) = 0; + virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock (BMDTimeScale desiredTimeScale, BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0; +}; + +// IDeckLinkInput_v7_1. Created by QueryInterface from IDeckLink. +class IDeckLinkInput_v7_1 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator (IDeckLinkDisplayModeIterator_v7_1 **iterator) = 0; + + // Video input + virtual HRESULT STDMETHODCALLTYPE EnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableVideoInput () = 0; + + // Audio input + virtual HRESULT STDMETHODCALLTYPE EnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0; + virtual HRESULT STDMETHODCALLTYPE DisableAudioInput () = 0; + virtual HRESULT STDMETHODCALLTYPE ReadAudioSamples (void* buffer, uint32_t sampleFrameCount, uint32_t *sampleFramesRead, BMDTimeValue *audioPacketTime, BMDTimeScale timeScale) = 0; + virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount (uint32_t *bufferedSampleCount) = 0; + + // Input control + virtual HRESULT STDMETHODCALLTYPE StartStreams () = 0; + virtual HRESULT STDMETHODCALLTYPE StopStreams () = 0; + virtual HRESULT STDMETHODCALLTYPE PauseStreams () = 0; + virtual HRESULT STDMETHODCALLTYPE SetCallback (IDeckLinkInputCallback_v7_1* theCallback) = 0; +}; + +// IDeckLinkVideoFrame_v7_1. Created by IDeckLinkOutput::CreateVideoFrame. +class IDeckLinkVideoFrame_v7_1 : public IUnknown +{ +public: + virtual long STDMETHODCALLTYPE GetWidth () = 0; + virtual long STDMETHODCALLTYPE GetHeight () = 0; + virtual long STDMETHODCALLTYPE GetRowBytes () = 0; + virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat () = 0; + virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags () = 0; + virtual HRESULT STDMETHODCALLTYPE GetBytes (void* *buffer) = 0; +}; + +// IDeckLinkVideoInputFrame_v7_1. Provided by the IDeckLinkInput_v7_1 frame arrival callback. +class IDeckLinkVideoInputFrame_v7_1 : public IDeckLinkVideoFrame_v7_1 +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetFrameTime (BMDTimeValue *frameTime, BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0; +}; + +// IDeckLinkAudioInputPacket_v7_1. Provided by the IDeckLinkInput_v7_1 callback. +class IDeckLinkAudioInputPacket_v7_1 : public IUnknown +{ +public: + virtual long STDMETHODCALLTYPE GetSampleCount () = 0; + virtual HRESULT STDMETHODCALLTYPE GetBytes (void* *buffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAudioPacketTime (BMDTimeValue *packetTime, BMDTimeScale timeScale) = 0; +}; + +#endif // defined(__cplusplus) + +#endif // __DeckLink_API_v7_1_h__ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_3.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_3.h new file mode 100644 index 0000000000..8634e9c809 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_3.h @@ -0,0 +1,186 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v7_3.h */ + +#ifndef __DeckLink_API_v7_3_h__ +#define __DeckLink_API_v7_3_h__ + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v7_6.h" + +/* Interface ID Declarations */ + +#define IID_IDeckLinkInputCallback_v7_3 /* FD6F311D-4D00-444B-9ED4-1F25B5730AD0 */ (REFIID){0xFD,0x6F,0x31,0x1D,0x4D,0x00,0x44,0x4B,0x9E,0xD4,0x1F,0x25,0xB5,0x73,0x0A,0xD0} +#define IID_IDeckLinkOutput_v7_3 /* 271C65E3-C323-4344-A30F-D908BCB20AA3 */ (REFIID){0x27,0x1C,0x65,0xE3,0xC3,0x23,0x43,0x44,0xA3,0x0F,0xD9,0x08,0xBC,0xB2,0x0A,0xA3} +#define IID_IDeckLinkInput_v7_3 /* 4973F012-9925-458C-871C-18774CDBBECB */ (REFIID){0x49,0x73,0xF0,0x12,0x99,0x25,0x45,0x8C,0x87,0x1C,0x18,0x77,0x4C,0xDB,0xBE,0xCB} +#define IID_IDeckLinkVideoInputFrame_v7_3 /* CF317790-2894-11DE-8C30-0800200C9A66 */ (REFIID){0xCF,0x31,0x77,0x90,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66} + +/* End Interface ID Declarations */ + +#if defined(__cplusplus) + +/* Forward Declarations */ + +class IDeckLinkVideoInputFrame_v7_3; + +/* End Forward Declarations */ + + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkOutput_v7_3 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (BMDDisplayMode displayMode, BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0; + virtual HRESULT CreateAncillaryData (BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount, BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, uint32_t sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetHardwareReferenceClock (BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0; + +protected: + virtual ~IDeckLinkOutput_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkOutput */ + + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +class IDeckLinkInputCallback_v7_3 : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode_v7_6 *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame_v7_3 *videoFrame, /* in */ IDeckLinkAudioInputPacket *audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkInputCallback */ + + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkInput_v7_3 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v7_3 *theCallback) = 0; + +protected: + virtual ~IDeckLinkInput_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkInput */ + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +class IDeckLinkVideoInputFrame_v7_3 : public IDeckLinkVideoFrame_v7_6 +{ +public: + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0; + +protected: + virtual ~IDeckLinkVideoInputFrame_v7_3 () {}; // call Release method to drop reference count +}; + +/* End Interface IDeckLinkVideoInputFrame */ + +#endif // defined(__cplusplus) +#endif // __DeckLink_API_v7_3_h__ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_6.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_6.h new file mode 100644 index 0000000000..df9e00712c --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_6.h @@ -0,0 +1,435 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v7_6.h */ + +#ifndef __DeckLink_API_v7_6_h__ +#define __DeckLink_API_v7_6_h__ + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// Interface ID Declarations + +#define IID_IDeckLinkVideoOutputCallback_v7_6 /* E763A626-4A3C-49D1-BF13-E7AD3692AE52 */ (REFIID){0xE7,0x63,0xA6,0x26,0x4A,0x3C,0x49,0xD1,0xBF,0x13,0xE7,0xAD,0x36,0x92,0xAE,0x52} +#define IID_IDeckLinkInputCallback_v7_6 /* 31D28EE7-88B6-4CB1-897A-CDBF79A26414 */ (REFIID){0x31,0xD2,0x8E,0xE7,0x88,0xB6,0x4C,0xB1,0x89,0x7A,0xCD,0xBF,0x79,0xA2,0x64,0x14} +#define IID_IDeckLinkDisplayModeIterator_v7_6 /* 455D741F-1779-4800-86F5-0B5D13D79751 */ (REFIID){0x45,0x5D,0x74,0x1F,0x17,0x79,0x48,0x00,0x86,0xF5,0x0B,0x5D,0x13,0xD7,0x97,0x51} +#define IID_IDeckLinkDisplayMode_v7_6 /* 87451E84-2B7E-439E-A629-4393EA4A8550 */ (REFIID){0x87,0x45,0x1E,0x84,0x2B,0x7E,0x43,0x9E,0xA6,0x29,0x43,0x93,0xEA,0x4A,0x85,0x50} +#define IID_IDeckLinkOutput_v7_6 /* 29228142-EB8C-4141-A621-F74026450955 */ (REFIID){0x29,0x22,0x81,0x42,0xEB,0x8C,0x41,0x41,0xA6,0x21,0xF7,0x40,0x26,0x45,0x09,0x55} +#define IID_IDeckLinkInput_v7_6 /* 300C135A-9F43-48E2-9906-6D7911D93CF1 */ (REFIID){0x30,0x0C,0x13,0x5A,0x9F,0x43,0x48,0xE2,0x99,0x06,0x6D,0x79,0x11,0xD9,0x3C,0xF1} +#define IID_IDeckLinkTimecode_v7_6 /* EFB9BCA6-A521-44F7-BD69-2332F24D9EE6 */ (REFIID){0xEF,0xB9,0xBC,0xA6,0xA5,0x21,0x44,0xF7,0xBD,0x69,0x23,0x32,0xF2,0x4D,0x9E,0xE6} +#define IID_IDeckLinkVideoFrame_v7_6 /* A8D8238E-6B18-4196-99E1-5AF717B83D32 */ (REFIID){0xA8,0xD8,0x23,0x8E,0x6B,0x18,0x41,0x96,0x99,0xE1,0x5A,0xF7,0x17,0xB8,0x3D,0x32} +#define IID_IDeckLinkMutableVideoFrame_v7_6 /* 46FCEE00-B4E6-43D0-91C0-023A7FCEB34F */ (REFIID){0x46,0xFC,0xEE,0x00,0xB4,0xE6,0x43,0xD0,0x91,0xC0,0x02,0x3A,0x7F,0xCE,0xB3,0x4F} +#define IID_IDeckLinkVideoInputFrame_v7_6 /* 9A74FA41-AE9F-47AC-8CF4-01F42DD59965 */ (REFIID){0x9A,0x74,0xFA,0x41,0xAE,0x9F,0x47,0xAC,0x8C,0xF4,0x01,0xF4,0x2D,0xD5,0x99,0x65} +#define IID_IDeckLinkScreenPreviewCallback_v7_6 /* 373F499D-4B4D-4518-AD22-6354E5A5825E */ (REFIID){0x37,0x3F,0x49,0x9D,0x4B,0x4D,0x45,0x18,0xAD,0x22,0x63,0x54,0xE5,0xA5,0x82,0x5E} +#define IID_IDeckLinkCocoaScreenPreviewCallback_v7_6 /* D174152F-8F96-4C07-83A5-DD5F5AF0A2AA */ (REFIID){0xD1,0x74,0x15,0x2F,0x8F,0x96,0x4C,0x07,0x83,0xA5,0xDD,0x5F,0x5A,0xF0,0xA2,0xAA} +#define IID_IDeckLinkGLScreenPreviewHelper_v7_6 /* BA575CD9-A15E-497B-B2C2-F9AFE7BE4EBA */ (REFIID){0xBA,0x57,0x5C,0xD9,0xA1,0x5E,0x49,0x7B,0xB2,0xC2,0xF9,0xAF,0xE7,0xBE,0x4E,0xBA} +#define IID_IDeckLinkVideoConversion_v7_6 /* 3EB504C9-F97D-40FE-A158-D407D48CB53B */ (REFIID){0x3E,0xB5,0x04,0xC9,0xF9,0x7D,0x40,0xFE,0xA1,0x58,0xD4,0x07,0xD4,0x8C,0xB5,0x3B} +#define IID_IDeckLinkConfiguration_v7_6 /* B8EAD569-B764-47F0-A73F-AE40DF6CBF10 */ (REFIID){0xB8,0xEA,0xD5,0x69,0xB7,0x64,0x47,0xF0,0xA7,0x3F,0xAE,0x40,0xDF,0x6C,0xBF,0x10} + + +#if defined(__cplusplus) + +/* Enum BMDVideoConnection - Video connection types */ + +typedef uint32_t BMDVideoConnection_v7_6; +enum _BMDVideoConnection_v7_6 { + bmdVideoConnectionSDI_v7_6 = 'sdi ', + bmdVideoConnectionHDMI_v7_6 = 'hdmi', + bmdVideoConnectionOpticalSDI_v7_6 = 'opti', + bmdVideoConnectionComponent_v7_6 = 'cpnt', + bmdVideoConnectionComposite_v7_6 = 'cmst', + bmdVideoConnectionSVideo_v7_6 = 'svid' +}; + + +// Forward Declarations + +class IDeckLinkVideoOutputCallback_v7_6; +class IDeckLinkInputCallback_v7_6; +class IDeckLinkDisplayModeIterator_v7_6; +class IDeckLinkDisplayMode_v7_6; +class IDeckLinkOutput_v7_6; +class IDeckLinkInput_v7_6; +class IDeckLinkTimecode_v7_6; +class IDeckLinkVideoFrame_v7_6; +class IDeckLinkMutableVideoFrame_v7_6; +class IDeckLinkVideoInputFrame_v7_6; +class IDeckLinkScreenPreviewCallback_v7_6; +class IDeckLinkCocoaScreenPreviewCallback_v7_6; +class IDeckLinkGLScreenPreviewHelper_v7_6; +class IDeckLinkVideoConversion_v7_6; + + +/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */ + +class IDeckLinkVideoOutputCallback_v7_6 : public IUnknown +{ +public: + virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame_v7_6 *completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0; + virtual HRESULT ScheduledPlaybackHasStopped (void) = 0; + +protected: + virtual ~IDeckLinkVideoOutputCallback_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +class IDeckLinkInputCallback_v7_6 : public IUnknown +{ +public: + virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode_v7_6 *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0; + virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame_v7_6* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0; + +protected: + virtual ~IDeckLinkInputCallback_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */ + +class IDeckLinkDisplayModeIterator_v7_6 : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode) = 0; + +protected: + virtual ~IDeckLinkDisplayModeIterator_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkDisplayMode - represents a display mode */ + +class IDeckLinkDisplayMode_v7_6 : public IUnknown +{ +public: + virtual HRESULT GetName (/* out */ CFStringRef *name) = 0; + virtual BMDDisplayMode GetDisplayMode (void) = 0; + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual HRESULT GetFrameRate (/* out */ BMDTimeValue *frameDuration, /* out */ BMDTimeScale *timeScale) = 0; + virtual BMDFieldDominance GetFieldDominance (void) = 0; + +protected: + virtual ~IDeckLinkDisplayMode_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkOutput_v7_6 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback_v7_6 *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkOutput_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkInput_v7_6 - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkInput_v7_6 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v7_6 *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */ + +class IDeckLinkTimecode_v7_6 : public IUnknown +{ +public: + virtual BMDTimecodeBCD GetBCD (void) = 0; + virtual HRESULT GetComponents (/* out */ uint8_t *hours, /* out */ uint8_t *minutes, /* out */ uint8_t *seconds, /* out */ uint8_t *frames) = 0; + virtual HRESULT GetString (/* out */ CFStringRef *timecode) = 0; + virtual BMDTimecodeFlags GetFlags (void) = 0; + +protected: + virtual ~IDeckLinkTimecode_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */ + +class IDeckLinkVideoFrame_v7_6 : public IUnknown +{ +public: + virtual long GetWidth (void) = 0; + virtual long GetHeight (void) = 0; + virtual long GetRowBytes (void) = 0; + virtual BMDPixelFormat GetPixelFormat (void) = 0; + virtual BMDFrameFlags GetFlags (void) = 0; + virtual HRESULT GetBytes (/* out */ void **buffer) = 0; + + virtual HRESULT GetTimecode (BMDTimecodeFormat format, /* out */ IDeckLinkTimecode_v7_6 **timecode) = 0; + virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary **ancillary) = 0; + +protected: + virtual ~IDeckLinkVideoFrame_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */ + +class IDeckLinkMutableVideoFrame_v7_6 : public IDeckLinkVideoFrame_v7_6 +{ +public: + virtual HRESULT SetFlags (BMDFrameFlags newFlags) = 0; + + virtual HRESULT SetTimecode (BMDTimecodeFormat format, /* in */ IDeckLinkTimecode_v7_6 *timecode) = 0; + virtual HRESULT SetTimecodeFromComponents (BMDTimecodeFormat format, uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t frames, BMDTimecodeFlags flags) = 0; + virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary *ancillary) = 0; + +protected: + virtual ~IDeckLinkMutableVideoFrame_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +class IDeckLinkVideoInputFrame_v7_6 : public IDeckLinkVideoFrame_v7_6 +{ +public: + virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0; + virtual HRESULT GetHardwareReferenceTimestamp (BMDTimeScale timeScale, /* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration) = 0; + +protected: + virtual ~IDeckLinkVideoInputFrame_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */ + +class IDeckLinkScreenPreviewCallback_v7_6 : public IUnknown +{ +public: + virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + +protected: + virtual ~IDeckLinkScreenPreviewCallback_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkCocoaScreenPreviewCallback - Screen preview callback for Cocoa-based applications */ + +class IDeckLinkCocoaScreenPreviewCallback_v7_6 : public IDeckLinkScreenPreviewCallback_v7_6 +{ +public: + +protected: + virtual ~IDeckLinkCocoaScreenPreviewCallback_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */ + +class IDeckLinkGLScreenPreviewHelper_v7_6 : public IUnknown +{ +public: + + /* Methods must be called with OpenGL context set */ + + virtual HRESULT InitializeGL (void) = 0; + virtual HRESULT PaintGL (void) = 0; + virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0; + +protected: + virtual ~IDeckLinkGLScreenPreviewHelper_v7_6 () {}; // call Release method to drop reference count +}; + + +/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */ + +class IDeckLinkVideoConversion_v7_6 : public IUnknown +{ +public: + virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame_v7_6* srcFrame, /* in */ IDeckLinkVideoFrame_v7_6* dstFrame) = 0; + +protected: + virtual ~IDeckLinkVideoConversion_v7_6 () {}; // call Release method to drop reference count +}; + +/* Interface IDeckLinkConfiguration - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkConfiguration_v7_6 : public IUnknown +{ +public: + virtual HRESULT GetConfigurationValidator (/* out */ IDeckLinkConfiguration_v7_6 **configObject) = 0; + virtual HRESULT WriteConfigurationToPreferences (void) = 0; + + /* Video Output Configuration */ + + virtual HRESULT SetVideoOutputFormat (/* in */ BMDVideoConnection_v7_6 videoOutputConnection) = 0; + virtual HRESULT IsVideoOutputActive (/* in */ BMDVideoConnection_v7_6 videoOutputConnection, /* out */ bool *active) = 0; + + virtual HRESULT SetAnalogVideoOutputFlags (/* in */ BMDAnalogVideoFlags analogVideoFlags) = 0; + virtual HRESULT GetAnalogVideoOutputFlags (/* out */ BMDAnalogVideoFlags *analogVideoFlags) = 0; + + virtual HRESULT EnableFieldFlickerRemovalWhenPaused (/* in */ bool enable) = 0; + virtual HRESULT IsEnabledFieldFlickerRemovalWhenPaused (/* out */ bool *enabled) = 0; + + virtual HRESULT Set444And3GBpsVideoOutput (/* in */ bool enable444VideoOutput, /* in */ bool enable3GbsOutput) = 0; + virtual HRESULT Get444And3GBpsVideoOutput (/* out */ bool *is444VideoOutputEnabled, /* out */ bool *threeGbsOutputEnabled) = 0; + + virtual HRESULT SetVideoOutputConversionMode (/* in */ BMDVideoOutputConversionMode conversionMode) = 0; + virtual HRESULT GetVideoOutputConversionMode (/* out */ BMDVideoOutputConversionMode *conversionMode) = 0; + + virtual HRESULT Set_HD1080p24_to_HD1080i5994_Conversion (/* in */ bool enable) = 0; + virtual HRESULT Get_HD1080p24_to_HD1080i5994_Conversion (/* out */ bool *enabled) = 0; + + /* Video Input Configuration */ + + virtual HRESULT SetVideoInputFormat (/* in */ BMDVideoConnection_v7_6 videoInputFormat) = 0; + virtual HRESULT GetVideoInputFormat (/* out */ BMDVideoConnection_v7_6 *videoInputFormat) = 0; + + virtual HRESULT SetAnalogVideoInputFlags (/* in */ BMDAnalogVideoFlags analogVideoFlags) = 0; + virtual HRESULT GetAnalogVideoInputFlags (/* out */ BMDAnalogVideoFlags *analogVideoFlags) = 0; + + virtual HRESULT SetVideoInputConversionMode (/* in */ BMDVideoInputConversionMode conversionMode) = 0; + virtual HRESULT GetVideoInputConversionMode (/* out */ BMDVideoInputConversionMode *conversionMode) = 0; + + virtual HRESULT SetBlackVideoOutputDuringCapture (/* in */ bool blackOutInCapture) = 0; + virtual HRESULT GetBlackVideoOutputDuringCapture (/* out */ bool *blackOutInCapture) = 0; + + virtual HRESULT Set32PulldownSequenceInitialTimecodeFrame (/* in */ uint32_t aFrameTimecode) = 0; + virtual HRESULT Get32PulldownSequenceInitialTimecodeFrame (/* out */ uint32_t *aFrameTimecode) = 0; + + virtual HRESULT SetVancSourceLineMapping (/* in */ uint32_t activeLine1VANCsource, /* in */ uint32_t activeLine2VANCsource, /* in */ uint32_t activeLine3VANCsource) = 0; + virtual HRESULT GetVancSourceLineMapping (/* out */ uint32_t *activeLine1VANCsource, /* out */ uint32_t *activeLine2VANCsource, /* out */ uint32_t *activeLine3VANCsource) = 0; + + /* Audio Input Configuration */ + + virtual HRESULT SetAudioInputFormat (/* in */ BMDAudioConnection audioInputFormat) = 0; + virtual HRESULT GetAudioInputFormat (/* out */ BMDAudioConnection *audioInputFormat) = 0; +}; + + + +/* Functions */ + +extern "C" { + + IDeckLinkIterator* CreateDeckLinkIteratorInstance_v7_6 (void); + IDeckLinkGLScreenPreviewHelper_v7_6* CreateOpenGLScreenPreviewHelper_v7_6 (void); + IDeckLinkCocoaScreenPreviewCallback_v7_6* CreateCocoaScreenPreview_v7_6 (void* /* (NSView*) */ parentView); + IDeckLinkVideoConversion_v7_6* CreateVideoConversionInstance_v7_6 (void); + +}; + + +#endif // defined(__cplusplus) +#endif // __DeckLink_API_v7_6_h__ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_9.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_9.h new file mode 100644 index 0000000000..4ea8e58f24 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v7_9.h @@ -0,0 +1,104 @@ +/* -LICENSE-START- +** Copyright (c) 2010 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v7_9.h */ + +#ifndef __DeckLink_API_v7_9_h__ +#define __DeckLink_API_v7_9_h__ + +#include "DeckLinkAPI.h" + +// Interface ID Declarations + +#define IID_IDeckLinkDeckControl_v7_9 /* A4D81043-0619-42B7-8ED6-602D29041DF7 */ (REFIID){0xA4,0xD8,0x10,0x43,0x06,0x19,0x42,0xB7,0x8E,0xD6,0x60,0x2D,0x29,0x04,0x1D,0xF7} + + +#if defined(__cplusplus) + +// Forward Declarations + +class IDeckLinkDeckControl_v7_9; + + +/* Interface IDeckLinkDeckControl_v7_9 - Deck Control main interface */ + +class IDeckLinkDeckControl_v7_9 : public IUnknown +{ +public: + virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Close (/* in */ bool standbyOn) = 0; + virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0; + virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0; + virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeString (/* out */ BMDstring *currentTimeCode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0; + virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0; + virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0; + virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0; + virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0; + virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0; + virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0; + virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Abort (void) = 0; + virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback *callback) = 0; + +protected: + virtual ~IDeckLinkDeckControl_v7_9 () {}; // call Release method to drop reference count +}; + + +#endif // defined(__cplusplus) +#endif // __DeckLink_API_v7_9_h__ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_0.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_0.h new file mode 100644 index 0000000000..0239ab6126 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_0.h @@ -0,0 +1,76 @@ +/* -LICENSE-START- +** Copyright (c) 2011 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v8_0_H +#define BMD_DECKLINKAPI_v8_0_H + +#include "DeckLinkAPI.h" + +// Interface ID Declarations + +#define IID_IDeckLink_v8_0 /* 62BFF75D-6569-4E55-8D4D-66AA03829ABC */ (REFIID){0x62,0xBF,0xF7,0x5D,0x65,0x69,0x4E,0x55,0x8D,0x4D,0x66,0xAA,0x03,0x82,0x9A,0xBC} +#define IID_IDeckLinkIterator_v8_0 /* 74E936FC-CC28-4A67-81A0-1E94E52D4E69 */ (REFIID){0x74,0xE9,0x36,0xFC,0xCC,0x28,0x4A,0x67,0x81,0xA0,0x1E,0x94,0xE5,0x2D,0x4E,0x69} + +#if defined (__cplusplus) + +/* Interface IDeckLink_v8_0 - represents a DeckLink device */ + +class IDeckLink_v8_0 : public IUnknown +{ +public: + virtual HRESULT GetModelName (/* out */ CFStringRef *modelName) = 0; +}; + +/* Interface IDeckLinkIterator_v8_0 - enumerates installed DeckLink hardware */ + +class IDeckLinkIterator_v8_0 : public IUnknown +{ +public: + virtual HRESULT Next (/* out */ IDeckLink_v8_0 **deckLinkInstance) = 0; +}; + +extern "C" { + IDeckLinkIterator_v8_0* CreateDeckLinkIteratorInstance_v8_0 (void); +}; + + +#endif // defined __cplusplus + +#endif /* defined(BMD_DECKLINKAPI_v8_0_H) */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_1.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_1.h new file mode 100644 index 0000000000..33c77f5575 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v8_1.h @@ -0,0 +1,124 @@ +/* -LICENSE-START- + ** Copyright (c) 2011 Blackmagic Design + ** + ** Permission is hereby granted, free of charge, to any person or organization + ** obtaining a copy of the software and accompanying documentation (the + ** "Software") to use, reproduce, display, distribute, sub-license, execute, + ** and transmit the Software, and to prepare derivative works of the Software, + ** and to permit third-parties to whom the Software is furnished to do so, in + ** accordance with: + ** + ** (1) if the Software is obtained from Blackmagic Design, the End User License + ** Agreement for the Software Development Kit (“EULA”) available at + ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + ** + ** (2) if the Software is obtained from any third party, such licensing terms + ** as notified by that third party, + ** + ** and all subject to the following: + ** + ** (3) the copyright notices in the Software and this entire statement, + ** including the above license grant, this restriction and the following + ** disclaimer, must be included in all copies of the Software, in whole or in + ** part, and all derivative works of the Software, unless such copies or + ** derivative works are solely in the form of machine-executable object code + ** generated by a source language processor. + ** + ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + ** DEALINGS IN THE SOFTWARE. + ** + ** A copy of the Software is available free of charge at + ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + ** + ** -LICENSE-END- + */ + +#ifndef BMD_DECKLINKAPI_v8_1_H +#define BMD_DECKLINKAPI_v8_1_H + +#include "DeckLinkAPI.h" + + +// Interface ID Declarations + +#define IID_IDeckLinkDeckControlStatusCallback_v8_1 /* E5F693C1-4283-4716-B18F-C1431521955B */ (REFIID){0xE5,0xF6,0x93,0xC1,0x42,0x83,0x47,0x16,0xB1,0x8F,0xC1,0x43,0x15,0x21,0x95,0x5B} +#define IID_IDeckLinkDeckControl_v8_1 /* 522A9E39-0F3C-4742-94EE-D80DE335DA1D */ (REFIID){0x52,0x2A,0x9E,0x39,0x0F,0x3C,0x47,0x42,0x94,0xEE,0xD8,0x0D,0xE3,0x35,0xDA,0x1D} + + +/* Enum BMDDeckControlVTRControlState_v8_1 - VTR Control state */ + +typedef uint32_t BMDDeckControlVTRControlState_v8_1; +enum _BMDDeckControlVTRControlState_v8_1 { + bmdDeckControlNotInVTRControlMode_v8_1 = 'nvcm', + bmdDeckControlVTRControlPlaying_v8_1 = 'vtrp', + bmdDeckControlVTRControlRecording_v8_1 = 'vtrr', + bmdDeckControlVTRControlStill_v8_1 = 'vtra', + bmdDeckControlVTRControlSeeking_v8_1 = 'vtrs', + bmdDeckControlVTRControlStopped_v8_1 = 'vtro' +}; + + +/* Interface IDeckLinkDeckControlStatusCallback_v8_1 - Deck control state change callback. */ + +class IDeckLinkDeckControlStatusCallback_v8_1 : public IUnknown +{ +public: + virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0; + virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState_v8_1 newState, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0; + virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0; + +protected: + virtual ~IDeckLinkDeckControlStatusCallback_v8_1 () {}; // call Release method to drop reference count +}; + +/* Interface IDeckLinkDeckControl_v8_1 - Deck Control main interface */ + +class IDeckLinkDeckControl_v8_1 : public IUnknown +{ +public: + virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Close (/* in */ bool standbyOn) = 0; + virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState_v8_1 *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0; + virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0; + virtual HRESULT SendCommand (/* in */ uint8_t *inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t *outBuffer, /* out */ uint32_t *outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeString (/* out */ CFStringRef *currentTimeCode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0; + virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0; + virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0; + virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0; + virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0; + virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0; + virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0; + virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0; + virtual HRESULT Abort (void) = 0; + virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback_v8_1 *callback) = 0; + +protected: + virtual ~IDeckLinkDeckControl_v8_1 () {}; // call Release method to drop reference count +}; + + +#endif // BMD_DECKLINKAPI_v8_1_H diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_2.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_2.h new file mode 100644 index 0000000000..e06210d9a1 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_2.h @@ -0,0 +1,96 @@ +/* -LICENSE-START- +** Copyright (c) 2012 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v9_2_H +#define BMD_DECKLINKAPI_v9_2_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" +#include "DeckLinkAPIVideoInput_v11_5_1.h" + + +// Interface ID Declarations + +#define IID_IDeckLinkInput_v9_2 /* 6D40EF78-28B9-4E21-990D-95BB7750A04F */ (REFIID){0x6D,0x40,0xEF,0x78,0x28,0xB9,0x4E,0x21,0x99,0x0D,0x95,0xBB,0x77,0x50,0xA0,0x4F} + + +#if defined(__cplusplus) + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkInput_v9_2 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Input */ + + virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0; + virtual HRESULT DisableVideoInput (void) = 0; + virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0; + + /* Audio Input */ + + virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0; + virtual HRESULT DisableAudioInput (void) = 0; + virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0; + + /* Input Control */ + + virtual HRESULT StartStreams (void) = 0; + virtual HRESULT StopStreams (void) = 0; + virtual HRESULT PauseStreams (void) = 0; + virtual HRESULT FlushStreams (void) = 0; + virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkInput_v9_2 () {}; // call Release method to drop reference count +}; + + +#endif // defined(__cplusplus) +#endif // BMD_DECKLINKAPI_v9_2_H diff --git a/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_9.h b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_9.h new file mode 100644 index 0000000000..095a1fed06 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/mac/DeckLinkAPI_v9_9.h @@ -0,0 +1,115 @@ +/* -LICENSE-START- +** Copyright (c) 2013 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +#ifndef BMD_DECKLINKAPI_v9_9_H +#define BMD_DECKLINKAPI_v9_9_H + +#include "DeckLinkAPI.h" +#include "DeckLinkAPI_v10_11.h" + +// Interface ID Declarations + +BMD_CONST REFIID IID_IDeckLinkOutput_v9_9 = /* A3EF0963-0862-44ED-92A9-EE89ABF431C7 */ {0xA3,0xEF,0x09,0x63,0x08,0x62,0x44,0xED,0x92,0xA9,0xEE,0x89,0xAB,0xF4,0x31,0xC7}; + + +#if defined(__cplusplus) + +// Forward Declarations +class IDeckLinkOutput_v9_9; + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +class IDeckLinkOutput_v9_9 : public IUnknown +{ +public: + virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0; + virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0; + + virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0; + + /* Video Output */ + + virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0; + virtual HRESULT DisableVideoOutput (void) = 0; + + virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0; + virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0; + virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0; + + virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0; + virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0; + virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0; + + /* Audio Output */ + + virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0; + virtual HRESULT DisableAudioOutput (void) = 0; + + virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT BeginAudioPreroll (void) = 0; + virtual HRESULT EndAudioPreroll (void) = 0; + virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0; + + virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0; + virtual HRESULT FlushBufferedAudioSamples (void) = 0; + + virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0; + + /* Output Control */ + + virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0; + virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0; + virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0; + virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0; + virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0; + + /* Hardware Timing */ + + virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0; + +protected: + virtual ~IDeckLinkOutput_v9_9 () {}; // call Release method to drop reference count +}; + +#endif // defined(__cplusplus) +#endif /* defined(BMD_DECKLINKAPI_v9_9_H) */ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI.idl new file mode 100644 index 0000000000..4179aeff6e --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI.idl @@ -0,0 +1,1376 @@ +/* -LICENSE-START- + ** Copyright (c) 2022 Blackmagic Design + ** + ** Permission is hereby granted, free of charge, to any person or organization + ** obtaining a copy of the software and accompanying documentation (the + ** "Software") to use, reproduce, display, distribute, sub-license, execute, + ** and transmit the Software, and to prepare derivative works of the Software, + ** and to permit third-parties to whom the Software is furnished to do so, in + ** accordance with: + ** + ** (1) if the Software is obtained from Blackmagic Design, the End User License + ** Agreement for the Software Development Kit ("EULA") available at + ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + ** + ** (2) if the Software is obtained from any third party, such licensing terms + ** as notified by that third party, + ** + ** and all subject to the following: + ** + ** (3) the copyright notices in the Software and this entire statement, + ** including the above license grant, this restriction and the following + ** disclaimer, must be included in all copies of the Software, in whole or in + ** part, and all derivative works of the Software, unless such copies or + ** derivative works are solely in the form of machine-executable object code + ** generated by a source language processor. + ** + ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + ** DEALINGS IN THE SOFTWARE. + ** + ** A copy of the Software is available free of charge at + ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + ** + ** -LICENSE-END- + */ + + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +/* DeckLink API */ + +import "unknwn.idl"; + +[uuid(D864517A-EDD5-466D-867D-C819F1C052BB), +version(1.0), helpstring("DeckLink API Library")] +library DeckLinkAPI +{ + +#include "DeckLinkAPITypes.idl" +#include "DeckLinkAPIModes.idl" +#include "DeckLinkAPIDiscovery.idl" +#include "DeckLinkAPIConfiguration.idl" +#include "DeckLinkAPIDeckControl.idl" +#include "DeckLinkAPIStreaming.idl" + +// Type Declarations + + +// Enumeration Mapping + +cpp_quote("typedef unsigned int BMDFrameFlags;") +cpp_quote("typedef unsigned int BMDVideoInputFlags;") +cpp_quote("typedef unsigned int BMDVideoInputFormatChangedEvents;") +cpp_quote("typedef unsigned int BMDDetectedVideoInputFormatFlags;") +cpp_quote("typedef unsigned int BMDDeckLinkCapturePassthroughMode;") +cpp_quote("typedef unsigned int BMDAnalogVideoFlags;") +cpp_quote("typedef unsigned int BMDDeviceBusyState;") +cpp_quote("#if 0") +typedef enum _BMDFrameFlags BMDFrameFlags; +typedef enum _BMDVideoInputFlags BMDVideoInputFlags; +typedef enum _BMDVideoInputFormatChangedEvents BMDVideoInputFormatChangedEvents; +typedef enum _BMDDetectedVideoInputFormatFlags BMDDetectedVideoInputFormatFlags; +typedef enum _BMDDeckLinkCapturePassthroughMode BMDDeckLinkCapturePassthroughMode; +typedef enum _BMDAnalogVideoFlags BMDAnalogVideoFlags; +typedef enum _BMDDeviceBusyState BMDDeviceBusyState; +cpp_quote("#endif") + +/* Enum BMDVideoOutputFlags - Flags to control the output of ancillary data along with video. */ + +typedef [v1_enum] enum _BMDVideoOutputFlags { + bmdVideoOutputFlagDefault = 0, + bmdVideoOutputVANC = 1 << 0, + bmdVideoOutputVITC = 1 << 1, + bmdVideoOutputRP188 = 1 << 2, + bmdVideoOutputDualStream3D = 1 << 4, + bmdVideoOutputSynchronizeToPlaybackGroup = 1 << 6 +} BMDVideoOutputFlags; + +/* Enum BMDSupportedVideoModeFlags - Flags to describe supported video modes */ + +typedef [v1_enum] enum _BMDSupportedVideoModeFlags { + bmdSupportedVideoModeDefault = 0, + bmdSupportedVideoModeKeying = 1 << 0, + bmdSupportedVideoModeDualStream3D = 1 << 1, + bmdSupportedVideoModeSDISingleLink = 1 << 2, + bmdSupportedVideoModeSDIDualLink = 1 << 3, + bmdSupportedVideoModeSDIQuadLink = 1 << 4, + bmdSupportedVideoModeInAnyProfile = 1 << 5 +} BMDSupportedVideoModeFlags; + +/* Enum BMDPacketType - Type of packet */ + +typedef [v1_enum] enum _BMDPacketType { + bmdPacketTypeStreamInterruptedMarker = /* 'sint' */ 0x73696E74, // A packet of this type marks the time when a video stream was interrupted, for example by a disconnected cable + bmdPacketTypeStreamData = /* 'sdat' */ 0x73646174 // Regular stream data +} BMDPacketType; + +/* Enum BMDFrameFlags - Frame flags */ + +[v1_enum] enum _BMDFrameFlags { + bmdFrameFlagDefault = 0, + bmdFrameFlagFlipVertical = 1 << 0, + bmdFrameContainsHDRMetadata = 1 << 1, + + /* Flags that are applicable only to instances of IDeckLinkVideoInputFrame */ + + bmdFrameCapturedAsPsF = 1 << 30, + bmdFrameHasNoInputSource = 1 << 31 +}; + +/* Enum BMDVideoInputFlags - Flags applicable to video input */ + +[v1_enum] enum _BMDVideoInputFlags { + bmdVideoInputFlagDefault = 0, + bmdVideoInputEnableFormatDetection = 1 << 0, + bmdVideoInputDualStream3D = 1 << 1, + bmdVideoInputSynchronizeToCaptureGroup = 1 << 2 +}; + +/* Enum BMDVideoInputFormatChangedEvents - Bitmask passed to the VideoInputFormatChanged notification to identify the properties of the input signal that have changed */ + +[v1_enum] enum _BMDVideoInputFormatChangedEvents { + bmdVideoInputDisplayModeChanged = 1 << 0, + bmdVideoInputFieldDominanceChanged = 1 << 1, + bmdVideoInputColorspaceChanged = 1 << 2 +}; + +/* Enum BMDDetectedVideoInputFormatFlags - Flags passed to the VideoInputFormatChanged notification to describe the detected video input signal */ + +[v1_enum] enum _BMDDetectedVideoInputFormatFlags { + bmdDetectedVideoInputYCbCr422 = 1 << 0, + bmdDetectedVideoInputRGB444 = 1 << 1, + bmdDetectedVideoInputDualStream3D = 1 << 2, + bmdDetectedVideoInput12BitDepth = 1 << 3, + bmdDetectedVideoInput10BitDepth = 1 << 4, + bmdDetectedVideoInput8BitDepth = 1 << 5 +}; + +/* Enum BMDDeckLinkCapturePassthroughMode - Enumerates whether the video output is electrically connected to the video input or if the clean switching mode is enabled */ + +[v1_enum] enum _BMDDeckLinkCapturePassthroughMode { + bmdDeckLinkCapturePassthroughModeDisabled = /* 'pdis' */ 0x70646973, + bmdDeckLinkCapturePassthroughModeDirect = /* 'pdir' */ 0x70646972, + bmdDeckLinkCapturePassthroughModeCleanSwitch = /* 'pcln' */ 0x70636C6E +}; + +/* Enum BMDOutputFrameCompletionResult - Frame Completion Callback */ + +typedef [v1_enum] enum _BMDOutputFrameCompletionResult { + bmdOutputFrameCompleted, + bmdOutputFrameDisplayedLate, + bmdOutputFrameDropped, + bmdOutputFrameFlushed +} BMDOutputFrameCompletionResult; + +/* Enum BMDReferenceStatus - GenLock input status */ + +typedef [v1_enum] enum _BMDReferenceStatus { + bmdReferenceUnlocked = 0, + bmdReferenceNotSupportedByHardware = 1 << 0, + bmdReferenceLocked = 1 << 1 +} BMDReferenceStatus; + +/* Enum BMDAudioFormat - Audio Format */ + +typedef [v1_enum] enum _BMDAudioFormat { + bmdAudioFormatPCM = /* 'lpcm' */ 0x6C70636D // Linear signed PCM samples +} BMDAudioFormat; + +/* Enum BMDAudioSampleRate - Audio sample rates supported for output/input */ + +typedef [v1_enum] enum _BMDAudioSampleRate { + bmdAudioSampleRate48kHz = 48000 +} BMDAudioSampleRate; + +/* Enum BMDAudioSampleType - Audio sample sizes supported for output/input */ + +typedef [v1_enum] enum _BMDAudioSampleType { + bmdAudioSampleType16bitInteger = 16, + bmdAudioSampleType32bitInteger = 32 +} BMDAudioSampleType; + +/* Enum BMDAudioOutputStreamType - Audio output stream type */ + +typedef [v1_enum] enum _BMDAudioOutputStreamType { + bmdAudioOutputStreamContinuous, + bmdAudioOutputStreamContinuousDontResample, + bmdAudioOutputStreamTimestamped +} BMDAudioOutputStreamType; + +/* Enum BMDAncillaryPacketFormat - Ancillary packet format */ + +typedef [v1_enum] enum _BMDAncillaryPacketFormat { + bmdAncillaryPacketFormatUInt8 = /* 'ui08' */ 0x75693038, + bmdAncillaryPacketFormatUInt16 = /* 'ui16' */ 0x75693136, + bmdAncillaryPacketFormatYCbCr10 = /* 'v210' */ 0x76323130 +} BMDAncillaryPacketFormat; + +/* Enum BMDTimecodeFormat - Timecode formats for frame metadata */ + +typedef [v1_enum] enum _BMDTimecodeFormat { + bmdTimecodeRP188VITC1 = /* 'rpv1' */ 0x72707631, // RP188 timecode where DBB1 equals VITC1 (line 9) + bmdTimecodeRP188VITC2 = /* 'rp12' */ 0x72703132, // RP188 timecode where DBB1 equals VITC2 (line 9 for progressive or line 571 for interlaced/PsF) + bmdTimecodeRP188LTC = /* 'rplt' */ 0x72706C74, // RP188 timecode where DBB1 equals LTC (line 10) + bmdTimecodeRP188HighFrameRate = /* 'rphr' */ 0x72706872, // RP188 timecode where DBB1 is an HFRTC (SMPTE ST 12-3), the only timecode allowing the frame value to go above 30 + bmdTimecodeRP188Any = /* 'rp18' */ 0x72703138, // Convenience for capture, returning the first valid timecode in {HFRTC (if supported), VITC1, VITC2, LTC } + bmdTimecodeVITC = /* 'vitc' */ 0x76697463, + bmdTimecodeVITCField2 = /* 'vit2' */ 0x76697432, + bmdTimecodeSerial = /* 'seri' */ 0x73657269 +} BMDTimecodeFormat; + +/* Enum BMDAnalogVideoFlags - Analog video display flags */ + +[v1_enum] enum _BMDAnalogVideoFlags { + bmdAnalogVideoFlagCompositeSetup75 = 1 << 0, + bmdAnalogVideoFlagComponentBetacamLevels = 1 << 1 +}; + +/* Enum BMDAudioOutputAnalogAESSwitch - Audio output Analog/AESEBU switch */ + +typedef [v1_enum] enum _BMDAudioOutputAnalogAESSwitch { + bmdAudioOutputSwitchAESEBU = /* 'aes ' */ 0x61657320, + bmdAudioOutputSwitchAnalog = /* 'anlg' */ 0x616E6C67 +} BMDAudioOutputAnalogAESSwitch; + +/* Enum BMDVideoOutputConversionMode - Video/audio conversion mode */ + +typedef [v1_enum] enum _BMDVideoOutputConversionMode { + bmdNoVideoOutputConversion = /* 'none' */ 0x6E6F6E65, + bmdVideoOutputLetterboxDownconversion = /* 'ltbx' */ 0x6C746278, + bmdVideoOutputAnamorphicDownconversion = /* 'amph' */ 0x616D7068, + bmdVideoOutputHD720toHD1080Conversion = /* '720c' */ 0x37323063, + bmdVideoOutputHardwareLetterboxDownconversion = /* 'HWlb' */ 0x48576C62, + bmdVideoOutputHardwareAnamorphicDownconversion = /* 'HWam' */ 0x4857616D, + bmdVideoOutputHardwareCenterCutDownconversion = /* 'HWcc' */ 0x48576363, + bmdVideoOutputHardware720p1080pCrossconversion = /* 'xcap' */ 0x78636170, + bmdVideoOutputHardwareAnamorphic720pUpconversion = /* 'ua7p' */ 0x75613770, + bmdVideoOutputHardwareAnamorphic1080iUpconversion = /* 'ua1i' */ 0x75613169, + bmdVideoOutputHardwareAnamorphic149To720pUpconversion = /* 'u47p' */ 0x75343770, + bmdVideoOutputHardwareAnamorphic149To1080iUpconversion = /* 'u41i' */ 0x75343169, + bmdVideoOutputHardwarePillarbox720pUpconversion = /* 'up7p' */ 0x75703770, + bmdVideoOutputHardwarePillarbox1080iUpconversion = /* 'up1i' */ 0x75703169 +} BMDVideoOutputConversionMode; + +/* Enum BMDVideoInputConversionMode - Video input conversion mode */ + +typedef [v1_enum] enum _BMDVideoInputConversionMode { + bmdNoVideoInputConversion = /* 'none' */ 0x6E6F6E65, + bmdVideoInputLetterboxDownconversionFromHD1080 = /* '10lb' */ 0x31306C62, + bmdVideoInputAnamorphicDownconversionFromHD1080 = /* '10am' */ 0x3130616D, + bmdVideoInputLetterboxDownconversionFromHD720 = /* '72lb' */ 0x37326C62, + bmdVideoInputAnamorphicDownconversionFromHD720 = /* '72am' */ 0x3732616D, + bmdVideoInputLetterboxUpconversion = /* 'lbup' */ 0x6C627570, + bmdVideoInputAnamorphicUpconversion = /* 'amup' */ 0x616D7570 +} BMDVideoInputConversionMode; + +/* Enum BMDVideo3DPackingFormat - Video 3D packing format */ + +typedef [v1_enum] enum _BMDVideo3DPackingFormat { + bmdVideo3DPackingSidebySideHalf = /* 'sbsh' */ 0x73627368, + bmdVideo3DPackingLinebyLine = /* 'lbyl' */ 0x6C62796C, + bmdVideo3DPackingTopAndBottom = /* 'tabo' */ 0x7461626F, + bmdVideo3DPackingFramePacking = /* 'frpk' */ 0x6672706B, + bmdVideo3DPackingLeftOnly = /* 'left' */ 0x6C656674, + bmdVideo3DPackingRightOnly = /* 'righ' */ 0x72696768 +} BMDVideo3DPackingFormat; + +/* Enum BMDIdleVideoOutputOperation - Video output operation when not playing video */ + +typedef [v1_enum] enum _BMDIdleVideoOutputOperation { + bmdIdleVideoOutputBlack = /* 'blac' */ 0x626C6163, + bmdIdleVideoOutputLastFrame = /* 'lafa' */ 0x6C616661 +} BMDIdleVideoOutputOperation; + +/* Enum BMDVideoEncoderFrameCodingMode - Video frame coding mode */ + +typedef [v1_enum] enum _BMDVideoEncoderFrameCodingMode { + bmdVideoEncoderFrameCodingModeInter = /* 'inte' */ 0x696E7465, + bmdVideoEncoderFrameCodingModeIntra = /* 'intr' */ 0x696E7472 +} BMDVideoEncoderFrameCodingMode; + +/* Enum BMDDNxHRLevel - DNxHR Levels */ + +typedef [v1_enum] enum _BMDDNxHRLevel { + bmdDNxHRLevelSQ = /* 'dnsq' */ 0x646E7371, + bmdDNxHRLevelLB = /* 'dnlb' */ 0x646E6C62, + bmdDNxHRLevelHQ = /* 'dnhq' */ 0x646E6871, + bmdDNxHRLevelHQX = /* 'dhqx' */ 0x64687178, + bmdDNxHRLevel444 = /* 'd444' */ 0x64343434 +} BMDDNxHRLevel; + +/* Enum BMDLinkConfiguration - Video link configuration */ + +typedef [v1_enum] enum _BMDLinkConfiguration { + bmdLinkConfigurationSingleLink = /* 'lcsl' */ 0x6C63736C, + bmdLinkConfigurationDualLink = /* 'lcdl' */ 0x6C63646C, + bmdLinkConfigurationQuadLink = /* 'lcql' */ 0x6C63716C +} BMDLinkConfiguration; + +/* Enum BMDDeviceInterface - Device interface type */ + +typedef [v1_enum] enum _BMDDeviceInterface { + bmdDeviceInterfacePCI = /* 'pci ' */ 0x70636920, + bmdDeviceInterfaceUSB = /* 'usb ' */ 0x75736220, + bmdDeviceInterfaceThunderbolt = /* 'thun' */ 0x7468756E +} BMDDeviceInterface; + +/* Enum BMDColorspace - Colorspace */ + +typedef [v1_enum] enum _BMDColorspace { + bmdColorspaceRec601 = /* 'r601' */ 0x72363031, + bmdColorspaceRec709 = /* 'r709' */ 0x72373039, + bmdColorspaceRec2020 = /* '2020' */ 0x32303230 +} BMDColorspace; + +/* Enum BMDDynamicRange - SDR or HDR */ + +typedef [v1_enum] enum _BMDDynamicRange { + bmdDynamicRangeSDR = 0, // Standard Dynamic Range in accordance with SMPTE ST 2036-1 + bmdDynamicRangeHDRStaticPQ = 1 << 29, // High Dynamic Range PQ in accordance with SMPTE ST 2084 + bmdDynamicRangeHDRStaticHLG = 1 << 30 // High Dynamic Range HLG in accordance with ITU-R BT.2100-0 +} BMDDynamicRange; + +/* Enum BMDDeckLinkHDMIInputEDIDID - DeckLink HDMI Input EDID ID */ + +typedef [v1_enum] enum _BMDDeckLinkHDMIInputEDIDID { + + /* Integers */ + + bmdDeckLinkHDMIInputEDIDDynamicRange = /* 'HIDy' */ 0x48494479 // Parameter is of type BMDDynamicRange. Default is (bmdDynamicRangeSDR|bmdDynamicRangeHDRStaticPQ) +} BMDDeckLinkHDMIInputEDIDID; + +/* Enum BMDDeckLinkFrameMetadataID - DeckLink Frame Metadata ID */ + +typedef [v1_enum] enum _BMDDeckLinkFrameMetadataID { + + /* Colorspace Metadata - Integers */ + + bmdDeckLinkFrameMetadataColorspace = /* 'cspc' */ 0x63737063, // Colorspace of video frame (see BMDColorspace) + + /* HDR Metadata - Integers */ + + bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc = /* 'eotf' */ 0x656F7466, // EOTF in range 0-7 as per CEA 861.3 + + /* HDR Metadata - Floats */ + + bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX = /* 'hdrx' */ 0x68647278, // Red display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY = /* 'hdry' */ 0x68647279, // Red display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX = /* 'hdgx' */ 0x68646778, // Green display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY = /* 'hdgy' */ 0x68646779, // Green display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX = /* 'hdbx' */ 0x68646278, // Blue display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY = /* 'hdby' */ 0x68646279, // Blue display primaries in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRWhitePointX = /* 'hdwx' */ 0x68647778, // White point in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRWhitePointY = /* 'hdwy' */ 0x68647779, // White point in range 0.0 - 1.0 + bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance = /* 'hdml' */ 0x68646D6C, // Max display mastering luminance in range 1 cd/m2 - 65535 cd/m2 + bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance = /* 'hmil' */ 0x686D696C, // Min display mastering luminance in range 0.0001 cd/m2 - 6.5535 cd/m2 + bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel = /* 'mcll' */ 0x6D636C6C, // Maximum Content Light Level in range 1 cd/m2 - 65535 cd/m2 + bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel = /* 'fall' */ 0x66616C6C // Maximum Frame Average Light Level in range 1 cd/m2 - 65535 cd/m2 +} BMDDeckLinkFrameMetadataID; + +/* Enum BMDProfileID - Identifies a profile */ + +typedef [v1_enum] enum _BMDProfileID { + bmdProfileOneSubDeviceFullDuplex = /* '1dfd' */ 0x31646664, + bmdProfileOneSubDeviceHalfDuplex = /* '1dhd' */ 0x31646864, + bmdProfileTwoSubDevicesFullDuplex = /* '2dfd' */ 0x32646664, + bmdProfileTwoSubDevicesHalfDuplex = /* '2dhd' */ 0x32646864, + bmdProfileFourSubDevicesHalfDuplex = /* '4dhd' */ 0x34646864 +} BMDProfileID; + +/* Enum BMDHDMITimecodePacking - Packing form of timecode on HDMI */ + +typedef [v1_enum] enum _BMDHDMITimecodePacking { + bmdHDMITimecodePackingIEEEOUI000085 = 0x00008500, + bmdHDMITimecodePackingIEEEOUI080046 = 0x08004601, + bmdHDMITimecodePackingIEEEOUI5CF9F0 = 0x5CF9F003 +} BMDHDMITimecodePacking; + +/* Enum BMDInternalKeyingAncillaryDataSource - Source for VANC and timecode data when performing internal keying */ + +typedef [v1_enum] enum _BMDInternalKeyingAncillaryDataSource { + bmdInternalKeyingUsesAncillaryDataFromInputSignal = /* 'ikai' */ 0x696B6169, + bmdInternalKeyingUsesAncillaryDataFromKeyFrame = /* 'ikak' */ 0x696B616B +} BMDInternalKeyingAncillaryDataSource; + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef [v1_enum] enum _BMDDeckLinkAttributeID { + + /* Flags */ + + BMDDeckLinkSupportsInternalKeying = /* 'keyi' */ 0x6B657969, + BMDDeckLinkSupportsExternalKeying = /* 'keye' */ 0x6B657965, + BMDDeckLinkSupportsInputFormatDetection = /* 'infd' */ 0x696E6664, + BMDDeckLinkHasReferenceInput = /* 'hrin' */ 0x6872696E, + BMDDeckLinkHasSerialPort = /* 'hspt' */ 0x68737074, + BMDDeckLinkHasAnalogVideoOutputGain = /* 'avog' */ 0x61766F67, + BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain = /* 'ovog' */ 0x6F766F67, + BMDDeckLinkHasVideoInputAntiAliasingFilter = /* 'aafl' */ 0x6161666C, + BMDDeckLinkHasBypass = /* 'byps' */ 0x62797073, + BMDDeckLinkSupportsClockTimingAdjustment = /* 'ctad' */ 0x63746164, + BMDDeckLinkSupportsFullFrameReferenceInputTimingOffset = /* 'frin' */ 0x6672696E, + BMDDeckLinkSupportsSMPTELevelAOutput = /* 'lvla' */ 0x6C766C61, + BMDDeckLinkSupportsAutoSwitchingPPsFOnInput = /* 'apsf' */ 0x61707366, + BMDDeckLinkSupportsDualLinkSDI = /* 'sdls' */ 0x73646C73, + BMDDeckLinkSupportsQuadLinkSDI = /* 'sqls' */ 0x73716C73, + BMDDeckLinkSupportsIdleOutput = /* 'idou' */ 0x69646F75, + BMDDeckLinkVANCRequires10BitYUVVideoFrames = /* 'vioY' */ 0x76696F59, // Legacy product requires v210 active picture for IDeckLinkVideoFrameAncillaryPackets or 10-bit VANC + BMDDeckLinkHasLTCTimecodeInput = /* 'hltc' */ 0x686C7463, + BMDDeckLinkSupportsHDRMetadata = /* 'hdrm' */ 0x6864726D, + BMDDeckLinkSupportsColorspaceMetadata = /* 'cmet' */ 0x636D6574, + BMDDeckLinkSupportsHDMITimecode = /* 'htim' */ 0x6874696D, + BMDDeckLinkSupportsHighFrameRateTimecode = /* 'HFRT' */ 0x48465254, + BMDDeckLinkSupportsSynchronizeToCaptureGroup = /* 'stcg' */ 0x73746367, + BMDDeckLinkSupportsSynchronizeToPlaybackGroup = /* 'stpg' */ 0x73747067, + + /* Integers */ + + BMDDeckLinkMaximumAudioChannels = /* 'mach' */ 0x6D616368, + BMDDeckLinkMaximumAnalogAudioInputChannels = /* 'iach' */ 0x69616368, + BMDDeckLinkMaximumAnalogAudioOutputChannels = /* 'aach' */ 0x61616368, + BMDDeckLinkNumberOfSubDevices = /* 'nsbd' */ 0x6E736264, + BMDDeckLinkSubDeviceIndex = /* 'subi' */ 0x73756269, + BMDDeckLinkPersistentID = /* 'peid' */ 0x70656964, + BMDDeckLinkDeviceGroupID = /* 'dgid' */ 0x64676964, + BMDDeckLinkTopologicalID = /* 'toid' */ 0x746F6964, + BMDDeckLinkVideoOutputConnections = /* 'vocn' */ 0x766F636E, // Returns a BMDVideoConnection bit field + BMDDeckLinkVideoInputConnections = /* 'vicn' */ 0x7669636E, // Returns a BMDVideoConnection bit field + BMDDeckLinkAudioOutputConnections = /* 'aocn' */ 0x616F636E, // Returns a BMDAudioConnection bit field + BMDDeckLinkAudioInputConnections = /* 'aicn' */ 0x6169636E, // Returns a BMDAudioConnection bit field + BMDDeckLinkVideoIOSupport = /* 'vios' */ 0x76696F73, // Returns a BMDVideoIOSupport bit field + BMDDeckLinkDeckControlConnections = /* 'dccn' */ 0x6463636E, // Returns a BMDDeckControlConnection bit field + BMDDeckLinkDeviceInterface = /* 'dbus' */ 0x64627573, // Returns a BMDDeviceInterface + BMDDeckLinkAudioInputRCAChannelCount = /* 'airc' */ 0x61697263, + BMDDeckLinkAudioInputXLRChannelCount = /* 'aixc' */ 0x61697863, + BMDDeckLinkAudioOutputRCAChannelCount = /* 'aorc' */ 0x616F7263, + BMDDeckLinkAudioOutputXLRChannelCount = /* 'aoxc' */ 0x616F7863, + BMDDeckLinkProfileID = /* 'prid' */ 0x70726964, // Returns a BMDProfileID + BMDDeckLinkDuplex = /* 'dupx' */ 0x64757078, + BMDDeckLinkMinimumPrerollFrames = /* 'mprf' */ 0x6D707266, + BMDDeckLinkSupportedDynamicRange = /* 'sudr' */ 0x73756472, + + /* Floats */ + + BMDDeckLinkVideoInputGainMinimum = /* 'vigm' */ 0x7669676D, + BMDDeckLinkVideoInputGainMaximum = /* 'vigx' */ 0x76696778, + BMDDeckLinkVideoOutputGainMinimum = /* 'vogm' */ 0x766F676D, + BMDDeckLinkVideoOutputGainMaximum = /* 'vogx' */ 0x766F6778, + BMDDeckLinkMicrophoneInputGainMinimum = /* 'migm' */ 0x6D69676D, + BMDDeckLinkMicrophoneInputGainMaximum = /* 'migx' */ 0x6D696778, + + /* Strings */ + + BMDDeckLinkSerialPortDeviceName = /* 'slpn' */ 0x736C706E, + BMDDeckLinkVendorName = /* 'vndr' */ 0x766E6472, + BMDDeckLinkDisplayName = /* 'dspn' */ 0x6473706E, + BMDDeckLinkModelName = /* 'mdln' */ 0x6D646C6E, + BMDDeckLinkDeviceHandle = /* 'devh' */ 0x64657668 +} BMDDeckLinkAttributeID; + +/* Enum BMDDeckLinkAPIInformationID - DeckLinkAPI information ID */ + +typedef [v1_enum] enum _BMDDeckLinkAPIInformationID { + + /* Integer or String */ + + BMDDeckLinkAPIVersion = /* 'vers' */ 0x76657273 +} BMDDeckLinkAPIInformationID; + +/* Enum BMDDeckLinkStatusID - DeckLink Status ID */ + +typedef [v1_enum] enum _BMDDeckLinkStatusID { + + /* Integers */ + + bmdDeckLinkStatusDetectedVideoInputMode = /* 'dvim' */ 0x6476696D, + bmdDeckLinkStatusDetectedVideoInputFormatFlags = /* 'dvff' */ 0x64766666, + bmdDeckLinkStatusDetectedVideoInputFieldDominance = /* 'dvfd' */ 0x64766664, + bmdDeckLinkStatusDetectedVideoInputColorspace = /* 'dscl' */ 0x6473636C, + bmdDeckLinkStatusDetectedVideoInputDynamicRange = /* 'dsdr' */ 0x64736472, + bmdDeckLinkStatusDetectedSDILinkConfiguration = /* 'dslc' */ 0x64736C63, + bmdDeckLinkStatusCurrentVideoInputMode = /* 'cvim' */ 0x6376696D, + bmdDeckLinkStatusCurrentVideoInputPixelFormat = /* 'cvip' */ 0x63766970, + bmdDeckLinkStatusCurrentVideoInputFlags = /* 'cvif' */ 0x63766966, + bmdDeckLinkStatusCurrentVideoOutputMode = /* 'cvom' */ 0x63766F6D, + bmdDeckLinkStatusCurrentVideoOutputFlags = /* 'cvof' */ 0x63766F66, + bmdDeckLinkStatusPCIExpressLinkWidth = /* 'pwid' */ 0x70776964, + bmdDeckLinkStatusPCIExpressLinkSpeed = /* 'plnk' */ 0x706C6E6B, + bmdDeckLinkStatusLastVideoOutputPixelFormat = /* 'opix' */ 0x6F706978, + bmdDeckLinkStatusReferenceSignalMode = /* 'refm' */ 0x7265666D, + bmdDeckLinkStatusReferenceSignalFlags = /* 'reff' */ 0x72656666, + bmdDeckLinkStatusBusy = /* 'busy' */ 0x62757379, + bmdDeckLinkStatusInterchangeablePanelType = /* 'icpt' */ 0x69637074, + bmdDeckLinkStatusDeviceTemperature = /* 'dtmp' */ 0x64746D70, + + /* Flags */ + + bmdDeckLinkStatusVideoInputSignalLocked = /* 'visl' */ 0x7669736C, + bmdDeckLinkStatusReferenceSignalLocked = /* 'refl' */ 0x7265666C, + + /* Bytes */ + + bmdDeckLinkStatusReceivedEDID = /* 'edid' */ 0x65646964 +} BMDDeckLinkStatusID; + +/* Enum BMDDeckLinkVideoStatusFlags - */ + +typedef [v1_enum] enum _BMDDeckLinkVideoStatusFlags { + bmdDeckLinkVideoStatusPsF = 1 << 0, + bmdDeckLinkVideoStatusDualStream3D = 1 << 1 +} BMDDeckLinkVideoStatusFlags; + +/* Enum BMDDuplexMode - Duplex of the device */ + +typedef [v1_enum] enum _BMDDuplexMode { + bmdDuplexFull = /* 'dxfu' */ 0x64786675, + bmdDuplexHalf = /* 'dxha' */ 0x64786861, + bmdDuplexSimplex = /* 'dxsp' */ 0x64787370, + bmdDuplexInactive = /* 'dxin' */ 0x6478696E +} BMDDuplexMode; + +/* Enum BMDPanelType - The type of interchangeable panel */ + +typedef [v1_enum] enum _BMDPanelType { + bmdPanelNotDetected = /* 'npnl' */ 0x6E706E6C, + bmdPanelTeranexMiniSmartPanel = /* 'tmsm' */ 0x746D736D +} BMDPanelType; + +/* Enum BMDDeviceBusyState - Current device busy state */ + +[v1_enum] enum _BMDDeviceBusyState { + bmdDeviceCaptureBusy = 1 << 0, + bmdDevicePlaybackBusy = 1 << 1, + bmdDeviceSerialPortBusy = 1 << 2 +}; + +/* Enum BMDVideoIOSupport - Device video input/output support */ + +typedef [v1_enum] enum _BMDVideoIOSupport { + bmdDeviceSupportsCapture = 1 << 0, + bmdDeviceSupportsPlayback = 1 << 1 +} BMDVideoIOSupport; + +/* Enum BMD3DPreviewFormat - Linked Frame preview format */ + +typedef [v1_enum] enum _BMD3DPreviewFormat { + bmd3DPreviewFormatDefault = /* 'defa' */ 0x64656661, + bmd3DPreviewFormatLeftOnly = /* 'left' */ 0x6C656674, + bmd3DPreviewFormatRightOnly = /* 'righ' */ 0x72696768, + bmd3DPreviewFormatSideBySide = /* 'side' */ 0x73696465, + bmd3DPreviewFormatTopBottom = /* 'topb' */ 0x746F7062 +} BMD3DPreviewFormat; + +/* Enum BMDNotifications - Events that can be subscribed through IDeckLinkNotification */ + +typedef [v1_enum] enum _BMDNotifications { + bmdPreferencesChanged = /* 'pref' */ 0x70726566, + bmdStatusChanged = /* 'stat' */ 0x73746174 +} BMDNotifications; + +// Forward Declarations + +interface IDeckLinkVideoOutputCallback; +interface IDeckLinkInputCallback; +interface IDeckLinkEncoderInputCallback; +interface IDeckLinkMemoryAllocator; +interface IDeckLinkAudioOutputCallback; +interface IDeckLinkIterator; +interface IDeckLinkAPIInformation; +interface IDeckLinkOutput; +interface IDeckLinkInput; +interface IDeckLinkHDMIInputEDID; +interface IDeckLinkEncoderInput; +interface IDeckLinkVideoFrame; +interface IDeckLinkMutableVideoFrame; +interface IDeckLinkVideoFrame3DExtensions; +interface IDeckLinkVideoFrameMetadataExtensions; +interface IDeckLinkVideoInputFrame; +interface IDeckLinkAncillaryPacket; +interface IDeckLinkAncillaryPacketIterator; +interface IDeckLinkVideoFrameAncillaryPackets; +interface IDeckLinkVideoFrameAncillary; +interface IDeckLinkEncoderPacket; +interface IDeckLinkEncoderVideoPacket; +interface IDeckLinkEncoderAudioPacket; +interface IDeckLinkH265NALPacket; +interface IDeckLinkAudioInputPacket; +interface IDeckLinkScreenPreviewCallback; +interface IDeckLinkGLScreenPreviewHelper; +interface IDeckLinkDX9ScreenPreviewHelper; +interface IDeckLinkWPFDX9ScreenPreviewHelper; +interface IDeckLinkNotificationCallback; +interface IDeckLinkNotification; +interface IDeckLinkProfileAttributes; +interface IDeckLinkProfileIterator; +interface IDeckLinkProfile; +interface IDeckLinkProfileCallback; +interface IDeckLinkProfileManager; +interface IDeckLinkStatus; +interface IDeckLinkKeyer; +interface IDeckLinkVideoConversion; +interface IDeckLinkDeviceNotificationCallback; +interface IDeckLinkDiscovery; + +/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */ + +[ + object, + uuid(20AA5225-1958-47CB-820B-80A8D521A6EE), + helpstring("Frame completion callback.") +] interface IDeckLinkVideoOutputCallback : IUnknown +{ + HRESULT ScheduledFrameCompleted ([in] IDeckLinkVideoFrame* completedFrame, [in] BMDOutputFrameCompletionResult result); + HRESULT ScheduledPlaybackHasStopped (void); +}; + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +[ + object, + uuid(C6FCE4C9-C4E4-4047-82FB-5D238232A902), + helpstring("Frame arrival callback.") +] interface IDeckLinkInputCallback : IUnknown +{ + HRESULT VideoInputFormatChanged ([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode* newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags); + HRESULT VideoInputFrameArrived ([in] IDeckLinkVideoInputFrame* videoFrame, [in] IDeckLinkAudioInputPacket* audioPacket); +}; + +/* Interface IDeckLinkEncoderInputCallback - Frame arrival callback. */ + +[ + object, + uuid(ACF13E61-F4A0-4974-A6A7-59AFF6268B31), + helpstring("Frame arrival callback.") +] interface IDeckLinkEncoderInputCallback : IUnknown +{ + HRESULT VideoInputSignalChanged ([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode* newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags); + HRESULT VideoPacketArrived ([in] IDeckLinkEncoderVideoPacket* videoPacket); + HRESULT AudioPacketArrived ([in] IDeckLinkEncoderAudioPacket* audioPacket); +}; + +/* Interface IDeckLinkMemoryAllocator - Memory allocator for video frames. */ + +[ + object, + uuid(B36EB6E7-9D29-4AA8-92EF-843B87A289E8), + local, + helpstring("Memory allocator for video frames.") +] interface IDeckLinkMemoryAllocator : IUnknown +{ + HRESULT AllocateBuffer ([in] unsigned int bufferSize, [out] void** allocatedBuffer); + HRESULT ReleaseBuffer ([in] void* buffer); + HRESULT Commit (void); + HRESULT Decommit (void); +}; + +/* Interface IDeckLinkAudioOutputCallback - Optional callback to allow audio samples to be pulled as required. */ + +[ + object, + uuid(403C681B-7F46-4A12-B993-2BB127084EE6), + local, + helpstring("Optional callback to allow audio samples to be pulled as required.") +] interface IDeckLinkAudioOutputCallback : IUnknown +{ + HRESULT RenderAudioSamples ([in] BOOL preroll); +}; + +/* Interface IDeckLinkIterator - Enumerates installed DeckLink hardware */ + +[ + object, + uuid(50FB36CD-3063-4B73-BDBB-958087F2D8BA), + helpstring("Enumerates installed DeckLink hardware") +] interface IDeckLinkIterator : IUnknown +{ + HRESULT Next ([out] IDeckLink** deckLinkInstance); +}; + +/* Interface IDeckLinkAPIInformation - DeckLinkAPI attribute interface */ + +[ + object, + uuid(7BEA3C68-730D-4322-AF34-8A7152B532A4), + helpstring("DeckLinkAPI attribute interface") +] interface IDeckLinkAPIInformation : IUnknown +{ + HRESULT GetFlag ([in] BMDDeckLinkAPIInformationID cfgID, [out] BOOL* value); + HRESULT GetInt ([in] BMDDeckLinkAPIInformationID cfgID, [out] LONGLONG* value); + HRESULT GetFloat ([in] BMDDeckLinkAPIInformationID cfgID, [out] double* value); + HRESULT GetString ([in] BMDDeckLinkAPIInformationID cfgID, [out] BSTR* value); +}; + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(BE2D9020-461E-442F-84B7-E949CB953B9D), + local, + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkOutput : IUnknown +{ + HRESULT DoesSupportVideoMode ([in] BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, [in] BMDDisplayMode requestedMode, [in] BMDPixelFormat requestedPixelFormat, [in] BMDVideoOutputConversionMode conversionMode, [in] BMDSupportedVideoModeFlags flags, [out] BMDDisplayMode* actualMode, [out] BOOL* supported); + HRESULT GetDisplayMode ([in] BMDDisplayMode displayMode, [out] IDeckLinkDisplayMode** resultDisplayMode); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator** iterator); + HRESULT SetScreenPreviewCallback ([in] IDeckLinkScreenPreviewCallback* previewCallback); + + /* Video Output */ + + HRESULT EnableVideoOutput ([in] BMDDisplayMode displayMode, [in] BMDVideoOutputFlags flags); + HRESULT DisableVideoOutput (void); + HRESULT SetVideoOutputFrameMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator); + HRESULT CreateVideoFrame ([in] int width, [in] int height, [in] int rowBytes, [in] BMDPixelFormat pixelFormat, [in] BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame** outFrame); + HRESULT CreateAncillaryData ([in] BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary** outBuffer); // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + HRESULT DisplayVideoFrameSync ([in] IDeckLinkVideoFrame* theFrame); + HRESULT ScheduleVideoFrame ([in] IDeckLinkVideoFrame* theFrame, [in] BMDTimeValue displayTime, [in] BMDTimeValue displayDuration, [in] BMDTimeScale timeScale); + HRESULT SetScheduledFrameCompletionCallback ([in] IDeckLinkVideoOutputCallback* theCallback); + HRESULT GetBufferedVideoFrameCount ([out] unsigned int* bufferedFrameCount); + + /* Audio Output */ + + HRESULT EnableAudioOutput ([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount, [in] BMDAudioOutputStreamType streamType); + HRESULT DisableAudioOutput (void); + HRESULT WriteAudioSamplesSync ([in] void* buffer, [in] unsigned int sampleFrameCount, [out] unsigned int* sampleFramesWritten); + HRESULT BeginAudioPreroll (void); + HRESULT EndAudioPreroll (void); + HRESULT ScheduleAudioSamples ([in] void* buffer, [in] unsigned int sampleFrameCount, [in] BMDTimeValue streamTime, [in] BMDTimeScale timeScale, [out] unsigned int* sampleFramesWritten); + HRESULT GetBufferedAudioSampleFrameCount ([out] unsigned int* bufferedSampleFrameCount); + HRESULT FlushBufferedAudioSamples (void); + HRESULT SetAudioCallback ([in] IDeckLinkAudioOutputCallback* theCallback); + + /* Output Control */ + + HRESULT StartScheduledPlayback ([in] BMDTimeValue playbackStartTime, [in] BMDTimeScale timeScale, [in] double playbackSpeed); + HRESULT StopScheduledPlayback ([in] BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue* actualStopTime, [in] BMDTimeScale timeScale); + HRESULT IsScheduledPlaybackRunning ([out] BOOL* active); + HRESULT GetScheduledStreamTime ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* streamTime, [out] double* playbackSpeed); + HRESULT GetReferenceStatus ([out] BMDReferenceStatus* referenceStatus); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* hardwareTime, [out] BMDTimeValue* timeInFrame, [out] BMDTimeValue* ticksPerFrame); + HRESULT GetFrameCompletionReferenceTimestamp ([in] IDeckLinkVideoFrame* theFrame, [in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* frameCompletionTimestamp); +}; + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(C21CDB6E-F414-46E4-A636-80A566E0ED37), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkInput : IUnknown +{ + HRESULT DoesSupportVideoMode ([in] BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, [in] BMDDisplayMode requestedMode, [in] BMDPixelFormat requestedPixelFormat, [in] BMDVideoInputConversionMode conversionMode, [in] BMDSupportedVideoModeFlags flags, [out] BMDDisplayMode* actualMode, [out] BOOL* supported); + HRESULT GetDisplayMode ([in] BMDDisplayMode displayMode, [out] IDeckLinkDisplayMode** resultDisplayMode); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator** iterator); + HRESULT SetScreenPreviewCallback ([in] IDeckLinkScreenPreviewCallback* previewCallback); + + /* Video Input */ + + HRESULT EnableVideoInput ([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags); + HRESULT DisableVideoInput (void); + HRESULT GetAvailableVideoFrameCount ([out] unsigned int* availableFrameCount); + HRESULT SetVideoInputFrameMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator); + + /* Audio Input */ + + HRESULT EnableAudioInput ([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount); + HRESULT DisableAudioInput (void); + HRESULT GetAvailableAudioSampleFrameCount ([out] unsigned int* availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams (void); + HRESULT StopStreams (void); + HRESULT PauseStreams (void); + HRESULT FlushStreams (void); + HRESULT SetCallback ([in] IDeckLinkInputCallback* theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* hardwareTime, [out] BMDTimeValue* timeInFrame, [out] BMDTimeValue* ticksPerFrame); +}; + +/* Interface IDeckLinkHDMIInputEDID - Created by QueryInterface from IDeckLink. Releasing all references will restore EDID to default */ + +[ + object, + uuid(ABBBACBC-45BC-4665-9D92-ACE6E5A97902), + helpstring("Created by QueryInterface from IDeckLink. Releasing all references will restore EDID to default") +] interface IDeckLinkHDMIInputEDID : IUnknown +{ + HRESULT SetInt ([in] BMDDeckLinkHDMIInputEDIDID cfgID, [in] LONGLONG value); + HRESULT GetInt ([in] BMDDeckLinkHDMIInputEDIDID cfgID, [out] LONGLONG* value); + HRESULT WriteToEDID (void); +}; + +/* Interface IDeckLinkEncoderInput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(F222551D-13DF-4FD8-B587-9D4F19EC12C9), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkEncoderInput : IUnknown +{ + HRESULT DoesSupportVideoMode ([in] BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, [in] BMDDisplayMode requestedMode, [in] BMDPixelFormat requestedCodec, [in] unsigned int requestedCodecProfile, [in] BMDSupportedVideoModeFlags flags, [out] BOOL* supported); + HRESULT GetDisplayMode ([in] BMDDisplayMode displayMode, [out] IDeckLinkDisplayMode** resultDisplayMode); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator** iterator); + + /* Video Input */ + + HRESULT EnableVideoInput ([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags); + HRESULT DisableVideoInput (void); + HRESULT GetAvailablePacketsCount ([out] unsigned int* availablePacketsCount); + HRESULT SetMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator); + + /* Audio Input */ + + HRESULT EnableAudioInput ([in] BMDAudioFormat audioFormat, [in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount); + HRESULT DisableAudioInput (void); + HRESULT GetAvailableAudioSampleFrameCount ([out] unsigned int* availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams (void); + HRESULT StopStreams (void); + HRESULT PauseStreams (void); + HRESULT FlushStreams (void); + HRESULT SetCallback ([in] IDeckLinkEncoderInputCallback* theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* hardwareTime, [out] BMDTimeValue* timeInFrame, [out] BMDTimeValue* ticksPerFrame); +}; + +/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */ + +[ + object, + uuid(3F716FE0-F023-4111-BE5D-EF4414C05B17), + local, + helpstring("Interface to encapsulate a video frame; can be caller-implemented.") +] interface IDeckLinkVideoFrame : IUnknown +{ + long GetWidth (void); + long GetHeight (void); + long GetRowBytes (void); + BMDPixelFormat GetPixelFormat (void); + BMDFrameFlags GetFlags (void); + HRESULT GetBytes ([out] void** buffer); + HRESULT GetTimecode ([in] BMDTimecodeFormat format, [out] IDeckLinkTimecode** timecode); + HRESULT GetAncillaryData ([out] IDeckLinkVideoFrameAncillary** ancillary); // Use of IDeckLinkVideoFrameAncillaryPackets is preferred +}; + +/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */ + +[ + object, + uuid(69E2639F-40DA-4E19-B6F2-20ACE815C390), + local, + helpstring("Created by IDeckLinkOutput::CreateVideoFrame.") +] interface IDeckLinkMutableVideoFrame : IDeckLinkVideoFrame +{ + HRESULT SetFlags ([in] BMDFrameFlags newFlags); + HRESULT SetTimecode ([in] BMDTimecodeFormat format, [in] IDeckLinkTimecode* timecode); + HRESULT SetTimecodeFromComponents ([in] BMDTimecodeFormat format, [in] unsigned char hours, [in] unsigned char minutes, [in] unsigned char seconds, [in] unsigned char frames, [in] BMDTimecodeFlags flags); + HRESULT SetAncillaryData ([in] IDeckLinkVideoFrameAncillary* ancillary); + HRESULT SetTimecodeUserBits ([in] BMDTimecodeFormat format, [in] BMDTimecodeUserBits userBits); +}; + +/* Interface IDeckLinkVideoFrame3DExtensions - Optional interface implemented on IDeckLinkVideoFrame to support 3D frames */ + +[ + object, + uuid(DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7), + local, + helpstring("Optional interface implemented on IDeckLinkVideoFrame to support 3D frames") +] interface IDeckLinkVideoFrame3DExtensions : IUnknown +{ + BMDVideo3DPackingFormat Get3DPackingFormat (void); + HRESULT GetFrameForRightEye ([out] IDeckLinkVideoFrame** rightEyeFrame); +}; + +/* Interface IDeckLinkVideoFrameMetadataExtensions - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDR information */ + +[ + object, + uuid(E232A5B7-4DB4-44C9-9152-F47C12E5F051), + local, + helpstring("Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDR information") +] interface IDeckLinkVideoFrameMetadataExtensions : IUnknown +{ + HRESULT GetInt ([in] BMDDeckLinkFrameMetadataID metadataID, [out] LONGLONG* value); + HRESULT GetFloat ([in] BMDDeckLinkFrameMetadataID metadataID, [out] double* value); + HRESULT GetFlag ([in] BMDDeckLinkFrameMetadataID metadataID, [out] BOOL* value); + HRESULT GetString ([in] BMDDeckLinkFrameMetadataID metadataID, [out] BSTR* value); + HRESULT GetBytes ([in] BMDDeckLinkFrameMetadataID metadataID, [out] void* buffer /* optional */, [in, out] unsigned int* bufferSize); +}; + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +[ + object, + uuid(05CFE374-537C-4094-9A57-680525118F44), + local, + helpstring("Provided by the IDeckLinkVideoInput frame arrival callback.") +] interface IDeckLinkVideoInputFrame : IDeckLinkVideoFrame +{ + HRESULT GetStreamTime ([out] BMDTimeValue* frameTime, [out] BMDTimeValue* frameDuration, [in] BMDTimeScale timeScale); + HRESULT GetHardwareReferenceTimestamp ([in] BMDTimeScale timeScale, [out] BMDTimeValue* frameTime, [out] BMDTimeValue* frameDuration); +}; + +/* Interface IDeckLinkAncillaryPacket - On output, user needs to implement this interface */ + +[ + object, + uuid(CC5BBF7E-029C-4D3B-9158-6000EF5E3670), + helpstring("On output, user needs to implement this interface") +] interface IDeckLinkAncillaryPacket : IUnknown +{ + HRESULT GetBytes ([in] BMDAncillaryPacketFormat format /* For output, only one format need be offered */, [out] const void** data /* Optional */, [out] unsigned int* size /* Optional */); + unsigned char GetDID (void); + unsigned char GetSDID (void); + unsigned int GetLineNumber (void); // On output, zero is auto + unsigned char GetDataStreamIndex (void); // Usually zero. Can only be 1 if non-SD and the first data stream is completely full +}; + +/* Interface IDeckLinkAncillaryPacketIterator - Enumerates ancillary packets */ + +[ + object, + uuid(3FC8994B-88FB-4C17-968F-9AAB69D964A7), + helpstring("Enumerates ancillary packets") +] interface IDeckLinkAncillaryPacketIterator : IUnknown +{ + HRESULT Next ([out] IDeckLinkAncillaryPacket** packet); +}; + +/* Interface IDeckLinkVideoFrameAncillaryPackets - Obtained through QueryInterface on an IDeckLinkVideoFrame object. */ + +[ + object, + uuid(6C186C0F-459E-41D8-AEE2-4812D81AEE68), + local, + helpstring("Obtained through QueryInterface on an IDeckLinkVideoFrame object.") +] interface IDeckLinkVideoFrameAncillaryPackets : IUnknown +{ + HRESULT GetPacketIterator ([out] IDeckLinkAncillaryPacketIterator** iterator); + HRESULT GetFirstPacketByID ([in] unsigned char DID, [in] unsigned char SDID, [out] IDeckLinkAncillaryPacket** packet); + HRESULT AttachPacket ([in] IDeckLinkAncillaryPacket* packet); // Implement IDeckLinkAncillaryPacket to output your own + HRESULT DetachPacket ([in] IDeckLinkAncillaryPacket* packet); + HRESULT DetachAllPackets (void); +}; + +/* Interface IDeckLinkVideoFrameAncillary - Use of IDeckLinkVideoFrameAncillaryPackets is preferred. Obtained through QueryInterface on an IDeckLinkVideoFrame object. */ + +[ + object, + uuid(732E723C-D1A4-4E29-9E8E-4A88797A0004), + local, + helpstring("Use of IDeckLinkVideoFrameAncillaryPackets is preferred. Obtained through QueryInterface on an IDeckLinkVideoFrame object.") +] interface IDeckLinkVideoFrameAncillary : IUnknown +{ + HRESULT GetBufferForVerticalBlankingLine ([in] unsigned int lineNumber, [out] void** buffer); // Pixels/rowbytes is same as display mode, except for above HD where it's 1920 pixels for UHD modes and 2048 pixels for DCI modes + BMDPixelFormat GetPixelFormat (void); + BMDDisplayMode GetDisplayMode (void); +}; + +/* Interface IDeckLinkEncoderPacket - Interface to encapsulate an encoded packet. */ + +[ + object, + uuid(B693F36C-316E-4AF1-B6C2-F389A4BCA620), + local, + helpstring("Interface to encapsulate an encoded packet.") +] interface IDeckLinkEncoderPacket : IUnknown +{ + HRESULT GetBytes ([out] void** buffer); + long GetSize (void); + HRESULT GetStreamTime ([out] BMDTimeValue* frameTime, [in] BMDTimeScale timeScale); + BMDPacketType GetPacketType (void); +}; + +/* Interface IDeckLinkEncoderVideoPacket - Provided by the IDeckLinkEncoderInput video packet arrival callback. */ + +[ + object, + uuid(4E7FD944-E8C7-4EAC-B8C0-7B77F80F5AE0), + local, + helpstring("Provided by the IDeckLinkEncoderInput video packet arrival callback.") +] interface IDeckLinkEncoderVideoPacket : IDeckLinkEncoderPacket +{ + BMDPixelFormat GetPixelFormat (void); + HRESULT GetHardwareReferenceTimestamp ([in] BMDTimeScale timeScale, [out] BMDTimeValue* frameTime, [out] BMDTimeValue* frameDuration); + HRESULT GetTimecode ([in] BMDTimecodeFormat format, [out] IDeckLinkTimecode** timecode); +}; + +/* Interface IDeckLinkEncoderAudioPacket - Provided by the IDeckLinkEncoderInput audio packet arrival callback. */ + +[ + object, + uuid(49E8EDC8-693B-4E14-8EF6-12C658F5A07A), + local, + helpstring("Provided by the IDeckLinkEncoderInput audio packet arrival callback.") +] interface IDeckLinkEncoderAudioPacket : IDeckLinkEncoderPacket +{ + BMDAudioFormat GetAudioFormat (void); +}; + +/* Interface IDeckLinkH265NALPacket - Obtained through QueryInterface on an IDeckLinkEncoderVideoPacket object */ + +[ + object, + uuid(639C8E0B-68D5-4BDE-A6D4-95F3AEAFF2E7), + local, + helpstring("Obtained through QueryInterface on an IDeckLinkEncoderVideoPacket object") +] interface IDeckLinkH265NALPacket : IDeckLinkEncoderVideoPacket +{ + HRESULT GetUnitType ([out] unsigned char* unitType); + HRESULT GetBytesNoPrefix ([out] void** buffer); + long GetSizeNoPrefix (void); +}; + +/* Interface IDeckLinkAudioInputPacket - Provided by the IDeckLinkInput callback. */ + +[ + object, + uuid(E43D5870-2894-11DE-8C30-0800200C9A66), + local, + helpstring("Provided by the IDeckLinkInput callback.") +] interface IDeckLinkAudioInputPacket : IUnknown +{ + long GetSampleFrameCount (void); + HRESULT GetBytes ([out] void** buffer); + HRESULT GetPacketTime ([out] BMDTimeValue* packetTime, [in] BMDTimeScale timeScale); +}; + +/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */ + +[ + object, + uuid(B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438), + local, + helpstring("Screen preview callback") +] interface IDeckLinkScreenPreviewCallback : IUnknown +{ + HRESULT DrawFrame ([in] IDeckLinkVideoFrame* theFrame); +}; + +/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance on platforms with native COM support or from CreateOpenGLScreenPreviewHelper/CreateOpenGL3ScreenPreviewHelper on other platforms. */ + +[ + object, + uuid(504E2209-CAC7-4C1A-9FB4-C5BB6274D22F), + local, + helpstring("Created with CoCreateInstance on platforms with native COM support or from CreateOpenGLScreenPreviewHelper/CreateOpenGL3ScreenPreviewHelper on other platforms.") +] interface IDeckLinkGLScreenPreviewHelper : IUnknown +{ + + /* Methods must be called with OpenGL context set */ + + HRESULT InitializeGL (void); + HRESULT PaintGL (void); + HRESULT SetFrame ([in] IDeckLinkVideoFrame* theFrame); + HRESULT Set3DPreviewFormat ([in] BMD3DPreviewFormat previewFormat); +}; + +/* Interface IDeckLinkDX9ScreenPreviewHelper - Created with CoCreateInstance. */ + +[ + object, + uuid(2094B522-D1A1-40C0-9AC7-1C012218EF02), + local, + helpstring("Created with CoCreateInstance.") +] interface IDeckLinkDX9ScreenPreviewHelper : IUnknown +{ + HRESULT Initialize ([in] void* device); + HRESULT Render ([in] RECT* rc); + HRESULT SetFrame ([in] IDeckLinkVideoFrame* theFrame); + HRESULT Set3DPreviewFormat ([in] BMD3DPreviewFormat previewFormat); +}; + +/* Interface IDeckLinkWPFDX9ScreenPreviewHelper - Created with CoCreateInstance(). */ + +[ + object, + uuid(AD8EC84A-7DDE-11E9-8F9E-2A86E4085A59), + local, + helpstring("Created with CoCreateInstance().") +] interface IDeckLinkWPFDX9ScreenPreviewHelper : IUnknown +{ + HRESULT Initialize (void); + HRESULT Render (void); + HRESULT SetSurfaceSize ([in] unsigned int width, [in] unsigned int height); + HRESULT SetFrame ([in] IDeckLinkVideoFrame* theFrame); + HRESULT Set3DPreviewFormat ([in] BMD3DPreviewFormat previewFormat); + HRESULT GetBackBuffer ([out] void** backBuffer); +}; + +/* Interface IDeckLinkNotificationCallback - DeckLink Notification Callback Interface */ + +[ + object, + uuid(b002a1ec-070d-4288-8289-bd5d36e5ff0d), + local, + helpstring("DeckLink Notification Callback Interface") +] interface IDeckLinkNotificationCallback : IUnknown +{ + HRESULT Notify ([in] BMDNotifications topic, [in] ULONGLONG param1, [in] ULONGLONG param2); +}; + +/* Interface IDeckLinkNotification - DeckLink Notification interface */ + +[ + object, + uuid(b85df4c8-bdf5-47c1-8064-28162ebdd4eb), + local, + helpstring("DeckLink Notification interface") +] interface IDeckLinkNotification : IUnknown +{ + HRESULT Subscribe ([in] BMDNotifications topic, [in] IDeckLinkNotificationCallback* theCallback); + HRESULT Unsubscribe ([in] BMDNotifications topic, [in] IDeckLinkNotificationCallback* theCallback); +}; + +/* Interface IDeckLinkProfileAttributes - Created by QueryInterface from an IDeckLinkProfile, or from IDeckLink. When queried from IDeckLink, interrogates the active profile */ + +[ + object, + uuid(17D4BF8E-4911-473A-80A0-731CF6FF345B), + local, + helpstring("Created by QueryInterface from an IDeckLinkProfile, or from IDeckLink. When queried from IDeckLink, interrogates the active profile") +] interface IDeckLinkProfileAttributes : IUnknown +{ + HRESULT GetFlag ([in] BMDDeckLinkAttributeID cfgID, [out] BOOL* value); + HRESULT GetInt ([in] BMDDeckLinkAttributeID cfgID, [out] LONGLONG* value); + HRESULT GetFloat ([in] BMDDeckLinkAttributeID cfgID, [out] double* value); + HRESULT GetString ([in] BMDDeckLinkAttributeID cfgID, [out] BSTR* value); +}; + +/* Interface IDeckLinkProfileIterator - Enumerates IDeckLinkProfile interfaces */ + +[ + object, + uuid(29E5A8C0-8BE4-46EB-93AC-31DAAB5B7BF2), + helpstring("Enumerates IDeckLinkProfile interfaces") +] interface IDeckLinkProfileIterator : IUnknown +{ + HRESULT Next ([out] IDeckLinkProfile** profile); +}; + +/* Interface IDeckLinkProfile - Represents the active profile when queried from IDeckLink */ + +[ + object, + uuid(16093466-674A-432B-9DA0-1AC2C5A8241C), + local, + helpstring("Represents the active profile when queried from IDeckLink") +] interface IDeckLinkProfile : IUnknown +{ + HRESULT GetDevice ([out] IDeckLink** device); // Device affected when this profile becomes active + HRESULT IsActive ([out] BOOL* isActive); + HRESULT SetActive (void); // Activating a profile will also change the profile on all devices enumerated by GetPeers. Activation is not complete until IDeckLinkProfileCallback::ProfileActivated is called + HRESULT GetPeers ([out] IDeckLinkProfileIterator** profileIterator); // Profiles of other devices activated with this profile +}; + +/* Interface IDeckLinkProfileCallback - Receive notifications about profiles related to this device */ + +[ + object, + uuid(A4F9341E-97AA-4E04-8935-15F809898CEA), + helpstring("Receive notifications about profiles related to this device") +] interface IDeckLinkProfileCallback : IUnknown +{ + HRESULT ProfileChanging ([in] IDeckLinkProfile* profileToBeActivated, [in] BOOL streamsWillBeForcedToStop); // Called before this device changes profile. User has an opportunity for teardown if streamsWillBeForcedToStop + HRESULT ProfileActivated ([in] IDeckLinkProfile* activatedProfile); // Called after this device has been activated with a new profile +}; + +/* Interface IDeckLinkProfileManager - Created by QueryInterface from IDeckLink when a device has multiple optional profiles */ + +[ + object, + uuid(30D41429-3998-4B6D-84F8-78C94A797C6E), + helpstring("Created by QueryInterface from IDeckLink when a device has multiple optional profiles") +] interface IDeckLinkProfileManager : IUnknown +{ + HRESULT GetProfiles ([out] IDeckLinkProfileIterator** profileIterator); // All available profiles for this device + HRESULT GetProfile ([in] BMDProfileID profileID, [out] IDeckLinkProfile** profile); + HRESULT SetCallback ([in] IDeckLinkProfileCallback* callback); +}; + +/* Interface IDeckLinkStatus - DeckLink Status interface */ + +[ + object, + uuid(5F558200-4028-49BC-BEAC-DB3FA4A96E46), + local, + helpstring("DeckLink Status interface") +] interface IDeckLinkStatus : IUnknown +{ + HRESULT GetFlag ([in] BMDDeckLinkStatusID statusID, [out] BOOL* value); + HRESULT GetInt ([in] BMDDeckLinkStatusID statusID, [out] LONGLONG* value); + HRESULT GetFloat ([in] BMDDeckLinkStatusID statusID, [out] double* value); + HRESULT GetString ([in] BMDDeckLinkStatusID statusID, [out] BSTR* value); + HRESULT GetBytes ([in] BMDDeckLinkStatusID statusID, [out] void* buffer, [in, out] unsigned int* bufferSize); +}; + +/* Interface IDeckLinkKeyer - DeckLink Keyer interface */ + +[ + object, + uuid(89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3), + local, + helpstring("DeckLink Keyer interface") +] interface IDeckLinkKeyer : IUnknown +{ + HRESULT Enable ([in] BOOL isExternal); + HRESULT SetLevel ([in] unsigned char level); + HRESULT RampUp ([in] unsigned int numberOfFrames); + HRESULT RampDown ([in] unsigned int numberOfFrames); + HRESULT Disable (void); +}; + +/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance. */ + +[ + object, + uuid(3BBCB8A2-DA2C-42D9-B5D8-88083644E99A), + local, + helpstring("Created with CoCreateInstance.") +] interface IDeckLinkVideoConversion : IUnknown +{ + HRESULT ConvertFrame ([in] IDeckLinkVideoFrame* srcFrame, [in] IDeckLinkVideoFrame* dstFrame); +}; + +/* Interface IDeckLinkDeviceNotificationCallback - DeckLink device arrival/removal notification callbacks */ + +[ + object, + uuid(4997053B-0ADF-4CC8-AC70-7A50C4BE728F), + helpstring("DeckLink device arrival/removal notification callbacks") +] interface IDeckLinkDeviceNotificationCallback : IUnknown +{ + HRESULT DeckLinkDeviceArrived ([in] IDeckLink* deckLinkDevice); + HRESULT DeckLinkDeviceRemoved ([in] IDeckLink* deckLinkDevice); +}; + +/* Interface IDeckLinkDiscovery - DeckLink device discovery */ + +[ + object, + uuid(CDBF631C-BC76-45FA-B44D-C55059BC6101), + helpstring("DeckLink device discovery") +] interface IDeckLinkDiscovery : IUnknown +{ + HRESULT InstallDeviceNotifications ([in] IDeckLinkDeviceNotificationCallback* deviceNotificationCallback); + HRESULT UninstallDeviceNotifications (void); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); + +[ + uuid(BA6C6F44-6DA5-4DCE-94AA-EE2D1372A676), + helpstring("CDeckLinkIterator Class") +] coclass CDeckLinkIterator +{ + [default] interface IDeckLinkIterator; +}; + +[ + uuid(263CA19F-ED09-482E-9F9D-84005783A237), + helpstring("CDeckLinkAPIInformation Class") +] coclass CDeckLinkAPIInformation +{ + [default] interface IDeckLinkAPIInformation; +}; + +[ + uuid(F63E77C7-B655-4A4A-9AD0-3CA85D394343), + helpstring("CDeckLinkGLScreenPreviewHelper Class") +] coclass CDeckLinkGLScreenPreviewHelper +{ + [default] interface IDeckLinkGLScreenPreviewHelper; +}; + +[ + uuid(00696A71-EBC7-491F-AC02-18D3393F33F0), + helpstring("CDeckLinkGL3ScreenPreviewHelper Class. Requires OpenGL 3.2 support and provides improved performance and color handling") +] coclass CDeckLinkGL3ScreenPreviewHelper +{ + [default] interface IDeckLinkGLScreenPreviewHelper; +}; + +[ + uuid(CC010023-E01D-4525-9D59-80C8AB3DC7A0), + helpstring("CDeckLinkDX9ScreenPreviewHelper Class") +] coclass CDeckLinkDX9ScreenPreviewHelper +{ + [default] interface IDeckLinkDX9ScreenPreviewHelper; +}; + +[ + uuid(EF2A8478-7DDF-11E9-8F9E-2A86E4085A59), + helpstring("CDeckLinkWPFDX9ScreenPreviewHelper Class") +] coclass CDeckLinkWPFDX9ScreenPreviewHelper +{ + [default] interface IDeckLinkWPFDX9ScreenPreviewHelper; +}; + +[ + uuid(7DBBBB11-5B7B-467D-AEA4-CEA468FD368C), + helpstring("CDeckLinkVideoConversion Class") +] coclass CDeckLinkVideoConversion +{ + [default] interface IDeckLinkVideoConversion; +}; + +[ + uuid(22FBFC33-8D07-495C-A5BF-DAB5EA9B82DB), + helpstring("CDeckLinkDiscovery Class") +] coclass CDeckLinkDiscovery +{ + [default] interface IDeckLinkDiscovery; +}; + +[ + uuid(F891AD29-D0C2-46E9-A926-4E2D0DD8CFAD), + helpstring("CDeckLinkVideoFrameAncillaryPackets Class") +] coclass CDeckLinkVideoFrameAncillaryPackets +{ + [default] interface IDeckLinkVideoFrameAncillaryPackets; +}; + +// import deprecated interfaces + +#include "DeckLinkAPI_v11_5_1.idl" +#include "DeckLinkAPI_v10_11.idl" +#include "DeckLinkAPI_v10_9.idl" +#include "DeckLinkAPIStreaming_v10_8.idl" +#include "DeckLinkAPI_v10_4.idl" +#include "DeckLinkAPI_v10_2.idl" +#include "DeckLinkAPI_v11_5.idl" +#include "DeckLinkAPI_v11_4.idl" +#include "DeckLinkAPI_v10_8.idl" +#include "DeckLinkAPI_v10_6.idl" +#include "DeckLinkAPI_v10_5.idl" +#include "DeckLinkAPI_v9_9.idl" +#include "DeckLinkAPI_v9_2.idl" +#include "DeckLinkAPI_v8_1.idl" +#include "DeckLinkAPI_v8_0.idl" +#include "DeckLinkAPI_v7_9.idl" +#include "DeckLinkAPI_v7_6.idl" +#include "DeckLinkAPI_v7_3.idl" +#include "DeckLinkAPI_v7_1.idl" +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIConfiguration.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIConfiguration.idl new file mode 100644 index 0000000000..10ebc09cd6 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIConfiguration.idl @@ -0,0 +1,252 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +// Type Declarations + + +// Enumeration Mapping + +cpp_quote("#if 0") +cpp_quote("#endif") + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef [v1_enum] enum _BMDDeckLinkConfigurationID { + + /* Serial port Flags */ + + bmdDeckLinkConfigSwapSerialRxTx = /* 'ssrt' */ 0x73737274, + + /* Video Input/Output Integers */ + + bmdDeckLinkConfigHDMI3DPackingFormat = /* '3dpf' */ 0x33647066, + bmdDeckLinkConfigBypass = /* 'byps' */ 0x62797073, + bmdDeckLinkConfigClockTimingAdjustment = /* 'ctad' */ 0x63746164, + + /* Audio Input/Output Flags */ + + bmdDeckLinkConfigAnalogAudioConsumerLevels = /* 'aacl' */ 0x6161636C, + bmdDeckLinkConfigSwapHDMICh3AndCh4OnInput = /* 'hi34' */ 0x68693334, + bmdDeckLinkConfigSwapHDMICh3AndCh4OnOutput = /* 'ho34' */ 0x686F3334, + + /* Video Output Flags */ + + bmdDeckLinkConfigFieldFlickerRemoval = /* 'fdfr' */ 0x66646672, + bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion = /* 'to59' */ 0x746F3539, + bmdDeckLinkConfig444SDIVideoOutput = /* '444o' */ 0x3434346F, + bmdDeckLinkConfigBlackVideoOutputDuringCapture = /* 'bvoc' */ 0x62766F63, + bmdDeckLinkConfigLowLatencyVideoOutput = /* 'llvo' */ 0x6C6C766F, + bmdDeckLinkConfigDownConversionOnAllAnalogOutput = /* 'caao' */ 0x6361616F, + bmdDeckLinkConfigSMPTELevelAOutput = /* 'smta' */ 0x736D7461, + bmdDeckLinkConfigRec2020Output = /* 'rec2' */ 0x72656332, // Ensure output is Rec.2020 colorspace + bmdDeckLinkConfigQuadLinkSDIVideoOutputSquareDivisionSplit = /* 'SDQS' */ 0x53445153, + bmdDeckLinkConfigOutput1080pAsPsF = /* 'pfpr' */ 0x70667072, + + /* Video Output Integers */ + + bmdDeckLinkConfigVideoOutputConnection = /* 'vocn' */ 0x766F636E, + bmdDeckLinkConfigVideoOutputConversionMode = /* 'vocm' */ 0x766F636D, + bmdDeckLinkConfigAnalogVideoOutputFlags = /* 'avof' */ 0x61766F66, + bmdDeckLinkConfigReferenceInputTimingOffset = /* 'glot' */ 0x676C6F74, + bmdDeckLinkConfigVideoOutputIdleOperation = /* 'voio' */ 0x766F696F, + bmdDeckLinkConfigDefaultVideoOutputMode = /* 'dvom' */ 0x64766F6D, + bmdDeckLinkConfigDefaultVideoOutputModeFlags = /* 'dvof' */ 0x64766F66, + bmdDeckLinkConfigSDIOutputLinkConfiguration = /* 'solc' */ 0x736F6C63, + bmdDeckLinkConfigHDMITimecodePacking = /* 'htpk' */ 0x6874706B, + bmdDeckLinkConfigPlaybackGroup = /* 'plgr' */ 0x706C6772, + + /* Video Output Floats */ + + bmdDeckLinkConfigVideoOutputComponentLumaGain = /* 'oclg' */ 0x6F636C67, + bmdDeckLinkConfigVideoOutputComponentChromaBlueGain = /* 'occb' */ 0x6F636362, + bmdDeckLinkConfigVideoOutputComponentChromaRedGain = /* 'occr' */ 0x6F636372, + bmdDeckLinkConfigVideoOutputCompositeLumaGain = /* 'oilg' */ 0x6F696C67, + bmdDeckLinkConfigVideoOutputCompositeChromaGain = /* 'oicg' */ 0x6F696367, + bmdDeckLinkConfigVideoOutputSVideoLumaGain = /* 'oslg' */ 0x6F736C67, + bmdDeckLinkConfigVideoOutputSVideoChromaGain = /* 'oscg' */ 0x6F736367, + + /* Video Input Flags */ + + bmdDeckLinkConfigVideoInputScanning = /* 'visc' */ 0x76697363, // Applicable to H264 Pro Recorder only + bmdDeckLinkConfigUseDedicatedLTCInput = /* 'dltc' */ 0x646C7463, // Use timecode from LTC input instead of SDI stream + bmdDeckLinkConfigSDIInput3DPayloadOverride = /* '3dds' */ 0x33646473, + bmdDeckLinkConfigCapture1080pAsPsF = /* 'cfpr' */ 0x63667072, + + /* Video Input Integers */ + + bmdDeckLinkConfigVideoInputConnection = /* 'vicn' */ 0x7669636E, + bmdDeckLinkConfigAnalogVideoInputFlags = /* 'avif' */ 0x61766966, + bmdDeckLinkConfigVideoInputConversionMode = /* 'vicm' */ 0x7669636D, + bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame = /* 'pdif' */ 0x70646966, + bmdDeckLinkConfigVANCSourceLine1Mapping = /* 'vsl1' */ 0x76736C31, + bmdDeckLinkConfigVANCSourceLine2Mapping = /* 'vsl2' */ 0x76736C32, + bmdDeckLinkConfigVANCSourceLine3Mapping = /* 'vsl3' */ 0x76736C33, + bmdDeckLinkConfigCapturePassThroughMode = /* 'cptm' */ 0x6370746D, + bmdDeckLinkConfigCaptureGroup = /* 'cpgr' */ 0x63706772, + + /* Video Input Floats */ + + bmdDeckLinkConfigVideoInputComponentLumaGain = /* 'iclg' */ 0x69636C67, + bmdDeckLinkConfigVideoInputComponentChromaBlueGain = /* 'iccb' */ 0x69636362, + bmdDeckLinkConfigVideoInputComponentChromaRedGain = /* 'iccr' */ 0x69636372, + bmdDeckLinkConfigVideoInputCompositeLumaGain = /* 'iilg' */ 0x69696C67, + bmdDeckLinkConfigVideoInputCompositeChromaGain = /* 'iicg' */ 0x69696367, + bmdDeckLinkConfigVideoInputSVideoLumaGain = /* 'islg' */ 0x69736C67, + bmdDeckLinkConfigVideoInputSVideoChromaGain = /* 'iscg' */ 0x69736367, + + /* Keying Integers */ + + bmdDeckLinkConfigInternalKeyingAncillaryDataSource = /* 'ikas' */ 0x696B6173, + + /* Audio Input Flags */ + + bmdDeckLinkConfigMicrophonePhantomPower = /* 'mphp' */ 0x6D706870, + + /* Audio Input Integers */ + + bmdDeckLinkConfigAudioInputConnection = /* 'aicn' */ 0x6169636E, + + /* Audio Input Floats */ + + bmdDeckLinkConfigAnalogAudioInputScaleChannel1 = /* 'ais1' */ 0x61697331, + bmdDeckLinkConfigAnalogAudioInputScaleChannel2 = /* 'ais2' */ 0x61697332, + bmdDeckLinkConfigAnalogAudioInputScaleChannel3 = /* 'ais3' */ 0x61697333, + bmdDeckLinkConfigAnalogAudioInputScaleChannel4 = /* 'ais4' */ 0x61697334, + bmdDeckLinkConfigDigitalAudioInputScale = /* 'dais' */ 0x64616973, + bmdDeckLinkConfigMicrophoneInputGain = /* 'micg' */ 0x6D696367, + + /* Audio Output Integers */ + + bmdDeckLinkConfigAudioOutputAESAnalogSwitch = /* 'aoaa' */ 0x616F6161, + + /* Audio Output Floats */ + + bmdDeckLinkConfigAnalogAudioOutputScaleChannel1 = /* 'aos1' */ 0x616F7331, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel2 = /* 'aos2' */ 0x616F7332, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel3 = /* 'aos3' */ 0x616F7333, + bmdDeckLinkConfigAnalogAudioOutputScaleChannel4 = /* 'aos4' */ 0x616F7334, + bmdDeckLinkConfigDigitalAudioOutputScale = /* 'daos' */ 0x64616F73, + bmdDeckLinkConfigHeadphoneVolume = /* 'hvol' */ 0x68766F6C, + + /* Device Information Strings */ + + bmdDeckLinkConfigDeviceInformationLabel = /* 'dila' */ 0x64696C61, + bmdDeckLinkConfigDeviceInformationSerialNumber = /* 'disn' */ 0x6469736E, + bmdDeckLinkConfigDeviceInformationCompany = /* 'dico' */ 0x6469636F, + bmdDeckLinkConfigDeviceInformationPhone = /* 'diph' */ 0x64697068, + bmdDeckLinkConfigDeviceInformationEmail = /* 'diem' */ 0x6469656D, + bmdDeckLinkConfigDeviceInformationDate = /* 'dida' */ 0x64696461, + + /* Deck Control Integers */ + + bmdDeckLinkConfigDeckControlConnection = /* 'dcco' */ 0x6463636F +} BMDDeckLinkConfigurationID; + +/* Enum BMDDeckLinkEncoderConfigurationID - DeckLink Encoder Configuration ID */ + +typedef [v1_enum] enum _BMDDeckLinkEncoderConfigurationID { + + /* Video Encoder Integers */ + + bmdDeckLinkEncoderConfigPreferredBitDepth = /* 'epbr' */ 0x65706272, + bmdDeckLinkEncoderConfigFrameCodingMode = /* 'efcm' */ 0x6566636D, + + /* HEVC/H.265 Encoder Integers */ + + bmdDeckLinkEncoderConfigH265TargetBitrate = /* 'htbr' */ 0x68746272, + + /* DNxHR/DNxHD Compression ID */ + + bmdDeckLinkEncoderConfigDNxHRCompressionID = /* 'dcid' */ 0x64636964, + + /* DNxHR/DNxHD Level */ + + bmdDeckLinkEncoderConfigDNxHRLevel = /* 'dlev' */ 0x646C6576, + + /* Encoded Sample Decriptions */ + + bmdDeckLinkEncoderConfigMPEG4SampleDescription = /* 'stsE' */ 0x73747345, // Full MPEG4 sample description (aka SampleEntry of an 'stsd' atom-box). Useful for MediaFoundation, QuickTime, MKV and more + bmdDeckLinkEncoderConfigMPEG4CodecSpecificDesc = /* 'esds' */ 0x65736473 // Sample description extensions only (atom stream, each with size and fourCC header). Useful for AVFoundation, VideoToolbox, MKV and more +} BMDDeckLinkEncoderConfigurationID; + +// Forward Declarations + +interface IDeckLinkConfiguration; +interface IDeckLinkEncoderConfiguration; + +/* Interface IDeckLinkConfiguration - DeckLink Configuration interface */ + +[ + object, + uuid(912F634B-2D4E-40A4-8AAB-8D80B73F1289), + local, + helpstring("DeckLink Configuration interface") +] interface IDeckLinkConfiguration : IUnknown +{ + HRESULT SetFlag ([in] BMDDeckLinkConfigurationID cfgID, [in] BOOL value); + HRESULT GetFlag ([in] BMDDeckLinkConfigurationID cfgID, [out] BOOL* value); + HRESULT SetInt ([in] BMDDeckLinkConfigurationID cfgID, [in] LONGLONG value); + HRESULT GetInt ([in] BMDDeckLinkConfigurationID cfgID, [out] LONGLONG* value); + HRESULT SetFloat ([in] BMDDeckLinkConfigurationID cfgID, [in] double value); + HRESULT GetFloat ([in] BMDDeckLinkConfigurationID cfgID, [out] double* value); + HRESULT SetString ([in] BMDDeckLinkConfigurationID cfgID, [in] BSTR value); + HRESULT GetString ([in] BMDDeckLinkConfigurationID cfgID, [out] BSTR* value); + HRESULT WriteConfigurationToPreferences (void); +}; + +/* Interface IDeckLinkEncoderConfiguration - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */ + +[ + object, + uuid(138050E5-C60A-4552-BF3F-0F358049327E), + local, + helpstring("DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput") +] interface IDeckLinkEncoderConfiguration : IUnknown +{ + HRESULT SetFlag ([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] BOOL value); + HRESULT GetFlag ([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] BOOL* value); + HRESULT SetInt ([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] LONGLONG value); + HRESULT GetInt ([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] LONGLONG* value); + HRESULT SetFloat ([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] double value); + HRESULT GetFloat ([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] double* value); + HRESULT SetString ([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] BSTR value); + HRESULT GetString ([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] BSTR* value); + HRESULT GetBytes ([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] void* buffer /* optional */, [in, out] unsigned int* bufferSize); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDeckControl.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDeckControl.idl new file mode 100644 index 0000000000..70275040b5 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDeckControl.idl @@ -0,0 +1,204 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +// Type Declarations + + +// Enumeration Mapping + +cpp_quote("typedef unsigned int BMDDeckControlStatusFlags;") +cpp_quote("typedef unsigned int BMDDeckControlExportModeOpsFlags;") +cpp_quote("#if 0") +typedef enum _BMDDeckControlStatusFlags BMDDeckControlStatusFlags; +typedef enum _BMDDeckControlExportModeOpsFlags BMDDeckControlExportModeOpsFlags; +cpp_quote("#endif") + +/* Enum BMDDeckControlMode - DeckControl mode */ + +typedef [v1_enum] enum _BMDDeckControlMode { + bmdDeckControlNotOpened = /* 'ntop' */ 0x6E746F70, + bmdDeckControlVTRControlMode = /* 'vtrc' */ 0x76747263, + bmdDeckControlExportMode = /* 'expm' */ 0x6578706D, + bmdDeckControlCaptureMode = /* 'capm' */ 0x6361706D +} BMDDeckControlMode; + +/* Enum BMDDeckControlEvent - DeckControl event */ + +typedef [v1_enum] enum _BMDDeckControlEvent { + bmdDeckControlAbortedEvent = /* 'abte' */ 0x61627465, // This event is triggered when a capture or edit-to-tape operation is aborted. + + /* Export-To-Tape events */ + + bmdDeckControlPrepareForExportEvent = /* 'pfee' */ 0x70666565, // This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback should be called at this point. + bmdDeckControlExportCompleteEvent = /* 'exce' */ 0x65786365, // This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode. + + /* Capture events */ + + bmdDeckControlPrepareForCaptureEvent = /* 'pfce' */ 0x70666365, // This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid. + bmdDeckControlCaptureCompleteEvent = /* 'ccev' */ 0x63636576 // This event is triggered a few frames after reaching the out-point. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode. +} BMDDeckControlEvent; + +/* Enum BMDDeckControlVTRControlState - VTR Control state */ + +typedef [v1_enum] enum _BMDDeckControlVTRControlState { + bmdDeckControlNotInVTRControlMode = /* 'nvcm' */ 0x6E76636D, + bmdDeckControlVTRControlPlaying = /* 'vtrp' */ 0x76747270, + bmdDeckControlVTRControlRecording = /* 'vtrr' */ 0x76747272, + bmdDeckControlVTRControlStill = /* 'vtra' */ 0x76747261, + bmdDeckControlVTRControlShuttleForward = /* 'vtsf' */ 0x76747366, + bmdDeckControlVTRControlShuttleReverse = /* 'vtsr' */ 0x76747372, + bmdDeckControlVTRControlJogForward = /* 'vtjf' */ 0x76746A66, + bmdDeckControlVTRControlJogReverse = /* 'vtjr' */ 0x76746A72, + bmdDeckControlVTRControlStopped = /* 'vtro' */ 0x7674726F +} BMDDeckControlVTRControlState; + +/* Enum BMDDeckControlStatusFlags - Deck Control status flags */ + +[v1_enum] enum _BMDDeckControlStatusFlags { + bmdDeckControlStatusDeckConnected = 1 << 0, + bmdDeckControlStatusRemoteMode = 1 << 1, + bmdDeckControlStatusRecordInhibited = 1 << 2, + bmdDeckControlStatusCassetteOut = 1 << 3 +}; + +/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */ + +[v1_enum] enum _BMDDeckControlExportModeOpsFlags { + bmdDeckControlExportModeInsertVideo = 1 << 0, + bmdDeckControlExportModeInsertAudio1 = 1 << 1, + bmdDeckControlExportModeInsertAudio2 = 1 << 2, + bmdDeckControlExportModeInsertAudio3 = 1 << 3, + bmdDeckControlExportModeInsertAudio4 = 1 << 4, + bmdDeckControlExportModeInsertAudio5 = 1 << 5, + bmdDeckControlExportModeInsertAudio6 = 1 << 6, + bmdDeckControlExportModeInsertAudio7 = 1 << 7, + bmdDeckControlExportModeInsertAudio8 = 1 << 8, + bmdDeckControlExportModeInsertAudio9 = 1 << 9, + bmdDeckControlExportModeInsertAudio10 = 1 << 10, + bmdDeckControlExportModeInsertAudio11 = 1 << 11, + bmdDeckControlExportModeInsertAudio12 = 1 << 12, + bmdDeckControlExportModeInsertTimeCode = 1 << 13, + bmdDeckControlExportModeInsertAssemble = 1 << 14, + bmdDeckControlExportModeInsertPreview = 1 << 15, + bmdDeckControlUseManualExport = 1 << 16 +}; + +/* Enum BMDDeckControlError - Deck Control error */ + +typedef [v1_enum] enum _BMDDeckControlError { + bmdDeckControlNoError = /* 'noer' */ 0x6E6F6572, + bmdDeckControlModeError = /* 'moer' */ 0x6D6F6572, + bmdDeckControlMissedInPointError = /* 'mier' */ 0x6D696572, + bmdDeckControlDeckTimeoutError = /* 'dter' */ 0x64746572, + bmdDeckControlCommandFailedError = /* 'cfer' */ 0x63666572, + bmdDeckControlDeviceAlreadyOpenedError = /* 'dalo' */ 0x64616C6F, + bmdDeckControlFailedToOpenDeviceError = /* 'fder' */ 0x66646572, + bmdDeckControlInLocalModeError = /* 'lmer' */ 0x6C6D6572, + bmdDeckControlEndOfTapeError = /* 'eter' */ 0x65746572, + bmdDeckControlUserAbortError = /* 'uaer' */ 0x75616572, + bmdDeckControlNoTapeInDeckError = /* 'nter' */ 0x6E746572, + bmdDeckControlNoVideoFromCardError = /* 'nvfc' */ 0x6E766663, + bmdDeckControlNoCommunicationError = /* 'ncom' */ 0x6E636F6D, + bmdDeckControlBufferTooSmallError = /* 'btsm' */ 0x6274736D, + bmdDeckControlBadChecksumError = /* 'chks' */ 0x63686B73, + bmdDeckControlUnknownError = /* 'uner' */ 0x756E6572 +} BMDDeckControlError; + +// Forward Declarations + +interface IDeckLinkDeckControlStatusCallback; +interface IDeckLinkDeckControl; + +/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */ + +[ + object, + uuid(53436FFB-B434-4906-BADC-AE3060FFE8EF), + helpstring("Deck control state change callback.") +] interface IDeckLinkDeckControlStatusCallback : IUnknown +{ + HRESULT TimecodeUpdate ([in] BMDTimecodeBCD currentTimecode); + HRESULT VTRControlStateChanged ([in] BMDDeckControlVTRControlState newState, [in] BMDDeckControlError error); + HRESULT DeckControlEventReceived ([in] BMDDeckControlEvent event, [in] BMDDeckControlError error); + HRESULT DeckControlStatusChanged ([in] BMDDeckControlStatusFlags flags, [in] unsigned int mask); +}; + +/* Interface IDeckLinkDeckControl - Deck Control main interface */ + +[ + object, + uuid(8E1C3ACE-19C7-4E00-8B92-D80431D958BE), + helpstring("Deck Control main interface") +] interface IDeckLinkDeckControl : IUnknown +{ + HRESULT Open ([in] BMDTimeScale timeScale, [in] BMDTimeValue timeValue, [in] BOOL timecodeIsDropFrame, [out] BMDDeckControlError* error); + HRESULT Close ([in] BOOL standbyOn); + HRESULT GetCurrentState ([out] BMDDeckControlMode* mode, [out] BMDDeckControlVTRControlState* vtrControlState, [out] BMDDeckControlStatusFlags* flags); + HRESULT SetStandby ([in] BOOL standbyOn); + HRESULT SendCommand ([in] unsigned char* inBuffer, [in] unsigned int inBufferSize, [out] unsigned char* outBuffer, [out] unsigned int* outDataSize, [in] unsigned int outBufferSize, [out] BMDDeckControlError* error); + HRESULT Play ([out] BMDDeckControlError* error); + HRESULT Stop ([out] BMDDeckControlError* error); + HRESULT TogglePlayStop ([out] BMDDeckControlError* error); + HRESULT Eject ([out] BMDDeckControlError* error); + HRESULT GoToTimecode ([in] BMDTimecodeBCD timecode, [out] BMDDeckControlError* error); + HRESULT FastForward ([in] BOOL viewTape, [out] BMDDeckControlError* error); + HRESULT Rewind ([in] BOOL viewTape, [out] BMDDeckControlError* error); + HRESULT StepForward ([out] BMDDeckControlError* error); + HRESULT StepBack ([out] BMDDeckControlError* error); + HRESULT Jog ([in] double rate, [out] BMDDeckControlError* error); + HRESULT Shuttle ([in] double rate, [out] BMDDeckControlError* error); + HRESULT GetTimecodeString ([out] BSTR* currentTimeCode, [out] BMDDeckControlError* error); + HRESULT GetTimecode ([out] IDeckLinkTimecode** currentTimecode, [out] BMDDeckControlError* error); + HRESULT GetTimecodeBCD ([out] BMDTimecodeBCD* currentTimecode, [out] BMDDeckControlError* error); + HRESULT SetPreroll ([in] unsigned int prerollSeconds); + HRESULT GetPreroll ([out] unsigned int* prerollSeconds); + HRESULT SetExportOffset ([in] int exportOffsetFields); + HRESULT GetExportOffset ([out] int* exportOffsetFields); + HRESULT GetManualExportOffset ([out] int* deckManualExportOffsetFields); + HRESULT SetCaptureOffset ([in] int captureOffsetFields); + HRESULT GetCaptureOffset ([out] int* captureOffsetFields); + HRESULT StartExport ([in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [in] BMDDeckControlExportModeOpsFlags exportModeOps, [out] BMDDeckControlError* error); + HRESULT StartCapture ([in] BOOL useVITC, [in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [out] BMDDeckControlError* error); + HRESULT GetDeviceID ([out] unsigned short* deviceId, [out] BMDDeckControlError* error); + HRESULT Abort (void); + HRESULT CrashRecordStart ([out] BMDDeckControlError* error); + HRESULT CrashRecordStop ([out] BMDDeckControlError* error); + HRESULT SetCallback ([in] IDeckLinkDeckControlStatusCallback* callback); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDiscovery.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDiscovery.idl new file mode 100644 index 0000000000..4ba8ae1817 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIDiscovery.idl @@ -0,0 +1,63 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +// Type Declarations + + +// Enumeration Mapping + +cpp_quote("#if 0") +cpp_quote("#endif") + +// Forward Declarations + +interface IDeckLink; + +/* Interface IDeckLink - Represents a DeckLink device */ + +[ + object, + uuid(C418FBDD-0587-48ED-8FE5-640F0A14AF91), + helpstring("Represents a DeckLink device") +] interface IDeckLink : IUnknown +{ + HRESULT GetModelName ([out] BSTR* modelName); + HRESULT GetDisplayName ([out] BSTR* displayName); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIModes.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIModes.idl new file mode 100644 index 0000000000..46b0fa21ff --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIModes.idl @@ -0,0 +1,270 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +// Type Declarations + + +// Enumeration Mapping + +cpp_quote("typedef unsigned int BMDDisplayModeFlags;") +cpp_quote("#if 0") +typedef enum _BMDDisplayModeFlags BMDDisplayModeFlags; +cpp_quote("#endif") + +/* Enum BMDDisplayMode - BMDDisplayMode enumerates the video modes supported. */ + +typedef [v1_enum] enum _BMDDisplayMode { + + /* SD Modes */ + + bmdModeNTSC = /* 'ntsc' */ 0x6E747363, + bmdModeNTSC2398 = /* 'nt23' */ 0x6E743233, // 3:2 pulldown + bmdModePAL = /* 'pal ' */ 0x70616C20, + bmdModeNTSCp = /* 'ntsp' */ 0x6E747370, + bmdModePALp = /* 'palp' */ 0x70616C70, + + /* HD 1080 Modes */ + + bmdModeHD1080p2398 = /* '23ps' */ 0x32337073, + bmdModeHD1080p24 = /* '24ps' */ 0x32347073, + bmdModeHD1080p25 = /* 'Hp25' */ 0x48703235, + bmdModeHD1080p2997 = /* 'Hp29' */ 0x48703239, + bmdModeHD1080p30 = /* 'Hp30' */ 0x48703330, + bmdModeHD1080p4795 = /* 'Hp47' */ 0x48703437, + bmdModeHD1080p48 = /* 'Hp48' */ 0x48703438, + bmdModeHD1080p50 = /* 'Hp50' */ 0x48703530, + bmdModeHD1080p5994 = /* 'Hp59' */ 0x48703539, + bmdModeHD1080p6000 = /* 'Hp60' */ 0x48703630, // N.B. This _really_ is 60.00 Hz. + bmdModeHD1080p9590 = /* 'Hp95' */ 0x48703935, + bmdModeHD1080p96 = /* 'Hp96' */ 0x48703936, + bmdModeHD1080p100 = /* 'Hp10' */ 0x48703130, + bmdModeHD1080p11988 = /* 'Hp11' */ 0x48703131, + bmdModeHD1080p120 = /* 'Hp12' */ 0x48703132, + bmdModeHD1080i50 = /* 'Hi50' */ 0x48693530, + bmdModeHD1080i5994 = /* 'Hi59' */ 0x48693539, + bmdModeHD1080i6000 = /* 'Hi60' */ 0x48693630, // N.B. This _really_ is 60.00 Hz. + + /* HD 720 Modes */ + + bmdModeHD720p50 = /* 'hp50' */ 0x68703530, + bmdModeHD720p5994 = /* 'hp59' */ 0x68703539, + bmdModeHD720p60 = /* 'hp60' */ 0x68703630, + + /* 2K Modes */ + + bmdMode2k2398 = /* '2k23' */ 0x326B3233, + bmdMode2k24 = /* '2k24' */ 0x326B3234, + bmdMode2k25 = /* '2k25' */ 0x326B3235, + + /* 2K DCI Modes */ + + bmdMode2kDCI2398 = /* '2d23' */ 0x32643233, + bmdMode2kDCI24 = /* '2d24' */ 0x32643234, + bmdMode2kDCI25 = /* '2d25' */ 0x32643235, + bmdMode2kDCI2997 = /* '2d29' */ 0x32643239, + bmdMode2kDCI30 = /* '2d30' */ 0x32643330, + bmdMode2kDCI4795 = /* '2d47' */ 0x32643437, + bmdMode2kDCI48 = /* '2d48' */ 0x32643438, + bmdMode2kDCI50 = /* '2d50' */ 0x32643530, + bmdMode2kDCI5994 = /* '2d59' */ 0x32643539, + bmdMode2kDCI60 = /* '2d60' */ 0x32643630, + bmdMode2kDCI9590 = /* '2d95' */ 0x32643935, + bmdMode2kDCI96 = /* '2d96' */ 0x32643936, + bmdMode2kDCI100 = /* '2d10' */ 0x32643130, + bmdMode2kDCI11988 = /* '2d11' */ 0x32643131, + bmdMode2kDCI120 = /* '2d12' */ 0x32643132, + + /* 4K UHD Modes */ + + bmdMode4K2160p2398 = /* '4k23' */ 0x346B3233, + bmdMode4K2160p24 = /* '4k24' */ 0x346B3234, + bmdMode4K2160p25 = /* '4k25' */ 0x346B3235, + bmdMode4K2160p2997 = /* '4k29' */ 0x346B3239, + bmdMode4K2160p30 = /* '4k30' */ 0x346B3330, + bmdMode4K2160p4795 = /* '4k47' */ 0x346B3437, + bmdMode4K2160p48 = /* '4k48' */ 0x346B3438, + bmdMode4K2160p50 = /* '4k50' */ 0x346B3530, + bmdMode4K2160p5994 = /* '4k59' */ 0x346B3539, + bmdMode4K2160p60 = /* '4k60' */ 0x346B3630, + bmdMode4K2160p9590 = /* '4k95' */ 0x346B3935, + bmdMode4K2160p96 = /* '4k96' */ 0x346B3936, + bmdMode4K2160p100 = /* '4k10' */ 0x346B3130, + bmdMode4K2160p11988 = /* '4k11' */ 0x346B3131, + bmdMode4K2160p120 = /* '4k12' */ 0x346B3132, + + /* 4K DCI Modes */ + + bmdMode4kDCI2398 = /* '4d23' */ 0x34643233, + bmdMode4kDCI24 = /* '4d24' */ 0x34643234, + bmdMode4kDCI25 = /* '4d25' */ 0x34643235, + bmdMode4kDCI2997 = /* '4d29' */ 0x34643239, + bmdMode4kDCI30 = /* '4d30' */ 0x34643330, + bmdMode4kDCI4795 = /* '4d47' */ 0x34643437, + bmdMode4kDCI48 = /* '4d48' */ 0x34643438, + bmdMode4kDCI50 = /* '4d50' */ 0x34643530, + bmdMode4kDCI5994 = /* '4d59' */ 0x34643539, + bmdMode4kDCI60 = /* '4d60' */ 0x34643630, + bmdMode4kDCI9590 = /* '4d95' */ 0x34643935, + bmdMode4kDCI96 = /* '4d96' */ 0x34643936, + bmdMode4kDCI100 = /* '4d10' */ 0x34643130, + bmdMode4kDCI11988 = /* '4d11' */ 0x34643131, + bmdMode4kDCI120 = /* '4d12' */ 0x34643132, + + /* 8K UHD Modes */ + + bmdMode8K4320p2398 = /* '8k23' */ 0x386B3233, + bmdMode8K4320p24 = /* '8k24' */ 0x386B3234, + bmdMode8K4320p25 = /* '8k25' */ 0x386B3235, + bmdMode8K4320p2997 = /* '8k29' */ 0x386B3239, + bmdMode8K4320p30 = /* '8k30' */ 0x386B3330, + bmdMode8K4320p4795 = /* '8k47' */ 0x386B3437, + bmdMode8K4320p48 = /* '8k48' */ 0x386B3438, + bmdMode8K4320p50 = /* '8k50' */ 0x386B3530, + bmdMode8K4320p5994 = /* '8k59' */ 0x386B3539, + bmdMode8K4320p60 = /* '8k60' */ 0x386B3630, + + /* 8K DCI Modes */ + + bmdMode8kDCI2398 = /* '8d23' */ 0x38643233, + bmdMode8kDCI24 = /* '8d24' */ 0x38643234, + bmdMode8kDCI25 = /* '8d25' */ 0x38643235, + bmdMode8kDCI2997 = /* '8d29' */ 0x38643239, + bmdMode8kDCI30 = /* '8d30' */ 0x38643330, + bmdMode8kDCI4795 = /* '8d47' */ 0x38643437, + bmdMode8kDCI48 = /* '8d48' */ 0x38643438, + bmdMode8kDCI50 = /* '8d50' */ 0x38643530, + bmdMode8kDCI5994 = /* '8d59' */ 0x38643539, + bmdMode8kDCI60 = /* '8d60' */ 0x38643630, + + /* PC Modes */ + + bmdMode640x480p60 = /* 'vga6' */ 0x76676136, + bmdMode800x600p60 = /* 'svg6' */ 0x73766736, + bmdMode1440x900p50 = /* 'wxg5' */ 0x77786735, + bmdMode1440x900p60 = /* 'wxg6' */ 0x77786736, + bmdMode1440x1080p50 = /* 'sxg5' */ 0x73786735, + bmdMode1440x1080p60 = /* 'sxg6' */ 0x73786736, + bmdMode1600x1200p50 = /* 'uxg5' */ 0x75786735, + bmdMode1600x1200p60 = /* 'uxg6' */ 0x75786736, + bmdMode1920x1200p50 = /* 'wux5' */ 0x77757835, + bmdMode1920x1200p60 = /* 'wux6' */ 0x77757836, + bmdMode1920x1440p50 = /* '1945' */ 0x31393435, + bmdMode1920x1440p60 = /* '1946' */ 0x31393436, + bmdMode2560x1440p50 = /* 'wqh5' */ 0x77716835, + bmdMode2560x1440p60 = /* 'wqh6' */ 0x77716836, + bmdMode2560x1600p50 = /* 'wqx5' */ 0x77717835, + bmdMode2560x1600p60 = /* 'wqx6' */ 0x77717836, + + /* Special Modes */ + + bmdModeUnknown = /* 'iunk' */ 0x69756E6B +} BMDDisplayMode; + +/* Enum BMDFieldDominance - BMDFieldDominance enumerates settings applicable to video fields. */ + +typedef [v1_enum] enum _BMDFieldDominance { + bmdUnknownFieldDominance = 0, + bmdLowerFieldFirst = /* 'lowr' */ 0x6C6F7772, + bmdUpperFieldFirst = /* 'uppr' */ 0x75707072, + bmdProgressiveFrame = /* 'prog' */ 0x70726F67, + bmdProgressiveSegmentedFrame = /* 'psf ' */ 0x70736620 +} BMDFieldDominance; + +/* Enum BMDPixelFormat - Video pixel formats supported for output/input */ + +typedef [v1_enum] enum _BMDPixelFormat { + bmdFormatUnspecified = 0, + bmdFormat8BitYUV = /* '2vuy' */ 0x32767579, + bmdFormat10BitYUV = /* 'v210' */ 0x76323130, + bmdFormat8BitARGB = 32, + bmdFormat8BitBGRA = /* 'BGRA' */ 0x42475241, + bmdFormat10BitRGB = /* 'r210' */ 0x72323130, // Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10 + bmdFormat12BitRGB = /* 'R12B' */ 0x52313242, // Big-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component + bmdFormat12BitRGBLE = /* 'R12L' */ 0x5231324C, // Little-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component + bmdFormat10BitRGBXLE = /* 'R10l' */ 0x5231306C, // Little-endian 10-bit RGB with SMPTE video levels (64-940) + bmdFormat10BitRGBX = /* 'R10b' */ 0x52313062, // Big-endian 10-bit RGB with SMPTE video levels (64-940) + bmdFormatH265 = /* 'hev1' */ 0x68657631, // High Efficiency Video Coding (HEVC/h.265) + + /* AVID DNxHR */ + + bmdFormatDNxHR = /* 'AVdh' */ 0x41566468 +} BMDPixelFormat; + +/* Enum BMDDisplayModeFlags - Flags to describe the characteristics of an IDeckLinkDisplayMode. */ + +[v1_enum] enum _BMDDisplayModeFlags { + bmdDisplayModeSupports3D = 1 << 0, + bmdDisplayModeColorspaceRec601 = 1 << 1, + bmdDisplayModeColorspaceRec709 = 1 << 2, + bmdDisplayModeColorspaceRec2020 = 1 << 3 +}; + +// Forward Declarations + +interface IDeckLinkDisplayModeIterator; +interface IDeckLinkDisplayMode; + +/* Interface IDeckLinkDisplayModeIterator - Enumerates over supported input/output display modes. */ + +[ + object, + uuid(9C88499F-F601-4021-B80B-032E4EB41C35), + helpstring("Enumerates over supported input/output display modes.") +] interface IDeckLinkDisplayModeIterator : IUnknown +{ + HRESULT Next ([out] IDeckLinkDisplayMode** deckLinkDisplayMode); +}; + +/* Interface IDeckLinkDisplayMode - Represents a display mode */ + +[ + object, + uuid(3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78), + helpstring("Represents a display mode") +] interface IDeckLinkDisplayMode : IUnknown +{ + HRESULT GetName ([out] BSTR* name); + BMDDisplayMode GetDisplayMode (void); + long GetWidth (void); + long GetHeight (void); + HRESULT GetFrameRate ([out] BMDTimeValue* frameDuration, [out] BMDTimeScale* timeScale); + BMDFieldDominance GetFieldDominance (void); + BMDDisplayModeFlags GetFlags (void); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming.idl new file mode 100644 index 0000000000..066ce17750 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming.idl @@ -0,0 +1,362 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +// Type Declarations + + +// Enumeration Mapping + +cpp_quote("#if 0") +cpp_quote("#endif") + +/* Enum BMDStreamingDeviceMode - Device modes */ + +typedef [v1_enum] enum _BMDStreamingDeviceMode { + bmdStreamingDeviceIdle = /* 'idle' */ 0x69646C65, + bmdStreamingDeviceEncoding = /* 'enco' */ 0x656E636F, + bmdStreamingDeviceStopping = /* 'stop' */ 0x73746F70, + bmdStreamingDeviceUnknown = /* 'munk' */ 0x6D756E6B +} BMDStreamingDeviceMode; + +/* Enum BMDStreamingEncodingFrameRate - Encoded frame rates */ + +typedef [v1_enum] enum _BMDStreamingEncodingFrameRate { + + /* Interlaced rates */ + + bmdStreamingEncodedFrameRate50i = /* 'e50i' */ 0x65353069, + bmdStreamingEncodedFrameRate5994i = /* 'e59i' */ 0x65353969, + bmdStreamingEncodedFrameRate60i = /* 'e60i' */ 0x65363069, + + /* Progressive rates */ + + bmdStreamingEncodedFrameRate2398p = /* 'e23p' */ 0x65323370, + bmdStreamingEncodedFrameRate24p = /* 'e24p' */ 0x65323470, + bmdStreamingEncodedFrameRate25p = /* 'e25p' */ 0x65323570, + bmdStreamingEncodedFrameRate2997p = /* 'e29p' */ 0x65323970, + bmdStreamingEncodedFrameRate30p = /* 'e30p' */ 0x65333070, + bmdStreamingEncodedFrameRate50p = /* 'e50p' */ 0x65353070, + bmdStreamingEncodedFrameRate5994p = /* 'e59p' */ 0x65353970, + bmdStreamingEncodedFrameRate60p = /* 'e60p' */ 0x65363070 +} BMDStreamingEncodingFrameRate; + +/* Enum BMDStreamingEncodingSupport - Output encoding mode supported flag */ + +typedef [v1_enum] enum _BMDStreamingEncodingSupport { + bmdStreamingEncodingModeNotSupported = 0, + bmdStreamingEncodingModeSupported, + bmdStreamingEncodingModeSupportedWithChanges +} BMDStreamingEncodingSupport; + +/* Enum BMDStreamingVideoCodec - Video codecs */ + +typedef [v1_enum] enum _BMDStreamingVideoCodec { + bmdStreamingVideoCodecH264 = /* 'H264' */ 0x48323634 +} BMDStreamingVideoCodec; + +/* Enum BMDStreamingH264Profile - H264 encoding profile */ + +typedef [v1_enum] enum _BMDStreamingH264Profile { + bmdStreamingH264ProfileHigh = /* 'high' */ 0x68696768, + bmdStreamingH264ProfileMain = /* 'main' */ 0x6D61696E, + bmdStreamingH264ProfileBaseline = /* 'base' */ 0x62617365 +} BMDStreamingH264Profile; + +/* Enum BMDStreamingH264Level - H264 encoding level */ + +typedef [v1_enum] enum _BMDStreamingH264Level { + bmdStreamingH264Level12 = /* 'lv12' */ 0x6C763132, + bmdStreamingH264Level13 = /* 'lv13' */ 0x6C763133, + bmdStreamingH264Level2 = /* 'lv2 ' */ 0x6C763220, + bmdStreamingH264Level21 = /* 'lv21' */ 0x6C763231, + bmdStreamingH264Level22 = /* 'lv22' */ 0x6C763232, + bmdStreamingH264Level3 = /* 'lv3 ' */ 0x6C763320, + bmdStreamingH264Level31 = /* 'lv31' */ 0x6C763331, + bmdStreamingH264Level32 = /* 'lv32' */ 0x6C763332, + bmdStreamingH264Level4 = /* 'lv4 ' */ 0x6C763420, + bmdStreamingH264Level41 = /* 'lv41' */ 0x6C763431, + bmdStreamingH264Level42 = /* 'lv42' */ 0x6C763432 +} BMDStreamingH264Level; + +/* Enum BMDStreamingH264EntropyCoding - H264 entropy coding */ + +typedef [v1_enum] enum _BMDStreamingH264EntropyCoding { + bmdStreamingH264EntropyCodingCAVLC = /* 'EVLC' */ 0x45564C43, + bmdStreamingH264EntropyCodingCABAC = /* 'EBAC' */ 0x45424143 +} BMDStreamingH264EntropyCoding; + +/* Enum BMDStreamingAudioCodec - Audio codecs */ + +typedef [v1_enum] enum _BMDStreamingAudioCodec { + bmdStreamingAudioCodecAAC = /* 'AAC ' */ 0x41414320 +} BMDStreamingAudioCodec; + +/* Enum BMDStreamingEncodingModePropertyID - Encoding mode properties */ + +typedef [v1_enum] enum _BMDStreamingEncodingModePropertyID { + + /* Integers, Video Properties */ + + bmdStreamingEncodingPropertyVideoFrameRate = /* 'vfrt' */ 0x76667274, // Uses values of type BMDStreamingEncodingFrameRate + bmdStreamingEncodingPropertyVideoBitRateKbps = /* 'vbrt' */ 0x76627274, + + /* Integers, H264 Properties */ + + bmdStreamingEncodingPropertyH264Profile = /* 'hprf' */ 0x68707266, + bmdStreamingEncodingPropertyH264Level = /* 'hlvl' */ 0x686C766C, + bmdStreamingEncodingPropertyH264EntropyCoding = /* 'hent' */ 0x68656E74, + + /* Flags, H264 Properties */ + + bmdStreamingEncodingPropertyH264HasBFrames = /* 'hBfr' */ 0x68426672, + + /* Integers, Audio Properties */ + + bmdStreamingEncodingPropertyAudioCodec = /* 'acdc' */ 0x61636463, + bmdStreamingEncodingPropertyAudioSampleRate = /* 'asrt' */ 0x61737274, + bmdStreamingEncodingPropertyAudioChannelCount = /* 'achc' */ 0x61636863, + bmdStreamingEncodingPropertyAudioBitRateKbps = /* 'abrt' */ 0x61627274 +} BMDStreamingEncodingModePropertyID; + +// Forward Declarations + +interface IBMDStreamingDeviceNotificationCallback; +interface IBMDStreamingH264InputCallback; +interface IBMDStreamingDiscovery; +interface IBMDStreamingVideoEncodingMode; +interface IBMDStreamingMutableVideoEncodingMode; +interface IBMDStreamingVideoEncodingModePresetIterator; +interface IBMDStreamingDeviceInput; +interface IBMDStreamingH264NALPacket; +interface IBMDStreamingAudioPacket; +interface IBMDStreamingMPEG2TSPacket; +interface IBMDStreamingH264NALParser; + +/* Interface IBMDStreamingDeviceNotificationCallback - Device notification callbacks. */ + +[ + object, + uuid(F9531D64-3305-4B29-A387-7F74BB0D0E84), + helpstring("Device notification callbacks.") +] interface IBMDStreamingDeviceNotificationCallback : IUnknown +{ + HRESULT StreamingDeviceArrived ([in] IDeckLink* device); + HRESULT StreamingDeviceRemoved ([in] IDeckLink* device); + HRESULT StreamingDeviceModeChanged ([in] IDeckLink* device, [in] BMDStreamingDeviceMode mode); +}; + +/* Interface IBMDStreamingH264InputCallback - H264 input callbacks. */ + +[ + object, + uuid(823C475F-55AE-46F9-890C-537CC5CEDCCA), + helpstring("H264 input callbacks.") +] interface IBMDStreamingH264InputCallback : IUnknown +{ + HRESULT H264NALPacketArrived ([in] IBMDStreamingH264NALPacket* nalPacket); + HRESULT H264AudioPacketArrived ([in] IBMDStreamingAudioPacket* audioPacket); + HRESULT MPEG2TSPacketArrived ([in] IBMDStreamingMPEG2TSPacket* tsPacket); + HRESULT H264VideoInputConnectorScanningChanged (void); + HRESULT H264VideoInputConnectorChanged (void); + HRESULT H264VideoInputModeChanged (void); +}; + +/* Interface IBMDStreamingDiscovery - Installs device notifications */ + +[ + object, + uuid(2C837444-F989-4D87-901A-47C8A36D096D), + helpstring("Installs device notifications") +] interface IBMDStreamingDiscovery : IUnknown +{ + HRESULT InstallDeviceNotifications ([in] IBMDStreamingDeviceNotificationCallback* theCallback); + HRESULT UninstallDeviceNotifications (void); +}; + +/* Interface IBMDStreamingVideoEncodingMode - Represents an encoded video mode. */ + +[ + object, + uuid(1AB8035B-CD13-458D-B6DF-5E8F7C2141D9), + helpstring("Represents an encoded video mode.") +] interface IBMDStreamingVideoEncodingMode : IUnknown +{ + HRESULT GetName ([out] BSTR* name); + unsigned int GetPresetID (void); + unsigned int GetSourcePositionX (void); + unsigned int GetSourcePositionY (void); + unsigned int GetSourceWidth (void); + unsigned int GetSourceHeight (void); + unsigned int GetDestWidth (void); + unsigned int GetDestHeight (void); + HRESULT GetFlag ([in] BMDStreamingEncodingModePropertyID cfgID, [out] BOOL* value); + HRESULT GetInt ([in] BMDStreamingEncodingModePropertyID cfgID, [out] LONGLONG* value); + HRESULT GetFloat ([in] BMDStreamingEncodingModePropertyID cfgID, [out] double* value); + HRESULT GetString ([in] BMDStreamingEncodingModePropertyID cfgID, [out] BSTR* value); + HRESULT CreateMutableVideoEncodingMode ([out] IBMDStreamingMutableVideoEncodingMode** newEncodingMode); // Creates a mutable copy of the encoding mode +}; + +/* Interface IBMDStreamingMutableVideoEncodingMode - Represents a mutable encoded video mode. */ + +[ + object, + uuid(19BF7D90-1E0A-400D-B2C6-FFC4E78AD49D), + helpstring("Represents a mutable encoded video mode.") +] interface IBMDStreamingMutableVideoEncodingMode : IBMDStreamingVideoEncodingMode +{ + HRESULT SetSourceRect ([in] unsigned int posX, [in] unsigned int posY, [in] unsigned int width, [in] unsigned int height); + HRESULT SetDestSize ([in] unsigned int width, [in] unsigned int height); + HRESULT SetFlag ([in] BMDStreamingEncodingModePropertyID cfgID, [in] BOOL value); + HRESULT SetInt ([in] BMDStreamingEncodingModePropertyID cfgID, [in] LONGLONG value); + HRESULT SetFloat ([in] BMDStreamingEncodingModePropertyID cfgID, [in] double value); + HRESULT SetString ([in] BMDStreamingEncodingModePropertyID cfgID, [in] BSTR value); +}; + +/* Interface IBMDStreamingVideoEncodingModePresetIterator - Enumerates encoding mode presets */ + +[ + object, + uuid(7AC731A3-C950-4AD0-804A-8377AA51C6C4), + helpstring("Enumerates encoding mode presets") +] interface IBMDStreamingVideoEncodingModePresetIterator : IUnknown +{ + HRESULT Next ([out] IBMDStreamingVideoEncodingMode** videoEncodingMode); +}; + +/* Interface IBMDStreamingDeviceInput - Created by QueryInterface from IDeckLink */ + +[ + object, + uuid(24B6B6EC-1727-44BB-9818-34FF086ACF98), + helpstring("Created by QueryInterface from IDeckLink") +] interface IBMDStreamingDeviceInput : IUnknown +{ + + /* Input modes */ + + HRESULT DoesSupportVideoInputMode ([in] BMDDisplayMode inputMode, [out] BOOL* result); + HRESULT GetVideoInputModeIterator ([out] IDeckLinkDisplayModeIterator** iterator); + HRESULT SetVideoInputMode ([in] BMDDisplayMode inputMode); + HRESULT GetCurrentDetectedVideoInputMode ([out] BMDDisplayMode* detectedMode); + + /* Capture modes */ + + HRESULT GetVideoEncodingMode ([out] IBMDStreamingVideoEncodingMode** encodingMode); + HRESULT GetVideoEncodingModePresetIterator ([in] BMDDisplayMode inputMode, [out] IBMDStreamingVideoEncodingModePresetIterator** iterator); + HRESULT DoesSupportVideoEncodingMode ([in] BMDDisplayMode inputMode, [in] IBMDStreamingVideoEncodingMode* encodingMode, [out] BMDStreamingEncodingSupport* result, [out] IBMDStreamingVideoEncodingMode** changedEncodingMode); + HRESULT SetVideoEncodingMode ([in] IBMDStreamingVideoEncodingMode* encodingMode); + + /* Input control */ + + HRESULT StartCapture (void); + HRESULT StopCapture (void); + HRESULT SetCallback ([in] IUnknown* theCallback); +}; + +/* Interface IBMDStreamingH264NALPacket - Represent an H.264 NAL packet */ + +[ + object, + uuid(E260E955-14BE-4395-9775-9F02CC0A9D89), + helpstring("Represent an H.264 NAL packet") +] interface IBMDStreamingH264NALPacket : IUnknown +{ + long GetPayloadSize (void); + HRESULT GetBytes ([out] void** buffer); + HRESULT GetBytesWithSizePrefix ([out] void** buffer); // Contains a 32-bit unsigned big endian size prefix + HRESULT GetDisplayTime ([in] ULONGLONG requestedTimeScale, [out] ULONGLONG* displayTime); + HRESULT GetPacketIndex ([out] unsigned int* packetIndex); // Deprecated +}; + +/* Interface IBMDStreamingAudioPacket - Represents a chunk of audio data */ + +[ + object, + uuid(D9EB5902-1AD2-43F4-9E2C-3CFA50B5EE19), + helpstring("Represents a chunk of audio data") +] interface IBMDStreamingAudioPacket : IUnknown +{ + BMDStreamingAudioCodec GetCodec (void); + long GetPayloadSize (void); + HRESULT GetBytes ([out] void** buffer); + HRESULT GetPlayTime ([in] ULONGLONG requestedTimeScale, [out] ULONGLONG* playTime); + HRESULT GetPacketIndex ([out] unsigned int* packetIndex); // Deprecated +}; + +/* Interface IBMDStreamingMPEG2TSPacket - Represent an MPEG2 Transport Stream packet */ + +[ + object, + uuid(91810D1C-4FB3-4AAA-AE56-FA301D3DFA4C), + helpstring("Represent an MPEG2 Transport Stream packet") +] interface IBMDStreamingMPEG2TSPacket : IUnknown +{ + long GetPayloadSize (void); + HRESULT GetBytes ([out] void** buffer); +}; + +/* Interface IBMDStreamingH264NALParser - For basic NAL parsing */ + +[ + object, + uuid(5867F18C-5BFA-4CCC-B2A7-9DFD140417D2), + helpstring("For basic NAL parsing") +] interface IBMDStreamingH264NALParser : IUnknown +{ + HRESULT IsNALSequenceParameterSet ([in] IBMDStreamingH264NALPacket* nal); + HRESULT IsNALPictureParameterSet ([in] IBMDStreamingH264NALPacket* nal); + HRESULT GetProfileAndLevelFromSPS ([in] IBMDStreamingH264NALPacket* nal, [out] unsigned int* profileIdc, [out] unsigned int* profileCompatability, [out] unsigned int* levelIdc); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); + +[ + uuid(23A4EDF5-A0E5-432C-94EF-3BABB5F81C82), + helpstring("CBMDStreamingDiscovery Class") +] coclass CBMDStreamingDiscovery +{ + [default] interface IBMDStreamingDiscovery; +}; + +[ + uuid(7753EFBD-951C-407C-97A5-23C737B73B52), + helpstring("CBMDStreamingH264NALParser Class") +] coclass CBMDStreamingH264NALParser +{ + [default] interface IBMDStreamingH264NALParser; +}; + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming_v10_8.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming_v10_8.idl new file mode 100644 index 0000000000..1a63027081 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIStreaming_v10_8.idl @@ -0,0 +1,53 @@ +/* -LICENSE-START- +** Copyright (c) 2016 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + + + +/* Coclasses */ + +importlib("stdole2.tlb"); + +[ + uuid(0CAA31F6-8A26-40B0-86A4-BF58DCCA710C), + helpstring("CBMDStreamingDiscovery Class") +] coclass CBMDStreamingDiscovery_v10_8 +{ + [default] interface IBMDStreamingDiscovery; +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPITypes.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPITypes.idl new file mode 100644 index 0000000000..d0a05313b7 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPITypes.idl @@ -0,0 +1,114 @@ +/* -LICENSE-START- +** Copyright (c) 2022 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation covered by +** this license (the "Software") to use, reproduce, display, distribute, +** execute, and transmit the Software, and to prepare derivative works of the +** Software, and to permit third-parties to whom the Software is furnished to +** do so, all subject to the following: +** +** The copyright notices in the Software and this entire statement, including +** the above license grant, this restriction and the following disclaimer, +** must be included in all copies of the Software, in whole or in part, and +** all derivative works of the Software, unless such copies or derivative +** works are solely in the form of machine-executable object code generated by +** a source language processor. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** -LICENSE-END- +*/ + +#ifndef BMD_CONST + #if defined(_MSC_VER) + #define BMD_CONST __declspec(selectany) static const + #else + #define BMD_CONST static const + #endif +#endif + +// Type Declarations + +typedef LONGLONG BMDTimeValue; +typedef LONGLONG BMDTimeScale; +typedef unsigned int BMDTimecodeBCD; +typedef unsigned int BMDTimecodeUserBits; + +// Enumeration Mapping + +cpp_quote("typedef unsigned int BMDTimecodeFlags;") +cpp_quote("#if 0") +typedef enum _BMDTimecodeFlags BMDTimecodeFlags; +cpp_quote("#endif") + +/* Enum BMDTimecodeFlags - Timecode flags */ + +[v1_enum] enum _BMDTimecodeFlags { + bmdTimecodeFlagDefault = 0, + bmdTimecodeIsDropFrame = 1 << 0, + bmdTimecodeFieldMark = 1 << 1, + bmdTimecodeColorFrame = 1 << 2, + bmdTimecodeEmbedRecordingTrigger = 1 << 3, // On SDI recording trigger utilises a user-bit. + bmdTimecodeRecordingTriggered = 1 << 4 +}; + +/* Enum BMDVideoConnection - Video connection types */ + +typedef [v1_enum] enum _BMDVideoConnection { + bmdVideoConnectionUnspecified = 0, + bmdVideoConnectionSDI = 1 << 0, + bmdVideoConnectionHDMI = 1 << 1, + bmdVideoConnectionOpticalSDI = 1 << 2, + bmdVideoConnectionComponent = 1 << 3, + bmdVideoConnectionComposite = 1 << 4, + bmdVideoConnectionSVideo = 1 << 5 +} BMDVideoConnection; + +/* Enum BMDAudioConnection - Audio connection types */ + +typedef [v1_enum] enum _BMDAudioConnection { + bmdAudioConnectionEmbedded = 1 << 0, + bmdAudioConnectionAESEBU = 1 << 1, + bmdAudioConnectionAnalog = 1 << 2, + bmdAudioConnectionAnalogXLR = 1 << 3, + bmdAudioConnectionAnalogRCA = 1 << 4, + bmdAudioConnectionMicrophone = 1 << 5, + bmdAudioConnectionHeadphones = 1 << 6 +} BMDAudioConnection; + +/* Enum BMDDeckControlConnection - Deck control connections */ + +typedef [v1_enum] enum _BMDDeckControlConnection { + bmdDeckControlConnectionRS422Remote1 = 1 << 0, + bmdDeckControlConnectionRS422Remote2 = 1 << 1 +} BMDDeckControlConnection; + +// Forward Declarations + +interface IDeckLinkTimecode; + +/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */ + +[ + object, + uuid(BC6CFBD3-8317-4325-AC1C-1216391E9340), + helpstring("Used for video frame timecode representation.") +] interface IDeckLinkTimecode : IUnknown +{ + BMDTimecodeBCD GetBCD (void); + HRESULT GetComponents ([out] unsigned char* hours, [out] unsigned char* minutes, [out] unsigned char* seconds, [out] unsigned char* frames); + HRESULT GetString ([out] BSTR* timecode); + BMDTimecodeFlags GetFlags (void); + HRESULT GetTimecodeUserBits ([out] BMDTimecodeUserBits* userBits); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIVersion.h b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIVersion.h new file mode 100644 index 0000000000..679ef92584 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPIVersion.h @@ -0,0 +1,50 @@ +/* -LICENSE-START- + * ** Copyright (c) 2014 Blackmagic Design + * ** + * ** Permission is hereby granted, free of charge, to any person or organization + * ** obtaining a copy of the software and accompanying documentation (the + * ** "Software") to use, reproduce, display, distribute, sub-license, execute, + * ** and transmit the Software, and to prepare derivative works of the Software, + * ** and to permit third-parties to whom the Software is furnished to do so, in + * ** accordance with: + * ** + * ** (1) if the Software is obtained from Blackmagic Design, the End User License + * ** Agreement for the Software Development Kit (“EULA”) available at + * ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or + * ** + * ** (2) if the Software is obtained from any third party, such licensing terms + * ** as notified by that third party, + * ** + * ** and all subject to the following: + * ** + * ** (3) the copyright notices in the Software and this entire statement, + * ** including the above license grant, this restriction and the following + * ** disclaimer, must be included in all copies of the Software, in whole or in + * ** part, and all derivative works of the Software, unless such copies or + * ** derivative works are solely in the form of machine-executable object code + * ** generated by a source language processor. + * ** + * ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * ** DEALINGS IN THE SOFTWARE. + * ** + * ** A copy of the Software is available free of charge at + * ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. + * ** + * ** -LICENSE-END- + * */ + +/* DeckLinkAPIVersion.h */ + +#ifndef __DeckLink_API_Version_h__ +#define __DeckLink_API_Version_h__ + +#define BLACKMAGIC_DECKLINK_API_VERSION 0x0c040200 +#define BLACKMAGIC_DECKLINK_API_VERSION_STRING "12.4.2" + +#endif // __DeckLink_API_Version_h__ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_11.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_11.idl new file mode 100644 index 0000000000..8b3317ab1d --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_11.idl @@ -0,0 +1,302 @@ +/* -LICENSE-START- +** Copyright (c) 2018 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v10_11.idl */ + +// Enumeration Mapping + +/* Enum BMDDisplayModeSupport_v10_11 - Output mode supported flags */ + +typedef [v1_enum] enum _BMDDisplayModeSupport_v10_11 { + bmdDisplayModeNotSupported_v10_11 = 0, + bmdDisplayModeSupported_v10_11, + bmdDisplayModeSupportedWithConversion_v10_11 +} BMDDisplayModeSupport_v10_11; + +/* Enum BMDDuplexMode - Duplex for configurable ports */ + +typedef [v1_enum] enum _BMDDuplexMode_v10_11 { + bmdDuplexModeFull_v10_11 = /* 'fdup' */ 0x66647570, + bmdDuplexModeHalf_v10_11 = /* 'hdup' */ 0x68647570 +} BMDDuplexMode_v10_11; + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef [v1_enum] enum _BMDDeckLinkConfigurationID_v10_11 { + + /* Video Input/Output Integers */ + + bmdDeckLinkConfigDuplexMode_v10_11 = /* 'dupx' */ 0x64757078, + +} BMDDeckLinkConfigurationID_v10_11; + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef [v1_enum] enum _BMDDeckLinkAttributeID_v10_11 { + + /* Flags */ + + BMDDeckLinkSupportsDuplexModeConfiguration_v10_11 = /* 'dupx' */ 0x64757078, + BMDDeckLinkSupportsHDKeying_v10_11 = /* 'keyh' */ 0x6B657968, + + /* Integers */ + + BMDDeckLinkPairedDevicePersistentID_v10_11 = /* 'ppid' */ 0x70706964, + BMDDeckLinkSupportsFullDuplex_v10_11 = /* 'fdup' */ 0x66647570, + +} BMDDeckLinkAttributeID_v10_11; + +typedef [v1_enum] enum _BMDDeckLinkStatusID_v10_11 { + bmdDeckLinkStatusDuplexMode_v10_11 = /* 'dupx' */ 0x64757078, +} BMDDeckLinkStatusID_v10_11; + +/* Enum BMDDuplexStatus - Duplex status of the device */ + +typedef [v1_enum] enum _BMDDuplexStatus_v10_11 { + bmdDuplexFullDuplex_v10_11 = /* 'fdup' */ 0x66647570, + bmdDuplexHalfDuplex_v10_11 = /* 'hdup' */ 0x68647570, + bmdDuplexSimplex_v10_11 = /* 'splx' */ 0x73706C78, + bmdDuplexInactive_v10_11 = /* 'inac' */ 0x696E6163 +} BMDDuplexStatus_v10_11; + +// Forward Declarations + +interface IDeckLinkConfiguration_v10_11; +interface IDeckLinkAttributes_v10_11; +interface IDeckLinkNotification_v10_11; + +/* Interface IDeckLinkConfiguration_v10_11 - DeckLink Configuration interface */ + +[ + object, + uuid(EF90380B-4AE5-4346-9077-E288E149F129), + local, + helpstring("DeckLink Configuration interface") +] interface IDeckLinkConfiguration_v10_11 : IUnknown +{ + HRESULT SetFlag([in] BMDDeckLinkConfigurationID cfgID, [in] BOOL value); + HRESULT GetFlag([in] BMDDeckLinkConfigurationID cfgID, [out] BOOL *value); + HRESULT SetInt([in] BMDDeckLinkConfigurationID cfgID, [in] LONGLONG value); + HRESULT GetInt([in] BMDDeckLinkConfigurationID cfgID, [out] LONGLONG *value); + HRESULT SetFloat([in] BMDDeckLinkConfigurationID cfgID, [in] double value); + HRESULT GetFloat([in] BMDDeckLinkConfigurationID cfgID, [out] double *value); + HRESULT SetString([in] BMDDeckLinkConfigurationID cfgID, [in] BSTR value); + HRESULT GetString([in] BMDDeckLinkConfigurationID cfgID, [out] BSTR *value); + HRESULT WriteConfigurationToPreferences(void); +}; + +/* Interface IDeckLinkAttributes_v10_11 - DeckLink Attribute interface */ + +[ + object, + uuid(ABC11843-D966-44CB-96E2-A1CB5D3135C4), + local, + helpstring("DeckLink Attribute interface") +] interface IDeckLinkAttributes_v10_11 : IUnknown +{ + HRESULT GetFlag([in] BMDDeckLinkAttributeID cfgID, [out] BOOL *value); + HRESULT GetInt([in] BMDDeckLinkAttributeID cfgID, [out] LONGLONG *value); + HRESULT GetFloat([in] BMDDeckLinkAttributeID cfgID, [out] double *value); + HRESULT GetString([in] BMDDeckLinkAttributeID cfgID, [out] BSTR *value); +}; + +/* Interface IDeckLinkOutput_v10_11 - DeckLink output interface. */ + +[ + object, + uuid(CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564), + local, + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkOutput_v10_11 : IUnknown +{ + HRESULT DoesSupportVideoMode([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoOutputFlags flags, [out] BMDDisplayModeSupport_v10_11 *result, [out] IDeckLinkDisplayMode **resultDisplayMode); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback); + + /* Video Output */ + + HRESULT EnableVideoOutput([in] BMDDisplayMode displayMode, [in] BMDVideoOutputFlags flags); + HRESULT DisableVideoOutput(void); + + HRESULT SetVideoOutputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator); + HRESULT CreateVideoFrame([in] int width, [in] int height, [in] int rowBytes, [in] BMDPixelFormat pixelFormat, [in] BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame **outFrame); + HRESULT CreateAncillaryData([in] BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary **outBuffer); + + HRESULT DisplayVideoFrameSync([in] IDeckLinkVideoFrame *theFrame); + HRESULT ScheduleVideoFrame([in] IDeckLinkVideoFrame *theFrame, [in] BMDTimeValue displayTime, [in] BMDTimeValue displayDuration, [in] BMDTimeScale timeScale); + HRESULT SetScheduledFrameCompletionCallback([in] IDeckLinkVideoOutputCallback *theCallback); + HRESULT GetBufferedVideoFrameCount([out] unsigned int *bufferedFrameCount); + + /* Audio Output */ + + HRESULT EnableAudioOutput([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount, [in] BMDAudioOutputStreamType streamType); + HRESULT DisableAudioOutput(void); + + HRESULT WriteAudioSamplesSync([in] void *buffer, [in] unsigned int sampleFrameCount, [out] unsigned int *sampleFramesWritten); + + HRESULT BeginAudioPreroll(void); + HRESULT EndAudioPreroll(void); + HRESULT ScheduleAudioSamples([in] void *buffer, [in] unsigned int sampleFrameCount, [in] BMDTimeValue streamTime, [in] BMDTimeScale timeScale, [out] unsigned int *sampleFramesWritten); + + HRESULT GetBufferedAudioSampleFrameCount([out] unsigned int *bufferedSampleFrameCount); + HRESULT FlushBufferedAudioSamples(void); + + HRESULT SetAudioCallback([in] IDeckLinkAudioOutputCallback *theCallback); + + /* Output Control */ + + HRESULT StartScheduledPlayback([in] BMDTimeValue playbackStartTime, [in] BMDTimeScale timeScale, [in] double playbackSpeed); + HRESULT StopScheduledPlayback([in] BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue *actualStopTime, [in] BMDTimeScale timeScale); + HRESULT IsScheduledPlaybackRunning([out] BOOL *active); + HRESULT GetScheduledStreamTime([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *streamTime, [out] double *playbackSpeed); + HRESULT GetReferenceStatus([out] BMDReferenceStatus *referenceStatus); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame); + HRESULT GetFrameCompletionReferenceTimestamp([in] IDeckLinkVideoFrame *theFrame, [in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *frameCompletionTimestamp); +}; + +/* Interface IDeckLinkInput_v10_11 - DeckLink input interface. */ + +[ + object, + uuid(AF22762B-DFAC-4846-AA79-FA8883560995), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkInput_v10_11 : IUnknown +{ + HRESULT DoesSupportVideoMode([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags, [out] BMDDisplayModeSupport_v10_11 *result, [out] IDeckLinkDisplayMode **resultDisplayMode); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback); + + /* Video Input */ + + HRESULT EnableVideoInput([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags); + HRESULT DisableVideoInput(void); + HRESULT GetAvailableVideoFrameCount([out] unsigned int *availableFrameCount); + HRESULT SetVideoInputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator); + + /* Audio Input */ + + HRESULT EnableAudioInput([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount); + HRESULT DisableAudioInput(void); + HRESULT GetAvailableAudioSampleFrameCount([out] unsigned int *availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams(void); + HRESULT StopStreams(void); + HRESULT PauseStreams(void); + HRESULT FlushStreams(void); + HRESULT SetCallback([in] IDeckLinkInputCallback_v11_5_1 *theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame); +}; + +/* Interface IDeckLinkEncoderInput_v10_11 - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(270587DA-6B7D-42E7-A1F0-6D853F581185), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkEncoderInput_v10_11 : IUnknown +{ + HRESULT DoesSupportVideoMode([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags, [out] BMDDisplayModeSupport_v10_11 *result, [out] IDeckLinkDisplayMode **resultDisplayMode); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator **iterator); + + /* Video Input */ + + HRESULT EnableVideoInput([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags); + HRESULT DisableVideoInput(void); + HRESULT GetAvailablePacketsCount([out] unsigned int *availablePacketsCount); + HRESULT SetMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator); + + /* Audio Input */ + + HRESULT EnableAudioInput([in] BMDAudioFormat audioFormat, [in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount); + HRESULT DisableAudioInput(void); + HRESULT GetAvailableAudioSampleFrameCount([out] unsigned int *availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams(void); + HRESULT StopStreams(void); + HRESULT PauseStreams(void); + HRESULT FlushStreams(void); + HRESULT SetCallback([in] IDeckLinkEncoderInputCallback *theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame); +}; + +/* Interface IDeckLinkNotification_v10_11 - DeckLink Notification interface */ + +[ + object, + uuid(0A1FB207-E215-441B-9B19-6FA1575946C5), + local, + helpstring("DeckLink Notification interface") +] interface IDeckLinkNotification_v10_11 : IUnknown +{ + HRESULT Subscribe([in] BMDNotifications topic, [in] IDeckLinkNotificationCallback *theCallback); + HRESULT Unsubscribe([in] BMDNotifications topic, [in] IDeckLinkNotificationCallback *theCallback); +}; + +importlib("stdole2.tlb"); + +[ + uuid(87D2693F-8D4A-45C7-B43F-10ACBA25E68F), + helpstring("CDeckLinkIterator_v10_11 Class") +] coclass CDeckLinkIterator_v10_11 +{ + [default] interface IDeckLinkIterator; +}; + +[ + uuid(652615D4-26CD-4514-B161-2FD5072ED008), + helpstring("CDeckLinkDiscovery_v10_11 Class") +] coclass CDeckLinkDiscovery_v10_11 +{ + [default] interface IDeckLinkDiscovery; +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_2.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_2.idl new file mode 100644 index 0000000000..e31ff599d3 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_2.idl @@ -0,0 +1,86 @@ +/* -LICENSE-START- +** Copyright (c) 2014 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v10_2.idl */ + +// Enumeration Mapping + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef [v1_enum] enum _BMDDeckLinkConfigurationID_v10_2 { + + /* Video output flags */ + + bmdDeckLinkConfig3GBpsVideoOutput_v10_2 = /* '3gbs' */ 0x33676273 + +} BMDDeckLinkConfigurationID_v10_2; + +/* Enum BMDAudioConnection_v10_2 - Audio connection types */ + +typedef [v1_enum] enum _BMDAudioConnection_v10_2 { + bmdAudioConnectionEmbedded_v10_2 = /* 'embd' */ 0x656D6264, + bmdAudioConnectionAESEBU_v10_2 = /* 'aes ' */ 0x61657320, + bmdAudioConnectionAnalog_v10_2 = /* 'anlg' */ 0x616E6C67, + bmdAudioConnectionAnalogXLR_v10_2 = /* 'axlr' */ 0x61786C72, + bmdAudioConnectionAnalogRCA_v10_2 = /* 'arca' */ 0x61726361 +} BMDAudioConnection_v10_2; + +// Forward Declarations + +interface IDeckLinkConfiguration_v10_2; + +/* Interface IDeckLinkConfiguration_v10_2 - DeckLink Configuration interface */ + +[ + object, + uuid(C679A35B-610C-4D09-B748-1D0478100FC0), + local, + helpstring("DeckLink Configuration interface") +] interface IDeckLinkConfiguration_v10_2 : IUnknown +{ + HRESULT SetFlag([in] BMDDeckLinkConfigurationID cfgID, [in] BOOL value); + HRESULT GetFlag([in] BMDDeckLinkConfigurationID cfgID, [out] BOOL *value); + HRESULT SetInt([in] BMDDeckLinkConfigurationID cfgID, [in] LONGLONG value); + HRESULT GetInt([in] BMDDeckLinkConfigurationID cfgID, [out] LONGLONG *value); + HRESULT SetFloat([in] BMDDeckLinkConfigurationID cfgID, [in] double value); + HRESULT GetFloat([in] BMDDeckLinkConfigurationID cfgID, [out] double *value); + HRESULT SetString([in] BMDDeckLinkConfigurationID cfgID, [in] BSTR value); + HRESULT GetString([in] BMDDeckLinkConfigurationID cfgID, [out] BSTR *value); + HRESULT WriteConfigurationToPreferences(void); +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_4.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_4.idl new file mode 100644 index 0000000000..e5e47942ac --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_4.idl @@ -0,0 +1,74 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v10_4.idl */ + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef [v1_enum] enum _BMDDeckLinkConfigurationID_v10_4 { + + /* Video output flags */ + + bmdDeckLinkConfigSingleLinkVideoOutput_v10_4 = /* 'sglo' */ 0x73676C6F, + +} BMDDeckLinkConfigurationID_v10_4; + +// Forward Declarations + +interface IDeckLinkConfiguration_v10_4; + +/* Interface IDeckLinkConfiguration_v10_4 - DeckLink Configuration interface */ + +[ + object, + uuid(1E69FCF6-4203-4936-8076-2A9F4CFD50CB), + local, + helpstring("DeckLink Configuration interface") +] interface IDeckLinkConfiguration_v10_4 : IUnknown +{ + HRESULT SetFlag([in] BMDDeckLinkConfigurationID cfgID, [in] BOOL value); + HRESULT GetFlag([in] BMDDeckLinkConfigurationID cfgID, [out] BOOL *value); + HRESULT SetInt([in] BMDDeckLinkConfigurationID cfgID, [in] LONGLONG value); + HRESULT GetInt([in] BMDDeckLinkConfigurationID cfgID, [out] LONGLONG *value); + HRESULT SetFloat([in] BMDDeckLinkConfigurationID cfgID, [in] double value); + HRESULT GetFloat([in] BMDDeckLinkConfigurationID cfgID, [out] double *value); + HRESULT SetString([in] BMDDeckLinkConfigurationID cfgID, [in] BSTR value); + HRESULT GetString([in] BMDDeckLinkConfigurationID cfgID, [out] BSTR *value); + HRESULT WriteConfigurationToPreferences(void); +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_5.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_5.idl new file mode 100644 index 0000000000..f18274494e --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_5.idl @@ -0,0 +1,74 @@ +/* -LICENSE-START- +** Copyright (c) 2015 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v10_5.idl */ + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef [v1_enum] enum _BMDDeckLinkAttributeID_v10_5 { + + /* Integers */ + + BMDDeckLinkDeviceBusyState_v10_5 = /* 'dbst' */ 0x64627374, + +} BMDDeckLinkAttributeID_v10_5; + +// Forward Declarations + +interface IDeckLinkEncoderConfiguration_v10_5; + +/* Interface IDeckLinkEncoderConfiguration_v10_5 - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */ + +[ + object, + uuid(67455668-0848-45DF-8D8E-350A77C9A028), + local, + helpstring("DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput") +] interface IDeckLinkEncoderConfiguration_v10_5 : IUnknown +{ + HRESULT SetFlag([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] BOOL value); + HRESULT GetFlag([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] BOOL *value); + HRESULT SetInt([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] LONGLONG value); + HRESULT GetInt([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] LONGLONG *value); + HRESULT SetFloat([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] double value); + HRESULT GetFloat([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] double *value); + HRESULT SetString([in] BMDDeckLinkEncoderConfigurationID cfgID, [in] BSTR value); + HRESULT GetString([in] BMDDeckLinkEncoderConfigurationID cfgID, [out] BSTR *value); + HRESULT GetDecoderConfigurationInfo([out] void *buffer, [in] long bufferSize, [out] long *returnedSize); +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_6.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_6.idl new file mode 100644 index 0000000000..4993772094 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_6.idl @@ -0,0 +1,54 @@ +/* -LICENSE-START- +** Copyright (c) 2016 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v10_6.idl */ + +/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */ + +typedef [v1_enum] enum _BMDDeckLinkAttributeID_v10_6 { + + /* Flags */ + + BMDDeckLinkSupportsDesktopDisplay_v10_6 = /* 'extd' */ 0x65787464, + +} BMDDeckLinkAttributeID_v10_6; + +typedef [v1_enum] enum _BMDIdleVideoOutputOperation_v10_6 { + bmdIdleVideoOutputDesktop_v10_6 = /* 'desk' */ 0x6465736B +} BMDIdleVideoOutputOperation_v10_6; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_8.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_8.idl new file mode 100644 index 0000000000..d115625e9e --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_8.idl @@ -0,0 +1,59 @@ +/* -LICENSE-START- +** Copyright (c) 2016 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v10_8.idl */ + + +importlib("stdole2.tlb"); + +[ + uuid(1F2E109A-8F4F-49E4-9203-135595CB6FA5), + helpstring("CDeckLinkIterator_v10_8 Class") +] coclass CDeckLinkIterator_v10_8 +{ + [default] interface IDeckLinkIterator; +}; + +[ + uuid(1073A05C-D885-47E9-B3C6-129B3F9F648B), + helpstring("CDeckLinkDiscovery_v10_8 Class") +] coclass CDeckLinkDiscovery_v10_8 +{ + [default] interface IDeckLinkDiscovery; +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_9.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_9.idl new file mode 100644 index 0000000000..db75747ee3 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v10_9.idl @@ -0,0 +1,74 @@ +/* -LICENSE-START- +** Copyright (c) 2017 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v10_9.idl */ + +/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */ + +typedef [v1_enum] enum _BMDDeckLinkConfigurationID_v10_9 { + + /* Video output flags */ + + bmdDeckLinkConfig1080pNotPsF_v10_9 = /* 'fpro' */ 0x6670726F, + +} BMDDeckLinkConfigurationID_v10_9; + +// Forward Declarations + +interface IDeckLinkConfiguration_v10_9; + +/* Interface IDeckLinkConfiguration_v10_9 - DeckLink Configuration interface */ + +[ + object, + uuid(CB71734A-FE37-4E8D-8E13-802133A1C3F2), + local, + helpstring("DeckLink Configuration interface") +] interface IDeckLinkConfiguration_v10_9 : IUnknown +{ + HRESULT SetFlag([in] BMDDeckLinkConfigurationID cfgID, [in] BOOL value); + HRESULT GetFlag([in] BMDDeckLinkConfigurationID cfgID, [out] BOOL *value); + HRESULT SetInt([in] BMDDeckLinkConfigurationID cfgID, [in] LONGLONG value); + HRESULT GetInt([in] BMDDeckLinkConfigurationID cfgID, [out] LONGLONG *value); + HRESULT SetFloat([in] BMDDeckLinkConfigurationID cfgID, [in] double value); + HRESULT GetFloat([in] BMDDeckLinkConfigurationID cfgID, [out] double *value); + HRESULT SetString([in] BMDDeckLinkConfigurationID cfgID, [in] BSTR value); + HRESULT GetString([in] BMDDeckLinkConfigurationID cfgID, [out] BSTR *value); + HRESULT WriteConfigurationToPreferences(void); +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_4.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_4.idl new file mode 100644 index 0000000000..a72bfad8df --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_4.idl @@ -0,0 +1,133 @@ +/* -LICENSE-START- +** Copyright (c) 2019 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v11_4.idl */ + +// Enumeration Mapping + +/* Interface IDeckLinkOutput_v11_4 - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(065A0F6C-C508-4D0D-B919-F5EB0EBFC96B), + local, + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkOutput_v11_4 : IUnknown +{ + HRESULT DoesSupportVideoMode ([in] BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, [in] BMDDisplayMode requestedMode, [in] BMDPixelFormat requestedPixelFormat, [in] BMDSupportedVideoModeFlags flags, [out] BMDDisplayMode* actualMode, [out] BOOL* supported); + HRESULT GetDisplayMode ([in] BMDDisplayMode displayMode, [out] IDeckLinkDisplayMode** resultDisplayMode); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator** iterator); + HRESULT SetScreenPreviewCallback ([in] IDeckLinkScreenPreviewCallback* previewCallback); + + /* Video Output */ + + HRESULT EnableVideoOutput ([in] BMDDisplayMode displayMode, [in] BMDVideoOutputFlags flags); + HRESULT DisableVideoOutput (void); + HRESULT SetVideoOutputFrameMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator); + HRESULT CreateVideoFrame ([in] int width, [in] int height, [in] int rowBytes, [in] BMDPixelFormat pixelFormat, [in] BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame** outFrame); + HRESULT CreateAncillaryData ([in] BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary** outBuffer); // Use of IDeckLinkVideoFrameAncillaryPackets is preferred + HRESULT DisplayVideoFrameSync ([in] IDeckLinkVideoFrame* theFrame); + HRESULT ScheduleVideoFrame ([in] IDeckLinkVideoFrame* theFrame, [in] BMDTimeValue displayTime, [in] BMDTimeValue displayDuration, [in] BMDTimeScale timeScale); + HRESULT SetScheduledFrameCompletionCallback ([in] IDeckLinkVideoOutputCallback* theCallback); + HRESULT GetBufferedVideoFrameCount ([out] unsigned int* bufferedFrameCount); + + /* Audio Output */ + + HRESULT EnableAudioOutput ([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount, [in] BMDAudioOutputStreamType streamType); + HRESULT DisableAudioOutput (void); + HRESULT WriteAudioSamplesSync ([in] void* buffer, [in] unsigned int sampleFrameCount, [out] unsigned int* sampleFramesWritten); + HRESULT BeginAudioPreroll (void); + HRESULT EndAudioPreroll (void); + HRESULT ScheduleAudioSamples ([in] void* buffer, [in] unsigned int sampleFrameCount, [in] BMDTimeValue streamTime, [in] BMDTimeScale timeScale, [out] unsigned int* sampleFramesWritten); + HRESULT GetBufferedAudioSampleFrameCount ([out] unsigned int* bufferedSampleFrameCount); + HRESULT FlushBufferedAudioSamples (void); + HRESULT SetAudioCallback ([in] IDeckLinkAudioOutputCallback* theCallback); + + /* Output Control */ + + HRESULT StartScheduledPlayback ([in] BMDTimeValue playbackStartTime, [in] BMDTimeScale timeScale, [in] double playbackSpeed); + HRESULT StopScheduledPlayback ([in] BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue* actualStopTime, [in] BMDTimeScale timeScale); + HRESULT IsScheduledPlaybackRunning ([out] BOOL* active); + HRESULT GetScheduledStreamTime ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* streamTime, [out] double* playbackSpeed); + HRESULT GetReferenceStatus ([out] BMDReferenceStatus* referenceStatus); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* hardwareTime, [out] BMDTimeValue* timeInFrame, [out] BMDTimeValue* ticksPerFrame); + HRESULT GetFrameCompletionReferenceTimestamp ([in] IDeckLinkVideoFrame* theFrame, [in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* frameCompletionTimestamp); +}; + +/* Interface IDeckLinkInput_v11_4 - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(2A88CF76-F494-4216-A7EF-DC74EEB83882), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkInput_v11_4 : IUnknown +{ + HRESULT DoesSupportVideoMode ([in] BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, [in] BMDDisplayMode requestedMode, [in] BMDPixelFormat requestedPixelFormat, [in] BMDSupportedVideoModeFlags flags, [out] BOOL* supported); + HRESULT GetDisplayMode ([in] BMDDisplayMode displayMode, [out] IDeckLinkDisplayMode** resultDisplayMode); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator** iterator); + HRESULT SetScreenPreviewCallback ([in] IDeckLinkScreenPreviewCallback* previewCallback); + + /* Video Input */ + + HRESULT EnableVideoInput ([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags); + HRESULT DisableVideoInput (void); + HRESULT GetAvailableVideoFrameCount ([out] unsigned int* availableFrameCount); + HRESULT SetVideoInputFrameMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator); + + /* Audio Input */ + + HRESULT EnableAudioInput ([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount); + HRESULT DisableAudioInput (void); + HRESULT GetAvailableAudioSampleFrameCount ([out] unsigned int* availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams (void); + HRESULT StopStreams (void); + HRESULT PauseStreams (void); + HRESULT FlushStreams (void); + HRESULT SetCallback ([in] IDeckLinkInputCallback_v11_5_1* theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* hardwareTime, [out] BMDTimeValue* timeInFrame, [out] BMDTimeValue* ticksPerFrame); +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5.idl new file mode 100644 index 0000000000..050bb6744e --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5.idl @@ -0,0 +1,112 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v11_5.idl */ + +typedef [v1_enum] enum _BMDDeckLinkFrameMetadataID_v11_5 { + bmdDeckLinkFrameMetadataCintelFilmType_v11_5 = /* 'cfty' */ 0x63667479, // Current film type + bmdDeckLinkFrameMetadataCintelFilmGauge_v11_5 = /* 'cfga' */ 0x63666761, // Current film gauge + bmdDeckLinkFrameMetadataCintelKeykodeLow_v11_5 = /* 'ckkl' */ 0x636B6B6C, // Raw keykode value - low 64 bits + bmdDeckLinkFrameMetadataCintelKeykodeHigh_v11_5 = /* 'ckkh' */ 0x636B6B68, // Raw keykode value - high 64 bits + bmdDeckLinkFrameMetadataCintelTile1Size_v11_5 = /* 'ct1s' */ 0x63743173, // Size in bytes of compressed raw tile 1 + bmdDeckLinkFrameMetadataCintelTile2Size_v11_5 = /* 'ct2s' */ 0x63743273, // Size in bytes of compressed raw tile 2 + bmdDeckLinkFrameMetadataCintelTile3Size_v11_5 = /* 'ct3s' */ 0x63743373, // Size in bytes of compressed raw tile 3 + bmdDeckLinkFrameMetadataCintelTile4Size_v11_5 = /* 'ct4s' */ 0x63743473, // Size in bytes of compressed raw tile 4 + bmdDeckLinkFrameMetadataCintelImageWidth_v11_5 = /* 'IWPx' */ 0x49575078, // Width in pixels of image + bmdDeckLinkFrameMetadataCintelImageHeight_v11_5 = /* 'IHPx' */ 0x49485078, // Height in pixels of image + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInRed_v11_5 = /* 'mrir' */ 0x6D726972, // Red in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInRed_v11_5 = /* 'mgir' */ 0x6D676972, // Green in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInRed_v11_5 = /* 'mbir' */ 0x6D626972, // Blue in red linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInGreen_v11_5 = /* 'mrig' */ 0x6D726967, // Red in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInGreen_v11_5 = /* 'mgig' */ 0x6D676967, // Green in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInGreen_v11_5 = /* 'mbig' */ 0x6D626967, // Blue in green linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingRedInBlue_v11_5 = /* 'mrib' */ 0x6D726962, // Red in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInBlue_v11_5 = /* 'mgib' */ 0x6D676962, // Green in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInBlue_v11_5 = /* 'mbib' */ 0x6D626962, // Blue in blue linear masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInRed_v11_5 = /* 'mlrr' */ 0x6D6C7272, // Red in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInRed_v11_5 = /* 'mlgr' */ 0x6D6C6772, // Green in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInRed_v11_5 = /* 'mlbr' */ 0x6D6C6272, // Blue in red log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInGreen_v11_5 = /* 'mlrg' */ 0x6D6C7267, // Red in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInGreen_v11_5 = /* 'mlgg' */ 0x6D6C6767, // Green in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInGreen_v11_5 = /* 'mlbg' */ 0x6D6C6267, // Blue in green log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingRedInBlue_v11_5 = /* 'mlrb' */ 0x6D6C7262, // Red in blue log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingGreenInBlue_v11_5 = /* 'mlgb' */ 0x6D6C6762, // Green in blue log masking parameter + bmdDeckLinkFrameMetadataCintelLogMaskingBlueInBlue_v11_5 = /* 'mlbb' */ 0x6D6C6262, // Blue in blue log masking parameter + bmdDeckLinkFrameMetadataCintelFilmFrameRate_v11_5 = /* 'cffr' */ 0x63666672, // Film frame rate + bmdDeckLinkFrameMetadataCintelOffsetToApplyHorizontal_v11_5 = /* 'otah' */ 0x6F746168, // Horizontal offset (pixels) to be applied to image + bmdDeckLinkFrameMetadataCintelOffsetToApplyVertical_v11_5 = /* 'otav' */ 0x6F746176, // Vertical offset (pixels) to be applied to image + bmdDeckLinkFrameMetadataCintelGainRed_v11_5 = /* 'LfRd' */ 0x4C665264, // Red gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelGainGreen_v11_5 = /* 'LfGr' */ 0x4C664772, // Green gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelGainBlue_v11_5 = /* 'LfBl' */ 0x4C66426C, // Blue gain parameter to apply after log + bmdDeckLinkFrameMetadataCintelLiftRed_v11_5 = /* 'GnRd' */ 0x476E5264, // Red lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelLiftGreen_v11_5 = /* 'GnGr' */ 0x476E4772, // Green lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelLiftBlue_v11_5 = /* 'GnBl' */ 0x476E426C, // Blue lift parameter to apply after log and gain + bmdDeckLinkFrameMetadataCintelHDRGainRed_v11_5 = /* 'HGRd' */ 0x48475264, // Red gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintelHDRGainGreen_v11_5 = /* 'HGGr' */ 0x48474772, // Green gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintelHDRGainBlue_v11_5 = /* 'HGBl' */ 0x4847426C, // Blue gain parameter to apply to linear data for HDR Combination + bmdDeckLinkFrameMetadataCintel16mmCropRequired_v11_5 = /* 'c16c' */ 0x63313663, // The image should be cropped to 16mm size + bmdDeckLinkFrameMetadataCintelInversionRequired_v11_5 = /* 'cinv' */ 0x63696E76, // The image should be colour inverted + bmdDeckLinkFrameMetadataCintelFlipRequired_v11_5 = /* 'cflr' */ 0x63666C72, // The image should be flipped horizontally + bmdDeckLinkFrameMetadataCintelFocusAssistEnabled_v11_5 = /* 'cfae' */ 0x63666165, // Focus Assist is currently enabled + bmdDeckLinkFrameMetadataCintelKeykodeIsInterpolated_v11_5 = /* 'kkii' */ 0x6B6B6969 // The keykode for this frame is interpolated from nearby keykodes +} BMDDeckLinkFrameMetadataID_v11_5; + +// Forward Declarations + +interface IDeckLinkVideoFrameMetadataExtensions_v11_5; + +/* Interface IDeckLinkVideoFrameMetadataExtensions_v11_5 - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDMI HDR information */ + +[ + object, + uuid(D5973DC9-6432-46D0-8F0B-2496F8A1238F), + local, + helpstring("Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDMI HDR information") +] interface IDeckLinkVideoFrameMetadataExtensions_v11_5 : IUnknown +{ + HRESULT GetInt([in] BMDDeckLinkFrameMetadataID_v11_5 metadataID, [out] LONGLONG *value); + HRESULT GetFloat([in] BMDDeckLinkFrameMetadataID_v11_5 metadataID, [out] double *value); + HRESULT GetFlag([in] BMDDeckLinkFrameMetadataID_v11_5 metadataID, [out] BOOL* value); + HRESULT GetString([in] BMDDeckLinkFrameMetadataID_v11_5 metadataID, [out] BSTR *value); +}; + +/* Coclasses */ + +importlib("stdole2.tlb"); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5_1.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5_1.idl new file mode 100644 index 0000000000..b9f3bd6a51 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v11_5_1.idl @@ -0,0 +1,104 @@ +/* -LICENSE-START- +** Copyright (c) 2020 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v11_5_1.idl */ + +// Enumeration Mapping + +/* Enum BMDDeckLinkStatusID - DeckLink Status ID */ + +typedef [v1_enum] enum _BMDDeckLinkStatusID_v11_5_1 { + + /* Video output flags */ + + bmdDeckLinkStatusDetectedVideoInputFlags_v11_5_1 = /* 'dvif' */ 0x64766966, + +} BMDDeckLinkStatusID_v11_5_1; + +/* Interface IDeckLinkInputCallback_v11_5_1 - Frame arrival callback. */ + +[ + object, + uuid(DD04E5EC-7415-42AB-AE4A-E80C4DFC044A), + helpstring("Frame arrival callback.") +] interface IDeckLinkInputCallback_v11_5_1 : IUnknown +{ + HRESULT VideoInputFormatChanged ([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode* newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags); + HRESULT VideoInputFrameArrived ([in] IDeckLinkVideoInputFrame* videoFrame, [in] IDeckLinkAudioInputPacket* audioPacket); +}; + +/* Interface IDeckLinkInput_v11_5_1 - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(9434C6E4-B15D-4B1C-979E-661E3DDCB4B9), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkInput_v11_5_1 : IUnknown +{ + HRESULT DoesSupportVideoMode ([in] BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, [in] BMDDisplayMode requestedMode, [in] BMDPixelFormat requestedPixelFormat, [in] BMDVideoInputConversionMode conversionMode, [in] BMDSupportedVideoModeFlags flags, [out] BMDDisplayMode* actualMode, [out] BOOL* supported); + HRESULT GetDisplayMode ([in] BMDDisplayMode displayMode, [out] IDeckLinkDisplayMode** resultDisplayMode); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator** iterator); + HRESULT SetScreenPreviewCallback ([in] IDeckLinkScreenPreviewCallback* previewCallback); + + /* Video Input */ + + HRESULT EnableVideoInput ([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags); + HRESULT DisableVideoInput (void); + HRESULT GetAvailableVideoFrameCount ([out] unsigned int* availableFrameCount); + HRESULT SetVideoInputFrameMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator); + + /* Audio Input */ + + HRESULT EnableAudioInput ([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount); + HRESULT DisableAudioInput (void); + HRESULT GetAvailableAudioSampleFrameCount ([out] unsigned int* availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams (void); + HRESULT StopStreams (void); + HRESULT PauseStreams (void); + HRESULT FlushStreams (void); + HRESULT SetCallback ([in] IDeckLinkInputCallback_v11_5_1* theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock ([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue* hardwareTime, [out] BMDTimeValue* timeInFrame, [out] BMDTimeValue* ticksPerFrame); +}; + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_1.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_1.idl new file mode 100644 index 0000000000..24707bf169 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_1.idl @@ -0,0 +1,173 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v7_1.idl */ + + interface IDeckLinkDisplayModeIterator_v7_1; + interface IDeckLinkDisplayMode_v7_1; + interface IDeckLinkVideoFrame_v7_1; + interface IDeckLinkVideoInputFrame_v7_1; + interface IDeckLinkAudioInputPacket_v7_1; + + [object, uuid(B28131B6-59AC-4857-B5AC-CD75D5883E2F), + helpstring("IDeckLinkDisplayModeIterator_v7_1 enumerates over supported input/output display modes.")] + interface IDeckLinkDisplayModeIterator_v7_1 : IUnknown + { + HRESULT Next ([out] IDeckLinkDisplayMode_v7_1** deckLinkDisplayMode); + }; + + + [object, uuid(AF0CD6D5-8376-435E-8433-54F9DD530AC3), + helpstring("IDeckLinkDisplayMode_v7_1 represents a display mode")] + interface IDeckLinkDisplayMode_v7_1 : IUnknown + { + HRESULT GetName ([out] BSTR* name); + BMDDisplayMode GetDisplayMode (); + long GetWidth (); + long GetHeight (); + HRESULT GetFrameRate ([out] BMDTimeValue *frameDuration, [out] BMDTimeScale *timeScale); + }; + + [object, uuid(EBD01AFA-E4B0-49C6-A01D-EDB9D1B55FD9), + helpstring("IDeckLinkVideoOutputCallback. Frame completion callback.")] + interface IDeckLinkVideoOutputCallback_v7_1 : IUnknown + { + HRESULT ScheduledFrameCompleted ([in] IDeckLinkVideoFrame_v7_1* completedFrame, [in] BMDOutputFrameCompletionResult result); + }; + + [object, uuid(7F94F328-5ED4-4E9F-9729-76A86BDC99CC), + helpstring("IDeckLinkInputCallback_v7_1. Frame arrival callback.")] + interface IDeckLinkInputCallback_v7_1 : IUnknown + { + HRESULT VideoInputFrameArrived ([in] IDeckLinkVideoInputFrame_v7_1* videoFrame, [in] IDeckLinkAudioInputPacket_v7_1* audioPacket); + }; + + + [object, uuid(AE5B3E9B-4E1E-4535-B6E8-480FF52F6CE5), local, + helpstring("IDeckLinkOutput_v7_1. Created by QueryInterface from IDeckLink.")] + interface IDeckLinkOutput_v7_1 : IUnknown + { + HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport_v10_11 *result); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator_v7_1 **iterator); + + // Video output + HRESULT EnableVideoOutput (BMDDisplayMode displayMode); + HRESULT DisableVideoOutput (); + + HRESULT SetVideoOutputFrameMemoryAllocator ([in] IDeckLinkMemoryAllocator* theAllocator); + HRESULT CreateVideoFrame (int width, int height, int rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1** outFrame); + HRESULT CreateVideoFrameFromBuffer (void* buffer, int width, int height, int rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1** outFrame); + + HRESULT DisplayVideoFrameSync (IDeckLinkVideoFrame_v7_1* theFrame); + HRESULT ScheduleVideoFrame (IDeckLinkVideoFrame_v7_1* theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale); + HRESULT SetScheduledFrameCompletionCallback ([in] IDeckLinkVideoOutputCallback_v7_1* theCallback); + + // Audio output + HRESULT EnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned int channelCount); + HRESULT DisableAudioOutput (); + + HRESULT WriteAudioSamplesSync (void* buffer, unsigned int sampleFrameCount, [out] unsigned int *sampleFramesWritten); + + HRESULT BeginAudioPreroll (); + HRESULT EndAudioPreroll (); + HRESULT ScheduleAudioSamples (void* buffer, unsigned int sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, [out] unsigned int *sampleFramesWritten); + + HRESULT GetBufferedAudioSampleFrameCount ( [out] unsigned int *bufferedSampleCount); + HRESULT FlushBufferedAudioSamples (); + + HRESULT SetAudioCallback ( [in] IDeckLinkAudioOutputCallback* theCallback); + + // Output control + HRESULT StartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed); + HRESULT StopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, BMDTimeValue *actualStopTime, BMDTimeScale timeScale); + HRESULT GetHardwareReferenceClock (BMDTimeScale desiredTimeScale, BMDTimeValue *elapsedTimeSinceSchedulerBegan); + }; + + [object, uuid(2B54EDEF-5B32-429F-BA11-BB990596EACD), + helpstring("IDeckLinkInput_v7_1. Created by QueryInterface from IDeckLink.")] + interface IDeckLinkInput_v7_1 : IUnknown + { + HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport_v10_11 *result); + HRESULT GetDisplayModeIterator ([out] IDeckLinkDisplayModeIterator_v7_1 **iterator); + + // Video input + HRESULT EnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags); + HRESULT DisableVideoInput (); + + // Audio input + HRESULT EnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned int channelCount); + HRESULT DisableAudioInput (); + HRESULT ReadAudioSamples (void* buffer, unsigned int sampleFrameCount, [out] unsigned int *sampleFramesRead, [out] BMDTimeValue *audioPacketTime, BMDTimeScale timeScale); + HRESULT GetBufferedAudioSampleFrameCount ( [out] unsigned int *bufferedSampleCount); + + // Input control + HRESULT StartStreams (); + HRESULT StopStreams (); + HRESULT PauseStreams (); + HRESULT SetCallback ([in] IDeckLinkInputCallback_v7_1* theCallback); + }; + + [object, uuid(333F3A10-8C2D-43CF-B79D-46560FEEA1CE), local, + helpstring("IDeckLinkVideoFrame_v7_1. Created by IDeckLinkVideoOutput::CreateVideoFrame.")] + interface IDeckLinkVideoFrame_v7_1 : IUnknown + { + long GetWidth (); + long GetHeight (); + long GetRowBytes (); + BMDPixelFormat GetPixelFormat (); + BMDFrameFlags GetFlags (); + HRESULT GetBytes (void* *buffer); + }; + + [object, uuid(C8B41D95-8848-40EE-9B37-6E3417FB114B), local, + helpstring("IDeckLinkVideoInputFrame_v7_1. Provided by the IDeckLinkVideoInput frame arrival callback.")] + interface IDeckLinkVideoInputFrame_v7_1 : IDeckLinkVideoFrame_v7_1 + { + HRESULT GetFrameTime (BMDTimeValue *frameTime, BMDTimeValue *frameDuration, BMDTimeScale timeScale); + }; + + [object, uuid(C86DE4F6-A29F-42E3-AB3A-1363E29F0788), local, + helpstring("IDeckLinkAudioInputPacket_v7_1. Provided by the IDeckLinkInput callback.")] + interface IDeckLinkAudioInputPacket_v7_1 : IUnknown + { + long GetSampleCount (); + HRESULT GetBytes (void* *buffer); + HRESULT GetAudioPacketTime (BMDTimeValue *packetTime, BMDTimeScale timeScale); + }; + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_3.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_3.idl new file mode 100644 index 0000000000..3cbb0455eb --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_3.idl @@ -0,0 +1,170 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* Forward Declarations */ + +interface IDeckLinkInputCallback_v7_3; +interface IDeckLinkOutput_v7_3; +interface IDeckLinkInput_v7_3; +interface IDeckLinkVideoInputFrame_v7_3; + +/* End Forward Declarations */ + + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +[ + object, + uuid(FD6F311D-4D00-444B-9ED4-1F25B5730AD0), + helpstring("Frame arrival callback.") +] interface IDeckLinkInputCallback_v7_3 : IUnknown +{ + HRESULT VideoInputFormatChanged([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode_v7_6 *newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags); + HRESULT VideoInputFrameArrived([in] IDeckLinkVideoInputFrame_v7_3 *videoFrame, [in] IDeckLinkAudioInputPacket *audioPacket); +}; + +/* End Interface IDeckLinkInputCallback */ + + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(271C65E3-C323-4344-A30F-D908BCB20AA3), + local, + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkOutput_v7_3 : IUnknown +{ + HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport_v10_11 *result); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback); + + /* Video Output */ + + HRESULT EnableVideoOutput(BMDDisplayMode displayMode, BMDVideoOutputFlags flags); + HRESULT DisableVideoOutput(void); + + HRESULT SetVideoOutputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator); + HRESULT CreateVideoFrame(int width, int height, int rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame_v7_6 **outFrame); + HRESULT CreateAncillaryData(BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary **outBuffer); + + HRESULT DisplayVideoFrameSync([in] IDeckLinkVideoFrame_v7_6 *theFrame); + HRESULT ScheduleVideoFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale); + HRESULT SetScheduledFrameCompletionCallback([in] IDeckLinkVideoOutputCallback *theCallback); + HRESULT GetBufferedVideoFrameCount([out] unsigned int *bufferedFrameCount); + + /* Audio Output */ + + HRESULT EnableAudioOutput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned int channelCount, BMDAudioOutputStreamType streamType); + HRESULT DisableAudioOutput(void); + + HRESULT WriteAudioSamplesSync([in] void *buffer, unsigned int sampleFrameCount, [out] unsigned int *sampleFramesWritten); + + HRESULT BeginAudioPreroll(void); + HRESULT EndAudioPreroll(void); + HRESULT ScheduleAudioSamples([in] void *buffer, unsigned int sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, [out] unsigned int *sampleFramesWritten); + + HRESULT GetBufferedAudioSampleFrameCount([out] unsigned int *bufferedSampleFrameCount); + HRESULT FlushBufferedAudioSamples(void); + + HRESULT SetAudioCallback([in] IDeckLinkAudioOutputCallback *theCallback); + + /* Output Control */ + + HRESULT StartScheduledPlayback(BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed); + HRESULT StopScheduledPlayback(BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue *actualStopTime, BMDTimeScale timeScale); + HRESULT IsScheduledPlaybackRunning([out] BOOL *active); + HRESULT GetHardwareReferenceClock(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *elapsedTimeSinceSchedulerBegan); +}; + +/* End Interface IDeckLinkOutput */ + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(4973F012-9925-458C-871C-18774CDBBECB), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkInput_v7_3 : IUnknown +{ + HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport_v10_11 *result); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback); + + /* Video Input */ + + HRESULT EnableVideoInput(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags); + HRESULT DisableVideoInput(void); + HRESULT GetAvailableVideoFrameCount([out] unsigned int *availableFrameCount); + + /* Audio Input */ + + HRESULT EnableAudioInput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned int channelCount); + HRESULT DisableAudioInput(void); + HRESULT GetAvailableAudioSampleFrameCount([out] unsigned int *availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams(void); + HRESULT StopStreams(void); + HRESULT PauseStreams(void); + HRESULT FlushStreams(void); + HRESULT SetCallback([in] IDeckLinkInputCallback_v7_3 *theCallback); +}; + +/* End Interface IDeckLinkInput */ + + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +[ + object, + uuid(CF317790-2894-11DE-8C30-0800200C9A66), + local, + helpstring("Provided by the IDeckLinkVideoInput frame arrival callback.") +] interface IDeckLinkVideoInputFrame_v7_3 : IDeckLinkVideoFrame_v7_6 +{ + HRESULT GetStreamTime([out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration, BMDTimeScale timeScale); +}; + +/* End Interface IDeckLinkVideoInputFrame */ + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_6.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_6.idl new file mode 100644 index 0000000000..ddf5a74b77 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_6.idl @@ -0,0 +1,409 @@ +/* -LICENSE-START- +** Copyright (c) 2009 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* Enum BMDVideoConnection - Video connection types */ + +typedef [v1_enum] enum _BMDVideoConnection_v7_6 { + bmdVideoConnectionSDI_v7_6 = /* 'sdi ' */ 0x73646920, + bmdVideoConnectionHDMI_v7_6 = /* 'hdmi' */ 0x68646D69, + bmdVideoConnectionOpticalSDI_v7_6 = /* 'opti' */ 0x6F707469, + bmdVideoConnectionComponent_v7_6 = /* 'cpnt' */ 0x63706E74, + bmdVideoConnectionComposite_v7_6 = /* 'cmst' */ 0x636D7374, + bmdVideoConnectionSVideo_v7_6 = /* 'svid' */ 0x73766964 +} BMDVideoConnection_v7_6; + + + +/* Forward Declarations */ + +interface IDeckLinkDisplayModeIterator_v7_6; +interface IDeckLinkDisplayMode_v7_6; +interface IDeckLinkOutput_v7_6; +interface IDeckLinkInput_v7_6; +interface IDeckLinkTimecode_v7_6; +interface IDeckLinkVideoFrame_v7_6; +interface IDeckLinkMutableVideoFrame_v7_6; +interface IDeckLinkVideoInputFrame_v7_6; +interface IDeckLinkScreenPreviewCallback_v7_6; +interface IDeckLinkGLScreenPreviewHelper_v7_6; +interface IDeckLinkVideoConversion_v7_6; +interface IDeckLinkConfiguration_v7_6; + + +/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */ + +[ + object, + uuid(E763A626-4A3C-49D1-BF13-E7AD3692AE52), + helpstring("Frame completion callback.") +] interface IDeckLinkVideoOutputCallback_v7_6 : IUnknown +{ + HRESULT ScheduledFrameCompleted([in] IDeckLinkVideoFrame_v7_6 *completedFrame, [in] BMDOutputFrameCompletionResult result); + HRESULT ScheduledPlaybackHasStopped(void); +}; + + +/* Interface IDeckLinkInputCallback - Frame arrival callback. */ + +[ + object, + uuid(31D28EE7-88B6-4CB1-897A-CDBF79A26414), + helpstring("Frame arrival callback.") +] interface IDeckLinkInputCallback_v7_6 : IUnknown +{ + HRESULT VideoInputFormatChanged([in] BMDVideoInputFormatChangedEvents notificationEvents, [in] IDeckLinkDisplayMode_v7_6 *newDisplayMode, [in] BMDDetectedVideoInputFormatFlags detectedSignalFlags); + HRESULT VideoInputFrameArrived([in] IDeckLinkVideoInputFrame_v7_6* videoFrame, [in] IDeckLinkAudioInputPacket* audioPacket); +}; + + +/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */ + +[ + object, + uuid(455D741F-1779-4800-86F5-0B5D13D79751), + helpstring("enumerates over supported input/output display modes.") +] interface IDeckLinkDisplayModeIterator_v7_6 : IUnknown +{ + HRESULT Next([out] IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode); +}; + + +/* Interface IDeckLinkDisplayMode - represents a display mode */ + +[ + object, + uuid(87451E84-2B7E-439E-A629-4393EA4A8550), + helpstring("represents a display mode") +] interface IDeckLinkDisplayMode_v7_6 : IUnknown +{ + HRESULT GetName([out] BSTR *name); + BMDDisplayMode GetDisplayMode(void); + long GetWidth(void); + long GetHeight(void); + HRESULT GetFrameRate([out] BMDTimeValue *frameDuration, [out] BMDTimeScale *timeScale); + BMDFieldDominance GetFieldDominance(void); +}; + + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(29228142-EB8C-4141-A621-F74026450955), + local, + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkOutput_v7_6 : IUnknown +{ + HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport_v10_11 *result); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback_v7_6 *previewCallback); + + /* Video Output */ + + HRESULT EnableVideoOutput(BMDDisplayMode displayMode, BMDVideoOutputFlags flags); + HRESULT DisableVideoOutput(void); + + HRESULT SetVideoOutputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator); + HRESULT CreateVideoFrame(int width, int height, int rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame_v7_6 **outFrame); + HRESULT CreateAncillaryData(BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary **outBuffer); + + HRESULT DisplayVideoFrameSync([in] IDeckLinkVideoFrame_v7_6 *theFrame); + HRESULT ScheduleVideoFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale); + HRESULT SetScheduledFrameCompletionCallback([in] IDeckLinkVideoOutputCallback_v7_6 *theCallback); + HRESULT GetBufferedVideoFrameCount([out] unsigned int *bufferedFrameCount); + + /* Audio Output */ + + HRESULT EnableAudioOutput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned int channelCount, BMDAudioOutputStreamType streamType); + HRESULT DisableAudioOutput(void); + + HRESULT WriteAudioSamplesSync([in] void *buffer, unsigned int sampleFrameCount, [out] unsigned int *sampleFramesWritten); + + HRESULT BeginAudioPreroll(void); + HRESULT EndAudioPreroll(void); + HRESULT ScheduleAudioSamples([in] void *buffer, unsigned int sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, [out] unsigned int *sampleFramesWritten); + + HRESULT GetBufferedAudioSampleFrameCount([out] unsigned int *bufferedSampleFrameCount); + HRESULT FlushBufferedAudioSamples(void); + + HRESULT SetAudioCallback([in] IDeckLinkAudioOutputCallback *theCallback); + + /* Output Control */ + + HRESULT StartScheduledPlayback(BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed); + HRESULT StopScheduledPlayback(BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue *actualStopTime, BMDTimeScale timeScale); + HRESULT IsScheduledPlaybackRunning([out] BOOL *active); + HRESULT GetScheduledStreamTime(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *streamTime, [out] double *playbackSpeed); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame); +}; + + +/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(300C135A-9F43-48E2-9906-6D7911D93CF1), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkInput_v7_6 : IUnknown +{ + HRESULT DoesSupportVideoMode(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, [out] BMDDisplayModeSupport_v10_11 *result); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator_v7_6 **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback_v7_6 *previewCallback); + + /* Video Input */ + + HRESULT EnableVideoInput(BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags); + HRESULT DisableVideoInput(void); + HRESULT GetAvailableVideoFrameCount([out] unsigned int *availableFrameCount); + + /* Audio Input */ + + HRESULT EnableAudioInput(BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, unsigned int channelCount); + HRESULT DisableAudioInput(void); + HRESULT GetAvailableAudioSampleFrameCount([out] unsigned int *availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams(void); + HRESULT StopStreams(void); + HRESULT PauseStreams(void); + HRESULT FlushStreams(void); + HRESULT SetCallback([in] IDeckLinkInputCallback_v7_6 *theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock(BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame); +}; + + +/* Interface IDeckLinkTimecode_v7_6 - Used for video frame timecode representation. */ + +[ + object, + uuid(EFB9BCA6-A521-44F7-BD69-2332F24D9EE6), + helpstring("Used for video frame timecode representation.") +] interface IDeckLinkTimecode_v7_6 : IUnknown +{ + BMDTimecodeBCD GetBCD(void); + HRESULT GetComponents([out] unsigned char *hours, [out] unsigned char *minutes, [out] unsigned char *seconds, [out] unsigned char *frames); + HRESULT GetString([out] BSTR *timecode); + BMDTimecodeFlags GetFlags(void); +}; + + +/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */ + +[ + object, + uuid(A8D8238E-6B18-4196-99E1-5AF717B83D32), + local, + helpstring("Interface to encapsulate a video frame; can be caller-implemented.") +] interface IDeckLinkVideoFrame_v7_6 : IUnknown +{ + long GetWidth(void); + long GetHeight(void); + long GetRowBytes(void); + BMDPixelFormat GetPixelFormat(void); + BMDFrameFlags GetFlags(void); + HRESULT GetBytes([out] void **buffer); + + HRESULT GetTimecode(BMDTimecodeFormat format, [out] IDeckLinkTimecode_v7_6 **timecode); + HRESULT GetAncillaryData([out] IDeckLinkVideoFrameAncillary **ancillary); +}; + + +/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */ + +[ + object, + uuid(46FCEE00-B4E6-43D0-91C0-023A7FCEB34F), + local, + helpstring("Created by IDeckLinkOutput::CreateVideoFrame.") +] interface IDeckLinkMutableVideoFrame_v7_6 : IDeckLinkVideoFrame_v7_6 +{ + HRESULT SetFlags(BMDFrameFlags newFlags); + + HRESULT SetTimecode(BMDTimecodeFormat format, [in] IDeckLinkTimecode_v7_6 *timecode); + HRESULT SetTimecodeFromComponents(BMDTimecodeFormat format, unsigned char hours, unsigned char minutes, unsigned char seconds, unsigned char frames, BMDTimecodeFlags flags); + HRESULT SetAncillaryData([in] IDeckLinkVideoFrameAncillary *ancillary); +}; + + +/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */ + +[ + object, + uuid(9A74FA41-AE9F-47AC-8CF4-01F42DD59965), + local, + helpstring("Provided by the IDeckLinkVideoInput frame arrival callback.") +] interface IDeckLinkVideoInputFrame_v7_6 : IDeckLinkVideoFrame_v7_6 +{ + HRESULT GetStreamTime([out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration, BMDTimeScale timeScale); + HRESULT GetHardwareReferenceTimestamp(BMDTimeScale timeScale, [out] BMDTimeValue *frameTime, [out] BMDTimeValue *frameDuration); +}; + + +/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */ + +[ + object, + uuid(373F499D-4B4D-4518-AD22-6354E5A5825E), + local, + helpstring("Screen preview callback") +] interface IDeckLinkScreenPreviewCallback_v7_6 : IUnknown +{ + HRESULT DrawFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame); +}; + + +/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */ + +[ + object, + uuid(BA575CD9-A15E-497B-B2C2-F9AFE7BE4EBA), + local, + helpstring("Created with CoCreateInstance().") +] interface IDeckLinkGLScreenPreviewHelper_v7_6 : IUnknown +{ + + /* Methods must be called with OpenGL context set */ + + HRESULT InitializeGL(void); + HRESULT PaintGL(void); + HRESULT SetFrame([in] IDeckLinkVideoFrame_v7_6 *theFrame); +}; + + +/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */ + +[ + object, + uuid(3EB504C9-F97D-40FE-A158-D407D48CB53B), + local, + helpstring("Created with CoCreateInstance().") +] interface IDeckLinkVideoConversion_v7_6 : IUnknown +{ + HRESULT ConvertFrame([in] IDeckLinkVideoFrame_v7_6* srcFrame, [in] IDeckLinkVideoFrame_v7_6* dstFrame); +}; + +/* Interface IDeckLinkConfiguration_v7_6 - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(B8EAD569-B764-47F0-A73F-AE40DF6CBF10), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkConfiguration_v7_6 : IUnknown +{ + HRESULT GetConfigurationValidator([out] IDeckLinkConfiguration_v7_6 **configObject); + HRESULT WriteConfigurationToPreferences(void); + + /* Video Output Configuration */ + + HRESULT SetVideoOutputFormat([in] BMDVideoConnection_v7_6 videoOutputConnection); + HRESULT IsVideoOutputActive([in] BMDVideoConnection_v7_6 videoOutputConnection, [out] BOOL *active); + + HRESULT SetAnalogVideoOutputFlags([in] BMDAnalogVideoFlags analogVideoFlags); + HRESULT GetAnalogVideoOutputFlags([out] BMDAnalogVideoFlags *analogVideoFlags); + + HRESULT EnableFieldFlickerRemovalWhenPaused([in] BOOL enable); + HRESULT IsEnabledFieldFlickerRemovalWhenPaused([out] BOOL *enabled); + + HRESULT Set444And3GBpsVideoOutput([in] BOOL enable444VideoOutput, [in] BOOL enable3GbsOutput); + HRESULT Get444And3GBpsVideoOutput([out] BOOL *is444VideoOutputEnabled, [out] BOOL *threeGbsOutputEnabled); + + HRESULT SetVideoOutputConversionMode([in] BMDVideoOutputConversionMode conversionMode); + HRESULT GetVideoOutputConversionMode([out] BMDVideoOutputConversionMode *conversionMode); + + HRESULT Set_HD1080p24_to_HD1080i5994_Conversion([in] BOOL enable); + HRESULT Get_HD1080p24_to_HD1080i5994_Conversion([out] BOOL *enabled); + + /* Video Input Configuration */ + + HRESULT SetVideoInputFormat([in] BMDVideoConnection_v7_6 videoInputFormat); + HRESULT GetVideoInputFormat([out] BMDVideoConnection_v7_6 *videoInputFormat); + + HRESULT SetAnalogVideoInputFlags([in] BMDAnalogVideoFlags analogVideoFlags); + HRESULT GetAnalogVideoInputFlags([out] BMDAnalogVideoFlags *analogVideoFlags); + + HRESULT SetVideoInputConversionMode([in] BMDVideoInputConversionMode conversionMode); + HRESULT GetVideoInputConversionMode([out] BMDVideoInputConversionMode *conversionMode); + + HRESULT SetBlackVideoOutputDuringCapture([in] BOOL blackOutInCapture); + HRESULT GetBlackVideoOutputDuringCapture([out] BOOL *blackOutInCapture); + + HRESULT Set32PulldownSequenceInitialTimecodeFrame([in] unsigned int aFrameTimecode); + HRESULT Get32PulldownSequenceInitialTimecodeFrame([out] unsigned int *aFrameTimecode); + + HRESULT SetVancSourceLineMapping([in] unsigned int activeLine1VANCsource, [in] unsigned int activeLine2VANCsource, [in] unsigned int activeLine3VANCsource); + HRESULT GetVancSourceLineMapping([out] unsigned int *activeLine1VANCsource, [out] unsigned int *activeLine2VANCsource, [out] unsigned int *activeLine3VANCsource); + + /* Audio Input Configuration */ + + HRESULT SetAudioInputFormat([in] BMDAudioConnection_v10_2 audioInputFormat); + HRESULT GetAudioInputFormat([out] BMDAudioConnection_v10_2 *audioInputFormat); +}; + + + +/* Coclasses */ + +importlib("stdole2.tlb"); + +[ + uuid(D398CEE7-4434-4CA3-9BA6-5AE34556B905), + helpstring("CDeckLinkGLScreenPreviewHelper Class (DeckLink API v7.6)") +] coclass CDeckLinkGLScreenPreviewHelper_v7_6 +{ + [default] interface IDeckLinkGLScreenPreviewHelper_v7_6; +}; + +[ + uuid(FFA84F77-73BE-4FB7-B03E-B5E44B9F759B), + helpstring("CDeckLinkVideoConversion Class (DeckLink API v7.6)") +] coclass CDeckLinkVideoConversion_v7_6 +{ + [default] interface IDeckLinkVideoConversion_v7_6; +}; + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_9.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_9.idl new file mode 100644 index 0000000000..97ecb1c3da --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v7_9.idl @@ -0,0 +1,82 @@ +/* -LICENSE-START- +** Copyright (c) 2010 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v7_9.idl */ + +/* Interface IDeckLinkDeckControl_v7_9 - Deck Control main interface */ + +[ + object, + uuid(A4D81043-0619-42B7-8ED6-602D29041DF7), + helpstring("Deck Control main interface") +] interface IDeckLinkDeckControl_v7_9 : IUnknown +{ + HRESULT Open([in] BMDTimeScale timeScale, [in] BMDTimeValue timeValue, [in] BOOL timecodeIsDropFrame, [out] BMDDeckControlError *error); + HRESULT Close([in] BOOL standbyOn); + HRESULT GetCurrentState([out] BMDDeckControlMode *mode, [out] BMDDeckControlVTRControlState *vtrControlState, [out] BMDDeckControlStatusFlags *flags); + HRESULT SetStandby([in] BOOL standbyOn); + HRESULT Play([out] BMDDeckControlError *error); + HRESULT Stop([out] BMDDeckControlError *error); + HRESULT TogglePlayStop([out] BMDDeckControlError *error); + HRESULT Eject([out] BMDDeckControlError *error); + HRESULT GoToTimecode([in] BMDTimecodeBCD timecode, [out] BMDDeckControlError *error); + HRESULT FastForward([in] BOOL viewTape, [out] BMDDeckControlError *error); + HRESULT Rewind([in] BOOL viewTape, [out] BMDDeckControlError *error); + HRESULT StepForward([out] BMDDeckControlError *error); + HRESULT StepBack([out] BMDDeckControlError *error); + HRESULT Jog([in] double rate, [out] BMDDeckControlError *error); + HRESULT Shuttle([in] double rate, [out] BMDDeckControlError *error); + HRESULT GetTimecodeString([out] BSTR *currentTimeCode, [out] BMDDeckControlError *error); + HRESULT GetTimecode([out] IDeckLinkTimecode **currentTimecode, [out] BMDDeckControlError *error); + HRESULT GetTimecodeBCD([out] BMDTimecodeBCD *currentTimecode, [out] BMDDeckControlError *error); + HRESULT SetPreroll([in] unsigned int prerollSeconds); + HRESULT GetPreroll([out] unsigned int *prerollSeconds); + HRESULT SetExportOffset([in] int exportOffsetFields); + HRESULT GetExportOffset([out] int *exportOffsetFields); + HRESULT GetManualExportOffset([out] int *deckManualExportOffsetFields); + HRESULT SetCaptureOffset([in] int captureOffsetFields); + HRESULT GetCaptureOffset([out] int *captureOffsetFields); + HRESULT StartExport([in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [in] BMDDeckControlExportModeOpsFlags exportModeOps, [out] BMDDeckControlError *error); + HRESULT StartCapture([in] BOOL useVITC, [in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [out] BMDDeckControlError *error); + HRESULT GetDeviceID([out] unsigned short *deviceId, [out] BMDDeckControlError *error); + HRESULT Abort(void); + HRESULT CrashRecordStart([out] BMDDeckControlError *error); + HRESULT CrashRecordStop([out] BMDDeckControlError *error); + HRESULT SetCallback([in] IDeckLinkDeckControlStatusCallback *callback); +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_0.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_0.idl new file mode 100644 index 0000000000..50d7e80ee9 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_0.idl @@ -0,0 +1,75 @@ +/* -LICENSE-START- +** Copyright (c) 2011 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v8_0.idl */ + +/* Interface IDeckLink_v8_0 - represents a DeckLink device */ + +[ + object, + uuid(62BFF75D-6569-4E55-8D4D-66AA03829ABC), + helpstring("represents a DeckLink device") +] interface IDeckLink_v8_0 : IUnknown +{ + HRESULT GetModelName([out] BSTR *modelName); +}; + +/* Interface IDeckLinkIterator_v8_0 - enumerates installed DeckLink hardware */ + +[ + object, + uuid(74E936FC-CC28-4A67-81A0-1E94E52D4E69), + helpstring("enumerates installed DeckLink hardware") +] interface IDeckLinkIterator_v8_0 : IUnknown +{ + HRESULT Next([out] IDeckLink_v8_0 **deckLinkInstance); +}; + + +/* Coclasses */ + +importlib("stdole2.tlb"); + +[ + uuid(D9EDA3B3-2887-41FA-B724-017CF1EB1D37), + helpstring("CDeckLinkIterator Class (DeckLink API v8.0)") +] coclass CDeckLinkIterator_v8_0 +{ + [default] interface IDeckLinkIterator_v8_0; +}; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_1.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_1.idl new file mode 100644 index 0000000000..8c1f9ce41c --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v8_1.idl @@ -0,0 +1,114 @@ +/* -LICENSE-START- +** Copyright (c) 2011 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ +/* DeckLinkAPI_v8_1.idl */ + +/* Enum BMDDeckControlVTRControlState_v8_1 - VTR Control state */ + +typedef [v1_enum] enum _BMDDeckControlVTRControlState_v8_1 { + bmdDeckControlNotInVTRControlMode_v8_1 = /* 'nvcm' */ 0x6E76636D, + bmdDeckControlVTRControlPlaying_v8_1 = /* 'vtrp' */ 0x76747270, + bmdDeckControlVTRControlRecording_v8_1 = /* 'vtrr' */ 0x76747272, + bmdDeckControlVTRControlStill_v8_1 = /* 'vtra' */ 0x76747261, + bmdDeckControlVTRControlSeeking_v8_1 = /* 'vtrs' */ 0x76747273, + bmdDeckControlVTRControlStopped_v8_1 = /* 'vtro' */ 0x7674726F +} BMDDeckControlVTRControlState_v8_1; + + +interface IDeckLinkDeckControlStatusCallback; +interface IDeckLinkDeckControl; + +/* Interface IDeckLinkDeckControlStatusCallback_v8_1 - Deck control state change callback. */ + +[ + object, + uuid(E5F693C1-4283-4716-B18F-C1431521955B), + helpstring("Deck control state change callback.") +] interface IDeckLinkDeckControlStatusCallback_v8_1 : IUnknown +{ + HRESULT TimecodeUpdate([in] BMDTimecodeBCD currentTimecode); + HRESULT VTRControlStateChanged([in] BMDDeckControlVTRControlState_v8_1 newState, [in] BMDDeckControlError error); + HRESULT DeckControlEventReceived([in] BMDDeckControlEvent event, [in] BMDDeckControlError error); + HRESULT DeckControlStatusChanged([in] BMDDeckControlStatusFlags flags, [in] unsigned int mask); +}; + +/* Interface IDeckLinkDeckControl - Deck Control main interface */ + +[ + object, + uuid(522A9E39-0F3C-4742-94EE-D80DE335DA1D), + helpstring("Deck Control main interface") +] interface IDeckLinkDeckControl_v8_1 : IUnknown +{ + HRESULT Open([in] BMDTimeScale timeScale, [in] BMDTimeValue timeValue, [in] BOOL timecodeIsDropFrame, [out] BMDDeckControlError *error); + HRESULT Close([in] BOOL standbyOn); + HRESULT GetCurrentState([out] BMDDeckControlMode *mode, [out] BMDDeckControlVTRControlState_v8_1 *vtrControlState, [out] BMDDeckControlStatusFlags *flags); + HRESULT SetStandby([in] BOOL standbyOn); + HRESULT SendCommand([in] unsigned char *inBuffer, [in] unsigned int inBufferSize, [out] unsigned char *outBuffer, [out] unsigned int *outDataSize, [in] unsigned int outBufferSize, [out] BMDDeckControlError *error); + HRESULT Play([out] BMDDeckControlError *error); + HRESULT Stop([out] BMDDeckControlError *error); + HRESULT TogglePlayStop([out] BMDDeckControlError *error); + HRESULT Eject([out] BMDDeckControlError *error); + HRESULT GoToTimecode([in] BMDTimecodeBCD timecode, [out] BMDDeckControlError *error); + HRESULT FastForward([in] BOOL viewTape, [out] BMDDeckControlError *error); + HRESULT Rewind([in] BOOL viewTape, [out] BMDDeckControlError *error); + HRESULT StepForward([out] BMDDeckControlError *error); + HRESULT StepBack([out] BMDDeckControlError *error); + HRESULT Jog([in] double rate, [out] BMDDeckControlError *error); + HRESULT Shuttle([in] double rate, [out] BMDDeckControlError *error); + HRESULT GetTimecodeString([out] BSTR *currentTimeCode, [out] BMDDeckControlError *error); + HRESULT GetTimecode([out] IDeckLinkTimecode **currentTimecode, [out] BMDDeckControlError *error); + HRESULT GetTimecodeBCD([out] BMDTimecodeBCD *currentTimecode, [out] BMDDeckControlError *error); + HRESULT SetPreroll([in] unsigned int prerollSeconds); + HRESULT GetPreroll([out] unsigned int *prerollSeconds); + HRESULT SetExportOffset([in] int exportOffsetFields); + HRESULT GetExportOffset([out] int *exportOffsetFields); + HRESULT GetManualExportOffset([out] int *deckManualExportOffsetFields); + HRESULT SetCaptureOffset([in] int captureOffsetFields); + HRESULT GetCaptureOffset([out] int *captureOffsetFields); + HRESULT StartExport([in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [in] BMDDeckControlExportModeOpsFlags exportModeOps, [out] BMDDeckControlError *error); + HRESULT StartCapture([in] BOOL useVITC, [in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [out] BMDDeckControlError *error); + HRESULT GetDeviceID([out] unsigned short *deviceId, [out] BMDDeckControlError *error); + HRESULT Abort(void); + HRESULT CrashRecordStart([out] BMDDeckControlError *error); + HRESULT CrashRecordStop([out] BMDDeckControlError *error); + HRESULT SetCallback([in] IDeckLinkDeckControlStatusCallback_v8_1 *callback); +}; + + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_2.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_2.idl new file mode 100644 index 0000000000..23060d9ef7 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_2.idl @@ -0,0 +1,81 @@ +/* -LICENSE-START- +** Copyright (c) 2012 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v9_2.idl */ + + +/* Interface IDeckLinkInput_v9_2 - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(6D40EF78-28B9-4E21-990D-95BB7750A04F), + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkInput_v9_2 : IUnknown +{ + HRESULT DoesSupportVideoMode([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags, [out] BMDDisplayModeSupport_v10_11 *result, [out] IDeckLinkDisplayMode **resultDisplayMode); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback); + + /* Video Input */ + + HRESULT EnableVideoInput([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoInputFlags flags); + HRESULT DisableVideoInput(void); + HRESULT GetAvailableVideoFrameCount([out] unsigned int *availableFrameCount); + + /* Audio Input */ + + HRESULT EnableAudioInput([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount); + HRESULT DisableAudioInput(void); + HRESULT GetAvailableAudioSampleFrameCount([out] unsigned int *availableSampleFrameCount); + + /* Input Control */ + + HRESULT StartStreams(void); + HRESULT StopStreams(void); + HRESULT PauseStreams(void); + HRESULT FlushStreams(void); + HRESULT SetCallback([in] IDeckLinkInputCallback_v11_5_1 *theCallback); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame); +}; + diff --git a/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_9.idl b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_9.idl new file mode 100644 index 0000000000..b6c7ca089e --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/win/DeckLinkAPI_v9_9.idl @@ -0,0 +1,100 @@ +/* -LICENSE-START- +** Copyright (c) 2012 Blackmagic Design +** +** Permission is hereby granted, free of charge, to any person or organization +** obtaining a copy of the software and accompanying documentation (the +** "Software") to use, reproduce, display, distribute, sub-license, execute, +** and transmit the Software, and to prepare derivative works of the Software, +** and to permit third-parties to whom the Software is furnished to do so, in +** accordance with: +** +** (1) if the Software is obtained from Blackmagic Design, the End User License +** Agreement for the Software Development Kit (“EULA”) available at +** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or +** +** (2) if the Software is obtained from any third party, such licensing terms +** as notified by that third party, +** +** and all subject to the following: +** +** (3) the copyright notices in the Software and this entire statement, +** including the above license grant, this restriction and the following +** disclaimer, must be included in all copies of the Software, in whole or in +** part, and all derivative works of the Software, unless such copies or +** derivative works are solely in the form of machine-executable object code +** generated by a source language processor. +** +** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +** +** A copy of the Software is available free of charge at +** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. +** +** -LICENSE-END- +*/ + +/* DeckLinkAPI_v9_9.idl */ + + +/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */ + +[ + object, + uuid(A3EF0963-0862-44ED-92A9-EE89ABF431C7), + local, + helpstring("Created by QueryInterface from IDeckLink.") +] interface IDeckLinkOutput_v9_9 : IUnknown +{ + HRESULT DoesSupportVideoMode([in] BMDDisplayMode displayMode, [in] BMDPixelFormat pixelFormat, [in] BMDVideoOutputFlags flags, [out] BMDDisplayModeSupport_v10_11 *result, [out] IDeckLinkDisplayMode **resultDisplayMode); + HRESULT GetDisplayModeIterator([out] IDeckLinkDisplayModeIterator **iterator); + + HRESULT SetScreenPreviewCallback([in] IDeckLinkScreenPreviewCallback *previewCallback); + + /* Video Output */ + + HRESULT EnableVideoOutput([in] BMDDisplayMode displayMode, [in] BMDVideoOutputFlags flags); + HRESULT DisableVideoOutput(void); + + HRESULT SetVideoOutputFrameMemoryAllocator([in] IDeckLinkMemoryAllocator *theAllocator); + HRESULT CreateVideoFrame([in] int width, [in] int height, [in] int rowBytes, [in] BMDPixelFormat pixelFormat, [in] BMDFrameFlags flags, [out] IDeckLinkMutableVideoFrame **outFrame); + HRESULT CreateAncillaryData([in] BMDPixelFormat pixelFormat, [out] IDeckLinkVideoFrameAncillary **outBuffer); + + HRESULT DisplayVideoFrameSync([in] IDeckLinkVideoFrame *theFrame); + HRESULT ScheduleVideoFrame([in] IDeckLinkVideoFrame *theFrame, [in] BMDTimeValue displayTime, [in] BMDTimeValue displayDuration, [in] BMDTimeScale timeScale); + HRESULT SetScheduledFrameCompletionCallback([in] IDeckLinkVideoOutputCallback *theCallback); + HRESULT GetBufferedVideoFrameCount([out] unsigned int *bufferedFrameCount); + + /* Audio Output */ + + HRESULT EnableAudioOutput([in] BMDAudioSampleRate sampleRate, [in] BMDAudioSampleType sampleType, [in] unsigned int channelCount, [in] BMDAudioOutputStreamType streamType); + HRESULT DisableAudioOutput(void); + + HRESULT WriteAudioSamplesSync([in] void *buffer, [in] unsigned int sampleFrameCount, [out] unsigned int *sampleFramesWritten); + + HRESULT BeginAudioPreroll(void); + HRESULT EndAudioPreroll(void); + HRESULT ScheduleAudioSamples([in] void *buffer, [in] unsigned int sampleFrameCount, [in] BMDTimeValue streamTime, [in] BMDTimeScale timeScale, [out] unsigned int *sampleFramesWritten); + + HRESULT GetBufferedAudioSampleFrameCount([out] unsigned int *bufferedSampleFrameCount); + HRESULT FlushBufferedAudioSamples(void); + + HRESULT SetAudioCallback([in] IDeckLinkAudioOutputCallback *theCallback); + + /* Output Control */ + + HRESULT StartScheduledPlayback([in] BMDTimeValue playbackStartTime, [in] BMDTimeScale timeScale, [in] double playbackSpeed); + HRESULT StopScheduledPlayback([in] BMDTimeValue stopPlaybackAtTime, [out] BMDTimeValue *actualStopTime, [in] BMDTimeScale timeScale); + HRESULT IsScheduledPlaybackRunning([out] BOOL *active); + HRESULT GetScheduledStreamTime([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *streamTime, [out] double *playbackSpeed); + HRESULT GetReferenceStatus([out] BMDReferenceStatus *referenceStatus); + + /* Hardware Timing */ + + HRESULT GetHardwareReferenceClock([in] BMDTimeScale desiredTimeScale, [out] BMDTimeValue *hardwareTime, [out] BMDTimeValue *timeInFrame, [out] BMDTimeValue *ticksPerFrame); +}; + From 3380b06981eacff44c8901bf72c1b0cee3d95706 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 22 Mar 2023 22:44:59 +0900 Subject: [PATCH 12/82] decklink2: Remove fprintf from SDK --- .../sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp | 2 ++ .../sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp | 2 ++ .../sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp | 2 ++ .../sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp | 2 ++ 4 files changed, 8 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp index 4ea27bb4a5..e0cac2be94 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_11.cpp @@ -66,6 +66,8 @@ static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc = NULL; static CreateVideoFrameAncillaryPacketsInstanceFunc gCreateVideoFrameAncillaryPacketsFunc = NULL; +#define fprintf(a,b,c) do{}while(0) + static void InitDeckLinkAPI (void) { void *libraryHandle; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp index a1236fe560..3260c52d27 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v10_8.cpp @@ -64,6 +64,8 @@ static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc = NULL; +#define fprintf(a,b,c) do{}while(0) + static void InitDeckLinkAPI(void) { void *libraryHandle; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp index a454fda8da..f65e815c26 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v7_6.cpp @@ -58,6 +58,8 @@ static CreateIteratorFunc_v7_6 gCreateIteratorFunc = NULL; static CreateOpenGLScreenPreviewHelperFunc_v7_6 gCreateOpenGLPreviewFunc = NULL; static CreateVideoConversionInstanceFunc_v7_6 gCreateVideoConversionFunc = NULL; +#define fprintf(a,b,c) do{}while(0) + static void InitDeckLinkAPI_v7_6 (void) { void *libraryHandle; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp index 22f2a71a0c..0d4be9fd56 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/linux/DeckLinkAPIDispatch_v8_0.cpp @@ -62,6 +62,8 @@ static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL; static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL; static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL; +#define fprintf(a,b,c) do{}while(0) + static void InitDeckLinkAPI (void) { void *libraryHandle; From 05ff22e5f3c735c41af89f6b53b0fece974c0785 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 31 Dec 2022 03:19:44 +0900 Subject: [PATCH 13/82] decklink2: Add new Blackmagic DeckLink plugin Key differences from the old decklink plugin: * Single source/sink element instead of separate audio/video source/sink * Supports old driver (version 10.11 or newer) * Windows DeckLink SDK build is integrated into plugin build --- .indent_cpp_list | 1 + .../docs/plugins/gst_plugins_cache.json | 1258 ++++++++++ subprojects/gst-plugins-bad/meson.options | 1 + .../sys/decklink2/gstdecklink2combiner.cpp | 683 ++++++ .../sys/decklink2/gstdecklink2combiner.h | 34 + .../sys/decklink2/gstdecklink2demux.cpp | 275 +++ .../sys/decklink2/gstdecklink2demux.h | 34 + .../decklink2/gstdecklink2deviceprovider.cpp | 158 ++ .../decklink2/gstdecklink2deviceprovider.h | 50 + .../sys/decklink2/gstdecklink2input.cpp | 2082 +++++++++++++++++ .../sys/decklink2/gstdecklink2input.h | 77 + .../sys/decklink2/gstdecklink2object.cpp | 712 ++++++ .../sys/decklink2/gstdecklink2object.h | 51 + .../sys/decklink2/gstdecklink2output.cpp | 1806 ++++++++++++++ .../sys/decklink2/gstdecklink2output.h | 72 + .../sys/decklink2/gstdecklink2sink.cpp | 901 +++++++ .../sys/decklink2/gstdecklink2sink.h | 34 + .../sys/decklink2/gstdecklink2src.cpp | 674 ++++++ .../sys/decklink2/gstdecklink2src.h | 36 + .../sys/decklink2/gstdecklink2srcbin.cpp | 206 ++ .../sys/decklink2/gstdecklink2srcbin.h | 34 + .../sys/decklink2/gstdecklink2utils.cpp | 1228 ++++++++++ .../sys/decklink2/gstdecklink2utils.h | 334 +++ .../gst-plugins-bad/sys/decklink2/meson.build | 96 + .../gst-plugins-bad/sys/decklink2/plugin.cpp | 74 + subprojects/gst-plugins-bad/sys/meson.build | 1 + 26 files changed, 10912 insertions(+) create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/meson.build create mode 100644 subprojects/gst-plugins-bad/sys/decklink2/plugin.cpp diff --git a/.indent_cpp_list b/.indent_cpp_list index e84f1e7815..276506df84 100644 --- a/.indent_cpp_list +++ b/.indent_cpp_list @@ -14,6 +14,7 @@ subprojects/gst-plugins-bad/sys/d3d11 subprojects/gst-plugins-bad/sys/d3d12 subprojects/gst-plugins-bad/sys/dwrite subprojects/gst-plugins-bad/sys/hip +^(subprojects/gst-plugins-bad/sys/decklink2/)+(\w)+([^/])+(cpp$) subprojects/gst-plugins-bad/sys/mediafoundation subprojects/gst-plugins-bad/sys/nvcodec ^(subprojects/gst-plugins-bad/sys/qsv/)+(\w)+([^/])+(cpp$) diff --git a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json index 340a28ca36..6dded21748 100644 --- a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json @@ -21406,6 +21406,1264 @@ "tracers": {}, "url": "Unknown package origin" }, + "decklink2": { + "description": "Blackmagic Decklink plugin", + "elements": { + "decklink2combiner": { + "author": "Seungha Yang ", + "description": "Combines video and audio frames", + "hierarchy": [ + "GstDeckLink2Combiner", + "GstAggregator", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "klass": "Combiner", + "pad-templates": { + "audio": { + "caps": "audio/x-raw:\n format: { S16LE, S32LE }\n rate: 48000\n channels: { (int)2, (int)8, (int)16 }\n layout: interleaved\n", + "direction": "sink", + "presence": "always", + "type": "GstAggregatorPad" + }, + "src": { + "caps": "video/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n", + "direction": "src", + "presence": "always", + "type": "GstAggregatorPad" + }, + "video": { + "caps": "video/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n", + "direction": "sink", + "presence": "always", + "type": "GstAggregatorPad" + } + }, + "rank": "none" + }, + "decklink2demux": { + "author": "Seungha Yang ", + "description": "Decklink2 Demux", + "hierarchy": [ + "GstDeckLink2Demux", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "klass": "Video/Audio/Demuxer/Hardware", + "pad-templates": { + "audio": { + "caps": "audio/x-raw:\n format: { S16LE, S32LE }\n rate: 48000\n channels: { (int)2, (int)8, (int)16 }\n layout: interleaved\n", + "direction": "src", + "presence": "sometimes" + }, + "sink": { + "caps": "video/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n", + "direction": "sink", + "presence": "always" + }, + "video": { + "caps": "video/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n", + "direction": "src", + "presence": "always" + } + }, + "rank": "none" + }, + "decklink2sink": { + "author": "Seungha Yang ", + "description": "Decklink2 Sink", + "hierarchy": [ + "GstDeckLink2Sink", + "GstBaseSink", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "klass": "Video/Audio/Sink/Hardware", + "pad-templates": { + "sink": { + "caps": "video/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n audio-channels: { (int)0, (int)2, (int)8, (int)16 }\n", + "direction": "sink", + "presence": "always" + } + }, + "properties": { + "afd-bar-line": { + "blurb": "Line number to use for inserting AFD/Bar data (0 = disabled)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "10000", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "cc-line": { + "blurb": "Line number to use for inserting closed captions (0 = disabled)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "22", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "device-number": { + "blurb": "Output device instance to use", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2147483647", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "keyer-level": { + "blurb": "Keyer level", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "255", + "max": "255", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "keyer-mode": { + "blurb": "Keyer mode to be enabled", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "off (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2KeyerMode", + "writable": true + }, + "mapping-format": { + "blurb": "3G-SDI Mapping Format (Level A/B)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "default (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2MappingFormat", + "writable": true + }, + "max-buffered-frames": { + "blurb": "Max number of frames to buffer before dropping", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "14", + "max": "16", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "min-buffered-frames": { + "blurb": "Min number of frames to buffer before duplicating", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "3", + "max": "16", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "mode": { + "blurb": "Video Mode to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "auto (1769303659)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2Mode", + "writable": true + }, + "n-preroll-frames": { + "blurb": "How many frames to preroll before starting scheduled playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "7", + "max": "16", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "persistent-id": { + "blurb": "Output device instance to use. Higher priority than \"device-number\".", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "18446744073709551615", + "max": "9223372036854775807", + "min": "-1", + "mutable": "ready", + "readable": true, + "type": "gint64", + "writable": true + }, + "profile": { + "blurb": "Certain DeckLink devices such as the DeckLink 8K Pro, the DeckLink Quad 2 and the DeckLink Duo 2 support multiple profiles to configure the capture and playback behavior of its sub-devices.For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared between any 2 sub-devices that utilize the same connectors. For the DeckLink 8K Pro, a profile is shared between all 4 sub-devices. Any sub-devices that share a profile are considered to be part of the same profile group.DeckLink Duo 2 support configuration of the duplex mode of individual sub-devices.", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "default (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2ProfileId", + "writable": true + }, + "timecode-format": { + "blurb": "Timecode format type to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "rp188any (1919955256)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2TimecodeFormat", + "writable": true + }, + "video-format": { + "blurb": "Video format type to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "8bit-yuv (846624121)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2VideoFormat", + "writable": true + } + }, + "rank": "none" + }, + "decklink2src": { + "author": "Seungha Yang ", + "description": "Decklink2 Source", + "hierarchy": [ + "GstDeckLink2Src", + "GstPushSrc", + "GstBaseSrc", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "klass": "Video/Audio/Source/Hardware", + "pad-templates": { + "src": { + "caps": "video/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n", + "direction": "src", + "presence": "always" + } + }, + "properties": { + "audio-channels": { + "blurb": "Audio Channels", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "2 (2)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2AudioChannels", + "writable": true + }, + "audio-connection": { + "blurb": "Audio input connection to use", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "auto (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2AudioConnection", + "writable": true + }, + "buffer-size": { + "blurb": "Size of internal buffer in number of video frames", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "5", + "max": "16", + "min": "1", + "mutable": "ready", + "readable": true, + "type": "guint", + "writable": true + }, + "device-number": { + "blurb": "Output device instance to use", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2147483647", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "mode": { + "blurb": "Video Mode to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "auto (1769303659)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2Mode", + "writable": true + }, + "output-afd-bar": { + "blurb": "Extract and output AFD/Bar as GstMeta (if present)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "ready", + "readable": true, + "type": "gboolean", + "writable": true + }, + "output-cc": { + "blurb": "Extract and output CC as GstMeta (if present)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "ready", + "readable": true, + "type": "gboolean", + "writable": true + }, + "persistent-id": { + "blurb": "Output device instance to use. Higher priority than \"device-number\".", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "18446744073709551615", + "max": "9223372036854775807", + "min": "-1", + "mutable": "ready", + "readable": true, + "type": "gint64", + "writable": true + }, + "profile": { + "blurb": "Certain DeckLink devices such as the DeckLink 8K Pro, the DeckLink Quad 2 and the DeckLink Duo 2 support multiple profiles to configure the capture and playback behavior of its sub-devices.For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared between any 2 sub-devices that utilize the same connectors. For the DeckLink 8K Pro, a profile is shared between all 4 sub-devices. Any sub-devices that share a profile are considered to be part of the same profile group.DeckLink Duo 2 support configuration of the duplex mode of individual sub-devices.", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "default (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2ProfileId", + "writable": true + }, + "signal": { + "blurb": "True if there is a valid input signal available", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": false + }, + "timecode-format": { + "blurb": "Timecode format type to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "rp188any (1919955256)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2TimecodeFormat", + "writable": true + }, + "video-connection": { + "blurb": "Video input connection to use", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "auto (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2VideoConnection", + "writable": true + }, + "video-format": { + "blurb": "Video format type to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "8bit-yuv (846624121)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2VideoFormat", + "writable": true + } + }, + "rank": "none" + }, + "decklink2srcbin": { + "author": "Seungha Yang ", + "description": "Decklink2 Source Bin", + "hierarchy": [ + "GstDeckLink2SrcBin", + "GstBin", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "interfaces": [ + "GstChildProxy" + ], + "klass": "Video/Audio/Source/Hardware", + "pad-templates": { + "audio": { + "caps": "audio/x-raw:\n format: { S16LE, S32LE }\n rate: 48000\n channels: { (int)2, (int)8, (int)16 }\n layout: interleaved\n", + "direction": "src", + "presence": "sometimes" + }, + "video": { + "caps": "video/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 10/11\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 12/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: interleaved\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 486\npixel-aspect-ratio: 40/33\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 720\n height: 576\npixel-aspect-ratio: 16/11\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1920\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: interleaved\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 1280\n height: 720\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1556\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 2048\n height: 1080\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 3840\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 4096\n height: 2160\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 7680\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 24/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 25/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 30/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 50/1\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60000/1001\n format: { UYVY, v210, ARGB, BGRA }\nvideo/x-raw:\n width: 8192\n height: 4320\npixel-aspect-ratio: 1/1\n interlace-mode: progressive\n framerate: 60/1\n format: { UYVY, v210, ARGB, BGRA }\n", + "direction": "src", + "presence": "always" + } + }, + "properties": { + "audio-channels": { + "blurb": "Audio Channels", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "2 (2)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2AudioChannels", + "writable": true + }, + "audio-connection": { + "blurb": "Audio input connection to use", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "auto (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2AudioConnection", + "writable": true + }, + "buffer-size": { + "blurb": "Size of internal buffer in number of video frames", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "5", + "max": "16", + "min": "1", + "mutable": "ready", + "readable": true, + "type": "guint", + "writable": true + }, + "device-number": { + "blurb": "Output device instance to use", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2147483647", + "min": "0", + "mutable": "ready", + "readable": true, + "type": "gint", + "writable": true + }, + "mode": { + "blurb": "Video Mode to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "auto (1769303659)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2Mode", + "writable": true + }, + "output-afd-bar": { + "blurb": "Extract and output AFD/Bar as GstMeta (if present)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "ready", + "readable": true, + "type": "gboolean", + "writable": true + }, + "output-cc": { + "blurb": "Extract and output CC as GstMeta (if present)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "ready", + "readable": true, + "type": "gboolean", + "writable": true + }, + "persistent-id": { + "blurb": "Output device instance to use. Higher priority than \"device-number\".", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "18446744073709551615", + "max": "9223372036854775807", + "min": "-1", + "mutable": "ready", + "readable": true, + "type": "gint64", + "writable": true + }, + "profile": { + "blurb": "Certain DeckLink devices such as the DeckLink 8K Pro, the DeckLink Quad 2 and the DeckLink Duo 2 support multiple profiles to configure the capture and playback behavior of its sub-devices.For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared between any 2 sub-devices that utilize the same connectors. For the DeckLink 8K Pro, a profile is shared between all 4 sub-devices. Any sub-devices that share a profile are considered to be part of the same profile group.DeckLink Duo 2 support configuration of the duplex mode of individual sub-devices.", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "default (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2ProfileId", + "writable": true + }, + "signal": { + "blurb": "True if there is a valid input signal available", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": false + }, + "timecode-format": { + "blurb": "Timecode format type to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "rp188any (1919955256)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2TimecodeFormat", + "writable": true + }, + "video-connection": { + "blurb": "Video input connection to use", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "auto (0)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2VideoConnection", + "writable": true + }, + "video-format": { + "blurb": "Video format type to use for playback", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "8bit-yuv (846624121)", + "mutable": "ready", + "readable": true, + "type": "GstDeckLink2VideoFormat", + "writable": true + } + }, + "rank": "none" + } + }, + "filename": "gstdecklink2", + "license": "LGPL", + "other-types": { + "GstDeckLink2AudioChannels": { + "kind": "enum", + "values": [ + { + "desc": "Disabled", + "name": "disabled", + "value": "-1" + }, + { + "desc": "2 Channels", + "name": "2", + "value": "2" + }, + { + "desc": "8 Channels", + "name": "8", + "value": "8" + }, + { + "desc": "16 Channels", + "name": "16", + "value": "16" + }, + { + "desc": "Maximum channels supported", + "name": "max", + "value": "0" + } + ] + }, + "GstDeckLink2AudioConnection": { + "kind": "enum", + "values": [ + { + "desc": "Auto", + "name": "auto", + "value": "0" + }, + { + "desc": "SDI/HDMI embedded audio", + "name": "embedded", + "value": "1" + }, + { + "desc": "AES/EBU", + "name": "aes", + "value": "2" + }, + { + "desc": "Analog", + "name": "analog", + "value": "4" + }, + { + "desc": "Analog (XLR)", + "name": "analog-xlr", + "value": "8" + }, + { + "desc": "Analog (RCA)", + "name": "analog-rca", + "value": "16" + } + ] + }, + "GstDeckLink2KeyerMode": { + "kind": "enum", + "values": [ + { + "desc": "Off", + "name": "off", + "value": "0" + }, + { + "desc": "Internal", + "name": "internal", + "value": "1" + }, + { + "desc": "External", + "name": "external", + "value": "2" + } + ] + }, + "GstDeckLink2MappingFormat": { + "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" + } + ] + }, + "GstDeckLink2Mode": { + "kind": "enum", + "values": [ + { + "desc": "Automatic detection", + "name": "auto", + "value": "1769303659" + }, + { + "desc": "NTSC SD 60i", + "name": "ntsc", + "value": "1853125475" + }, + { + "desc": "NTSC SD 60i (24 fps)", + "name": "ntsc2398", + "value": "1853108787" + }, + { + "desc": "PAL SD 50i", + "name": "pal", + "value": "1885432864" + }, + { + "desc": "NTSC SD 60p", + "name": "ntsc-p", + "value": "1853125488" + }, + { + "desc": "PAL SD 50p", + "name": "pal-p", + "value": "1885432944" + }, + { + "desc": "NTSC SD 60i Widescreen", + "name": "ntsc-widescreen", + "value": "1314149187" + }, + { + "desc": "NTSC SD 60i Widescreen (24 fps)", + "name": "ntsc2398-widescreen", + "value": "1314140723" + }, + { + "desc": "PAL SD 50i Widescreen", + "name": "pal-widescreen", + "value": "1346456608" + }, + { + "desc": "NTSC SD 60p Widescreen", + "name": "ntsc-p-widescreen", + "value": "1314149200" + }, + { + "desc": "PAL SD 50p Widescreen", + "name": "pal-p-widescreen", + "value": "1346456656" + }, + { + "desc": "HD1080 23.98p", + "name": "1080p2398", + "value": "842231923" + }, + { + "desc": "HD1080 24p", + "name": "1080p24", + "value": "842297459" + }, + { + "desc": "HD1080 25p", + "name": "1080p25", + "value": "1215312437" + }, + { + "desc": "HD1080 29.97p", + "name": "1080p2997", + "value": "1215312441" + }, + { + "desc": "HD1080 30p", + "name": "1080p30", + "value": "1215312688" + }, + { + "desc": "HD1080 50p", + "name": "1080p50", + "value": "1215313200" + }, + { + "desc": "HD1080 59.94p", + "name": "1080p5994", + "value": "1215313209" + }, + { + "desc": "HD1080 60p", + "name": "1080p60", + "value": "1215313456" + }, + { + "desc": "HD1080 50i", + "name": "1080i50", + "value": "1214854448" + }, + { + "desc": "HD1080 59.94i", + "name": "1080i5994", + "value": "1214854457" + }, + { + "desc": "HD1080 60i", + "name": "1080i60", + "value": "1214854704" + }, + { + "desc": "HD720 50p", + "name": "720p50", + "value": "1752184112" + }, + { + "desc": "HD720 59.94p", + "name": "720p5994", + "value": "1752184121" + }, + { + "desc": "HD720 60p", + "name": "720p60", + "value": "1752184368" + }, + { + "desc": "2k 23.98p", + "name": "1556p2398", + "value": "845886003" + }, + { + "desc": "2k 24p", + "name": "1556p24", + "value": "845886004" + }, + { + "desc": "2k 25p", + "name": "1556p25", + "value": "845886005" + }, + { + "desc": "2k dci 23.98p", + "name": "2kdcip2398", + "value": "845427251" + }, + { + "desc": "2k dci 24p", + "name": "2kdcip24", + "value": "845427252" + }, + { + "desc": "2k dci 25p", + "name": "2kdcip25", + "value": "845427253" + }, + { + "desc": "2k dci 29.97p", + "name": "2kdcip2997", + "value": "845427257" + }, + { + "desc": "2k dci 30p", + "name": "2kdcip30", + "value": "845427504" + }, + { + "desc": "2k dci 50p", + "name": "2kdcip50", + "value": "845428016" + }, + { + "desc": "2k dci 59.94p", + "name": "2kdcip5994", + "value": "845428025" + }, + { + "desc": "2k dci 60p", + "name": "2kdcip60", + "value": "845428272" + }, + { + "desc": "4k 23.98p", + "name": "2160p2398", + "value": "879440435" + }, + { + "desc": "4k 24p", + "name": "2160p24", + "value": "879440436" + }, + { + "desc": "4k 25p", + "name": "2160p25", + "value": "879440437" + }, + { + "desc": "4k 29.97p", + "name": "2160p2997", + "value": "879440441" + }, + { + "desc": "4k 30p", + "name": "2160p30", + "value": "879440688" + }, + { + "desc": "4k 50p", + "name": "2160p50", + "value": "879441200" + }, + { + "desc": "4k 59.94p", + "name": "2160p5994", + "value": "879441209" + }, + { + "desc": "4k 60p", + "name": "2160p60", + "value": "879441456" + }, + { + "desc": "4k dci 23.98p", + "name": "4kdcip2398", + "value": "878981683" + }, + { + "desc": "4k dci 24p", + "name": "4kdcip24", + "value": "878981684" + }, + { + "desc": "4k dci 25p", + "name": "4kdcip25", + "value": "878981685" + }, + { + "desc": "4k dci 29.97p", + "name": "4kdcip2997", + "value": "878981689" + }, + { + "desc": "4k dci 30p", + "name": "4kdcip30", + "value": "878981936" + }, + { + "desc": "4k dci 50p", + "name": "4kdcip50", + "value": "878982448" + }, + { + "desc": "4k dci 59.94p", + "name": "4kdcip5994", + "value": "878982457" + }, + { + "desc": "4k dci 60p", + "name": "4kdcip60", + "value": "878982704" + }, + { + "desc": "8k 23.98p", + "name": "8kp2398", + "value": "946549299" + }, + { + "desc": "8k 24p", + "name": "8kp24", + "value": "946549300" + }, + { + "desc": "8k 25p", + "name": "8kp25", + "value": "946549301" + }, + { + "desc": "8k 29.97p", + "name": "8kp2997", + "value": "946549305" + }, + { + "desc": "8k 30p", + "name": "8kp30", + "value": "946549552" + }, + { + "desc": "8k 50p", + "name": "8kp50", + "value": "946550064" + }, + { + "desc": "8k 59.94p", + "name": "8kp5994", + "value": "946550073" + }, + { + "desc": "8k 60p", + "name": "8kp60", + "value": "946550320" + }, + { + "desc": "8k dci 23.98p", + "name": "8kdcip2398", + "value": "946090547" + }, + { + "desc": "8k dci 24p", + "name": "8kdcip24", + "value": "946090548" + }, + { + "desc": "8k dci 25p", + "name": "8kdcip25", + "value": "946090549" + }, + { + "desc": "8k dci 29.97p", + "name": "8kdcip2997", + "value": "946090553" + }, + { + "desc": "8k dci 30p", + "name": "8kdcip30", + "value": "946090800" + }, + { + "desc": "8k dci 50p", + "name": "8kdcip50", + "value": "946091312" + }, + { + "desc": "8k dci 59.94p", + "name": "8kdcip5994", + "value": "946091321" + }, + { + "desc": "8k dci 60p", + "name": "8kdcip60", + "value": "946091568" + } + ] + }, + "GstDeckLink2ProfileId": { + "kind": "enum", + "values": [ + { + "desc": "Default, don't change profile", + "name": "default", + "value": "0" + }, + { + "desc": "One sub-device, Full-Duplex", + "name": "one-sub-device-full", + "value": "828663396" + }, + { + "desc": "One sub-device, Half-Duplex", + "name": "one-sub-device-half", + "value": "828663908" + }, + { + "desc": "Two sub-devices, Full-Duplex", + "name": "two-sub-devices-full", + "value": "845440612" + }, + { + "desc": "Two sub-devices, Half-Duplex", + "name": "two-sub-devices-half", + "value": "845441124" + }, + { + "desc": "Four sub-devices, Half-Duplex", + "name": "four-sub-devices-half", + "value": "878995556" + } + ] + }, + "GstDeckLink2TimecodeFormat": { + "kind": "enum", + "values": [ + { + "desc": "bmdTimecodeRP188VITC1", + "name": "rp188vitc1", + "value": "1919972913" + }, + { + "desc": "bmdTimecodeRP188VITC2", + "name": "rp188vitc2", + "value": "1919955250" + }, + { + "desc": "bmdTimecodeRP188LTC", + "name": "rp188ltc", + "value": "1919970420" + }, + { + "desc": "bmdTimecodeRP188Any", + "name": "rp188any", + "value": "1919955256" + }, + { + "desc": "bmdTimecodeVITC", + "name": "vitc", + "value": "1986622563" + }, + { + "desc": "bmdTimecodeVITCField2", + "name": "vitcfield2", + "value": "1986622514" + }, + { + "desc": "bmdTimecodeSerial", + "name": "serial", + "value": "1936028265" + } + ] + }, + "GstDeckLink2VideoConnection": { + "kind": "enum", + "values": [ + { + "desc": "Auto", + "name": "auto", + "value": "0" + }, + { + "desc": "SDI", + "name": "sdi", + "value": "1" + }, + { + "desc": "HDMI", + "name": "hdmi", + "value": "2" + }, + { + "desc": "Optical SDI", + "name": "optical-sdi", + "value": "4" + }, + { + "desc": "Component", + "name": "component", + "value": "8" + }, + { + "desc": "Composite", + "name": "composite", + "value": "16" + }, + { + "desc": "S-Video", + "name": "svideo", + "value": "32" + } + ] + }, + "GstDeckLink2VideoFormat": { + "kind": "enum", + "values": [ + { + "desc": "Auto", + "name": "auto", + "value": "0" + }, + { + "desc": "bmdFormat8BitYUV", + "name": "8bit-yuv", + "value": "846624121" + }, + { + "desc": "bmdFormat10BitYUV", + "name": "10bit-yuv", + "value": "1983000880" + }, + { + "desc": "bmdFormat8BitARGB", + "name": "8bit-argb", + "value": "32" + }, + { + "desc": "bmdFormat8BitBGRA", + "name": "8bit-bgra", + "value": "1111970369" + } + ] + } + }, + "package": "GStreamer Bad Plug-ins", + "source": "gst-plugins-bad", + "tracers": {}, + "url": "Unknown package origin" + }, "directfb": { "description": "DirectFB video output plugin", "elements": { diff --git a/subprojects/gst-plugins-bad/meson.options b/subprojects/gst-plugins-bad/meson.options index 7dd5309aaf..8e388986ad 100644 --- a/subprojects/gst-plugins-bad/meson.options +++ b/subprojects/gst-plugins-bad/meson.options @@ -109,6 +109,7 @@ option('d3d12', type : 'feature', value : 'auto', description : 'Direct3D12 plug option('dash', type : 'feature', value : 'auto', description : 'DASH demuxer plugin') option('dc1394', type : 'feature', value : 'auto', description : 'libdc1394 IIDC camera source plugin') option('decklink', type : 'feature', value : 'auto', description : 'DeckLink audio/video source/sink plugin') +option('decklink2', type : 'feature', value : 'auto', description : 'DeckLink plugin') option('directfb', type : 'feature', value : 'auto', description : 'DirectFB video sink plugin') option('directsound', type : 'feature', value : 'auto', description : 'Directsound audio source plugin') option('directshow', type : 'feature', value : 'auto', description : 'Directshow audio/video plugins') diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp new file mode 100644 index 0000000000..c82f3e0d03 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp @@ -0,0 +1,683 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2combiner.h" +#include "gstdecklink2utils.h" + +GST_DEBUG_CATEGORY_STATIC (gst_decklink2_combiner_debug); +#define GST_CAT_DEFAULT gst_decklink2_combiner_debug + +static GstStaticPadTemplate audio_template = GST_STATIC_PAD_TEMPLATE ("audio", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw, format = (string) { S16LE, S32LE }, " + "rate = (int) 48000, channels = (int) { 2, 8, 16 }, " + "layout = (string) interleaved")); + +struct _GstDeckLink2Combiner +{ + GstAggregator parent; + + GstAggregatorPad *video_pad; + GstAggregatorPad *audio_pad; + + GstCaps *video_caps; + GstCaps *audio_caps; + + GstVideoInfo video_info; + GstAudioInfo audio_info; + + GstAdapter *audio_buffers; + + GstClockTime video_start_time; + GstClockTime audio_start_time; + + GstClockTime video_running_time; + GstClockTime audio_running_time; +}; + +static void gst_decklink2_combiner_dispose (GObject * object); +static gboolean gst_decklink2_combiner_sink_event (GstAggregator * agg, + GstAggregatorPad * pad, GstEvent * event); +static gboolean gst_decklink2_combiner_sink_query (GstAggregator * agg, + GstAggregatorPad * aggpad, GstQuery * query); +static GstFlowReturn gst_decklink2_combiner_aggregate (GstAggregator * agg, + gboolean timeout); +static gboolean gst_decklink2_combiner_start (GstAggregator * agg); +static gboolean gst_decklink2_combiner_stop (GstAggregator * agg); +static GstBuffer *gst_decklink2_combiner_clip (GstAggregator * agg, + GstAggregatorPad * aggpad, GstBuffer * buffer); + +#define gst_decklink2_combiner_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2Combiner, gst_decklink2_combiner, + GST_TYPE_AGGREGATOR); +GST_ELEMENT_REGISTER_DEFINE (decklink2combiner, "decklink2combiner", + GST_RANK_NONE, GST_TYPE_DECKLINK2_COMBINER); + +static void +gst_decklink2_combiner_class_init (GstDeckLink2CombinerClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstAggregatorClass *agg_class = GST_AGGREGATOR_CLASS (klass); + GstCaps *templ_caps; + + object_class->dispose = gst_decklink2_combiner_dispose; + + gst_element_class_add_static_pad_template_with_gtype (element_class, + &audio_template, GST_TYPE_AGGREGATOR_PAD); + + templ_caps = gst_decklink2_get_default_template_caps (); + gst_element_class_add_pad_template (element_class, + gst_pad_template_new_with_gtype ("video", GST_PAD_SINK, GST_PAD_ALWAYS, + templ_caps, GST_TYPE_AGGREGATOR_PAD)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new_with_gtype ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + templ_caps, GST_TYPE_AGGREGATOR_PAD)); + gst_caps_unref (templ_caps); + + gst_element_class_set_static_metadata (element_class, + "DeckLink2 Combiner", + "Combiner", "Combines video and audio frames", + "Seungha Yang "); + + agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_decklink2_combiner_sink_event); + agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_decklink2_combiner_sink_query); + agg_class->aggregate = GST_DEBUG_FUNCPTR (gst_decklink2_combiner_aggregate); + agg_class->start = GST_DEBUG_FUNCPTR (gst_decklink2_combiner_start); + agg_class->stop = GST_DEBUG_FUNCPTR (gst_decklink2_combiner_stop); + agg_class->clip = GST_DEBUG_FUNCPTR (gst_decklink2_combiner_clip); + agg_class->get_next_time = + GST_DEBUG_FUNCPTR (gst_aggregator_simple_get_next_time); + /* No negotiation needed */ + agg_class->negotiate = NULL; + + GST_DEBUG_CATEGORY_INIT (gst_decklink2_combiner_debug, + "decklink2combiner", 0, "decklink2combiner"); +} + +static void +gst_decklink2_combiner_init (GstDeckLink2Combiner * self) +{ + GstPadTemplate *templ; + GstElementClass *klass = GST_ELEMENT_GET_CLASS (self); + + templ = gst_element_class_get_pad_template (klass, "video"); + self->video_pad = (GstAggregatorPad *) + g_object_new (GST_TYPE_AGGREGATOR_PAD, "name", "video", "direction", + GST_PAD_SINK, "template", templ, NULL); + gst_object_unref (templ); + gst_element_add_pad (GST_ELEMENT_CAST (self), GST_PAD_CAST (self->video_pad)); + + templ = gst_static_pad_template_get (&audio_template); + self->audio_pad = (GstAggregatorPad *) + g_object_new (GST_TYPE_AGGREGATOR_PAD, "name", "audio", "direction", + GST_PAD_SINK, "template", templ, NULL); + gst_object_unref (templ); + gst_element_add_pad (GST_ELEMENT_CAST (self), GST_PAD_CAST (self->audio_pad)); + + self->audio_buffers = gst_adapter_new (); +} + +static void +gst_decklink2_combiner_dispose (GObject * object) +{ + GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (object); + + g_clear_object (&self->audio_buffers); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static gboolean +gst_decklink2_combiner_sink_event (GstAggregator * agg, + GstAggregatorPad * aggpad, GstEvent * event) +{ + GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (agg); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + + GST_DEBUG_OBJECT (self, "Got caps from %s pad %" GST_PTR_FORMAT, + aggpad == self->video_pad ? "video" : "audio", caps); + + if (aggpad == self->video_pad) { + gst_caps_replace (&self->video_caps, caps); + gst_video_info_from_caps (&self->video_info, caps); + } else { + /* FIXME: flush audio if audio info is changed or disallow audio update */ + gst_caps_replace (&self->audio_caps, caps); + gst_audio_info_from_caps (&self->audio_info, caps); + } + + if (self->video_caps) { + gint fps_n, fps_d; + GstClockTime latency; + + caps = gst_caps_copy (self->video_caps); + if (GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { + gst_caps_set_simple (caps, "audio-channels", G_TYPE_INT, + self->audio_info.channels, + "audio-format", G_TYPE_STRING, + gst_audio_format_to_string (self->audio_info.finfo->format), + NULL); + } else { + gst_caps_set_simple (caps, "audio-channels", G_TYPE_INT, 0, NULL); + } + + GST_DEBUG_OBJECT (self, "Set caps %" GST_PTR_FORMAT, caps); + + if (self->video_info.fps_n > 0 && self->video_info.fps_d > 0) { + fps_n = self->video_info.fps_n; + fps_d = self->video_info.fps_d; + } else { + fps_n = 30; + fps_d = 1; + } + + latency = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); + gst_aggregator_set_latency (agg, latency, latency); + + gst_aggregator_set_src_caps (agg, caps); + gst_caps_unref (caps); + } + break; + } + case GST_EVENT_SEGMENT: + { + const GstSegment *segment; + + gst_event_parse_segment (event, &segment); + + /* pass through video segment as-is */ + gst_aggregator_update_segment (agg, segment); + break; + } + default: + break; + } + + return GST_AGGREGATOR_CLASS (parent_class)->sink_event (agg, aggpad, event); +} + +static gboolean +gst_decklink2_combiner_sink_query (GstAggregator * agg, + GstAggregatorPad * aggpad, GstQuery * query) +{ + GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (agg); + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + GstQuery *caps_query; + GstCaps *filter = NULL; + GstStructure *s; + GstCaps *caps = NULL; + GstCaps *templ_caps = gst_pad_get_pad_template_caps (GST_PAD (aggpad)); + + gst_query_parse_caps (query, &filter); + + GST_LOG_OBJECT (aggpad, "Handle query caps with filter %" GST_PTR_FORMAT, + filter); + + if (filter) + caps_query = gst_query_new_caps (filter); + else + caps_query = gst_query_new_caps (templ_caps); + + ret = gst_pad_peer_query (GST_AGGREGATOR_SRC_PAD (agg), caps_query); + gst_query_parse_caps_result (caps_query, &caps); + + GST_LOG_OBJECT (aggpad, "Downstream query caps result %d, %" + GST_PTR_FORMAT, ret, caps); + + if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) { + if (filter) { + GstCaps *temp = gst_caps_intersect_full (filter, templ_caps, + GST_CAPS_INTERSECT_FIRST); + gst_query_set_caps_result (query, temp); + gst_caps_unref (temp); + } else { + gst_query_set_caps_result (query, templ_caps); + } + gst_caps_unref (templ_caps); + gst_query_unref (caps_query); + + return TRUE; + } + + caps = gst_caps_copy (caps); + gst_query_unref (caps_query); + + if (aggpad == self->video_pad) { + /* Remove audio related fields */ + for (guint i = 0; i < gst_caps_get_size (caps); i++) { + s = gst_caps_get_structure (caps, i); + gst_structure_remove_field (s, "audio-channels"); + } + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + } else { + GstCaps *audio_caps = gst_caps_copy (templ_caps); + const GValue *ch; + + /* construct caps with updated channels field */ + s = gst_caps_get_structure (caps, 0); + ch = gst_structure_get_value (s, "audio-channels"); + if (ch) + gst_caps_set_value (audio_caps, "channels", ch); + + gst_caps_unref (caps); + + if (filter) { + GstCaps *temp = gst_caps_intersect_full (filter, audio_caps, + GST_CAPS_INTERSECT_FIRST); + gst_query_set_caps_result (query, temp); + gst_caps_unref (temp); + } else { + gst_query_set_caps_result (query, audio_caps); + } + gst_caps_unref (audio_caps); + } + gst_caps_unref (templ_caps); + return TRUE; + } + case GST_QUERY_ACCEPT_CAPS: + GST_DEBUG_OBJECT (aggpad, "Handle accept caps"); + + if (aggpad == self->video_pad) { + ret = gst_pad_peer_query (GST_AGGREGATOR_SRC_PAD (agg), query); + GST_DEBUG_OBJECT (aggpad, "Video accept caps result %d", ret); + } else { + GstQuery *caps_query; + GstCaps *audio_caps; + GstCaps *caps = NULL; + const GValue *ch; + GstStructure *s; + + caps_query = gst_query_new_caps (NULL); + ret = gst_pad_peer_query (GST_AGGREGATOR_SRC_PAD (agg), caps_query); + + gst_query_parse_caps_result (caps_query, &caps); + GST_LOG_OBJECT (aggpad, "Downstream query caps result %d, %" + GST_PTR_FORMAT, ret, caps); + + if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) { + gst_query_unref (caps_query); + gst_query_set_accept_caps_result (query, TRUE); + + return TRUE; + } + + audio_caps = gst_static_pad_template_get_caps (&audio_template); + /* construct caps with updated channels field */ + audio_caps = gst_caps_copy (audio_caps); + + s = gst_caps_get_structure (caps, 0); + ch = gst_structure_get_value (s, "audio-channels"); + if (ch) + gst_caps_set_value (audio_caps, "channels", ch); + + gst_query_unref (caps_query); + + gst_query_parse_accept_caps (query, &caps); + gst_query_set_accept_caps_result (query, gst_caps_is_subset (caps, + audio_caps)); + gst_caps_unref (audio_caps); + ret = TRUE; + } + return ret; + default: + break; + } + + return GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, aggpad, query); +} + +static void +gst_decklink2_combiner_reset (GstDeckLink2Combiner * self) +{ + gst_clear_caps (&self->video_caps); + gst_clear_caps (&self->audio_caps); + + gst_adapter_clear (self->audio_buffers); + + gst_video_info_init (&self->video_info); + gst_audio_info_init (&self->audio_info); + + self->video_start_time = GST_CLOCK_TIME_NONE; + self->audio_start_time = GST_CLOCK_TIME_NONE; + self->video_running_time = GST_CLOCK_TIME_NONE; + self->audio_running_time = GST_CLOCK_TIME_NONE; +} + +static gboolean +gst_decklink2_combiner_start (GstAggregator * agg) +{ + GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (agg); + + gst_decklink2_combiner_reset (self); + + return TRUE; +} + +static gboolean +gst_decklink2_combiner_stop (GstAggregator * agg) +{ + GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (agg); + + gst_decklink2_combiner_reset (self); + + return TRUE; +} + +static GstBuffer * +gst_decklink2_combiner_clip (GstAggregator * agg, GstAggregatorPad * aggpad, + GstBuffer * buffer) +{ + GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (agg); + GstClockTime pts; + + pts = GST_BUFFER_PTS (buffer); + + if (!GST_CLOCK_TIME_IS_VALID (pts)) { + GST_ERROR_OBJECT (self, "Only buffers with PTS supported"); + return buffer; + } + + if (aggpad == self->video_pad) { + GstClockTime dur; + GstClockTime start, stop, cstart, cstop; + + dur = GST_BUFFER_DURATION (buffer); + if (!GST_CLOCK_TIME_IS_VALID (dur) && + self->video_info.fps_n > 0 && self->video_info.fps_d > 0) { + dur = gst_util_uint64_scale_int (GST_SECOND, self->video_info.fps_d, + self->video_info.fps_n); + } + + start = pts; + if (GST_CLOCK_TIME_IS_VALID (dur)) + stop = start + dur; + else + stop = GST_CLOCK_TIME_NONE; + + if (!gst_segment_clip (&aggpad->segment, GST_FORMAT_TIME, start, stop, + &cstart, &cstop)) { + GST_LOG_OBJECT (self, "Dropping buffer outside segment"); + gst_buffer_unref (buffer); + return NULL; + } + + if (GST_BUFFER_PTS (buffer) != cstart) { + buffer = gst_buffer_make_writable (buffer); + GST_BUFFER_PTS (buffer) = cstart; + } + + if (GST_CLOCK_TIME_IS_VALID (stop) && GST_CLOCK_TIME_IS_VALID (cstop)) { + dur = cstop - cstart; + + if (GST_BUFFER_DURATION (buffer) != dur) + buffer = gst_buffer_make_writable (buffer); + + GST_BUFFER_DURATION (buffer) = dur; + } + } else { + buffer = gst_audio_buffer_clip (buffer, &aggpad->segment, + self->audio_info.rate, self->audio_info.bpf); + } + + return buffer; +} + +static GstFlowReturn +gst_decklink2_combiner_aggregate (GstAggregator * agg, gboolean timeout) +{ + GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (agg); + GstBuffer *video_buf = NULL; + GstBuffer *audio_buf = NULL; + gsize audio_buf_size; + GstDeckLink2AudioMeta *meta; + GstClockTime video_running_time = GST_CLOCK_TIME_NONE; + GstClockTime video_running_time_end = GST_CLOCK_TIME_NONE; + + video_buf = gst_aggregator_pad_peek_buffer (self->video_pad); + if (!video_buf) { + if (gst_aggregator_pad_is_eos (self->video_pad)) { + /* Follow video stream's timeline */ + GST_DEBUG_OBJECT (self, "Video pad is EOS"); + return GST_FLOW_EOS; + } + + /* Need to know video start time */ + if (!GST_CLOCK_TIME_IS_VALID (self->video_start_time)) { + GST_LOG_OBJECT (self, "Waiting for first video buffer"); + goto again; + } + + GST_LOG_OBJECT (self, "Video is not ready"); + } else { + /* Drop empty buffer */ + if (gst_buffer_get_size (video_buf) == 0) { + GST_LOG_OBJECT (self, "Dropping empty video buffer"); + gst_aggregator_pad_drop_buffer (self->video_pad); + goto again; + } + + video_running_time = video_running_time_end = + gst_segment_to_running_time (&self->video_pad->segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (video_buf)); + if (GST_BUFFER_DURATION_IS_VALID (video_buf)) { + video_running_time_end += GST_BUFFER_DURATION (video_buf); + } else if (self->video_info.fps_n > 0 && self->video_info.fps_d > 0) { + video_running_time_end += gst_util_uint64_scale_int (GST_SECOND, + self->video_info.fps_d, self->video_info.fps_n); + } else { + /* XXX: shouldn't happen */ + video_running_time_end = video_running_time; + } + + if (!GST_CLOCK_TIME_IS_VALID (self->video_start_time)) { + self->video_start_time = video_running_time; + GST_DEBUG_OBJECT (self, "Video start time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->video_start_time)); + } + + self->video_running_time = video_running_time_end; + } + + audio_buf = gst_aggregator_pad_peek_buffer (self->audio_pad); + if (!audio_buf) { + if (gst_adapter_available (self->audio_buffers) == 0 && + !gst_aggregator_pad_is_eos (self->audio_pad) && + self->audio_running_time < self->video_running_time) { + GST_LOG_OBJECT (self, "Waiting for audio buffer"); + goto again; + } + } else if (gst_buffer_get_size (audio_buf) == 0) { + GST_LOG_OBJECT (self, "Dropping empty audio buffer"); + gst_aggregator_pad_drop_buffer (self->audio_pad); + goto again; + } else { + GstClockTime audio_running_time, audio_running_time_end; + + audio_running_time = gst_segment_to_running_time (&self->audio_pad->segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (audio_buf)); + if (GST_BUFFER_DURATION_IS_VALID (audio_buf)) { + audio_running_time_end = audio_running_time + + GST_BUFFER_DURATION (audio_buf); + } else { + audio_running_time_end = gst_util_uint64_scale (GST_SECOND, + gst_buffer_get_size (audio_buf), + self->audio_info.rate * self->audio_info.bpf); + audio_running_time_end += audio_running_time; + } + + self->audio_running_time = audio_running_time_end; + + /* Do initial video/audio align */ + if (!GST_CLOCK_TIME_IS_VALID (self->audio_start_time)) { + GST_DEBUG_OBJECT (self, "Initial audio running time %" GST_TIME_FORMAT, + GST_TIME_ARGS (audio_running_time)); + + if (audio_running_time_end <= self->video_start_time) { + GST_DEBUG_OBJECT (self, "audio running-time end %" GST_TIME_FORMAT + " < video-start-time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->video_start_time), + GST_TIME_ARGS (audio_running_time_end)); + /* completely outside */ + gst_aggregator_pad_drop_buffer (self->audio_pad); + goto again; + } else if (audio_running_time < self->video_start_time && + audio_running_time_end >= self->video_start_time) { + /* partial overlap */ + GstClockTime diff; + gsize in_samples, diff_samples; + GstAudioMeta *meta; + GstBuffer *trunc_buf; + + meta = gst_buffer_get_audio_meta (audio_buf); + in_samples = meta ? meta->samples : + gst_buffer_get_size (audio_buf) / self->audio_info.bpf; + + diff = self->video_start_time - audio_running_time; + diff_samples = gst_util_uint64_scale (diff, + self->audio_info.rate, GST_SECOND); + + GST_DEBUG_OBJECT (self, "Truncate initial audio buffer duration %" + GST_TIME_FORMAT, GST_TIME_ARGS (diff)); + + trunc_buf = gst_audio_buffer_truncate ( + (GstBuffer *) g_steal_pointer (&audio_buf), + self->audio_info.bpf, diff_samples, in_samples - diff_samples); + gst_aggregator_pad_drop_buffer (self->audio_pad); + if (!trunc_buf) { + GST_DEBUG_OBJECT (self, "Empty truncated buffer"); + gst_aggregator_pad_drop_buffer (self->audio_pad); + goto again; + } + + self->audio_start_time = self->video_start_time; + gst_adapter_push (self->audio_buffers, trunc_buf); + } else if (audio_running_time >= self->video_start_time) { + /* fill silence if needed */ + GstClockTime diff; + gsize diff_samples; + + diff = audio_running_time - self->video_start_time; + if (diff > 0) { + gsize fill_size; + + diff_samples = gst_util_uint64_scale (diff, + self->audio_info.rate, GST_SECOND); + + fill_size = diff_samples * self->audio_info.bpf; + if (fill_size > 0) { + GstBuffer *fill_buf; + GstMapInfo map; + + GST_DEBUG_OBJECT (self, "Fill initial %" G_GSIZE_FORMAT + " audio samples", diff_samples); + + fill_buf = gst_buffer_new_and_alloc (fill_size); + gst_buffer_map (fill_buf, &map, GST_MAP_WRITE); + gst_audio_format_info_fill_silence (self->audio_info.finfo, + map.data, map.size); + gst_buffer_unmap (fill_buf, &map); + gst_adapter_push (self->audio_buffers, fill_buf); + } + } + + self->audio_start_time = self->video_start_time; + + gst_adapter_push (self->audio_buffers, + (GstBuffer *) g_steal_pointer (&audio_buf)); + gst_aggregator_pad_drop_buffer (self->audio_pad); + } + } else { + GST_LOG_OBJECT (self, "Pushing audio buffer to adapter, %" GST_PTR_FORMAT, + audio_buf); + gst_adapter_push (self->audio_buffers, + (GstBuffer *) g_steal_pointer (&audio_buf)); + gst_aggregator_pad_drop_buffer (self->audio_pad); + } + } + + if (!video_buf) { + GST_LOG_OBJECT (self, "Waiting for video"); + goto again; + } else if (!gst_aggregator_pad_is_eos (self->audio_pad) && + self->audio_running_time < self->video_running_time) { + GST_LOG_OBJECT (self, "Waiting for audio, audio running time %" + GST_TIME_FORMAT " < video running time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->audio_running_time), + GST_TIME_ARGS (self->video_running_time)); + goto again; + } + + gst_aggregator_pad_drop_buffer (self->video_pad); + video_buf = gst_buffer_make_writable (video_buf); + + /* Remove external audio meta if any */ + meta = gst_buffer_get_decklink2_audio_meta (video_buf); + if (meta) { + GST_LOG_OBJECT (self, "Removing old audio meta"); + gst_buffer_remove_meta (video_buf, GST_META_CAST (meta)); + } + + audio_buf_size = gst_adapter_available (self->audio_buffers); + if (audio_buf_size > 0) { + GstSample *audio_sample; + + audio_buf = gst_adapter_take_buffer (self->audio_buffers, audio_buf_size); + audio_sample = gst_sample_new (audio_buf, self->audio_caps, NULL, NULL); + + GST_LOG_OBJECT (self, "Adding meta with size %" G_GSIZE_FORMAT, + gst_buffer_get_size (audio_buf)); + gst_buffer_unref (audio_buf); + + gst_buffer_add_decklink2_audio_meta (video_buf, audio_sample); + gst_sample_unref (audio_sample); + } else { + GST_LOG_OBJECT (self, "No audio meta"); + } + + GST_LOG_OBJECT (self, "Finish buffer %" GST_PTR_FORMAT, video_buf); + + GST_AGGREGATOR_PAD (agg->srcpad)->segment.position = self->video_running_time; + + return gst_aggregator_finish_buffer (agg, video_buf); + +again: + gst_clear_buffer (&video_buf); + gst_clear_buffer (&audio_buf); + + return GST_AGGREGATOR_FLOW_NEED_DATA; +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.h new file mode 100644 index 0000000000..7cec7d6bae --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.h @@ -0,0 +1,34 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_COMBINER (gst_decklink2_combiner_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Combiner, gst_decklink2_combiner, + GST, DECKLINK2_COMBINER, GstAggregator); + +GST_ELEMENT_REGISTER_DECLARE (decklink2combiner); + +G_END_DECLS \ No newline at end of file diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp new file mode 100644 index 0000000000..53f35c99af --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp @@ -0,0 +1,275 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2demux.h" +#include "gstdecklink2utils.h" +#include "gstdecklink2object.h" + +GST_DEBUG_CATEGORY_STATIC (gst_decklink2_demux_debug); +#define GST_CAT_DEFAULT gst_decklink2_demux_debug + +static GstStaticPadTemplate audio_template = GST_STATIC_PAD_TEMPLATE ("audio", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("audio/x-raw, format = (string) { S16LE, S32LE }, " + "rate = (int) 48000, channels = (int) { 2, 8, 16 }, " + "layout = (string) interleaved")); + +struct _GstDeckLink2Demux +{ + GstElement parent; + + GstPad *sink_pad; + GstPad *video_pad; + GstPad *audio_pad; + + GstFlowCombiner *flow_combiner; + GstCaps *audio_caps; +}; + +static void gst_decklink2_demux_finalize (GObject * object); +static GstStateChangeReturn +gst_decklink2_demux_change_state (GstElement * element, + GstStateChange transition); +static GstFlowReturn gst_decklink2_demux_chain (GstPad * sinkpad, + GstObject * parent, GstBuffer * inbuf); +static gboolean gst_decklink2_demux_sink_event (GstPad * sinkpad, + GstObject * parent, GstEvent * event); + +#define gst_decklink2_demux_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2Demux, gst_decklink2_demux, GST_TYPE_ELEMENT); +GST_ELEMENT_REGISTER_DEFINE (decklink2demux, "decklink2demux", + GST_RANK_NONE, GST_TYPE_DECKLINK2_DEMUX); + +static void +gst_decklink2_demux_class_init (GstDeckLink2DemuxClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + object_class->finalize = gst_decklink2_demux_finalize; + + GstCaps *templ_caps = gst_decklink2_get_default_template_caps (); + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, templ_caps)); + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("video", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps)); + gst_caps_unref (templ_caps); + gst_element_class_add_static_pad_template (element_class, &audio_template); + + gst_element_class_set_static_metadata (element_class, + "Decklink2 Demux", "Video/Audio/Demuxer/Hardware", "Decklink2 Demux", + "Seungha Yang "); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_decklink2_demux_change_state); + + GST_DEBUG_CATEGORY_INIT (gst_decklink2_demux_debug, "decklink2demux", + 0, "decklink2demux"); +} + +static void +gst_decklink2_demux_init (GstDeckLink2Demux * self) +{ + GstPadTemplate *templ; + GstElementClass *klass = GST_ELEMENT_GET_CLASS (self); + + templ = gst_element_class_get_pad_template (klass, "sink"); + self->sink_pad = gst_pad_new_from_template (templ, "sink"); + gst_pad_set_chain_function (self->sink_pad, gst_decklink2_demux_chain); + gst_pad_set_event_function (self->sink_pad, gst_decklink2_demux_sink_event); + gst_element_add_pad (GST_ELEMENT (self), self->sink_pad); + gst_object_unref (templ); + + templ = gst_element_class_get_pad_template (klass, "video"); + self->video_pad = gst_pad_new_from_template (templ, "video"); + gst_element_add_pad (GST_ELEMENT (self), self->video_pad); + gst_pad_use_fixed_caps (self->video_pad); + gst_object_unref (templ); + + self->flow_combiner = gst_flow_combiner_new (); + gst_flow_combiner_add_pad (self->flow_combiner, self->video_pad); +} + +static void +gst_decklink2_demux_finalize (GObject * object) +{ + GstDeckLink2Demux *self = GST_DECKLINK2_DEMUX (object); + + gst_flow_combiner_free (self->flow_combiner); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstStateChangeReturn +gst_decklink2_demux_change_state (GstElement * element, + GstStateChange transition) +{ + GstDeckLink2Demux *self = GST_DECKLINK2_DEMUX (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_clear_caps (&self->audio_caps); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (self->audio_pad) { + gst_flow_combiner_remove_pad (self->flow_combiner, self->audio_pad); + gst_element_remove_pad (element, self->audio_pad); + self->audio_pad = NULL; + } + gst_clear_caps (&self->audio_caps); + break; + default: + break; + } + + return ret; +} + +static GstFlowReturn +gst_decklink2_demux_chain (GstPad * sinkpad, GstObject * parent, + GstBuffer * inbuf) +{ + GstDeckLink2Demux *self = GST_DECKLINK2_DEMUX (parent); + GstDeckLink2AudioMeta *meta; + GstSample *audio_sample = NULL; + GstFlowReturn ret; + + meta = gst_buffer_get_decklink2_audio_meta (inbuf); + if (meta) { + audio_sample = gst_sample_ref (meta->sample); + inbuf = gst_buffer_make_writable (inbuf); + gst_buffer_remove_meta (inbuf, GST_META_CAST (meta)); + } + + if (audio_sample) { + GstCaps *audio_caps = gst_sample_get_caps (audio_sample); + GstBuffer *audio_buf = gst_sample_get_buffer (audio_sample); + + if (!audio_caps) { + GST_WARNING_OBJECT (self, "Audio sample without caps"); + gst_sample_unref (audio_sample); + audio_sample = NULL; + goto out; + } + + if (!audio_buf) { + GST_WARNING_OBJECT (self, "Audio sample without buffer"); + gst_sample_unref (audio_sample); + audio_sample = NULL; + goto out; + } + + if (!self->audio_pad) { + GstEvent *event; + + self->audio_pad = gst_pad_new_from_static_template (&audio_template, + "audio"); + gst_pad_set_active (self->audio_pad, TRUE); + + event = gst_pad_get_sticky_event (self->sink_pad, + GST_EVENT_STREAM_START, 0); + + gst_pad_store_sticky_event (self->audio_pad, event); + gst_event_unref (event); + + gst_caps_replace (&self->audio_caps, audio_caps); + + event = gst_event_new_caps (self->audio_caps); + gst_pad_store_sticky_event (self->audio_pad, event); + gst_event_unref (event); + + event = gst_pad_get_sticky_event (self->sink_pad, GST_EVENT_SEGMENT, 0); + if (event) { + gst_pad_store_sticky_event (self->audio_pad, event); + gst_event_unref (event); + } + + gst_element_add_pad (GST_ELEMENT (self), self->audio_pad); + gst_flow_combiner_add_pad (self->flow_combiner, self->audio_pad); + + gst_element_no_more_pads (GST_ELEMENT (self)); + } else if (!self->audio_caps || !gst_caps_is_equal (self->audio_caps, + audio_caps)) { + GstEvent *event; + + gst_caps_replace (&self->audio_caps, audio_caps); + + event = gst_event_new_caps (self->audio_caps); + gst_pad_push_event (self->audio_pad, event); + } + } + +out: + GST_LOG_OBJECT (self, "Pushing video buffer %" GST_PTR_FORMAT, inbuf); + ret = gst_pad_push (self->video_pad, inbuf); + ret = gst_flow_combiner_update_pad_flow (self->flow_combiner, + self->video_pad, ret); + + if (audio_sample) { + GstBuffer *audio_buf = gst_sample_get_buffer (audio_sample); + gst_buffer_ref (audio_buf); + gst_sample_unref (audio_sample); + + GST_LOG_OBJECT (self, "Pushing audio buffer %" GST_PTR_FORMAT, audio_buf); + ret = gst_pad_push (self->audio_pad, audio_buf); + ret = gst_flow_combiner_update_pad_flow (self->flow_combiner, + self->audio_pad, ret); + } + + return ret; +} + +static gboolean +gst_decklink2_demux_sink_event (GstPad * sinkpad, GstObject * parent, + GstEvent * event) +{ + GstDeckLink2Demux *self = GST_DECKLINK2_DEMUX (parent); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS:{ + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + GST_DEBUG_OBJECT (self, "Forwarding %" GST_PTR_FORMAT, caps); + + return gst_pad_push_event (self->video_pad, event); + } + case GST_EVENT_FLUSH_STOP: + gst_flow_combiner_reset (self->flow_combiner); + break; + default: + break; + } + + return gst_pad_event_default (sinkpad, parent, event); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.h new file mode 100644 index 0000000000..8c35035416 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.h @@ -0,0 +1,34 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_DEMUX (gst_decklink2_demux_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Demux, gst_decklink2_demux, + GST, DECKLINK2_DEMUX, GstElement); + +GST_ELEMENT_REGISTER_DECLARE (decklink2demux); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.cpp new file mode 100644 index 0000000000..c55bdbd647 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.cpp @@ -0,0 +1,158 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2deviceprovider.h" +#include + +GST_DEBUG_CATEGORY_EXTERN (gst_decklink2_debug); +#define GST_CAT_DEFAULT gst_decklink2_debug + +struct _GstDeckLink2Device +{ + GstDevice parent; + + gboolean is_src; + guint device_number; + gint64 persistent_id; +}; + +static GstElement *gst_decklink2_device_create_element (GstDevice * device, + const gchar * name); + +G_DEFINE_TYPE (GstDeckLink2Device, gst_decklink2_device, GST_TYPE_DEVICE); + +static void +gst_decklink2_device_class_init (GstDeckLink2DeviceClass * klass) +{ + GstDeviceClass *dev_class = GST_DEVICE_CLASS (klass); + + dev_class->create_element = + GST_DEBUG_FUNCPTR (gst_decklink2_device_create_element); +} + +static void +gst_decklink2_device_init (GstDeckLink2Device * self) +{ +} + +static GstElement * +gst_decklink2_device_create_element (GstDevice * device, const gchar * name) +{ + GstDeckLink2Device *self = GST_DECKLINK2_DEVICE (device); + GstElement *elem; + + if (self->is_src) { + elem = gst_element_factory_make ("decklink2src", name); + } else { + elem = gst_element_factory_make ("decklink2sink", name); + } + + g_object_set (elem, "persistent-id", self->persistent_id, NULL); + + return elem; +} + +GstDevice * +gst_decklink2_device_new (gboolean is_src, const gchar * model_name, + const gchar * display_name, const gchar * serial_number, GstCaps * caps, + gint64 persistent_id, guint device_number, guint max_audio_channels, + const gchar * driver_ver, const gchar * api_ver) +{ + GstDevice *device; + GstDeckLink2Device *self; + const gchar *device_class; + GstStructure *props; + + if (is_src) + device_class = "Video/Audio/Source/Hardware"; + else + device_class = "Video/Audio/Sink/Hardware"; + + props = gst_structure_new ("properties", + "driver-version", G_TYPE_STRING, driver_ver, + "api-version", G_TYPE_STRING, api_ver, + "device-number", G_TYPE_UINT, device_number, + "persistent-id", G_TYPE_INT64, persistent_id, NULL); + + if (max_audio_channels > 0) { + gst_structure_set (props, + "max-channels", G_TYPE_UINT, max_audio_channels, NULL); + } + + if (serial_number && serial_number[0] != '\0') { + gst_structure_set (props, + "serial-number", G_TYPE_STRING, serial_number, NULL); + } + + device = (GstDevice *) g_object_new (GST_TYPE_DECKLINK2_DEVICE, + "display-name", display_name, "device-class", device_class, + "caps", caps, "properties", props, NULL); + + self = GST_DECKLINK2_DEVICE (device); + self->device_number = device_number; + self->persistent_id = persistent_id; + self->is_src = is_src; + + return device; +} + +struct _GstDeckLink2DeviceProvider +{ + GstDeviceProvider parent; +}; + +static GList *gst_decklink2_device_provider_probe (GstDeviceProvider * + provider); + +G_DEFINE_TYPE (GstDeckLink2DeviceProvider, gst_decklink2_device_provider, + GST_TYPE_DEVICE_PROVIDER); +GST_DEVICE_PROVIDER_REGISTER_DEFINE (decklink2deviceprovider, + "decklink2deviceprovider", GST_RANK_SECONDARY, + GST_TYPE_DECKLINK2_DEVICE_PROVIDER); + +static void +gst_decklink2_device_provider_class_init (GstDeckLink2DeviceProviderClass * + klass) +{ + GstDeviceProviderClass *provider_class = GST_DEVICE_PROVIDER_CLASS (klass); + + provider_class->probe = + GST_DEBUG_FUNCPTR (gst_decklink2_device_provider_probe); + + gst_device_provider_class_set_static_metadata (provider_class, + "Decklink Device Provider", "Hardware/Source/Sink/Audio/Video", + "Lists and provides Decklink devices", + "Seungha Yang "); +} + +static void +gst_decklink2_device_provider_init (GstDeckLink2DeviceProvider * self) +{ +} + +static GList * +gst_decklink2_device_provider_probe (GstDeviceProvider * provider) +{ + return gst_decklink2_get_devices (); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.h new file mode 100644 index 0000000000..33b268fcdc --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2deviceprovider.h @@ -0,0 +1,50 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include "gstdecklink2utils.h" +#include "gstdecklink2object.h" + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_DEVICE (gst_decklink2_device_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Device, gst_decklink2_device, + GST, DECKLINK2_DEVICE, GstDevice); + +#define GST_TYPE_DECKLINK2_DEVICE_PROVIDER (gst_decklink2_device_provider_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2DeviceProvider, gst_decklink2_device_provider, + GST, DECKLINK2_DEVICE_PROVIDER, GstDeviceProvider); + +GstDevice * gst_decklink2_device_new (gboolean is_src, + const gchar * model_name, + const gchar * display_name, + const gchar * serial_number, + GstCaps * caps, + gint64 persistent_id, + guint device_number, + guint max_audio_channels, + const gchar * driver_ver, + const gchar * api_ver); + +GST_DEVICE_PROVIDER_REGISTER_DECLARE (decklink2deviceprovider); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp new file mode 100644 index 0000000000..d77dba9120 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -0,0 +1,2082 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2input.h" +#include "gstdecklink2object.h" +#include +#include +#include +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_decklink2_input_debug); +#define GST_CAT_DEFAULT gst_decklink2_input_debug + +#define INVALID_AUDIO_OFFSET ((guint64) -1) + +static HRESULT gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, + BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode * mode, + BMDDetectedVideoInputFormatFlags flags); +static void gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, + IDeckLinkVideoInputFrame * frame, IDeckLinkAudioInputPacket * packet); + +class IGstDeckLinkMemoryAllocator:public IDeckLinkMemoryAllocator +{ +public: + IGstDeckLinkMemoryAllocator ():ref_count_ (1) + { + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkInputCallback) { + *object = static_cast < IDeckLinkMemoryAllocator * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkMemoryAllocator */ + HRESULT STDMETHODCALLTYPE AllocateBuffer (unsigned int size, void **alloced) + { + std::unique_lock < std::mutex > lk (lock_); + guint8 *buf = NULL; + guint8 offset = 0; + + if (size != last_alloc_size_) { + GST_DEBUG ("%p size changed %u -> %u", this, last_alloc_size_, size); + ClearPool (); + last_alloc_size_ = size; + } + + if (!buffers_.empty ()) { + buf = (guint8 *) buffers_.front (); + buffers_.pop (); + } + lk.unlock (); + + if (!buf) { + buf = (uint8_t *) g_malloc (size + 128); + + /* The Decklink SDK requires 16 byte aligned memory at least but for us + * to work nicely let's align to 64 bytes (512 bits) as this allows + * aligned AVX2 operations for example */ + if (((guintptr) buf) % 64 != 0) + offset = ((guintptr) buf) % 64; + + /* Write the allocation size at the very beginning. It's guaranteed by + * malloc() to be allocated aligned enough for doing this. */ + *((guint32 *) buf) = size; + + /* Align our buffer */ + buf += 128 - offset; + + /* And write the alignment offset right before the buffer */ + *(buf - 1) = offset; + } + + *alloced = (void *) buf; + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE ReleaseBuffer (void *buffer) + { + std::lock_guard < std::mutex > lk (lock_); + guint8 offset = *(((guint8 *) buffer) - 1); + guint8 *alloc_buffer = ((guint8 *) buffer) - 128 + offset; + guint32 size = *(guint32 *) alloc_buffer; + + if (!commited_ || size != last_alloc_size_) + g_free (alloc_buffer); + else + buffers_.push (buffer); + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE Commit (void) + { + std::lock_guard < std::mutex > lk (lock_); + GST_DEBUG ("Commit %p", this); + + ClearPool (); + commited_ = true; + last_alloc_size_ = 0; + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE Decommit (void) + { + std::lock_guard < std::mutex > lk (lock_); + + GST_DEBUG ("Decommit %p", this); + + ClearPool (); + commited_ = false; + + return S_OK; + } + +private: + virtual ~ IGstDeckLinkMemoryAllocator () { + Decommit (); + } + + void ClearPool (void) + { + while (!buffers_.empty ()) { + guint8 *buf = (guint8 *) buffers_.front (); + buffers_.pop (); + + guint8 offset = *(buf - 1); + void *alloc_buf = buf - 128 + offset; + g_free (alloc_buf); + } + } + +private: + std::atomic < ULONG > ref_count_; + std::mutex lock_; + std::queue < void *>buffers_; + unsigned int last_alloc_size_ = 0; + bool commited_ = false; +}; + + +/* IDeckLinkInputCallback interface for API version < 12.0 */ +class IGstDeckLinkInputCallback_v11_5_1:public IDeckLinkInputCallback_v11_5_1 +{ +public: + IGstDeckLinkInputCallback_v11_5_1 (GstDeckLink2Input * input) + :ref_count_ (1), input_ (input) + { + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkInputCallback) { + *object = static_cast < IGstDeckLinkInputCallback_v11_5_1 * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkInputCallback_v11_5_1 */ + HRESULT STDMETHODCALLTYPE + VideoInputFormatChanged (BMDVideoInputFormatChangedEvents events, + IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags flags) + { + return gst_decklink2_input_on_format_changed (input_, events, mode, flags); + } + + HRESULT STDMETHODCALLTYPE + VideoInputFrameArrived (IDeckLinkVideoInputFrame * frame, + IDeckLinkAudioInputPacket * packet) + { + gst_decklink2_input_on_frame_arrived (input_, frame, packet); + return S_OK; + } + +private: + virtual ~ IGstDeckLinkInputCallback_v11_5_1 () { + } + +private: + std::atomic < ULONG > ref_count_; + GstDeckLink2Input *input_; +}; + +class IGstDeckLinkInputCallback:public IDeckLinkInputCallback +{ +public: + IGstDeckLinkInputCallback (GstDeckLink2Input * input) + :ref_count_ (1), input_ (input) + { + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkInputCallback) { + *object = static_cast < IDeckLinkInputCallback * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkInputCallback */ + HRESULT STDMETHODCALLTYPE + VideoInputFormatChanged (BMDVideoInputFormatChangedEvents events, + IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags flags) + { + return gst_decklink2_input_on_format_changed (input_, events, mode, flags); + } + + HRESULT STDMETHODCALLTYPE + VideoInputFrameArrived (IDeckLinkVideoInputFrame * frame, + IDeckLinkAudioInputPacket * packet) + { + gst_decklink2_input_on_frame_arrived (input_, frame, packet); + return S_OK; + } + +private: + virtual ~ IGstDeckLinkInputCallback () { + } + +private: + std::atomic < ULONG > ref_count_; + GstDeckLink2Input *input_; +}; + +struct TimeMapping +{ + GstClockTime xbase; + GstClockTime b; + GstClockTime num; + GstClockTime den; +}; + +struct GstDeckLink2InputPrivate +{ + GstDeckLink2InputPrivate () + { + signal = false; + } + + std::mutex lock; + std::condition_variable cond; + std::queue < GstSample * >queue; + std::atomic < bool >signal; +}; + +struct _GstDeckLink2Input +{ + GstObject parent; + + GstDeckLink2InputPrivate *priv; + + GstDeckLink2APILevel api_level; + + IDeckLink *device; + IDeckLinkProfileAttributes *attr; + IDeckLinkAttributes_v10_11 *attr_10_11; + IDeckLinkConfiguration_v10_11 *config_10_11; + IDeckLinkConfiguration *config; + + IDeckLinkInput *input; + IDeckLinkInput_v11_5_1 *input_11_5_1; + IDeckLinkInput_v11_4 *input_11_4; + IDeckLinkInput_v10_11 *input_10_11; + + IGstDeckLinkMemoryAllocator *allocator; + IGstDeckLinkInputCallback_v11_5_1 *callback_11_5_1; + IGstDeckLinkInputCallback *callback; + + GstCaps *caps; + GArray *format_table; + GstCaps *selected_video_caps; + GstAudioInfo audio_info; + guint max_audio_channels; + GstCaps *selected_audio_caps; + gboolean auto_detect; + + guint64 next_audio_offset; + guint64 audio_offset; + GstAdapter *audio_buf; + + GstDeckLink2DisplayMode selected_mode; + BMDPixelFormat pixel_format; + GstElement *client; + gboolean output_cc; + gboolean output_afd_bar; + gint aspect_ratio_flag; + BMDTimecodeFormat timecode_format; + guint buffer_size; + gboolean discont; + gboolean audio_discont; + gboolean flushing; + + guint window_size; + guint window_fill; + gboolean window_filled; + guint window_skip; + guint window_skip_count; + TimeMapping current_time_mapping; + TimeMapping next_time_mapping; + gboolean next_time_mapping_pending; + + GstClockTime times[256]; + + GstVideoVBIParser *vbi_parser; + GstVideoFormat anc_vformat; + + gint anc_width; + gint last_cc_vbi_line; + gint last_cc_vbi_line_field2; + gint last_afd_bar_vbi_line; + gint last_afd_bar_vbi_line_field2; +}; + +static void gst_decklink2_input_dispose (GObject * object); +static void gst_decklink2_input_finalize (GObject * object); +static HRESULT gst_decklink2_input_set_allocator (GstDeckLink2Input * input, + IDeckLinkMemoryAllocator * allocator); + +#define gst_decklink2_input_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2Input, gst_decklink2_input, GST_TYPE_OBJECT); + +static void +gst_decklink2_input_class_init (GstDeckLink2InputClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gst_decklink2_input_dispose; + object_class->finalize = gst_decklink2_input_finalize; + + GST_DEBUG_CATEGORY_INIT (gst_decklink2_input_debug, "decklink2input", + 0, "decklink2input"); +} + +static void +gst_decklink2_input_init (GstDeckLink2Input * self) +{ + self->format_table = g_array_new (FALSE, + FALSE, sizeof (GstDeckLink2DisplayMode)); + self->audio_buf = gst_adapter_new (); + self->allocator = new IGstDeckLinkMemoryAllocator (); + self->priv = new GstDeckLink2InputPrivate (); +} + +static void +gst_decklink2_input_dispose (GObject * object) +{ + GstDeckLink2Input *self = GST_DECKLINK2_INPUT (object); + + gst_clear_caps (&self->caps); + gst_clear_caps (&self->selected_video_caps); + gst_clear_caps (&self->selected_audio_caps); + g_clear_pointer (&self->vbi_parser, gst_video_vbi_parser_free); + g_clear_object (&self->audio_buf); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_decklink2_input_finalize (GObject * object) +{ + GstDeckLink2Input *self = GST_DECKLINK2_INPUT (object); + + GST_DECKLINK2_CLEAR_COM (self->input); + GST_DECKLINK2_CLEAR_COM (self->input_11_5_1); + GST_DECKLINK2_CLEAR_COM (self->input_11_4); + GST_DECKLINK2_CLEAR_COM (self->input_10_11); + GST_DECKLINK2_CLEAR_COM (self->allocator); + GST_DECKLINK2_CLEAR_COM (self->callback); + GST_DECKLINK2_CLEAR_COM (self->callback_11_5_1); + GST_DECKLINK2_CLEAR_COM (self->attr); + GST_DECKLINK2_CLEAR_COM (self->attr_10_11); + GST_DECKLINK2_CLEAR_COM (self->config); + GST_DECKLINK2_CLEAR_COM (self->config_10_11); + GST_DECKLINK2_CLEAR_COM (self->device); + + g_array_unref (self->format_table); + + delete self->priv; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* Returns true if format is supported without conversion */ +static gboolean +gst_decklink2_input_does_support_video_mode (GstDeckLink2Input * self, + BMDDisplayMode mode, BMDPixelFormat format) +{ + HRESULT hr; + BMDDisplayModeSupport_v10_11 supported_v10_11 = + bmdDisplayModeNotSupported_v10_11; + dlbool_t supported = (dlbool_t) 0; + BMDDisplayMode actual_mode = mode; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->DoesSupportVideoMode (mode, format, + bmdVideoOutputFlagDefault, &supported_v10_11, NULL); + if (hr != S_OK || supported_v10_11 != bmdDisplayModeSupported_v10_11) + return FALSE; + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self-> + input_11_4->DoesSupportVideoMode (bmdVideoConnectionUnspecified, mode, + format, bmdSupportedVideoModeDefault, &supported); + if (hr != S_OK || !supported) + return FALSE; + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self-> + input_11_5_1->DoesSupportVideoMode (bmdVideoConnectionUnspecified, + mode, format, bmdNoVideoInputConversion, bmdSupportedVideoModeDefault, + &actual_mode, &supported); + if (hr != S_OK || !supported || actual_mode != mode) + return FALSE; + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->DoesSupportVideoMode (bmdVideoConnectionUnspecified, + mode, format, bmdNoVideoInputConversion, bmdSupportedVideoModeDefault, + &actual_mode, &supported); + if (hr != S_OK || !supported || actual_mode != mode) + return FALSE; + break; + default: + g_assert_not_reached (); + return FALSE; + } + + return TRUE; +} + +static IDeckLinkDisplayModeIterator * +gst_decklink2_input_get_iterator (GstDeckLink2Input * self) +{ + IDeckLinkDisplayModeIterator *iter = NULL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + self->input_10_11->GetDisplayModeIterator (&iter); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + self->input_11_4->GetDisplayModeIterator (&iter); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + self->input_11_5_1->GetDisplayModeIterator (&iter); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + self->input->GetDisplayModeIterator (&iter); + break; + default: + g_assert_not_reached (); + break; + } + + return iter; +} + +GstDeckLink2Input * +gst_decklink2_input_new (IDeckLink * device, GstDeckLink2APILevel api_level) +{ + GstDeckLink2Input *self; + IDeckLinkDisplayModeIterator *iter = NULL; + HRESULT hr; + + if (!device || api_level == GST_DECKLINK2_API_LEVEL_UNKNOWN) + return NULL; + + self = (GstDeckLink2Input *) g_object_new (GST_TYPE_DECKLINK2_INPUT, NULL); + self->api_level = api_level; + self->device = device; + device->AddRef (); + + if (api_level == GST_DECKLINK2_API_LEVEL_10_11) { + device->QueryInterface (IID_IDeckLinkAttributes_v10_11, + (void **) &self->attr_10_11); + } else { + device->QueryInterface (IID_IDeckLinkProfileAttributes, + (void **) &self->attr); + } + + self->max_audio_channels = 2; + gint64 max_audio_channels = 2; + if (self->attr) { + hr = self->attr->GetInt (BMDDeckLinkMaximumAudioChannels, + &max_audio_channels); + if (gst_decklink2_result (hr)) + self->max_audio_channels = (guint) max_audio_channels; + } else if (self->attr_10_11) { + hr = self->attr_10_11->GetInt (BMDDeckLinkMaximumAudioChannels, + &max_audio_channels); + if (gst_decklink2_result (hr)) + self->max_audio_channels = (guint) max_audio_channels; + } + + if (api_level == GST_DECKLINK2_API_LEVEL_10_11) { + device->QueryInterface (IID_IDeckLinkConfiguration_v10_11, + (void **) &self->config_10_11); + } else { + device->QueryInterface (IID_IDeckLinkConfiguration, + (void **) &self->config); + } + + if (api_level > GST_DECKLINK2_API_LEVEL_11_5_1) { + self->callback = new IGstDeckLinkInputCallback (self); + } else { + self->callback_11_5_1 = new IGstDeckLinkInputCallback_v11_5_1 (self); + } + + switch (api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = device->QueryInterface (IID_IDeckLinkInput_v10_11, + (void **) &self->input_10_11); + if (!gst_decklink2_result (hr)) { + gst_object_unref (self); + return NULL; + } + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = device->QueryInterface (IID_IDeckLinkInput_v11_4, + (void **) &self->input_11_4); + if (!gst_decklink2_result (hr)) { + gst_object_unref (self); + return NULL; + } + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = device->QueryInterface (IID_IDeckLinkInputCallback_v11_5_1, + (void **) &self->input_11_5_1); + if (!gst_decklink2_result (hr)) { + gst_object_unref (self); + return NULL; + } + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = device->QueryInterface (IID_IDeckLinkInput, (void **) &self->input); + if (hr != S_OK) { + gst_object_unref (self); + return NULL; + } + break; + default: + g_assert_not_reached (); + gst_object_unref (self); + return NULL; + } + + iter = gst_decklink2_input_get_iterator (self); + if (!iter) { + gst_object_unref (self); + return NULL; + } + + hr = gst_decklink2_input_set_allocator (self, self->allocator); + if (!gst_decklink2_result (hr)) { + gst_object_unref (self); + return NULL; + } + + self->caps = gst_decklink2_build_template_caps (GST_OBJECT (self), iter, + (GstDeckLink2DoesSupportVideoMode) + gst_decklink2_input_does_support_video_mode, self->format_table); + iter->Release (); + + if (!self->caps) + gst_clear_object (&self); + + return self; +} + +GstCaps * +gst_decklink2_input_get_caps (GstDeckLink2Input * input, BMDDisplayMode mode, + BMDPixelFormat format) +{ + IDeckLinkDisplayModeIterator *iter = NULL; + GstCaps *caps; + + if (mode == bmdModeUnknown && format == bmdFormatUnspecified) + return gst_caps_ref (input->caps); + + iter = gst_decklink2_input_get_iterator (input); + if (!iter) + return NULL; + + caps = gst_decklink2_build_caps (GST_OBJECT (input), iter, + mode, format, (GstDeckLink2DoesSupportVideoMode) + gst_decklink2_input_does_support_video_mode); + iter->Release (); + + return caps; +} + +gboolean +gst_decklink2_input_get_display_mode (GstDeckLink2Input * input, + const GstVideoInfo * info, GstDeckLink2DisplayMode * display_mode) +{ + for (guint i = 0; i < input->format_table->len; i++) { + const GstDeckLink2DisplayMode *m = &g_array_index (input->format_table, + GstDeckLink2DisplayMode, i); + + if (m->width == info->width && m->height == info->height && + m->fps_n == info->fps_n && m->fps_d == info->fps_d && + m->par_n == info->par_n && m->par_d == info->par_d) { + if ((m->interlaced && !GST_VIDEO_INFO_IS_INTERLACED (info)) || + (!m->interlaced && GST_VIDEO_INFO_IS_INTERLACED (info))) { + continue; + } + + *display_mode = *m; + return TRUE; + } + } + + return FALSE; +} + +static gboolean +gst_decklink2_input_get_display_mode_from_native (GstDeckLink2Input * input, + BMDDisplayMode native, GstDeckLink2DisplayMode * display_mode) +{ + for (guint i = 0; i < input->format_table->len; i++) { + const GstDeckLink2DisplayMode *m = &g_array_index (input->format_table, + GstDeckLink2DisplayMode, i); + + if (m->mode == native) { + *display_mode = *m; + return TRUE; + } + } + + return FALSE; +} + +static HRESULT +gst_decklink2_input_set_callback (GstDeckLink2Input * self, IUnknown * callback) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->SetCallback ( + (IDeckLinkInputCallback_v11_5_1 *) callback); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->SetCallback ( + (IDeckLinkInputCallback_v11_5_1 *) callback); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->SetCallback ( + (IDeckLinkInputCallback_v11_5_1 *) callback); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->SetCallback ((IDeckLinkInputCallback *) callback); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_set_allocator (GstDeckLink2Input * self, + IDeckLinkMemoryAllocator * allocator) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->SetVideoInputFrameMemoryAllocator (allocator); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->SetVideoInputFrameMemoryAllocator (allocator); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->SetVideoInputFrameMemoryAllocator (allocator); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->SetVideoInputFrameMemoryAllocator (allocator); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_enable_video (GstDeckLink2Input * self, + BMDDisplayMode mode, BMDPixelFormat format, BMDVideoInputFlags flags) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->EnableVideoInput (mode, format, flags); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->EnableVideoInput (mode, format, flags); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->EnableVideoInput (mode, format, flags); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->EnableVideoInput (mode, format, flags); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_disable_video (GstDeckLink2Input * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->DisableVideoInput (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->DisableVideoInput (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->DisableVideoInput (); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->DisableVideoInput (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_enable_audio (GstDeckLink2Input * self, + BMDAudioSampleRate rate, BMDAudioSampleType type, guint channels) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->EnableAudioInput (rate, type, channels); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->EnableAudioInput (rate, type, channels); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->EnableAudioInput (rate, type, channels); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->EnableAudioInput (rate, type, channels); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_disable_audio (GstDeckLink2Input * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->DisableAudioInput (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->DisableAudioInput (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->DisableAudioInput (); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->DisableAudioInput (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_start_streams (GstDeckLink2Input * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->StartStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->StartStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->StartStreams (); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->StartStreams (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_stop_streams (GstDeckLink2Input * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->StopStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->StopStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->StopStreams (); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->StopStreams (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_pause_streams (GstDeckLink2Input * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->PauseStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->PauseStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->PauseStreams (); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->PauseStreams (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_flush_streams (GstDeckLink2Input * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->FlushStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->FlushStreams (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->FlushStreams (); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->FlushStreams (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_input_get_reference_clock (GstDeckLink2Input * self, + BMDTimeScale scale, BMDTimeValue * hw_time, BMDTimeValue * time_in_frame, + BMDTimeValue * ticks_per_frame) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->input_10_11->GetHardwareReferenceClock (scale, + hw_time, time_in_frame, ticks_per_frame); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->input_11_4->GetHardwareReferenceClock (scale, + hw_time, time_in_frame, ticks_per_frame); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + hr = self->input_11_5_1->GetHardwareReferenceClock (scale, + hw_time, time_in_frame, ticks_per_frame); + break; + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->input->GetHardwareReferenceClock (scale, + hw_time, time_in_frame, ticks_per_frame); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static void +gst_decklink2_input_reset_time_mapping (GstDeckLink2Input * self) +{ + self->window_size = 64; + self->window_fill = 0; + self->window_filled = FALSE; + self->window_skip = 1; + self->window_skip_count = 0; + self->current_time_mapping.xbase = 0; + self->current_time_mapping.b = 0; + self->current_time_mapping.num = 1; + self->current_time_mapping.den = 1; + self->next_time_mapping.xbase = 0; + self->next_time_mapping.b = 0; + self->next_time_mapping.num = 1; + self->next_time_mapping.den = 1; +} + +static HRESULT +gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, + BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode * mode, + BMDDetectedVideoInputFormatFlags flags) +{ + BMDPixelFormat pixel_format = bmdFormatUnspecified; + GstVideoFormat video_format; + BMDDisplayMode display_mode = mode->GetDisplayMode (); + GstDeckLink2DisplayMode new_mode; + GstCaps *caps; + + GST_DEBUG_OBJECT (self, "format changed, flags 0x%x", flags); + + if ((flags & bmdDetectedVideoInputRGB444) != 0) { + /* XXX: cannot detect RGB format. + * decklink SDK sample is using this value anyway */ + if ((flags & bmdDetectedVideoInput8BitDepth) != 0 || + flags == bmdDetectedVideoInputRGB444) { + pixel_format = bmdFormat8BitARGB; + } + } else if ((flags & bmdDetectedVideoInputYCbCr422) != 0) { + if ((flags & bmdDetectedVideoInput8BitDepth) != 0 || + (flags == bmdDetectedVideoInputYCbCr422)) { + pixel_format = bmdFormat8BitYUV; + } else if ((flags & bmdDetectedVideoInput10BitDepth) != 0) { + pixel_format = bmdFormat10BitYUV; + } + } + + if (pixel_format == bmdFormatUnspecified) { + GST_WARNING_OBJECT (self, "Unknown pixel format"); + return E_INVALIDARG; + } + + if (!gst_decklink2_input_get_display_mode_from_native (self, + display_mode, &new_mode)) { + GST_WARNING_OBJECT (self, "Unknown display mode"); + return E_INVALIDARG; + } + + video_format = gst_decklink2_video_format_from_pixel_format (pixel_format); + + caps = gst_decklink2_get_caps_from_mode (&new_mode); + gst_caps_set_simple (caps, "format", G_TYPE_STRING, + gst_video_format_to_string (video_format), NULL); + + GST_DEBUG_OBJECT (self, "Updated caps %" GST_PTR_FORMAT, caps); + + self->selected_mode = new_mode; + self->pixel_format = pixel_format; + + gst_decklink2_input_pause_streams (self); + gst_decklink2_input_enable_video (self, display_mode, pixel_format, + bmdVideoInputEnableFormatDetection); + gst_decklink2_input_flush_streams (self); + + gst_clear_caps (&self->selected_video_caps); + self->selected_video_caps = caps; + self->aspect_ratio_flag = -1; + self->discont = TRUE; + gst_adapter_clear (self->audio_buf); + self->audio_offset = INVALID_AUDIO_OFFSET; + self->next_audio_offset = INVALID_AUDIO_OFFSET; + + gst_decklink2_input_reset_time_mapping (self); + gst_decklink2_input_start_streams (self); + + return S_OK; +} + +static void +gst_decklink2_frame_free (IDeckLinkVideoInputFrame * frame) +{ + frame->Release (); +} + +static void +extract_vbi_line (GstDeckLink2Input * self, GstBuffer * buffer, + IDeckLinkVideoFrameAncillary * vanc_frame, guint field2_offset, guint line, + gboolean * found_cc_out, gboolean * found_afd_bar_out) +{ + GstVideoAncillary gstanc; + const guint8 *vancdata; + gboolean found_cc = FALSE, found_afd_bar = FALSE; + + if (vanc_frame->GetBufferForVerticalBlankingLine (field2_offset + line, + (void **) &vancdata) != S_OK) + return; + + GST_LOG_OBJECT (self, "Checking for VBI data on field line %u (field %u)", + field2_offset + line, field2_offset ? 2 : 1); + gst_video_vbi_parser_add_line (self->vbi_parser, vancdata); + + /* Check if CC or AFD/Bar is on this line if we didn't find any on a + * previous line. Remember the line where we found them */ + + while (gst_video_vbi_parser_get_ancillary (self->vbi_parser, + &gstanc) == GST_VIDEO_VBI_PARSER_RESULT_OK) { + switch (GST_VIDEO_ANCILLARY_DID16 (&gstanc)) { + case GST_VIDEO_ANCILLARY_DID16_S334_EIA_708: + if (*found_cc_out || !self->output_cc) + continue; + + GST_LOG_OBJECT (self, + "Adding CEA-708 CDP meta to buffer for line %u", + field2_offset + line); + GST_MEMDUMP_OBJECT (self, "CDP", gstanc.data, gstanc.data_count); + gst_buffer_add_video_caption_meta (buffer, + GST_VIDEO_CAPTION_TYPE_CEA708_CDP, gstanc.data, gstanc.data_count); + + found_cc = TRUE; + if (field2_offset) + self->last_cc_vbi_line_field2 = line; + else + self->last_cc_vbi_line = line; + break; + case GST_VIDEO_ANCILLARY_DID16_S334_EIA_608: + if (*found_cc_out || !self->output_cc) + continue; + + GST_LOG_OBJECT (self, + "Adding CEA-608 meta to buffer for line %u", field2_offset + line); + GST_MEMDUMP_OBJECT (self, "CEA608", gstanc.data, gstanc.data_count); + gst_buffer_add_video_caption_meta (buffer, + GST_VIDEO_CAPTION_TYPE_CEA608_S334_1A, gstanc.data, + gstanc.data_count); + + found_cc = TRUE; + if (field2_offset) + self->last_cc_vbi_line_field2 = line; + else + self->last_cc_vbi_line = line; + break; + case GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR:{ + GstVideoAFDValue afd; + gboolean is_letterbox; + guint16 bar1, bar2; + + if (*found_afd_bar_out || !self->output_afd_bar) + continue; + + GST_LOG_OBJECT (self, + "Adding AFD/Bar meta to buffer for line %u", field2_offset + line); + GST_MEMDUMP_OBJECT (self, "AFD/Bar", gstanc.data, gstanc.data_count); + + if (gstanc.data_count < 8) { + GST_WARNING_OBJECT (self, "AFD/Bar data too small"); + continue; + } + + self->aspect_ratio_flag = (gstanc.data[0] >> 2) & 0x1; + + afd = (GstVideoAFDValue) ((gstanc.data[0] >> 3) & 0xf); + is_letterbox = ((gstanc.data[3] >> 4) & 0x3) == 0; + bar1 = GST_READ_UINT16_BE (&gstanc.data[4]); + bar2 = GST_READ_UINT16_BE (&gstanc.data[6]); + + gst_buffer_add_video_afd_meta (buffer, field2_offset ? 1 : 0, + GST_VIDEO_AFD_SPEC_SMPTE_ST2016_1, afd); + gst_buffer_add_video_bar_meta (buffer, field2_offset ? 1 : 0, + is_letterbox, bar1, bar2); + + found_afd_bar = TRUE; + if (field2_offset) + self->last_afd_bar_vbi_line_field2 = line; + else + self->last_afd_bar_vbi_line = line; + break; + } + default: + /* otherwise continue looking */ + continue; + } + } + + if (found_cc) + *found_cc_out = TRUE; + if (found_afd_bar) + *found_afd_bar_out = TRUE; +} + +static void +extract_vbi (GstDeckLink2Input * self, GstBuffer * buffer, + IDeckLinkVideoInputFrame * frame) +{ + IDeckLinkVideoFrameAncillary *vanc_frame = NULL; + gint line; + BMDPixelFormat pixel_format; + GstVideoFormat video_format; + gboolean found_cc = FALSE, found_afd_bar = FALSE; + HRESULT hr; + const GstDeckLink2DisplayMode *mode = &self->selected_mode; + + hr = frame->GetAncillaryData (&vanc_frame); + if (!gst_decklink2_result (hr) || !vanc_frame) + return; + + pixel_format = vanc_frame->GetPixelFormat (); + video_format = gst_decklink2_video_format_from_pixel_format (pixel_format); + if (video_format != GST_VIDEO_FORMAT_UYVY && + video_format != GST_VIDEO_FORMAT_v210) { + GST_DEBUG_OBJECT (self, "Unknown video format for Ancillary data"); + vanc_frame->Release (); + return; + } + + if (video_format != self->anc_vformat || mode->width != self->anc_width) + g_clear_pointer (&self->vbi_parser, gst_video_vbi_parser_free); + + if (!self->vbi_parser) { + self->vbi_parser = gst_video_vbi_parser_new (video_format, mode->width); + self->anc_vformat = video_format; + self->anc_width = mode->width; + } + + GST_LOG_OBJECT (self, "Checking for ancillary data in VBI"); + + /* First check last known lines, if any */ + if (self->last_cc_vbi_line > 0) { + extract_vbi_line (self, buffer, vanc_frame, 0, self->last_cc_vbi_line, + &found_cc, &found_afd_bar); + } + if (self->last_afd_bar_vbi_line > 0 + && self->last_cc_vbi_line != self->last_afd_bar_vbi_line) { + extract_vbi_line (self, buffer, vanc_frame, 0, self->last_afd_bar_vbi_line, + &found_cc, &found_afd_bar); + } + + if (!found_cc) + self->last_cc_vbi_line = -1; + if (!found_afd_bar) + self->last_afd_bar_vbi_line = -1; + + if ((self->output_cc && !found_cc) || (self->output_afd_bar + && !found_afd_bar)) { + /* Otherwise loop through the first 21 lines and hope to find the data */ + /* FIXME: For the different formats the number of lines that can contain + * VANC are different */ + for (line = 1; line < 22; line++) { + extract_vbi_line (self, buffer, vanc_frame, 0, line, &found_cc, + &found_afd_bar); + + /* If we found everything we wanted to extract, stop here */ + if ((!self->output_cc || found_cc) && + (!self->output_afd_bar || found_afd_bar)) + break; + } + } + + /* Do the same for field 2 in case of interlaced content */ + if (mode->interlaced) { + gboolean found_cc_field2 = FALSE, found_afd_bar_field2 = FALSE; + guint field2_offset = 0; + + /* The VANC lines for the second field are at an offset, depending on + * the format in use + */ + switch (mode->height) { + case 486: + /* NTSC: 525 / 2 + 1 */ + field2_offset = 263; + break; + case 576: + /* PAL: 625 / 2 + 1 */ + field2_offset = 313; + break; + case 1080: + /* 1080i: 1125 / 2 + 1 */ + field2_offset = 563; + break; + default: + g_assert_not_reached (); + } + + /* First try the same lines as for field 1 if we don't know yet */ + if (self->last_cc_vbi_line_field2 <= 0) + self->last_cc_vbi_line_field2 = self->last_cc_vbi_line; + if (self->last_afd_bar_vbi_line_field2 <= 0) + self->last_afd_bar_vbi_line_field2 = self->last_afd_bar_vbi_line; + + if (self->last_cc_vbi_line_field2 > 0) { + extract_vbi_line (self, buffer, vanc_frame, field2_offset, + self->last_cc_vbi_line_field2, &found_cc_field2, + &found_afd_bar_field2); + } + if (self->last_afd_bar_vbi_line_field2 > 0 + && self->last_cc_vbi_line_field2 != + self->last_afd_bar_vbi_line_field2) { + extract_vbi_line (self, buffer, vanc_frame, field2_offset, + self->last_afd_bar_vbi_line_field2, &found_cc_field2, + &found_afd_bar_field2); + } + + if (!found_cc_field2) + self->last_cc_vbi_line_field2 = -1; + if (!found_afd_bar_field2) + self->last_afd_bar_vbi_line_field2 = -1; + + if (((self->output_cc && !found_cc_field2) || (self->output_afd_bar + && !found_afd_bar_field2))) { + for (line = 1; line < 22; line++) { + extract_vbi_line (self, buffer, vanc_frame, field2_offset, line, + &found_cc_field2, &found_afd_bar_field2); + + /* If we found everything we wanted to extract, stop here */ + if ((!self->output_cc || found_cc_field2) && + (!self->output_afd_bar || found_afd_bar_field2)) + break; + } + } + } + + vanc_frame->Release (); +} + +static void +gst_decklink2_input_update_time_mapping (GstDeckLink2Input * self, + GstClockTime capture_time, GstClockTime stream_time) +{ + if (self->window_skip_count == 0) { + GstClockTime num, den, b, xbase; + gdouble r_squared; + + self->times[2 * self->window_fill] = stream_time; + self->times[2 * self->window_fill + 1] = capture_time; + + self->window_fill++; + self->window_skip_count++; + if (self->window_skip_count >= self->window_skip) + self->window_skip_count = 0; + + if (self->window_fill >= self->window_size) { + guint fps = + ((gdouble) self->selected_mode.fps_n + self->selected_mode.fps_d - + 1) / ((gdouble) self->selected_mode.fps_d); + + /* Start by updating first every frame, once full every second frame, + * etc. until we update once every 4 seconds */ + if (self->window_skip < 4 * fps) + self->window_skip *= 2; + if (self->window_skip >= 4 * fps) + self->window_skip = 4 * fps; + + self->window_fill = 0; + self->window_filled = TRUE; + } + + /* First sample ever, create some basic mapping to start */ + if (!self->window_filled && self->window_fill == 1) { + self->current_time_mapping.xbase = stream_time; + self->current_time_mapping.b = capture_time; + self->current_time_mapping.num = 1; + self->current_time_mapping.den = 1; + self->next_time_mapping_pending = FALSE; + } + + /* Only bother calculating anything here once we had enough measurements, + * i.e. let's take the window size as a start */ + if (self->window_filled && + gst_calculate_linear_regression (self->times, &self->times[128], + self->window_size, &num, &den, &b, &xbase, &r_squared)) { + + GST_LOG_OBJECT (self, + "Calculated new time mapping: pipeline time = %lf * (stream time - %" + G_GUINT64_FORMAT ") + %" G_GUINT64_FORMAT " (%lf)", + ((gdouble) num) / ((gdouble) den), xbase, b, r_squared); + + self->next_time_mapping.xbase = xbase; + self->next_time_mapping.b = b; + self->next_time_mapping.num = num; + self->next_time_mapping.den = den; + self->next_time_mapping_pending = TRUE; + } + } else { + self->window_skip_count++; + if (self->window_skip_count >= self->window_skip) + self->window_skip_count = 0; + } + + if (self->next_time_mapping_pending) { + GstClockTime expected, new_calculated, diff, max_diff; + + expected = + gst_clock_adjust_with_calibration (NULL, stream_time, + self->current_time_mapping.xbase, self->current_time_mapping.b, + self->current_time_mapping.num, self->current_time_mapping.den); + new_calculated = + gst_clock_adjust_with_calibration (NULL, stream_time, + self->next_time_mapping.xbase, self->next_time_mapping.b, + self->next_time_mapping.num, self->next_time_mapping.den); + + if (new_calculated > expected) + diff = new_calculated - expected; + else + diff = expected - new_calculated; + + /* At most 5% frame duration change per update */ + max_diff = + gst_util_uint64_scale (GST_SECOND / 20, self->selected_mode.fps_d, + self->selected_mode.fps_n); + + GST_LOG_OBJECT (self, + "New time mapping causes difference of %" GST_TIME_FORMAT, + GST_TIME_ARGS (diff)); + GST_LOG_OBJECT (self, "Maximum allowed per frame %" GST_TIME_FORMAT, + GST_TIME_ARGS (max_diff)); + + if (diff > max_diff) { + /* adjust so that we move that much closer */ + if (new_calculated > expected) { + self->current_time_mapping.b = expected + max_diff; + self->current_time_mapping.xbase = stream_time; + } else { + self->current_time_mapping.b = expected - max_diff; + self->current_time_mapping.xbase = stream_time; + } + } else { + self->current_time_mapping.xbase = self->next_time_mapping.xbase; + self->current_time_mapping.b = self->next_time_mapping.b; + self->current_time_mapping.num = self->next_time_mapping.num; + self->current_time_mapping.den = self->next_time_mapping.den; + self->next_time_mapping_pending = FALSE; + } + } +} + +static void +gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, + IDeckLinkVideoInputFrame * frame, IDeckLinkAudioInputPacket * packet) +{ + GstDeckLink2InputPrivate *priv = self->priv; + static GstStaticCaps stream_reference = + GST_STATIC_CAPS ("timestamp/x-decklink-stream"); + static GstStaticCaps hardware_reference = + GST_STATIC_CAPS ("timestamp/x-decklink-hardware"); + HRESULT hr; + GstClockTime capture_time = 0; + GstClockTime base_time = 0; + GstBuffer *buffer = NULL; + GstClock *clock = NULL; + BMDTimeValue hw_now, dummy, dummy2; + BMDTimeValue stream_time = GST_CLOCK_TIME_NONE; + BMDTimeValue stream_dur; + + std::unique_lock < std::mutex > lk (priv->lock); + hr = gst_decklink2_input_get_reference_clock (self, GST_SECOND, + &hw_now, &dummy, &dummy2); + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, "Couldn't get H/W reference clock"); + hw_now = GST_CLOCK_TIME_NONE; + } + + if (self->client) + clock = gst_element_get_clock (GST_ELEMENT (self->client)); + + if (!clock) { + GST_WARNING_OBJECT (self, + "Frame arrived but we dont have configured clock"); + } else { + base_time = gst_element_get_base_time (GST_ELEMENT (self->client)); + capture_time = gst_clock_get_time (clock); + gst_object_unref (clock); + if (capture_time >= base_time) + capture_time -= base_time; + } + + if (frame) { + void *frame_data; + gsize frame_size; + BMDFrameFlags flags; + BMDTimeValue frame_time, frame_dur; + IDeckLinkTimecode *timecode = NULL; + GstClockTime pts, dur; + + hr = frame->GetBytes (&frame_data); + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, "Couldn't get byte from frame"); + return; + } + + frame_size = frame->GetHeight () * frame->GetRowBytes (); + buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, + frame_data, frame_size, 0, frame_size, frame, + (GDestroyNotify) gst_decklink2_frame_free); + frame->AddRef (); + + hr = frame->GetHardwareReferenceTimestamp (GST_SECOND, + &frame_time, &frame_dur); + if (gst_decklink2_result (hr)) { + GstCaps *caps = gst_static_caps_get (&hardware_reference); + gst_buffer_add_reference_timestamp_meta (buffer, caps, frame_time, + frame_dur); + if (GST_CLOCK_TIME_IS_VALID (hw_now) && hw_now > frame_time) { + GstClockTime diff = hw_now - frame_time; + if (capture_time >= diff) + capture_time -= diff; + } + } + + hr = frame->GetStreamTime (&stream_time, &stream_dur, GST_SECOND); + if (gst_decklink2_result (hr)) { + GstCaps *caps = gst_static_caps_get (&stream_reference); + gst_buffer_add_reference_timestamp_meta (buffer, caps, stream_time, + stream_dur); + + gst_decklink2_input_update_time_mapping (self, capture_time, stream_time); + pts = gst_clock_adjust_with_calibration (NULL, stream_time, + self->current_time_mapping.xbase, self->current_time_mapping.b, + self->current_time_mapping.num, self->current_time_mapping.den); + dur = gst_util_uint64_scale (stream_dur, + self->current_time_mapping.num, self->current_time_mapping.den); + } else { + pts = capture_time; + dur = GST_CLOCK_TIME_NONE; + } + + flags = frame->GetFlags (); + if ((flags & bmdFrameHasNoInputSource) != 0) { + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_GAP); + priv->signal = false; + } else { + priv->signal = true; + + if (self->output_cc || self->output_afd_bar) { + extract_vbi (self, buffer, frame); + + if (self->aspect_ratio_flag == 1 && self->auto_detect) { + BMDDisplayMode mode = self->selected_mode.mode; + + switch (self->selected_mode.mode) { + case bmdModeNTSC: + mode = bmdModeNTSC_W; + break; + case bmdModeNTSC2398: + mode = bmdModeNTSC2398_W; + break; + case bmdModePAL: + mode = bmdModePAL_W; + break; + case bmdModeNTSCp: + mode = bmdModeNTSCp_W; + break; + case bmdModePALp: + mode = bmdModePALp_W; + break; + default: + break; + } + + if (mode != self->selected_mode.mode) { + GstDeckLink2DisplayMode new_mode; + GstVideoFormat video_format; + GstCaps *caps; + gst_decklink2_input_get_display_mode_from_native (self, + mode, &new_mode); + + video_format = + gst_decklink2_video_format_from_pixel_format + (self->pixel_format); + caps = gst_decklink2_get_caps_from_mode (&new_mode); + gst_caps_set_simple (caps, "format", G_TYPE_STRING, + gst_video_format_to_string (video_format), NULL); + + GST_DEBUG_OBJECT (self, "Update caps %" GST_PTR_FORMAT " to %" + GST_PTR_FORMAT, self->selected_video_caps, caps); + self->selected_mode = new_mode; + gst_caps_replace (&self->selected_video_caps, caps); + gst_caps_unref (caps); + } + } + } + } + + hr = frame->GetTimecode (self->timecode_format, &timecode); + if (hr == S_OK) { + guint8 h, m, s, f; + hr = timecode->GetComponents (&h, &m, &s, &f); + if (gst_decklink2_result (hr)) { + GstVideoTimeCodeFlags tc_flags = GST_VIDEO_TIME_CODE_FLAGS_NONE; + GstVideoTimeCode tc; + + if (self->selected_mode.interlaced) { + tc_flags = (GstVideoTimeCodeFlags) (tc_flags | + GST_VIDEO_TIME_CODE_FLAGS_INTERLACED); + } + + if (self->selected_mode.fps_d == 1001 && + (self->selected_mode.fps_n == 30000 || + self->selected_mode.fps_d == 60000)) { + tc_flags = (GstVideoTimeCodeFlags) (tc_flags | + GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME); + } + + gst_video_time_code_init (&tc, self->selected_mode.fps_n, + self->selected_mode.fps_d, NULL, tc_flags, h, m, s, f, 0); + gst_buffer_add_video_time_code_meta (buffer, &tc); + gst_video_time_code_clear (&tc); + } + + timecode->Release (); + } + + if (self->selected_mode.interlaced) { + GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED); + if (self->selected_mode.tff) + GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_FLAG_TFF); + } + + if (self->discont) { + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + self->discont = FALSE; + } + + GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_PTS (buffer) = pts; + GST_BUFFER_DURATION (buffer) = dur; + } + + if (packet) { + GstBuffer *audio_buf = NULL; + void *packet_data; + BMDTimeValue packet_time; + guint64 audio_offset, audio_offset_end; + gsize audio_buf_size; + GstMapInfo map; + + if (self->audio_offset == INVALID_AUDIO_OFFSET && !frame) { + GST_DEBUG_OBJECT (self, "Drop audio without video frame"); + goto out; + } + + long sample_count = packet->GetSampleFrameCount (); + if (sample_count == 0) { + GST_DEBUG_OBJECT (self, "Empty audio packet"); + goto out; + } + + hr = packet->GetPacketTime (&packet_time, self->audio_info.rate); + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, "Unknown audio packet time"); + goto out; + } + + hr = packet->GetBytes (&packet_data); + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, "Couldn't get audio packet data"); + goto out; + } + + audio_offset = packet_time; + audio_offset_end = audio_offset + sample_count; + audio_buf_size = self->audio_info.bpf * sample_count; + audio_buf = gst_buffer_new_and_alloc (audio_buf_size); + gst_buffer_map (audio_buf, &map, GST_MAP_WRITE); + memcpy (map.data, packet_data, map.size); + gst_buffer_unmap (audio_buf, &map); + + if (self->audio_offset == INVALID_AUDIO_OFFSET) { + GstClockTime audio_pts; + GstClockTime packet_time_in_gst; + + packet_time_in_gst = gst_util_uint64_scale (GST_SECOND, packet_time, + self->audio_info.rate); + + audio_pts = gst_clock_adjust_with_calibration (NULL, + packet_time_in_gst, + self->current_time_mapping.xbase, self->current_time_mapping.b, + self->current_time_mapping.num, self->current_time_mapping.den); + + /* Back to sample offset */ + self->audio_offset = gst_util_uint64_scale (audio_pts, + self->audio_info.rate, GST_SECOND); + + GST_DEBUG_OBJECT (self, "Initial audio offset at %" G_GUINT64_FORMAT + " for pts %" GST_TIME_FORMAT ", packet time %" GST_TIME_FORMAT, + self->audio_offset, GST_TIME_ARGS (audio_pts), + GST_TIME_ARGS (packet_time_in_gst)); + } + + if (self->next_audio_offset == INVALID_AUDIO_OFFSET) { + self->next_audio_offset = audio_offset_end; + } else if (self->next_audio_offset != audio_offset) { + GST_WARNING_OBJECT (self, "Expected offset %" G_GUINT64_FORMAT + ", received %" G_GUINT64_FORMAT, self->next_audio_offset, + audio_offset); + self->audio_discont = TRUE; + + if (self->next_audio_offset > audio_offset) { + gsize trim = self->next_audio_offset - audio_offset; + gsize count; + + if (trim >= (gsize) sample_count) { + GST_WARNING_OBJECT (self, "Complately backward audio pts"); + gst_buffer_unref (audio_buf); + goto out; + } + + count = sample_count - trim; + audio_buf = gst_audio_buffer_truncate (audio_buf, self->audio_info.bpf, + trim, count); + self->next_audio_offset += count; + } else { + GstBuffer *silence; + gsize diff = audio_offset - self->next_audio_offset; + + silence = gst_buffer_new_and_alloc (diff * self->audio_info.bpf); + gst_buffer_map (silence, &map, GST_MAP_WRITE); + gst_audio_format_info_fill_silence (self->audio_info.finfo, + map.data, map.size); + gst_buffer_unmap (silence, &map); + gst_adapter_push (self->audio_buf, silence); + self->next_audio_offset += sample_count + diff; + } + } else { + GST_LOG_OBJECT (self, "Got expected audio samples"); + self->next_audio_offset += sample_count; + } + + if (audio_buf) + gst_adapter_push (self->audio_buf, audio_buf); + } + +out: + if (buffer) { + GstSample *sample; + gsize audio_size; + while (priv->queue.size () > self->buffer_size) { + GstBuffer *old_buf; + + sample = priv->queue.front (); + old_buf = gst_sample_get_buffer (sample); + + GST_DEBUG_OBJECT (self, "Dropping old buffer %" GST_PTR_FORMAT, old_buf); + gst_sample_unref (sample); + priv->queue.pop (); + } + + audio_size = gst_adapter_available (self->audio_buf); + if (audio_size > 0) { + GstBuffer *audio_buf = gst_adapter_take_buffer (self->audio_buf, + audio_size); + guint64 sample_count = audio_size / self->audio_info.bpf; + + GST_BUFFER_DTS (audio_buf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_PTS (audio_buf) = + gst_util_uint64_scale (self->audio_offset, GST_SECOND, + self->audio_info.rate); + GST_BUFFER_DURATION (audio_buf) = + gst_util_uint64_scale (sample_count, GST_SECOND, + self->audio_info.rate); + if (self->audio_discont) { + GST_BUFFER_FLAG_SET (audio_buf, GST_BUFFER_FLAG_DISCONT); + self->audio_discont = FALSE; + } + + self->audio_offset += sample_count; + + GST_LOG_OBJECT (self, "Adding audio buffer %" GST_PTR_FORMAT, audio_buf); + + sample = gst_sample_new (audio_buf, self->selected_audio_caps, NULL, + NULL); + gst_buffer_add_decklink2_audio_meta (buffer, sample); + gst_sample_unref (sample); + + /* FIXME: make configurable? */ + if (frame && packet) { + GstClockTime diff = 0; + /* Video PTS are calibrated but not for audio to make audio pts + * and duration perfect. Then audio/video may be out of sync. + * Determine resync if large gap is detected */ + if (GST_BUFFER_PTS (buffer) >= GST_BUFFER_PTS (audio_buf)) + diff = GST_BUFFER_PTS (buffer) - GST_BUFFER_PTS (audio_buf); + else + diff = GST_BUFFER_PTS (audio_buf) - GST_BUFFER_PTS (buffer); + + if (diff > 250 * GST_MSECOND) { + GST_WARNING_OBJECT (self, "Large gap detected %" GST_TIME_FORMAT + ", video pts %" GST_TIME_FORMAT ", audio pts %" GST_TIME_FORMAT + ", do resync", GST_TIME_ARGS (diff), + GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_PTS (audio_buf))); + self->audio_offset = INVALID_AUDIO_OFFSET; + self->next_audio_offset = INVALID_AUDIO_OFFSET; + self->audio_discont = TRUE; + } + } + + gst_buffer_unref (audio_buf); + } + + sample = gst_sample_new (buffer, self->selected_video_caps, NULL, NULL); + GST_LOG_OBJECT (self, "Enqueue buffer %" GST_PTR_FORMAT, buffer); + gst_buffer_unref (buffer); + + priv->queue.push (sample); + priv->cond.notify_all (); + } +} + +static void +gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) +{ + GstDeckLink2InputPrivate *priv = self->priv; + + gst_decklink2_input_stop_streams (self); + gst_decklink2_input_disable_video (self); + gst_decklink2_input_disable_audio (self); + gst_decklink2_input_set_callback (self, NULL); + while (!priv->queue.empty ()) { + GstSample *sample = priv->queue.front (); + gst_sample_unref (sample); + priv->queue.pop (); + } + gst_clear_caps (&self->selected_video_caps); + gst_clear_caps (&self->selected_audio_caps); + priv->signal = false; +} + +HRESULT +gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, + BMDProfileID profile_id, guint buffer_size, + const GstDeckLink2InputVideoConfig * video_config, + const GstDeckLink2InputAudioConfig * audio_config) +{ + GstDeckLink2InputPrivate *priv = input->priv; + std::lock_guard < std::mutex > lk (priv->lock); + HRESULT hr; + BMDVideoInputFlags input_flags = bmdVideoInputFlagDefault; + + gst_decklink2_input_stop_unlocked (input); + gst_decklink2_input_reset_time_mapping (input); + + if (profile_id != bmdProfileDefault) { + GstDeckLink2Object *object; + gchar *profile_id_str = g_enum_to_string (GST_TYPE_DECKLINK2_PROFILE_ID, + profile_id); + + object = (GstDeckLink2Object *) gst_object_get_parent (GST_OBJECT (input)); + g_assert (object); + + gst_decklink2_object_set_profile_id (object, profile_id); + gst_object_unref (object); + + g_free (profile_id_str); + } + + if (video_config->connection != bmdVideoConnectionUnspecified) { + hr = E_FAIL; + if (input->config) { + hr = input->config->SetInt (bmdDeckLinkConfigVideoInputConnection, + video_config->connection); + } else if (input->config_10_11) { + hr = input->config_10_11->SetInt (bmdDeckLinkConfigVideoInputConnection, + video_config->connection); + } + + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (input, "Couldn't set video connection, hr: 0x%x", + (guint) hr); + return hr; + } + + if (video_config->connection == bmdVideoConnectionComposite) { + hr = E_FAIL; + if (input->config) { + hr = input->config->SetInt (bmdDeckLinkConfigAnalogVideoInputFlags, + bmdAnalogVideoFlagCompositeSetup75); + } else if (input->config_10_11) { + hr = input-> + config_10_11->SetInt (bmdDeckLinkConfigAnalogVideoInputFlags, + bmdAnalogVideoFlagCompositeSetup75); + } + + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (input, + "Couldn't set analog video input flags, hr: 0x%x", (guint) hr); + return hr; + } + } + } + + if (video_config->auto_detect) { + dlbool_t auto_detect = false; + + if (input->attr) { + hr = input->attr->GetFlag (BMDDeckLinkSupportsInputFormatDetection, + &auto_detect); + if (!gst_decklink2_result (hr) || !auto_detect) { + GST_ERROR_OBJECT (input, "Auto detect is not supported"); + return E_FAIL; + } + } else if (input->attr_10_11) { + hr = input->attr_10_11->GetFlag (BMDDeckLinkSupportsInputFormatDetection, + &auto_detect); + if (!gst_decklink2_result (hr) || !auto_detect) { + GST_ERROR_OBJECT (input, "Auto detect is not supported"); + return E_FAIL; + } + } else { + GST_ERROR_OBJECT (input, + "IDeckLinkProfileAttributes interface is not available"); + return E_FAIL; + } + + GST_DEBUG_OBJECT (input, "Enable format detection"); + + input_flags |= bmdVideoInputEnableFormatDetection; + } + + input->client = client; + input->selected_mode = video_config->display_mode; + input->pixel_format = video_config->pixel_format; + input->output_cc = video_config->output_cc; + input->output_afd_bar = video_config->output_afd_bar; + input->buffer_size = buffer_size; + input->selected_video_caps = gst_decklink2_input_get_caps (input, + input->selected_mode.mode, video_config->pixel_format); + if (!input->selected_video_caps) { + GST_ERROR_OBJECT (input, "Unable to get caps from requested mode"); + goto error; + } + + input->auto_detect = video_config->auto_detect; + input->aspect_ratio_flag = -1; + input->audio_offset = INVALID_AUDIO_OFFSET; + input->next_audio_offset = INVALID_AUDIO_OFFSET; + input->audio_discont = FALSE; + + if (input->callback) + hr = gst_decklink2_input_set_callback (input, input->callback); + else + hr = gst_decklink2_input_set_callback (input, input->callback_11_5_1); + + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (input, "Couldn't set callback"); + goto error; + } + + hr = gst_decklink2_input_enable_video (input, + gst_decklink2_get_real_display_mode (input->selected_mode.mode), + video_config->pixel_format, input_flags); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (input, "Couldn't enable video"); + goto error; + } + + if (audio_config->channels != GST_DECKLINK2_AUDIO_CHANNELS_DISABLED) { + guint channels = 2; + switch (audio_config->channels) { + case GST_DECKLINK2_AUDIO_CHANNELS_2: + channels = 2; + break; + case GST_DECKLINK2_AUDIO_CHANNELS_8: + channels = 8; + break; + case GST_DECKLINK2_AUDIO_CHANNELS_16: + channels = 16; + break; + case GST_DECKLINK2_AUDIO_CHANNELS_MAX: + channels = input->max_audio_channels; + break; + default: + break; + } + + hr = gst_decklink2_input_enable_audio (input, bmdAudioSampleRate48kHz, + audio_config->sample_type, channels); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (input, "Couldn't enable audio"); + goto error; + } + + gst_audio_info_set_format (&input->audio_info, + audio_config->sample_type == bmdAudioSampleType32bitInteger ? + GST_AUDIO_FORMAT_S32LE : GST_AUDIO_FORMAT_S16LE, 48000, channels, NULL); + input->selected_audio_caps = gst_audio_info_to_caps (&input->audio_info); + } + + hr = gst_decklink2_input_start_streams (input); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (input, "Couldn't start streams"); + goto error; + } + + return S_OK; + +error: + gst_decklink2_input_stop_unlocked (input); + input->client = NULL; + return E_FAIL; +} + +void +gst_decklink2_input_stop (GstDeckLink2Input * input) +{ + GstDeckLink2InputPrivate *priv = input->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + gst_decklink2_input_stop_unlocked (input); + input->client = NULL; +} + +void +gst_decklink2_input_set_flushing (GstDeckLink2Input * input, gboolean flush) +{ + GstDeckLink2InputPrivate *priv = input->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + input->flushing = flush; + priv->cond.notify_all (); +} + +GstFlowReturn +gst_decklink2_input_get_sample (GstDeckLink2Input * input, GstSample ** sample) +{ + GstDeckLink2InputPrivate *priv = input->priv; + std::unique_lock < std::mutex > lk (priv->lock); + + while (priv->queue.empty () && !input->flushing) + priv->cond.wait (lk); + + if (input->flushing) + return GST_FLOW_FLUSHING; + + *sample = priv->queue.front (); + priv->queue.pop (); + + return GST_FLOW_OK; +} + +gboolean +gst_decklink2_input_has_signal (GstDeckLink2Input * input) +{ + GstDeckLink2InputPrivate *priv = input->priv; + + if (priv->signal) + return TRUE; + + return FALSE; +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h new file mode 100644 index 0000000000..481a9a6a62 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h @@ -0,0 +1,77 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include "gstdecklink2utils.h" + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_INPUT (gst_decklink2_input_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Input, gst_decklink2_input, + GST, DECKLINK2_INPUT, GstObject); + +typedef struct _GstDeckLink2InputVideoConfig +{ + BMDVideoConnection connection; + GstDeckLink2DisplayMode display_mode; + BMDPixelFormat pixel_format; + gboolean auto_detect; + gboolean output_cc; + gboolean output_afd_bar; +} GstDeckLink2InputVideoConfig; + +typedef struct _GstDeckLink2InputAudioConfig +{ + BMDAudioConnection connection; + BMDAudioSampleType sample_type; + GstDeckLink2AudioChannels channels; +} GstDeckLink2InputAudioConfig; + +GstDeckLink2Input * gst_decklink2_input_new (IDeckLink * device, + GstDeckLink2APILevel api_level); + +GstCaps * gst_decklink2_input_get_caps (GstDeckLink2Input * input, + BMDDisplayMode mode, + BMDPixelFormat format); + +gboolean gst_decklink2_input_get_display_mode (GstDeckLink2Input * input, + const GstVideoInfo * info, + GstDeckLink2DisplayMode * display_mode); + +HRESULT gst_decklink2_input_start (GstDeckLink2Input * input, + GstElement * client, + BMDProfileID profile_id, + guint buffer_size, + const GstDeckLink2InputVideoConfig * video_config, + const GstDeckLink2InputAudioConfig * audio_config); + +void gst_decklink2_input_stop (GstDeckLink2Input * input); + +void gst_decklink2_input_set_flushing (GstDeckLink2Input * input, + gboolean flush); + +GstFlowReturn gst_decklink2_input_get_sample (GstDeckLink2Input * input, + GstSample ** sample); + +gboolean gst_decklink2_input_has_signal (GstDeckLink2Input * input); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.cpp new file mode 100644 index 0000000000..9f958cc549 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.cpp @@ -0,0 +1,712 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2object.h" +#include "gstdecklink2deviceprovider.h" +#include +#include +#include +#include +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (gst_decklink2_debug); +#define GST_CAT_DEFAULT gst_decklink2_debug + +/* *INDENT-OFF* */ +static std::vector device_list; +static std::mutex device_lock; +/* *INDENT-ON* */ + +struct _GstDeckLink2Object +{ + GstObject parent; + + GstDeckLink2APILevel api_level; + + IDeckLink *device; + IDeckLinkProfileAttributes *attr; + IDeckLinkAttributes_v10_11 *attr_10_11; + IDeckLinkConfiguration *config; + IDeckLinkConfiguration_v10_11 *config_10_11; + IDeckLinkProfileManager *profile_manager; + + GstDeckLink2Input *input; + GstDevice *input_device; + + GstDeckLink2Output *output; + GstDevice *output_device; + + guint device_number; + gint64 persistent_id; + gchar *serial_number; + gchar *model_name; + gchar *display_name; + + gboolean input_acquired; + gboolean output_acquired; +}; + +static void gst_decklink2_object_dispose (GObject * object); +static void gst_decklink2_object_finalize (GObject * object); + +#define gst_decklink2_object_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2Object, gst_decklink2_object, GST_TYPE_OBJECT); + +static void +gst_decklink2_object_class_init (GstDeckLink2ObjectClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gst_decklink2_object_dispose; + object_class->finalize = gst_decklink2_object_finalize; +} + +static void +gst_decklink2_object_init (GstDeckLink2Object * self) +{ +} + +static void +gst_decklink2_object_dispose (GObject * object) +{ + GstDeckLink2Object *self = GST_DECKLINK2_OBJECT (object); + + if (self->input) { + gst_object_unparent (GST_OBJECT (self->input)); + self->input = NULL; + } + + if (self->output) { + gst_object_unparent (GST_OBJECT (self->output)); + self->output = NULL; + } + + gst_clear_object (&self->input_device); + gst_clear_object (&self->output_device); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_decklink2_object_finalize (GObject * object) +{ + GstDeckLink2Object *self = GST_DECKLINK2_OBJECT (object); + + GST_DECKLINK2_CLEAR_COM (self->attr); + GST_DECKLINK2_CLEAR_COM (self->attr_10_11); + GST_DECKLINK2_CLEAR_COM (self->config); + GST_DECKLINK2_CLEAR_COM (self->config_10_11); + GST_DECKLINK2_CLEAR_COM (self->profile_manager); + GST_DECKLINK2_CLEAR_COM (self->device); + + g_free (self->serial_number); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstDeckLink2Object * +gst_decklink2_object_new (IDeckLink * device, guint index, + GstDeckLink2APILevel api_level, const gchar * api_ver_str, + const gchar * driver_ver_str) +{ + HRESULT hr; + GstDeckLink2Input *input; + GstDeckLink2Output *output; + GstDeckLink2Object *self; + dlstring_t str; + gint64 max_num_audio_channels = 0; + GstCaps *caps = NULL; + + input = gst_decklink2_input_new (device, api_level); + output = gst_decklink2_output_new (device, api_level); + + if (!output && !input) + return NULL; + + self = (GstDeckLink2Object *) + g_object_new (GST_TYPE_DECKLINK2_OBJECT, NULL); + gst_object_ref_sink (self); + + self->api_level = api_level; + + if (input) + gst_object_set_parent (GST_OBJECT (input), GST_OBJECT (self)); + + if (output) + gst_object_set_parent (GST_OBJECT (output), GST_OBJECT (self)); + + self->input = input; + self->output = output; + self->device_number = index; + self->device = device; + device->AddRef (); + + if (api_level == GST_DECKLINK2_API_LEVEL_10_11) { + IDeckLinkConfiguration_v10_11 *config_10_11 = NULL; + hr = device->QueryInterface (IID_IDeckLinkConfiguration_v10_11, + (void **) &config_10_11); + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, "Couldn't get config object"); + gst_object_unref (self); + return NULL; + } + + hr = config_10_11->GetString + (bmdDeckLinkConfigDeviceInformationSerialNumber, &str); + + if (gst_decklink2_result (hr)) { + std::string serial_number = DlToStdString (str); + DeleteString (str); + + self->serial_number = g_strdup (serial_number.c_str ()); + GST_DEBUG_OBJECT (self, "device %d has serial number %s", index, + GST_STR_NULL (self->serial_number)); + } + + self->config_10_11 = config_10_11; + } else { + IDeckLinkConfiguration *config = NULL; + hr = device->QueryInterface (IID_IDeckLinkConfiguration, (void **) &config); + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, "Couldn't get config object"); + gst_object_unref (self); + return NULL; + } + + hr = config->GetString (bmdDeckLinkConfigDeviceInformationSerialNumber, + &str); + if (gst_decklink2_result (hr)) { + std::string serial_number = DlToStdString (str); + DeleteString (str); + + self->serial_number = g_strdup (serial_number.c_str ()); + GST_DEBUG_OBJECT (self, "device %d has serial number %s", index, + GST_STR_NULL (self->serial_number)); + } + + self->config = config; + device->QueryInterface (IID_IDeckLinkProfileManager, + (void **) &self->profile_manager); + } + + if (api_level == GST_DECKLINK2_API_LEVEL_10_11) { + hr = device->QueryInterface (IID_IDeckLinkAttributes_v10_11, + (void **) &self->attr_10_11); + } else { + hr = device->QueryInterface (IID_IDeckLinkProfileAttributes, + (void **) &self->attr); + } + + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, + "IDeckLinkProfileAttributes interface is not available"); + self->persistent_id = self->device_number; + } else { + hr = E_FAIL; + if (self->attr) { + hr = self->attr->GetInt (BMDDeckLinkPersistentID, &self->persistent_id); + if (!gst_decklink2_result (hr)) + self->persistent_id = self->device_number; + hr = self->attr->GetInt (BMDDeckLinkMaximumAudioChannels, + &max_num_audio_channels); + } else if (self->attr_10_11) { + hr = self->attr_10_11->GetInt (BMDDeckLinkPersistentID, + &self->persistent_id); + if (!gst_decklink2_result (hr)) + self->persistent_id = self->device_number; + hr = self->attr_10_11->GetInt (BMDDeckLinkMaximumAudioChannels, + &max_num_audio_channels); + } + + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (self, "Couldn't query max audio channels"); + max_num_audio_channels = 0; + } + } + + hr = device->GetModelName (&str); + if (gst_decklink2_result (hr)) { + std::string model_name = DlToStdString (str); + DeleteString (str); + + self->model_name = g_strdup (model_name.c_str ()); + } + + hr = device->GetDisplayName (&str); + if (gst_decklink2_result (hr)) { + std::string display_name = DlToStdString (str); + DeleteString (str); + + self->display_name = g_strdup (display_name.c_str ()); + } + + if (self->input) { + caps = gst_decklink2_input_get_caps (self->input, + bmdModeUnknown, bmdFormatUnspecified); + self->input_device = gst_decklink2_device_new (TRUE, self->model_name, + self->display_name, self->serial_number, caps, self->persistent_id, + self->device_number, (guint) max_num_audio_channels, driver_ver_str, + api_ver_str); + gst_clear_caps (&caps); + gst_object_ref_sink (self->input_device); + } + + if (self->output) { + caps = gst_decklink2_output_get_caps (self->output, + bmdModeUnknown, bmdFormatUnspecified); + self->output_device = gst_decklink2_device_new (FALSE, self->model_name, + self->display_name, self->serial_number, caps, self->persistent_id, + self->device_number, (guint) max_num_audio_channels, driver_ver_str, + api_ver_str); + gst_clear_caps (&caps); + gst_object_ref_sink (self->output_device); + } + + return self; +} + +#ifdef G_OS_WIN32 +static IDeckLinkIterator * +CreateDeckLinkIteratorInstance (void) +{ + IDeckLinkIterator *iter = NULL; + CoCreateInstance (CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, + IID_IDeckLinkIterator, (void **) &iter); + + return iter; +} + +static IDeckLinkIterator * +CreateDeckLinkIteratorInstance_v10_11 (void) +{ + IDeckLinkIterator *iter = NULL; + CoCreateInstance (CLSID_CDeckLinkIterator_v10_11, NULL, CLSCTX_ALL, + IID_IDeckLinkIterator, (void **) &iter); + + return iter; +} +#endif + +static void +gst_decklink2_device_init (void) +{ + GstDeckLink2APILevel api_level = gst_decklink2_get_api_level (); + IDeckLinkIterator *iter = NULL; + HRESULT hr = S_OK; + guint major, minor, sub, extra; + std::string driver_version; + std::string api_version; + + if (api_level == GST_DECKLINK2_API_LEVEL_UNKNOWN) + return; + + api_version = gst_decklink2_api_level_to_string (api_level); + + gst_decklink2_get_api_version (&major, &minor, &sub, &extra); + driver_version = std::to_string (major) + "." + std::to_string (minor) + + "." + std::to_string (sub) + "." + std::to_string (extra); + + if (api_level == GST_DECKLINK2_API_LEVEL_10_11) { + iter = CreateDeckLinkIteratorInstance_v10_11 (); + } else { + iter = CreateDeckLinkIteratorInstance (); + } + + if (!iter) { + GST_DEBUG ("Couldn't create device iterator"); + return; + } + + guint i = 0; + do { + IDeckLink *device = NULL; + GstDeckLink2Object *object; + hr = iter->Next (&device); + if (!gst_decklink2_result (hr)) + break; + + object = gst_decklink2_object_new (device, i, api_level, + api_version.c_str (), driver_version.c_str ()); + device->Release (); + + if (object) + device_list.push_back (object); + + i++; + } while (gst_decklink2_result (hr)); + + iter->Release (); + + std::sort (device_list.begin (), device_list.end (), + [](const GstDeckLink2Object * a, const GstDeckLink2Object * b)->bool + { + { + return a->persistent_id < b->persistent_id; + } + } + ); + + GST_DEBUG ("Found %u device", (guint) device_list.size ()); +} + +static void +gst_decklink2_device_init_once (void) +{ + GST_DECKLINK2_CALL_ONCE_BEGIN { + std::lock_guard < std::mutex > lk (device_lock); + gst_decklink2_device_init (); + } GST_DECKLINK2_CALL_ONCE_END; +} + +GstDeckLink2Input * +gst_decklink2_acquire_input (guint device_number, gint64 persistent_id) +{ + GstDeckLink2Object *target = NULL; + + gst_decklink2_device_init_once (); + + std::lock_guard < std::mutex > lk (device_lock); + + /* *INDENT-OFF* */ + if (persistent_id != -1) { + auto object = std::find_if (device_list.begin (), device_list.end (), + [&](const GstDeckLink2Object * obj) { + return obj->persistent_id == persistent_id; + }); + + if (object == device_list.end ()) { + GST_WARNING ("Couldn't find object for persistent id %" G_GINT64_FORMAT, + persistent_id); + return NULL; + } + + target = *object; + } + + if (!target) { + auto object = std::find_if (device_list.begin (), device_list.end (), + [&](const GstDeckLink2Object * obj) { + return obj->device_number == device_number; + }); + + if (object == device_list.end ()) { + GST_WARNING ("Couldn't find object for device number %u", device_number); + return NULL; + } + + target = *object; + } + /* *INDENT-ON* */ + + if (!target->input) { + GST_WARNING_OBJECT (target, "Device does not support input"); + return NULL; + } + + if (target->input_acquired) { + GST_WARNING_OBJECT (target, "Input was already acquired"); + return NULL; + } + + target->input_acquired = TRUE; + return (GstDeckLink2Input *) gst_object_ref (target->input); +} + +GstDeckLink2Output * +gst_decklink2_acquire_output (guint device_number, gint64 persistent_id) +{ + GstDeckLink2Object *target = NULL; + + gst_decklink2_device_init_once (); + + std::lock_guard < std::mutex > lk (device_lock); + + /* *INDENT-OFF* */ + if (persistent_id != -1) { + auto object = std::find_if (device_list.begin (), device_list.end (), + [&](const GstDeckLink2Object * obj) { + return obj->persistent_id == persistent_id; + }); + + if (object == device_list.end ()) { + GST_WARNING ("Couldn't find object for persistent id %" G_GINT64_FORMAT, + persistent_id); + return NULL; + } + + target = *object; + } + + if (!target) { + auto object = std::find_if (device_list.begin (), device_list.end (), + [&](const GstDeckLink2Object * obj) { + return obj->device_number == device_number; + }); + + if (object == device_list.end ()) { + GST_WARNING ("Couldn't find object for device number %u", device_number); + return NULL; + } + + target = *object; + } + /* *INDENT-ON* */ + + if (!target->output) { + GST_WARNING_OBJECT (target, "Device does not support output"); + return NULL; + } + + if (target->output_acquired) { + GST_WARNING_OBJECT (target, "Output was already acquired"); + return NULL; + } + + target->output_acquired = TRUE; + return (GstDeckLink2Output *) gst_object_ref (target->output); +} + +void +gst_decklink2_release_input (GstDeckLink2Input * input) +{ + std::unique_lock < std::mutex > lk (device_lock); + auto object = std::find_if (device_list.begin (), device_list.end (), + [&](const GstDeckLink2Object * obj) { + return obj->input == input; + } + ); + + if (object == device_list.end ()) { + GST_ERROR_OBJECT (input, "Couldn't find parent object"); + } else { + (*object)->input_acquired = FALSE; + } + lk.unlock (); + + gst_object_unref (input); +} + +void +gst_decklink2_release_output (GstDeckLink2Output * output) +{ + std::unique_lock < std::mutex > lk (device_lock); + auto object = std::find_if (device_list.begin (), device_list.end (), + [&](const GstDeckLink2Object * obj) { + return obj->output == output; + } + ); + + if (object == device_list.end ()) { + GST_ERROR_OBJECT (output, "Couldn't find parent object"); + } else { + (*object)->output_acquired = FALSE; + } + lk.unlock (); + + gst_object_unref (output); +} + +void +gst_decklink2_object_deinit (void) +{ + std::lock_guard < std::mutex > lk (device_lock); + + /* *INDENT-OFF* */ + for (auto iter : device_list) + gst_object_unref (iter); + /* *INDENT-ON* */ + + device_list.clear (); +} + +GList * +gst_decklink2_get_devices (void) +{ + GList *list = NULL; + + gst_decklink2_device_init_once (); + + std::lock_guard < std::mutex > lk (device_lock); + + /* *INDENT-OFF* */ + for (auto iter : device_list) { + if (iter->input_device) + list = g_list_append (list, gst_object_ref (iter->input_device)); + + if (iter->output_device) + list = g_list_append (list, gst_object_ref (iter->output_device)); + } + /* *INDENT-ON* */ + + return list; +} + +static HRESULT +gst_decklink2_set_duplex_mode (gint64 persistent_id, BMDDuplexMode_v10_11 mode) +{ + GstDeckLink2Object *object = NULL; + HRESULT hr = E_FAIL; + dlbool_t duplex_supported = FALSE; + + std::lock_guard < std::mutex > lk (device_lock); + + /* *INDENT-OFF* */ + for (auto iter : device_list) { + if (iter->persistent_id == persistent_id) { + object = iter; + break; + } + } + /* *INDENT-ON* */ + + if (!object) { + GST_ERROR ("Couldn't find device for persistent id %" G_GINT64_FORMAT, + persistent_id); + return E_FAIL; + } + + if (!object->attr_10_11 || !object->config_10_11) { + GST_WARNING_OBJECT (object, + "Couldn't set duplex mode, missing required interface"); + return E_FAIL; + } + + hr = object->attr_10_11->GetFlag ((BMDDeckLinkAttributeID) + BMDDeckLinkSupportsDuplexModeConfiguration_v10_11, &duplex_supported); + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (object, "Couldn't query duplex mode support"); + return hr; + } + + if (!duplex_supported) { + GST_WARNING_OBJECT (object, "Duplex mode is not supported"); + return E_FAIL; + } + + return object->config_10_11->SetInt ((BMDDeckLinkConfigurationID) + bmdDeckLinkConfigDuplexMode_v10_11, mode); +} + +HRESULT +gst_decklink2_object_set_profile_id (GstDeckLink2Object * object, + BMDProfileID profile_id) +{ + gchar *profile_id_str = NULL; + HRESULT hr = E_FAIL; + + g_return_val_if_fail (GST_IS_DECKLINK2_OBJECT (object), E_INVALIDARG); + + if (profile_id == bmdProfileDefault) + return S_OK; + + profile_id_str = g_enum_to_string (GST_TYPE_DECKLINK2_PROFILE_ID, profile_id); + + GST_DEBUG_OBJECT (object, "Setting profile id \"%s\"", profile_id_str); + + if (object->api_level == GST_DECKLINK2_API_LEVEL_10_11) { + dlbool_t duplex_supported = FALSE; + BMDDuplexMode_v10_11 duplex_mode = bmdDuplexModeHalf_v10_11; + + if (!object->attr_10_11 || !object->config_10_11) { + GST_WARNING_OBJECT (object, + "Couldn't set duplex mode, missing required interface"); + hr = E_FAIL; + goto out; + } + + switch (profile_id) { + case bmdProfileOneSubDeviceHalfDuplex: + case bmdProfileTwoSubDevicesHalfDuplex: + case bmdProfileFourSubDevicesHalfDuplex: + duplex_mode = bmdDuplexModeHalf_v10_11; + GST_DEBUG_OBJECT (object, "Mapping \"%s\" to bmdDuplexModeHalf"); + break; + default: + GST_DEBUG_OBJECT (object, "Mapping \"%s\" to bmdDuplexModeFull"); + duplex_mode = bmdDuplexModeFull_v10_11; + break; + } + + hr = object->attr_10_11->GetFlag ((BMDDeckLinkAttributeID) + BMDDeckLinkSupportsDuplexModeConfiguration_v10_11, &duplex_supported); + if (!gst_decklink2_result (hr)) + duplex_supported = FALSE; + + if (!duplex_supported) { + gint64 paired_device_id = 0; + if (duplex_mode == bmdDuplexModeFull_v10_11) { + GST_WARNING_OBJECT (object, "Device does not support Full-Duplex-Mode"); + goto out; + } + + hr = object->attr_10_11->GetInt ((BMDDeckLinkAttributeID) + BMDDeckLinkPairedDevicePersistentID_v10_11, &paired_device_id); + if (gst_decklink2_result (hr)) { + GST_DEBUG_OBJECT (object, + "Device has paired device, Setting duplex mode to paired device"); + hr = gst_decklink2_set_duplex_mode (paired_device_id, duplex_mode); + } else { + GST_WARNING_OBJECT (object, "Device does not support Half-Duplex-Mode"); + } + } else { + hr = object->config_10_11->SetInt ((BMDDeckLinkConfigurationID) + bmdDeckLinkConfigDuplexMode_v10_11, duplex_mode); + } + + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (object, + "Couldn't set profile \"%s\"", profile_id_str); + } else { + GST_DEBUG_OBJECT (object, "Profile \"%s\" is configured", profile_id_str); + } + } else { + IDeckLinkProfile *profile = NULL; + + if (!object->profile_manager) { + GST_WARNING_OBJECT (object, + "Profile \"%s\" is requested but profile manager is not available", + profile_id_str); + goto out; + } + + hr = object->profile_manager->GetProfile (profile_id, &profile); + if (gst_decklink2_result (hr)) { + hr = profile->SetActive (); + profile->Release (); + } + + if (!gst_decklink2_result (hr)) { + GST_WARNING_OBJECT (object, + "Couldn't set profile \"%s\"", profile_id_str); + } else { + GST_DEBUG_OBJECT (object, "Profile \"%s\" is configured", profile_id_str); + } + } + +out: + g_free (profile_id_str); + + return hr; +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.h new file mode 100644 index 0000000000..3f001e0f3c --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2object.h @@ -0,0 +1,51 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include "gstdecklink2utils.h" +#include "gstdecklink2input.h" +#include "gstdecklink2output.h" + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_OBJECT (gst_decklink2_object_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Object, gst_decklink2_object, + GST, DECKLINK2_OBJECT, GstObject); + +GstDeckLink2Input * gst_decklink2_acquire_input (guint device_number, + gint64 persistent_id); + +GstDeckLink2Output * gst_decklink2_acquire_output (guint device_number, + gint64 persistent_id); + +void gst_decklink2_release_input (GstDeckLink2Input * input); + +void gst_decklink2_release_output (GstDeckLink2Output * output); + +void gst_decklink2_object_deinit (void); + +GList * gst_decklink2_get_devices (void); + +HRESULT gst_decklink2_object_set_profile_id (GstDeckLink2Object * object, + BMDProfileID profile_id); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp new file mode 100644 index 0000000000..01c508493d --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -0,0 +1,1806 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2output.h" +#include "gstdecklink2object.h" +#include + +#include +#include +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_decklink2_output_debug); +#define GST_CAT_DEFAULT gst_decklink2_output_debug + +class IGstDeckLinkVideoOutputCallback; + +struct GstDeckLink2OutputPrivate +{ + std::mutex extern_lock; + std::mutex schedule_lock; + std::condition_variable cond; +}; + +struct _GstDeckLink2Output +{ + GstObject parent; + + GstDeckLink2OutputPrivate *priv; + + GstDeckLink2APILevel api_level; + + IDeckLink *device; + IDeckLinkProfileAttributes *attr; + IDeckLinkAttributes_v10_11 *attr_10_11; + IDeckLinkConfiguration *config; + IDeckLinkConfiguration_v10_11 *config_10_11; + IDeckLinkKeyer *keyer; + + IDeckLinkOutput *output; + IDeckLinkOutput_v11_4 *output_11_4; + IDeckLinkOutput_v10_11 *output_10_11; + + IGstDeckLinkVideoOutputCallback *callback; + IDeckLinkVideoFrame *last_frame; + + GstCaps *caps; + GArray *format_table; + guint max_audio_channels; + + GstDeckLink2DisplayMode selected_mode; + GstAudioInfo audio_info; + + GstVideoVBIEncoder *vbi_enc; + gint vbi_width; + guint16 cdp_hdr_sequence_cntr; + guint n_prerolled; + guint64 n_frames; + guint n_preroll_frames; + guint min_buffered; + guint max_buffered; + GstClockTime pts; + + gboolean configured; + gboolean prerolled; +}; + +static void gst_decklink2_output_dispose (GObject * object); +static void gst_decklink2_output_finalize (GObject * object); +static void gst_decklink2_output_on_stopped (GstDeckLink2Output * self); +static void gst_decklink2_output_on_completed (GstDeckLink2Output * self); + +#define gst_decklink2_output_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2Output, gst_decklink2_output, GST_TYPE_OBJECT); + +class IGstDeckLinkVideoOutputCallback:public IDeckLinkVideoOutputCallback +{ +public: + IGstDeckLinkVideoOutputCallback (GstDeckLink2Output * output) + :ref_count_ (1), output_ (output) + { + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkVideoOutputCallback) { + *object = static_cast < IDeckLinkVideoOutputCallback * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkVideoOutputCallback */ + HRESULT STDMETHODCALLTYPE + ScheduledFrameCompleted (IDeckLinkVideoFrame * frame, + BMDOutputFrameCompletionResult result) + { + switch (result) { + case bmdOutputFrameCompleted: + GST_LOG_OBJECT (output_, "Completed frame %p", frame); + break; + case bmdOutputFrameDisplayedLate: + GST_WARNING_OBJECT (output_, "Late Frame %p", frame); + break; + case bmdOutputFrameDropped: + GST_WARNING_OBJECT (output_, "Dropped Frame %p", frame); + break; + case bmdOutputFrameFlushed: + GST_LOG_OBJECT (output_, "Flushed Frame %p", frame); + break; + default: + GST_WARNING_OBJECT (output_, "Unknown Frame %p: %d", + frame, (gint) result); + break; + } + + if (result == bmdOutputFrameCompleted || + result == bmdOutputFrameDisplayedLate) { + gst_decklink2_output_on_completed (output_); + } + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped (void) + { + gst_decklink2_output_on_stopped (output_); + return S_OK; + } + +private: + virtual ~ IGstDeckLinkVideoOutputCallback () { + } + +private: + std::atomic < ULONG > ref_count_; + GstDeckLink2Output *output_; +}; + +static void +gst_decklink2_output_class_init (GstDeckLink2OutputClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gst_decklink2_output_dispose; + object_class->finalize = gst_decklink2_output_finalize; + + GST_DEBUG_CATEGORY_INIT (gst_decklink2_output_debug, "decklink2output", + 0, "decklink2output"); +} + +static void +gst_decklink2_output_init (GstDeckLink2Output * self) +{ + self->priv = new GstDeckLink2OutputPrivate (); + self->format_table = g_array_new (FALSE, + FALSE, sizeof (GstDeckLink2DisplayMode)); + self->callback = new IGstDeckLinkVideoOutputCallback (self); +} + +static void +gst_decklink2_output_dispose (GObject * object) +{ + GstDeckLink2Output *self = GST_DECKLINK2_OUTPUT (object); + + gst_clear_caps (&self->caps); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_decklink2_output_finalize (GObject * object) +{ + GstDeckLink2Output *self = GST_DECKLINK2_OUTPUT (object); + + GST_DECKLINK2_CLEAR_COM (self->output); + GST_DECKLINK2_CLEAR_COM (self->output_11_4); + GST_DECKLINK2_CLEAR_COM (self->output_10_11); + GST_DECKLINK2_CLEAR_COM (self->keyer); + GST_DECKLINK2_CLEAR_COM (self->attr); + GST_DECKLINK2_CLEAR_COM (self->attr_10_11); + GST_DECKLINK2_CLEAR_COM (self->config); + GST_DECKLINK2_CLEAR_COM (self->config_10_11); + GST_DECKLINK2_CLEAR_COM (self->device); + GST_DECKLINK2_CLEAR_COM (self->callback); + + g_array_unref (self->format_table); + g_clear_pointer (&self->vbi_enc, gst_video_vbi_encoder_free); + + delete self->priv; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* Returns true if format is supported without conversion */ +static gboolean +gst_decklink2_output_does_support_video_mode (GstDeckLink2Output * self, + BMDDisplayMode mode, BMDPixelFormat format) +{ + HRESULT hr; + BMDDisplayModeSupport_v10_11 supported_v10_11 = + bmdDisplayModeNotSupported_v10_11; + dlbool_t supported = (dlbool_t) 0; + BMDDisplayMode actual_mode = mode; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->DoesSupportVideoMode (mode, format, + bmdVideoOutputFlagDefault, &supported_v10_11, NULL); + if (hr != S_OK || supported_v10_11 != bmdDisplayModeSupported_v10_11) + return FALSE; + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self-> + output_11_4->DoesSupportVideoMode (bmdVideoConnectionUnspecified, + mode, format, bmdSupportedVideoModeDefault, &actual_mode, &supported); + if (hr != S_OK || !supported || actual_mode != mode) + return FALSE; + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->DoesSupportVideoMode (bmdVideoConnectionUnspecified, + mode, format, bmdNoVideoOutputConversion, + bmdSupportedVideoModeDefault, &actual_mode, &supported); + if (hr != S_OK || !supported || actual_mode != mode) + return FALSE; + break; + default: + g_assert_not_reached (); + return FALSE; + } + + return TRUE; +} + +static IDeckLinkDisplayModeIterator * +gst_decklink2_output_get_iterator (GstDeckLink2Output * self) +{ + IDeckLinkDisplayModeIterator *iter = NULL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + self->output_10_11->GetDisplayModeIterator (&iter); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + self->output_11_4->GetDisplayModeIterator (&iter); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + self->output->GetDisplayModeIterator (&iter); + break; + default: + g_assert_not_reached (); + break; + } + + return iter; +} + +GstDeckLink2Output * +gst_decklink2_output_new (IDeckLink * device, GstDeckLink2APILevel api_level) +{ + GstDeckLink2Output *self; + IDeckLinkDisplayModeIterator *iter = NULL; + HRESULT hr; + + if (!device || api_level == GST_DECKLINK2_API_LEVEL_UNKNOWN) + return NULL; + + self = (GstDeckLink2Output *) g_object_new (GST_TYPE_DECKLINK2_OUTPUT, NULL); + self->api_level = api_level; + self->device = device; + device->AddRef (); + device->QueryInterface (IID_IDeckLinkKeyer, (void **) &self->keyer); + + if (api_level == GST_DECKLINK2_API_LEVEL_10_11) { + device->QueryInterface (IID_IDeckLinkAttributes_v10_11, + (void **) &self->attr_10_11); + } else { + device->QueryInterface (IID_IDeckLinkProfileAttributes, + (void **) &self->attr); + } + + self->max_audio_channels = 2; + gint64 max_audio_channels = 2; + if (self->attr) { + hr = self->attr->GetInt (BMDDeckLinkMaximumAudioChannels, + &max_audio_channels); + if (gst_decklink2_result (hr)) + self->max_audio_channels = (guint) max_audio_channels; + } else if (self->attr_10_11) { + hr = self->attr_10_11->GetInt (BMDDeckLinkMaximumAudioChannels, + &max_audio_channels); + if (gst_decklink2_result (hr)) + self->max_audio_channels = (guint) max_audio_channels; + } + + if (api_level == GST_DECKLINK2_API_LEVEL_10_11) { + device->QueryInterface (IID_IDeckLinkConfiguration_v10_11, + (void **) &self->config_10_11); + } else { + device->QueryInterface (IID_IDeckLinkConfiguration, + (void **) &self->config); + } + + switch (api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = device->QueryInterface (IID_IDeckLinkOutput_v10_11, + (void **) &self->output_10_11); + if (!gst_decklink2_result (hr)) { + gst_object_unref (self); + return NULL; + } + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = device->QueryInterface (IID_IDeckLinkOutput_v11_4, + (void **) &self->output_11_4); + if (!gst_decklink2_result (hr)) { + gst_object_unref (self); + return NULL; + } + + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = device->QueryInterface (IID_IDeckLinkOutput, + (void **) &self->output); + if (!gst_decklink2_result (hr)) { + gst_object_unref (self); + return NULL; + } + break; + default: + g_assert_not_reached (); + gst_object_unref (self); + return NULL; + } + + iter = gst_decklink2_output_get_iterator (self); + if (!iter) { + gst_object_unref (self); + return NULL; + } + + self->caps = gst_decklink2_build_template_caps (GST_OBJECT (self), iter, + (GstDeckLink2DoesSupportVideoMode) + gst_decklink2_output_does_support_video_mode, self->format_table); + iter->Release (); + + if (!self->caps) + gst_clear_object (&self); + + return self; +} + +GstCaps * +gst_decklink2_output_get_caps (GstDeckLink2Output * output, BMDDisplayMode mode, + BMDPixelFormat format) +{ + IDeckLinkDisplayModeIterator *iter = NULL; + GstCaps *caps; + + if (mode == bmdModeUnknown && format == bmdFormatUnspecified) + return gst_caps_ref (output->caps); + + iter = gst_decklink2_output_get_iterator (output); + if (!iter) + return NULL; + + caps = gst_decklink2_build_caps (GST_OBJECT (output), iter, + mode, format, (GstDeckLink2DoesSupportVideoMode) + gst_decklink2_output_does_support_video_mode); + iter->Release (); + + return caps; +} + +gboolean +gst_decklink2_output_get_display_mode (GstDeckLink2Output * output, + const GstVideoInfo * info, GstDeckLink2DisplayMode * display_mode) +{ + for (guint i = 0; i < output->format_table->len; i++) { + const GstDeckLink2DisplayMode *m = &g_array_index (output->format_table, + GstDeckLink2DisplayMode, i); + + if (m->width == info->width && m->height == info->height && + m->fps_n == info->fps_n && m->fps_d == info->fps_d && + m->par_n == info->par_n && m->par_d == info->par_d) { + if ((m->interlaced && !GST_VIDEO_INFO_IS_INTERLACED (info)) || + (!m->interlaced && GST_VIDEO_INFO_IS_INTERLACED (info))) { + continue; + } + + *display_mode = *m; + return TRUE; + } + } + + return FALSE; +} + +guint +gst_decklink2_output_get_max_audio_channels (GstDeckLink2Output * output) +{ + return output->max_audio_channels; +} + +static HRESULT +gst_decklink2_output_enable_video (GstDeckLink2Output * self, + BMDDisplayMode mode, BMDVideoOutputFlags flags) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->EnableVideoOutput (mode, flags); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->EnableVideoOutput (mode, flags); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->EnableVideoOutput (mode, flags); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_enable_audio (GstDeckLink2Output * self, + BMDAudioSampleRate rate, BMDAudioSampleType sample_type, guint channels, + BMDAudioOutputStreamType stream_type) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->EnableAudioOutput (rate, + sample_type, channels, stream_type); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->EnableAudioOutput (rate, + sample_type, channels, stream_type); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->EnableAudioOutput (rate, + sample_type, channels, stream_type); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_disable_video (GstDeckLink2Output * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->DisableVideoOutput (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->DisableVideoOutput (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->DisableVideoOutput (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_disable_audio (GstDeckLink2Output * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->DisableAudioOutput (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->DisableAudioOutput (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->DisableAudioOutput (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_begin_audio_preroll (GstDeckLink2Output * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->BeginAudioPreroll (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->BeginAudioPreroll (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->BeginAudioPreroll (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_end_audio_preroll (GstDeckLink2Output * self) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->EndAudioPreroll (); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->EndAudioPreroll (); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->EndAudioPreroll (); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_schedule_audio_samples (GstDeckLink2Output * self, + void *buffer, guint count, BMDTimeValue stream_time, + BMDTimeScale scale, guint * written) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->ScheduleAudioSamples (buffer, count, stream_time, + scale, written); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->ScheduleAudioSamples (buffer, count, stream_time, + scale, written); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->ScheduleAudioSamples (buffer, count, stream_time, + scale, written); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_set_video_callback (GstDeckLink2Output * self, + IDeckLinkVideoOutputCallback * callback) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->SetScheduledFrameCompletionCallback (callback); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->SetScheduledFrameCompletionCallback (callback); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->SetScheduledFrameCompletionCallback (callback); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_create_ancillary_data (GstDeckLink2Output * self, + BMDPixelFormat format, IDeckLinkVideoFrameAncillary ** frame) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->CreateAncillaryData (format, frame); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->CreateAncillaryData (format, frame); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->CreateAncillaryData (format, frame); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_is_running (GstDeckLink2Output * self, dlbool_t * active) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->IsScheduledPlaybackRunning (active); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->IsScheduledPlaybackRunning (active); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->IsScheduledPlaybackRunning (active); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_get_num_bufferred (GstDeckLink2Output * self, + guint32 * count) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->GetBufferedVideoFrameCount (count); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->GetBufferedVideoFrameCount (count); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->GetBufferedVideoFrameCount (count); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_start (GstDeckLink2Output * self, + BMDTimeValue start_time, BMDTimeScale scale, double speed) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->StartScheduledPlayback (start_time, + scale, speed); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->StartScheduledPlayback (start_time, scale, speed); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->StartScheduledPlayback (start_time, scale, speed); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, + IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size) +{ + GstClockTime next_pts, dur; + HRESULT hr = E_FAIL; + + frame->AddRef (); + GST_DECKLINK2_CLEAR_COM (self->last_frame); + self->last_frame = frame; + + self->n_frames++; + next_pts = gst_util_uint64_scale (self->n_frames, + self->selected_mode.fps_d * GST_SECOND, self->selected_mode.fps_n); + dur = next_pts - self->pts; + + GST_LOG_OBJECT (self, "Scheduling video frame %p, audio-buf-size %" + G_GSIZE_FORMAT, frame, audio_buf_size); + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->ScheduleVideoFrame (frame, + self->pts, dur, GST_SECOND); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->ScheduleVideoFrame (frame, + self->pts, dur, GST_SECOND); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->ScheduleVideoFrame (frame, self->pts, dur, GST_SECOND); + break; + default: + g_assert_not_reached (); + break; + } + + self->pts = next_pts; + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule video frame, hr: 0x%x", + (guint) hr); + return hr; + } + + if (!self->prerolled) { + if (self->n_prerolled == 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { + GST_DEBUG_OBJECT (self, "Begin audio preroll"); + + hr = gst_decklink2_output_begin_audio_preroll (self); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't start audio preroll, hr: 0x%x", + (guint) hr); + return hr; + } + } + + if (audio_buf && audio_buf_size > 0) { + guint num_samples = audio_buf_size / self->audio_info.bpf; + + hr = gst_decklink2_output_schedule_audio_samples (self, + audio_buf, num_samples, 0, 0, NULL); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", + (guint) hr); + return hr; + } + } + + self->n_prerolled++; + if (self->n_prerolled >= self->n_preroll_frames) { + if (GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { + hr = gst_decklink2_output_end_audio_preroll (self); + + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Audio preroll failed, hr: 0x%x", (guint) hr); + return hr; + } + } + + hr = gst_decklink2_output_start (self, 0, GST_SECOND, 1.0); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't start playback, hr: 0x%x", + (guint) hr); + return hr; + } + + GST_DEBUG_OBJECT (self, "Prerolled, start playback"); + + self->prerolled = TRUE; + } + } else if (audio_buf && audio_buf_size > 0) { + guint num_samples = audio_buf_size / self->audio_info.bpf; + + hr = gst_decklink2_output_schedule_audio_samples (self, + audio_buf, num_samples, 0, 0, NULL); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", + (guint) hr); + return hr; + } + } + + return S_OK; +} + +HRESULT +gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, + IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size) +{ + GstDeckLink2OutputPrivate *priv = output->priv; + HRESULT hr; + std::unique_lock < std::mutex > lk (priv->extern_lock); + dlbool_t active; + + g_assert (output->configured); + + hr = gst_decklink2_output_is_running (output, &active); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (output, "Couldn't query active state, hr: 0x%x", + (guint) hr); + return hr; + } + + if (active) { + guint32 count = 0; + hr = gst_decklink2_output_get_num_bufferred (output, &count); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (output, + "Couldn't query bufferred frame count, hr: 0x%x", (guint) hr); + return hr; + } + + if (count > output->max_buffered) { + GST_WARNING_OBJECT (output, "Skipping frame, buffered count %u > %u", + count, output->max_buffered); + return S_OK; + } + } + lk.unlock (); + + std::lock_guard < std::mutex > slk (priv->schedule_lock); + return gst_decklink2_output_schedule_video_internal (output, frame, + audio_buf, audio_buf_size); +} + +static HRESULT +gst_decklink2_output_stop_internal (GstDeckLink2Output * self) +{ + GstDeckLink2OutputPrivate *priv = self->priv; + HRESULT hr = E_FAIL; + + GST_DEBUG_OBJECT (self, "Stopping"); + + std::unique_lock < std::mutex > lk (priv->schedule_lock); + /* Steal last frame to avoid re-rendering */ + GST_DECKLINK2_CLEAR_COM (self->last_frame); + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->StopScheduledPlayback (0, NULL, 0); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->StopScheduledPlayback (0, NULL, 0); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->StopScheduledPlayback (0, NULL, 0); + break; + default: + g_assert_not_reached (); + break; + } + lk.unlock (); + + GST_DEBUG_OBJECT (self, "StopScheduledPlayback result 0x%x", (guint) hr); + + gst_decklink2_output_disable_audio (self); + gst_decklink2_output_disable_video (self); + gst_decklink2_output_set_video_callback (self, NULL); + self->configured = FALSE; + + return hr; +} + +HRESULT +gst_decklink2_output_stop (GstDeckLink2Output * output) +{ + GstDeckLink2OutputPrivate *priv = output->priv; + std::lock_guard < std::mutex > lk (priv->extern_lock); + + return gst_decklink2_output_stop_internal (output); +} + +class IGstDeckLinkTimecode:public IDeckLinkTimecode +{ +public: + IGstDeckLinkTimecode (GstVideoTimeCode * timecode):ref_count_ (1) + { + g_assert (timecode); + + timecode_ = gst_video_time_code_copy (timecode); + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkTimecode) { + *object = static_cast < IDeckLinkTimecode * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkTimecode */ + BMDTimecodeBCD STDMETHODCALLTYPE GetBCD (void) + { + BMDTimecodeBCD bcd = 0; + + bcd |= (timecode_->frames % 10) << 0; + bcd |= ((timecode_->frames / 10) & 0x0f) << 4; + bcd |= (timecode_->seconds % 10) << 8; + bcd |= ((timecode_->seconds / 10) & 0x0f) << 12; + bcd |= (timecode_->minutes % 10) << 16; + bcd |= ((timecode_->minutes / 10) & 0x0f) << 20; + bcd |= (timecode_->hours % 10) << 24; + bcd |= ((timecode_->hours / 10) & 0x0f) << 28; + + if (timecode_->config.fps_n == 24 && timecode_->config.fps_d == 1) + bcd |= 0x0 << 30; + else if (timecode_->config.fps_n == 25 && timecode_->config.fps_d == 1) + bcd |= 0x1 << 30; + else if (timecode_->config.fps_n == 30 && timecode_->config.fps_d == 1001) + bcd |= 0x2 << 30; + else if (timecode_->config.fps_n == 30 && timecode_->config.fps_d == 1) + bcd |= 0x3 << 30; + + return bcd; + } + + HRESULT STDMETHODCALLTYPE + GetComponents (unsigned char *hours, unsigned char *minutes, + unsigned char *seconds, unsigned char *frames) + { + *hours = timecode_->hours; + *minutes = timecode_->minutes; + *seconds = timecode_->seconds; + *frames = timecode_->frames; + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE GetString (dlstring_t * timecode) + { + gchar *s = gst_video_time_code_to_string (timecode_); + *timecode = StdToDlString (s); + g_free (s); + + return S_OK; + } + + BMDTimecodeFlags STDMETHODCALLTYPE GetFlags (void) + { + BMDTimecodeFlags flags = (BMDTimecodeFlags) 0; + + if ((timecode_->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) != 0) + flags = (BMDTimecodeFlags) (flags | bmdTimecodeIsDropFrame); + else + flags = (BMDTimecodeFlags) (flags | bmdTimecodeFlagDefault); + + if (timecode_->field_count == 2) + flags = (BMDTimecodeFlags) (flags | bmdTimecodeFieldMark); + + return flags; + } + + HRESULT STDMETHODCALLTYPE GetTimecodeUserBits (BMDTimecodeUserBits * userBits) + { + *userBits = 0; + return S_OK; + } + +private: + virtual ~ IGstDeckLinkTimecode () { + gst_video_time_code_free (timecode_); + } + +private: + GstVideoTimeCode * timecode_; + std::atomic < ULONG > ref_count_; +}; + +class IGstDeckLinkVideoFrame:public IDeckLinkVideoFrame +{ +public: + IGstDeckLinkVideoFrame (GstVideoFrame * frame):ref_count_ (1) + { + frame_ = *frame; + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkVideoOutputCallback) { + *object = static_cast < IDeckLinkVideoFrame * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkVideoFrame */ + long STDMETHODCALLTYPE GetWidth (void) + { + return GST_VIDEO_FRAME_WIDTH (&frame_); + } + + long STDMETHODCALLTYPE GetHeight (void) + { + return GST_VIDEO_FRAME_HEIGHT (&frame_); + } + + long STDMETHODCALLTYPE GetRowBytes (void) + { + return GST_VIDEO_FRAME_PLANE_STRIDE (&frame_, 0); + } + + BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat (void) + { + BMDPixelFormat format = bmdFormatUnspecified; + switch (GST_VIDEO_FRAME_FORMAT (&frame_)) { + case GST_VIDEO_FORMAT_UYVY: + format = bmdFormat8BitYUV; + break; + case GST_VIDEO_FORMAT_v210: + format = bmdFormat10BitYUV; + break; + case GST_VIDEO_FORMAT_ARGB: + format = bmdFormat8BitARGB; + break; + case GST_VIDEO_FORMAT_BGRA: + format = bmdFormat8BitBGRA; + break; + default: + g_assert_not_reached (); + break; + } + + return format; + } + + BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) + { + return bmdFrameFlagDefault; + } + + HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) + { + *buffer = GST_VIDEO_FRAME_PLANE_DATA (&frame_, 0); + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE + GetTimecode (BMDTimecodeFormat format, IDeckLinkTimecode ** timecode) + { + if (timecode_) { + *timecode = timecode_; + timecode_->AddRef (); + return S_OK; + } + + return S_FALSE; + } + + HRESULT STDMETHODCALLTYPE + GetAncillaryData (IDeckLinkVideoFrameAncillary ** ancillary) + { + if (ancillary_) { + *ancillary = ancillary_; + ancillary_->AddRef (); + return S_OK; + } + + return S_FALSE; + } + + /* Non-interface methods */ + HRESULT STDMETHODCALLTYPE SetTimecode (GstVideoTimeCode * timecode) + { + GST_DECKLINK2_CLEAR_COM (timecode_); + + if (timecode) + timecode_ = new IGstDeckLinkTimecode (timecode); + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE + SetAncillaryData (IDeckLinkVideoFrameAncillary * ancillary) + { + GST_DECKLINK2_CLEAR_COM (ancillary_); + + ancillary_ = ancillary; + if (ancillary_) + ancillary_->AddRef (); + + return S_OK; + } + +private: + virtual ~ IGstDeckLinkVideoFrame () { + gst_video_frame_unmap (&frame_); + GST_DECKLINK2_CLEAR_COM (timecode_); + GST_DECKLINK2_CLEAR_COM (ancillary_); + } + +private: + std::atomic < ULONG > ref_count_; + GstVideoFrame frame_; + IDeckLinkTimecode *timecode_ = NULL; + IDeckLinkVideoFrameAncillary *ancillary_ = NULL; +}; + +/* Copied from ext/closedcaption/gstccconverter.c */ +/* Converts raw CEA708 cc_data and an optional timecode into CDP */ +static guint +convert_cea708_cc_data_cea708_cdp_internal (GstDeckLink2Output * self, + const guint8 * cc_data, guint cc_data_len, guint8 * cdp, guint cdp_len, + const GstVideoTimeCodeMeta * tc_meta) +{ + GstByteWriter bw; + guint8 flags, checksum; + guint i, len; + const GstDeckLink2DisplayMode *mode = &self->selected_mode; + + gst_byte_writer_init_with_data (&bw, cdp, cdp_len, FALSE); + gst_byte_writer_put_uint16_be_unchecked (&bw, 0x9669); + /* Write a length of 0 for now */ + gst_byte_writer_put_uint8_unchecked (&bw, 0); + if (mode->fps_n == 24000 && mode->fps_d == 1001) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x1f); + } else if (mode->fps_n == 24 && mode->fps_d == 1) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x2f); + } else if (mode->fps_n == 25 && mode->fps_d == 1) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x3f); + } else if (mode->fps_n == 30000 && mode->fps_d == 1001) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x4f); + } else if (mode->fps_n == 30 && mode->fps_d == 1) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x5f); + } else if (mode->fps_n == 50 && mode->fps_d == 1) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x6f); + } else if (mode->fps_n == 60000 && mode->fps_d == 1001) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x7f); + } else if (mode->fps_n == 60 && mode->fps_d == 1) { + gst_byte_writer_put_uint8_unchecked (&bw, 0x8f); + } else { + g_assert_not_reached (); + } + + /* ccdata_present | caption_service_active */ + flags = 0x42; + + /* time_code_present */ + if (tc_meta) + flags |= 0x80; + + /* reserved */ + flags |= 0x01; + + gst_byte_writer_put_uint8_unchecked (&bw, flags); + gst_byte_writer_put_uint16_be_unchecked (&bw, self->cdp_hdr_sequence_cntr); + + if (tc_meta) { + const GstVideoTimeCode *tc = &tc_meta->tc; + guint8 u8; + + gst_byte_writer_put_uint8_unchecked (&bw, 0x71); + /* reserved 11 - 2 bits */ + u8 = 0xc0; + /* tens of hours - 2 bits */ + u8 |= ((tc->hours / 10) & 0x3) << 4; + /* units of hours - 4 bits */ + u8 |= (tc->hours % 10) & 0xf; + gst_byte_writer_put_uint8_unchecked (&bw, u8); + + /* reserved 1 - 1 bit */ + u8 = 0x80; + /* tens of minutes - 3 bits */ + u8 |= ((tc->minutes / 10) & 0x7) << 4; + /* units of minutes - 4 bits */ + u8 |= (tc->minutes % 10) & 0xf; + gst_byte_writer_put_uint8_unchecked (&bw, u8); + + /* field flag - 1 bit */ + u8 = tc->field_count < 2 ? 0x00 : 0x80; + /* tens of seconds - 3 bits */ + u8 |= ((tc->seconds / 10) & 0x7) << 4; + /* units of seconds - 4 bits */ + u8 |= (tc->seconds % 10) & 0xf; + gst_byte_writer_put_uint8_unchecked (&bw, u8); + + /* drop frame flag - 1 bit */ + u8 = (tc->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) ? 0x80 : + 0x00; + /* reserved0 - 1 bit */ + /* tens of frames - 2 bits */ + u8 |= ((tc->frames / 10) & 0x3) << 4; + /* units of frames 4 bits */ + u8 |= (tc->frames % 10) & 0xf; + gst_byte_writer_put_uint8_unchecked (&bw, u8); + } + + gst_byte_writer_put_uint8_unchecked (&bw, 0x72); + gst_byte_writer_put_uint8_unchecked (&bw, 0xe0 | cc_data_len / 3); + gst_byte_writer_put_data_unchecked (&bw, cc_data, cc_data_len); + + gst_byte_writer_put_uint8_unchecked (&bw, 0x74); + gst_byte_writer_put_uint16_be_unchecked (&bw, self->cdp_hdr_sequence_cntr); + self->cdp_hdr_sequence_cntr++; + /* We calculate the checksum afterwards */ + gst_byte_writer_put_uint8_unchecked (&bw, 0); + + len = gst_byte_writer_get_pos (&bw); + gst_byte_writer_set_pos (&bw, 2); + gst_byte_writer_put_uint8_unchecked (&bw, len); + + checksum = 0; + for (i = 0; i < len; i++) { + checksum += cdp[i]; + } + checksum &= 0xff; + checksum = 256 - checksum; + cdp[len - 1] = checksum; + + return len; +} + +static void +gst_decklink2_output_write_vbi (GstDeckLink2Output * self, + const GstVideoInfo * info, GstBuffer * buffer, + IGstDeckLinkVideoFrame * frame, GstVideoTimeCodeMeta * tc_meta, + gint caption_line, gint afd_bar_line) +{ + IDeckLinkVideoFrameAncillary *vanc_frame = NULL; + gpointer iter = NULL; + GstVideoCaptionMeta *cc_meta; + guint8 *vancdata; + gboolean got_captions = FALSE; + + if (caption_line == 0 && afd_bar_line == 0) + return; + + if (self->vbi_width != info->width) + g_clear_pointer (&self->vbi_enc, gst_video_vbi_encoder_free); + + if (!self->vbi_enc) { + self->vbi_enc = gst_video_vbi_encoder_new (GST_VIDEO_FORMAT_v210, + info->width); + self->vbi_width = info->width; + } + + /* Put any closed captions into the configured line */ + while ((cc_meta = + (GstVideoCaptionMeta *) gst_buffer_iterate_meta_filtered (buffer, + &iter, GST_VIDEO_CAPTION_META_API_TYPE))) { + switch (cc_meta->caption_type) { + case GST_VIDEO_CAPTION_TYPE_CEA608_RAW:{ + guint8 data[138]; + guint i, n; + + n = cc_meta->size / 2; + if (cc_meta->size > 46) { + GST_WARNING_OBJECT (self, "Too big raw CEA608 buffer"); + break; + } + + /* This is the offset from line 9 for 525-line fields and from line + * 5 for 625-line fields. + * + * The highest bit is set for field 1 but not for field 0, but we + * have no way of knowning the field here + */ + for (i = 0; i < n; i++) { + data[3 * i] = 0x80 | (info->height == + 525 ? caption_line - 9 : caption_line - 5); + data[3 * i + 1] = cc_meta->data[2 * i]; + data[3 * i + 2] = cc_meta->data[2 * i + 1]; + } + + if (!gst_video_vbi_encoder_add_ancillary (self->vbi_enc, FALSE, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_608 >> 8, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_608 & 0xff, data, 3)) { + GST_WARNING_OBJECT (self, "Couldn't add meta to ancillary data"); + } + + got_captions = TRUE; + + break; + } + case GST_VIDEO_CAPTION_TYPE_CEA608_S334_1A:{ + if (!gst_video_vbi_encoder_add_ancillary (self->vbi_enc, FALSE, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_608 >> 8, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_608 & 0xff, cc_meta->data, + cc_meta->size)) + GST_WARNING_OBJECT (self, "Couldn't add meta to ancillary data"); + + got_captions = TRUE; + + break; + } + case GST_VIDEO_CAPTION_TYPE_CEA708_RAW:{ + guint8 data[256]; + guint n; + + n = cc_meta->size / 3; + if (cc_meta->size > 46) { + GST_WARNING_OBJECT (self, "Too big raw CEA708 buffer"); + break; + } + + n = convert_cea708_cc_data_cea708_cdp_internal (self, cc_meta->data, + cc_meta->size, data, sizeof (data), tc_meta); + if (!gst_video_vbi_encoder_add_ancillary (self->vbi_enc, FALSE, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_708 >> 8, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_708 & 0xff, data, n)) + GST_WARNING_OBJECT (self, "Couldn't add meta to ancillary data"); + + got_captions = TRUE; + + break; + } + case GST_VIDEO_CAPTION_TYPE_CEA708_CDP:{ + if (!gst_video_vbi_encoder_add_ancillary (self->vbi_enc, + FALSE, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_708 >> 8, + GST_VIDEO_ANCILLARY_DID16_S334_EIA_708 & 0xff, cc_meta->data, + cc_meta->size)) + GST_WARNING_OBJECT (self, "Couldn't add meta to ancillary data"); + + got_captions = TRUE; + + break; + } + default:{ + GST_FIXME_OBJECT (self, "Caption type %d not supported", + cc_meta->caption_type); + break; + } + } + } + + if ((got_captions || afd_bar_line != 0) + && gst_decklink2_output_create_ancillary_data (self, + bmdFormat10BitYUV, &vanc_frame) == S_OK) { + GstVideoAFDMeta *afd_meta = NULL, *afd_meta2 = NULL; + GstVideoBarMeta *bar_meta = NULL, *bar_meta2 = NULL; + GstMeta *meta; + gpointer meta_iter; + guint8 afd_bar_data[8] = { 0, }; + guint8 afd_bar_data2[8] = { 0, }; + guint8 afd = 0; + gboolean is_letterbox = 0; + guint16 bar1 = 0, bar2 = 0; + guint i; + + // Get any reasonable AFD/Bar metas for both fields + meta_iter = NULL; + while ((meta = + gst_buffer_iterate_meta_filtered (buffer, &meta_iter, + GST_VIDEO_AFD_META_API_TYPE))) { + GstVideoAFDMeta *tmp_meta = (GstVideoAFDMeta *) meta; + + if (tmp_meta->field == 0 || !afd_meta || (afd_meta && afd_meta->field != 0 + && tmp_meta->field == 0)) + afd_meta = tmp_meta; + if (tmp_meta->field == 1 || !afd_meta2 || (afd_meta2 + && afd_meta->field != 1 && tmp_meta->field == 1)) + afd_meta2 = tmp_meta; + } + + meta_iter = NULL; + while ((meta = + gst_buffer_iterate_meta_filtered (buffer, &meta_iter, + GST_VIDEO_BAR_META_API_TYPE))) { + GstVideoBarMeta *tmp_meta = (GstVideoBarMeta *) meta; + + if (tmp_meta->field == 0 || !bar_meta || (bar_meta && bar_meta->field != 0 + && tmp_meta->field == 0)) + bar_meta = tmp_meta; + if (tmp_meta->field == 1 || !bar_meta2 || (bar_meta2 + && bar_meta->field != 1 && tmp_meta->field == 1)) + bar_meta2 = tmp_meta; + } + + for (i = 0; i < 2; i++) { + guint8 *afd_bar_data_ptr; + + if (i == 0) { + afd_bar_data_ptr = afd_bar_data; + afd = afd_meta ? afd_meta->afd : 0; + is_letterbox = bar_meta ? bar_meta->is_letterbox : FALSE; + bar1 = bar_meta ? bar_meta->bar_data1 : 0; + bar2 = bar_meta ? bar_meta->bar_data2 : 0; + } else { + afd_bar_data_ptr = afd_bar_data2; + afd = afd_meta2 ? afd_meta2->afd : 0; + is_letterbox = bar_meta2 ? bar_meta2->is_letterbox : FALSE; + bar1 = bar_meta2 ? bar_meta2->bar_data1 : 0; + bar2 = bar_meta2 ? bar_meta2->bar_data2 : 0; + } + + /* See SMPTE 2016-3 Section 4 */ + /* AFD and AR */ + if (self->selected_mode.mode == bmdModeNTSC || + self->selected_mode.mode == bmdModeNTSC2398 || + self->selected_mode.mode == bmdModePAL || + self->selected_mode.mode == bmdModeNTSCp || + self->selected_mode.mode == bmdModePALp) { + afd_bar_data_ptr[0] = (afd << 3) | 0x0; + } else { + afd_bar_data_ptr[0] = (afd << 3) | 0x4; + } + + /* Bar flags */ + afd_bar_data_ptr[3] = is_letterbox ? 0xc0 : 0x30; + + /* Bar value 1 and 2 */ + GST_WRITE_UINT16_BE (&afd_bar_data_ptr[4], bar1); + GST_WRITE_UINT16_BE (&afd_bar_data_ptr[6], bar2); + } + + /* AFD on the same line as the captions */ + if (caption_line == afd_bar_line) { + if (!gst_video_vbi_encoder_add_ancillary (self->vbi_enc, + FALSE, GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR >> 8, + GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR & 0xff, afd_bar_data, + sizeof (afd_bar_data))) + GST_WARNING_OBJECT (self, + "Couldn't add AFD/Bar data to ancillary data"); + } + + /* FIXME: Add captions to the correct field? Captions for the second + * field should probably be inserted into the second field */ + + if (got_captions || caption_line == afd_bar_line) { + if (vanc_frame->GetBufferForVerticalBlankingLine (caption_line, + (void **) &vancdata) == S_OK) { + gst_video_vbi_encoder_write_line (self->vbi_enc, vancdata); + } else { + GST_WARNING_OBJECT (self, + "Failed to get buffer for line %d ancillary data", caption_line); + } + } + + /* AFD on a different line than the captions */ + if (afd_bar_line != 0 && caption_line != afd_bar_line) { + if (!gst_video_vbi_encoder_add_ancillary (self->vbi_enc, + FALSE, GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR >> 8, + GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR & 0xff, afd_bar_data, + sizeof (afd_bar_data))) + GST_WARNING_OBJECT (self, + "Couldn't add AFD/Bar data to ancillary data"); + + if (vanc_frame->GetBufferForVerticalBlankingLine (afd_bar_line, + (void **) &vancdata) == S_OK) { + gst_video_vbi_encoder_write_line (self->vbi_enc, vancdata); + } else { + GST_WARNING_OBJECT (self, + "Failed to get buffer for line %d ancillary data", afd_bar_line); + } + } + + /* For interlaced video we need to also add AFD to the second field */ + if (GST_VIDEO_INFO_IS_INTERLACED (info) && afd_bar_line != 0) { + guint field2_offset; + + /* The VANC lines for the second field are at an offset, depending on + * the format in use. + */ + switch (info->height) { + case 486: + /* NTSC: 525 / 2 + 1 */ + field2_offset = 263; + break; + case 576: + /* PAL: 625 / 2 + 1 */ + field2_offset = 313; + break; + case 1080: + /* 1080i: 1125 / 2 + 1 */ + field2_offset = 563; + break; + default: + g_assert_not_reached (); + } + + if (!gst_video_vbi_encoder_add_ancillary (self->vbi_enc, + FALSE, GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR >> 8, + GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR & 0xff, afd_bar_data2, + sizeof (afd_bar_data))) + GST_WARNING_OBJECT (self, + "Couldn't add AFD/Bar data to ancillary data"); + + if (vanc_frame->GetBufferForVerticalBlankingLine (afd_bar_line + + field2_offset, (void **) &vancdata) == S_OK) { + gst_video_vbi_encoder_write_line (self->vbi_enc, vancdata); + } else { + GST_WARNING_OBJECT (self, + "Failed to get buffer for line %d ancillary data", afd_bar_line); + } + } + + if (frame->SetAncillaryData (vanc_frame) != S_OK) { + GST_WARNING_OBJECT (self, "Failed to set ancillary data"); + } + + vanc_frame->Release (); + } else if (got_captions || afd_bar_line != 0) { + GST_WARNING_OBJECT (self, "Failed to allocate ancillary data frame"); + } +} + +IDeckLinkVideoFrame * +gst_decklink2_output_upload (GstDeckLink2Output * output, + const GstVideoInfo * info, GstBuffer * buffer, gint caption_line, + gint afd_bar_line) +{ + GstVideoFrame vframe; + IGstDeckLinkVideoFrame *frame; + GstVideoTimeCodeMeta *tc_meta; + + if (!gst_video_frame_map (&vframe, info, buffer, GST_MAP_READ)) { + GST_ERROR_OBJECT (output, "Failed to map video frame"); + return NULL; + } + + frame = new IGstDeckLinkVideoFrame (&vframe); + + tc_meta = gst_buffer_get_video_time_code_meta (buffer); + if (tc_meta) + frame->SetTimecode (&tc_meta->tc); + + gst_decklink2_output_write_vbi (output, info, buffer, frame, tc_meta, + caption_line, afd_bar_line); + + return frame; +} + +HRESULT +gst_decklink2_output_configure (GstDeckLink2Output * output, + guint n_preroll_frames, guint min_buffered, guint max_buffered, + const GstDeckLink2DisplayMode * display_mode, + BMDVideoOutputFlags output_flags, BMDProfileID profile_id, + GstDeckLink2KeyerMode keyer_mode, guint8 keyer_level, + GstDeckLink2MappingFormat mapping_format, + BMDAudioSampleType audio_sample_type, guint audio_channels) +{ + GstDeckLink2OutputPrivate *priv = output->priv; + HRESULT hr = S_OK; + + std::lock_guard < std::mutex > lk (priv->extern_lock); + if (output->configured) + gst_decklink2_output_stop_internal (output); + + output->selected_mode = *display_mode; + + if (profile_id != bmdProfileDefault) { + GstDeckLink2Object *object; + gchar *profile_id_str = g_enum_to_string (GST_TYPE_DECKLINK2_PROFILE_ID, + profile_id); + + object = (GstDeckLink2Object *) gst_object_get_parent (GST_OBJECT (output)); + g_assert (object); + + gst_decklink2_object_set_profile_id (object, profile_id); + gst_object_unref (object); + + g_free (profile_id_str); + } + + if (mapping_format != GST_DECKLINK2_MAPPING_FORMAT_DEFAULT && + (output->attr || output->attr_10_11)) { + dlbool_t supported = false; + + if (output->attr) { + hr = output->attr->GetFlag (BMDDeckLinkSupportsSMPTELevelAOutput, + &supported); + } else { + hr = output->attr_10_11->GetFlag (BMDDeckLinkSupportsSMPTELevelAOutput, + &supported); + } + + if (gst_decklink2_result (hr) && supported) { + hr = E_FAIL; + if (mapping_format == GST_DECKLINK2_MAPPING_FORMAT_LEVEL_A) { + if (output->config_10_11) { + hr = output-> + config_10_11->SetFlag (bmdDeckLinkConfigSMPTELevelAOutput, true); + } else if (output->config) { + hr = output->config->SetFlag (bmdDeckLinkConfigSMPTELevelAOutput, + true); + } + } else if (mapping_format == GST_DECKLINK2_MAPPING_FORMAT_LEVEL_B) { + if (output->config_10_11) { + hr = output-> + config_10_11->SetFlag (bmdDeckLinkConfigSMPTELevelAOutput, false); + } else if (output->config) { + hr = output->config->SetFlag (bmdDeckLinkConfigSMPTELevelAOutput, + false); + } + } + + if (gst_decklink2_result (hr)) + GST_DEBUG_OBJECT (output, "SMPTELevelAOutput is configured"); + else + GST_WARNING_OBJECT (output, "Couldn't configure SMPTELevelAOutput"); + } else { + GST_WARNING_OBJECT (output, "SMPTELevelAOutput is not supported"); + } + } + + if (output->keyer) { + switch (keyer_mode) { + case GST_DECKLINK2_KEYER_MODE_INTERNAL: + output->keyer->Enable (false); + output->keyer->SetLevel (keyer_level); + break; + case GST_DECKLINK2_KEYER_MODE_EXTERNAL: + output->keyer->Enable (true); + output->keyer->SetLevel (keyer_level); + break; + case GST_DECKLINK2_KEYER_MODE_OFF: + default: + output->keyer->Disable (); + break; + } + } else if (keyer_mode != GST_DECKLINK2_KEYER_MODE_OFF) { + GST_WARNING_OBJECT (output, "Keyer interface is unavailable"); + } + + hr = gst_decklink2_output_enable_video (output, + gst_decklink2_get_real_display_mode (output->selected_mode.mode), + output_flags); + if (!gst_decklink2_result (hr)) + goto error; + + hr = gst_decklink2_output_set_video_callback (output, output->callback); + if (!gst_decklink2_result (hr)) + goto error; + + gst_audio_info_init (&output->audio_info); + if (audio_channels > 0) { + GST_DEBUG_OBJECT (output, "Enabling audio"); + hr = gst_decklink2_output_enable_audio (output, bmdAudioSampleRate48kHz, + audio_sample_type, audio_channels, bmdAudioOutputStreamContinuous); + if (!gst_decklink2_result (hr)) + goto error; + + gst_audio_info_set_format (&output->audio_info, + audio_sample_type == bmdAudioSampleType16bitInteger ? + GST_AUDIO_FORMAT_S16LE : GST_AUDIO_FORMAT_S32LE, 48000, + audio_channels, NULL); + } + + g_clear_pointer (&output->vbi_enc, gst_video_vbi_encoder_free); + + output->n_prerolled = 0; + output->n_preroll_frames = n_preroll_frames; + output->min_buffered = min_buffered; + output->max_buffered = max_buffered; + output->n_frames = 0; + output->cdp_hdr_sequence_cntr = 0; + output->configured = TRUE; + output->pts = 0; + + return S_OK; + +error: + gst_decklink2_output_disable_audio (output); + gst_decklink2_output_disable_video (output); + gst_decklink2_output_set_video_callback (output, NULL); + return hr; +} + +static void +gst_decklink2_output_on_stopped (GstDeckLink2Output * self) +{ + GST_DEBUG_OBJECT (self, "Scheduled playback stopped"); +} + +static void +gst_decklink2_output_on_completed (GstDeckLink2Output * self) +{ + GstDeckLink2OutputPrivate *priv = self->priv; + dlbool_t active; + guint32 count = 0; + + std::lock_guard < std::mutex > lk (priv->schedule_lock); + if (!self->last_frame) + return; + + HRESULT hr = gst_decklink2_output_is_running (self, &active); + if (gst_decklink2_result (hr) && active) { + hr = gst_decklink2_output_get_num_bufferred (self, &count); + if (gst_decklink2_result (hr) && count <= self->min_buffered) { + GST_WARNING_OBJECT (self, "Underrun, buffered count %u", count); + gst_decklink2_output_schedule_video_internal (self, self->last_frame, + NULL, 0); + } + } +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h new file mode 100644 index 0000000000..551fe5de68 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h @@ -0,0 +1,72 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include "gstdecklink2utils.h" + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_OUTPUT (gst_decklink2_output_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Output, gst_decklink2_output, + GST, DECKLINK2_OUTPUT, GstObject); + +GstDeckLink2Output * gst_decklink2_output_new (IDeckLink * device, + GstDeckLink2APILevel api_level); + +GstCaps * gst_decklink2_output_get_caps (GstDeckLink2Output * output, + BMDDisplayMode mode, + BMDPixelFormat format); + +gboolean gst_decklink2_output_get_display_mode (GstDeckLink2Output * output, + const GstVideoInfo * info, + GstDeckLink2DisplayMode * display_mode); + +guint gst_decklink2_output_get_max_audio_channels (GstDeckLink2Output * output); + +HRESULT gst_decklink2_output_configure (GstDeckLink2Output * output, + guint n_preroll_frames, + guint min_buffered, + guint max_buffered, + const GstDeckLink2DisplayMode * display_mode, + BMDVideoOutputFlags output_flags, + BMDProfileID profile_id, + GstDeckLink2KeyerMode keyer_mode, + guint8 keyer_level, + GstDeckLink2MappingFormat mapping_format, + BMDAudioSampleType audio_sample_type, + guint audio_channels); + +IDeckLinkVideoFrame * gst_decklink2_output_upload (GstDeckLink2Output * output, + const GstVideoInfo * info, + GstBuffer * buffer, + gint caption_line, + gint afd_bar_line); + + +HRESULT gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, + IDeckLinkVideoFrame * frame, + guint8 *audio_buf, + gsize audio_buf_size); + +HRESULT gst_decklink2_output_stop (GstDeckLink2Output * output); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp new file mode 100644 index 0000000000..9d966108f1 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -0,0 +1,901 @@ +/* + * GStreamer + * Copyright (C) 2021 Mathieu Duponchelle + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2sink.h" +#include "gstdecklink2utils.h" +#include "gstdecklink2object.h" +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_decklink2_sink_debug); +#define GST_CAT_DEFAULT gst_decklink2_sink_debug + +enum +{ + PROP_0, + PROP_MODE, + PROP_DEVICE_NUMBER, + PROP_VIDEO_FORMAT, + PROP_PROFILE_ID, + PROP_TIMECODE_FORMAT, + PROP_KEYER_MODE, + PROP_KEYER_LEVEL, + PROP_CC_LINE, + PROP_AFD_BAR_LINE, + PROP_MAPPING_FORMAT, + PROP_PERSISTENT_ID, + PROP_N_PREROLL_FRAMES, + PROP_MIN_BUFFERED_FRAMES, + PROP_MAX_BUFFERED_FRAMES, +}; + +#define DEFAULT_MODE bmdModeUnknown +#define DEFAULT_DEVICE_NUMBER 0 +#define DEFAULT_PERSISTENT_ID -1 +#define DEFAULT_VIDEO_FORMAT bmdFormat8BitYUV +#define DEFAULT_PROFILE_ID bmdProfileDefault +#define DEFAULT_TIMECODE_FORMAT bmdTimecodeRP188Any +#define DEFAULT_KEYER_MODE GST_DECKLINK2_KEYER_MODE_OFF +#define DEFAULT_KEYER_LEVEL 255 +#define DEFAULT_CC_LINE 0 +#define DEFAULT_AFD_BAR_LINE 0 +#define DEFAULT_MAPPING_FORMAT GST_DECKLINK2_MAPPING_FORMAT_DEFAULT +#define DEFAULT_N_PREROLL_FRAMES 7 +#define DEFAULT_MIN_BUFFERED_FRAMES 3 +#define DEFAULT_MAX_BUFFERED_FRAMES 14 + +struct GstDeckLink2SinkPrivate +{ + std::mutex lock; +}; + +struct _GstDeckLink2Sink +{ + GstBaseSink parent; + + GstDeckLink2SinkPrivate *priv; + + GstDeckLink2Output *output; + + GstVideoInfo video_info; + + GstDeckLink2DisplayMode selected_mode; + BMDAudioSampleType audio_sample_type; + gint audio_channels; + gboolean configured; + + GstBufferPool *fallback_pool; + IDeckLinkVideoFrame *prepared_frame; + + /* properties */ + BMDDisplayMode display_mode; + gint device_number; + gint64 persistent_id; + BMDPixelFormat video_format; + BMDProfileID profile_id; + BMDTimecodeFormat timecode_format; + GstDeckLink2KeyerMode keyer_mode; + gint keyer_level; + gint caption_line; + gint afd_bar_line; + GstDeckLink2MappingFormat mapping_format; + guint n_preroll_frames; + guint min_buffered_frames; + guint max_buffered_frames; +}; + +static void gst_decklink2_sink_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_decklink2_sink_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_decklink2_sink_finalize (GObject * object); +static gboolean gst_decklink2_sink_query (GstBaseSink * sink, GstQuery * query); +static GstCaps *gst_decklink2_sink_get_caps (GstBaseSink * sink, + GstCaps * filter); +static gboolean gst_decklink2_sink_set_caps (GstBaseSink * sink, + GstCaps * caps); +static gboolean gst_decklink2_sink_propose_allocation (GstBaseSink * sink, + GstQuery * query); +static gboolean gst_decklink2_sink_start (GstBaseSink * sink); +static gboolean gst_decklink2_sink_stop (GstBaseSink * sink); +static gboolean gst_decklink2_sink_unlock_stop (GstBaseSink * sink); +static GstFlowReturn gst_decklink2_sink_prepare (GstBaseSink * sink, + GstBuffer * buffer); +static GstFlowReturn gst_decklink2_sink_render (GstBaseSink * sink, + GstBuffer * buffer); + +#define gst_decklink2_sink_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2Sink, gst_decklink2_sink, GST_TYPE_BASE_SINK); +GST_ELEMENT_REGISTER_DEFINE (decklink2sink, "decklink2sink", + GST_RANK_NONE, GST_TYPE_DECKLINK2_SINK); + +static void +gst_decklink2_sink_class_init (GstDeckLink2SinkClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS (klass); + GParamFlags param_flags = (GParamFlags) (G_PARAM_READWRITE | + GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS); + + object_class->finalize = gst_decklink2_sink_finalize; + object_class->set_property = gst_decklink2_sink_set_property; + object_class->get_property = gst_decklink2_sink_get_property; + + g_object_class_install_property (object_class, PROP_MODE, + g_param_spec_enum ("mode", "Playback Mode", + "Video Mode to use for playback", + GST_TYPE_DECKLINK2_MODE, DEFAULT_MODE, param_flags)); + + g_object_class_install_property (object_class, PROP_DEVICE_NUMBER, + g_param_spec_int ("device-number", "Device number", + "Output device instance to use", 0, G_MAXINT, DEFAULT_DEVICE_NUMBER, + param_flags)); + + g_object_class_install_property (object_class, PROP_PERSISTENT_ID, + g_param_spec_int64 ("persistent-id", "Persistent id", + "Output device instance to use. Higher priority than \"device-number\".", + DEFAULT_PERSISTENT_ID, G_MAXINT64, DEFAULT_PERSISTENT_ID, + param_flags)); + + g_object_class_install_property (object_class, PROP_VIDEO_FORMAT, + g_param_spec_enum ("video-format", "Video format", + "Video format type to use for playback", + GST_TYPE_DECKLINK2_VIDEO_FORMAT, DEFAULT_VIDEO_FORMAT, param_flags)); + + g_object_class_install_property (object_class, PROP_PROFILE_ID, + g_param_spec_enum ("profile", "Profile", + "Certain DeckLink devices such as the DeckLink 8K Pro, the DeckLink " + "Quad 2 and the DeckLink Duo 2 support multiple profiles to " + "configure the capture and playback behavior of its sub-devices." + "For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared " + "between any 2 sub-devices that utilize the same connectors. For the " + "DeckLink 8K Pro, a profile is shared between all 4 sub-devices. Any " + "sub-devices that share a profile are considered to be part of the " + "same profile group." + "DeckLink Duo 2 support configuration of the duplex mode of " + "individual sub-devices.", + GST_TYPE_DECKLINK2_PROFILE_ID, DEFAULT_PROFILE_ID, param_flags)); + + g_object_class_install_property (object_class, PROP_TIMECODE_FORMAT, + g_param_spec_enum ("timecode-format", "Timecode format", + "Timecode format type to use for playback", + GST_TYPE_DECKLINK2_TIMECODE_FORMAT, DEFAULT_TIMECODE_FORMAT, + param_flags)); + + g_object_class_install_property (object_class, PROP_KEYER_MODE, + g_param_spec_enum ("keyer-mode", "Keyer mode", + "Keyer mode to be enabled", + GST_TYPE_DECKLINK2_KEYER_MODE, DEFAULT_KEYER_MODE, param_flags)); + + g_object_class_install_property (object_class, PROP_KEYER_LEVEL, + g_param_spec_int ("keyer-level", "Keyer level", + "Keyer level", 0, 255, DEFAULT_KEYER_LEVEL, param_flags)); + + g_object_class_install_property (object_class, PROP_CC_LINE, + g_param_spec_int ("cc-line", "CC Line", + "Line number to use for inserting closed captions (0 = disabled)", + 0, 22, DEFAULT_CC_LINE, param_flags)); + + g_object_class_install_property (object_class, PROP_AFD_BAR_LINE, + g_param_spec_int ("afd-bar-line", "AFD/Bar Line", + "Line number to use for inserting AFD/Bar data (0 = disabled)", + 0, 10000, DEFAULT_AFD_BAR_LINE, param_flags)); + + g_object_class_install_property (object_class, PROP_MAPPING_FORMAT, + g_param_spec_enum ("mapping-format", "3G-SDI Mapping Format", + "3G-SDI Mapping Format (Level A/B)", + GST_TYPE_DECKLINK2_MAPPING_FORMAT, DEFAULT_MAPPING_FORMAT, + param_flags)); + + g_object_class_install_property (object_class, PROP_N_PREROLL_FRAMES, + g_param_spec_int ("n-preroll-frames", "Number of preroll frames", + "How many frames to preroll before starting scheduled playback", + 0, 16, DEFAULT_N_PREROLL_FRAMES, param_flags)); + + g_object_class_install_property (object_class, PROP_MIN_BUFFERED_FRAMES, + g_param_spec_int ("min-buffered-frames", "Min number of buffered frames", + "Min number of frames to buffer before duplicating", + 0, 16, DEFAULT_MIN_BUFFERED_FRAMES, param_flags)); + + g_object_class_install_property (object_class, PROP_MAX_BUFFERED_FRAMES, + g_param_spec_int ("max-buffered-frames", "Max number of buffered frames", + "Max number of frames to buffer before dropping", + 0, 16, DEFAULT_MAX_BUFFERED_FRAMES, param_flags)); + + GstCaps *templ_caps = gst_decklink2_get_default_template_caps (); + templ_caps = gst_caps_make_writable (templ_caps); + + GValue ch_list = G_VALUE_INIT; + gint ch[] = { 0, 2, 8, 16 }; + g_value_init (&ch_list, GST_TYPE_LIST); + for (guint i = 0; i < G_N_ELEMENTS (ch); i++) { + GValue ch_val = G_VALUE_INIT; + g_value_init (&ch_val, G_TYPE_INT); + g_value_set_int (&ch_val, ch[i]); + gst_value_list_append_and_take_value (&ch_list, &ch_val); + } + + gst_caps_set_value (templ_caps, "audio-channels", &ch_list); + g_value_unset (&ch_list); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, templ_caps)); + gst_caps_unref (templ_caps); + + gst_element_class_set_static_metadata (element_class, + "Decklink2 Sink", "Video/Audio/Sink/Hardware", "Decklink2 Sink", + "Seungha Yang "); + + basesink_class->query = GST_DEBUG_FUNCPTR (gst_decklink2_sink_query); + basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink2_sink_get_caps); + basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_decklink2_sink_set_caps); + basesink_class->propose_allocation = + GST_DEBUG_FUNCPTR (gst_decklink2_sink_propose_allocation); + basesink_class->start = GST_DEBUG_FUNCPTR (gst_decklink2_sink_start); + basesink_class->stop = GST_DEBUG_FUNCPTR (gst_decklink2_sink_stop); + basesink_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_decklink2_sink_unlock_stop); + basesink_class->prepare = GST_DEBUG_FUNCPTR (gst_decklink2_sink_prepare); + basesink_class->render = GST_DEBUG_FUNCPTR (gst_decklink2_sink_render); + + GST_DEBUG_CATEGORY_INIT (gst_decklink2_sink_debug, "decklink2sink", + 0, "decklink2sink"); + + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_MODE, (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_VIDEO_FORMAT, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_PROFILE_ID, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_TIMECODE_FORMAT, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_KEYER_MODE, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_MAPPING_FORMAT, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_MAPPING_FORMAT, + (GstPluginAPIFlags) 0); +} + +static void +gst_decklink2_sink_init (GstDeckLink2Sink * self) +{ + self->display_mode = DEFAULT_MODE; + self->device_number = DEFAULT_DEVICE_NUMBER; + self->persistent_id = DEFAULT_PERSISTENT_ID; + self->video_format = DEFAULT_VIDEO_FORMAT; + self->profile_id = DEFAULT_PROFILE_ID; + self->timecode_format = DEFAULT_TIMECODE_FORMAT; + self->keyer_mode = DEFAULT_KEYER_MODE; + self->keyer_level = DEFAULT_KEYER_LEVEL; + self->caption_line = DEFAULT_CC_LINE; + self->afd_bar_line = DEFAULT_AFD_BAR_LINE; + self->mapping_format = DEFAULT_MAPPING_FORMAT; + self->n_preroll_frames = DEFAULT_N_PREROLL_FRAMES; + self->min_buffered_frames = DEFAULT_MIN_BUFFERED_FRAMES; + self->max_buffered_frames = DEFAULT_MAX_BUFFERED_FRAMES; + + self->priv = new GstDeckLink2SinkPrivate (); +} + +static void +gst_decklink2_sink_finalize (GObject * object) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (object); + + delete self->priv; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_decklink2_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (object); + GstDeckLink2SinkPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + switch (prop_id) { + case PROP_MODE: + self->display_mode = (BMDDisplayMode) g_value_get_enum (value); + break; + case PROP_DEVICE_NUMBER: + self->device_number = g_value_get_int (value); + break; + case PROP_PERSISTENT_ID: + self->persistent_id = g_value_get_int64 (value); + break; + case PROP_VIDEO_FORMAT: + self->video_format = (BMDPixelFormat) g_value_get_enum (value); + break; + case PROP_PROFILE_ID: + self->profile_id = (BMDProfileID) g_value_get_enum (value); + break; + case PROP_TIMECODE_FORMAT: + self->timecode_format = (BMDTimecodeFormat) g_value_get_enum (value); + break; + case PROP_KEYER_MODE: + self->keyer_mode = (GstDeckLink2KeyerMode) g_value_get_enum (value); + break; + case PROP_KEYER_LEVEL: + self->keyer_level = g_value_get_int (value); + break; + case PROP_CC_LINE: + self->caption_line = g_value_get_int (value); + break; + case PROP_AFD_BAR_LINE: + self->afd_bar_line = g_value_get_int (value); + break; + case PROP_MAPPING_FORMAT: + self->mapping_format = + (GstDeckLink2MappingFormat) g_value_get_enum (value); + break; + case PROP_N_PREROLL_FRAMES: + self->n_preroll_frames = g_value_get_int (value); + break; + case PROP_MIN_BUFFERED_FRAMES: + self->min_buffered_frames = g_value_get_int (value); + break; + case PROP_MAX_BUFFERED_FRAMES: + self->max_buffered_frames = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_decklink2_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (object); + GstDeckLink2SinkPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + switch (prop_id) { + case PROP_MODE: + g_value_set_enum (value, self->display_mode); + break; + case PROP_DEVICE_NUMBER: + g_value_set_int (value, self->device_number); + break; + case PROP_PERSISTENT_ID: + g_value_set_int64 (value, self->persistent_id); + break; + case PROP_VIDEO_FORMAT: + g_value_set_enum (value, self->video_format); + break; + case PROP_PROFILE_ID: + g_value_set_enum (value, self->profile_id); + break; + case PROP_TIMECODE_FORMAT: + g_value_set_enum (value, self->timecode_format); + break; + case PROP_KEYER_MODE: + g_value_set_enum (value, self->keyer_mode); + break; + case PROP_KEYER_LEVEL: + g_value_set_int (value, self->keyer_level); + break; + case PROP_CC_LINE: + g_value_set_int (value, self->caption_line); + break; + 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; + case PROP_N_PREROLL_FRAMES: + g_value_set_int (value, self->n_preroll_frames); + break; + case PROP_MIN_BUFFERED_FRAMES: + g_value_set_int (value, self->min_buffered_frames); + break; + case PROP_MAX_BUFFERED_FRAMES: + g_value_set_int (value, self->max_buffered_frames); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_decklink2_sink_query (GstBaseSink * sink, GstQuery * query) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_ACCEPT_CAPS: + { + GstCaps *caps, *allowed; + gboolean can_intercept; + + gst_query_parse_accept_caps (query, &caps); + allowed = gst_decklink2_sink_get_caps (sink, NULL); + can_intercept = gst_caps_can_intersect (caps, allowed); + GST_DEBUG_OBJECT (self, "Checking if requested caps %" GST_PTR_FORMAT + " are intersectable of pad caps %" GST_PTR_FORMAT " result %d", caps, + allowed, can_intercept); + gst_caps_unref (allowed); + gst_query_set_accept_caps_result (query, can_intercept); + return TRUE; + } + default: + break; + } + + return GST_BASE_SINK_CLASS (parent_class)->query (sink, query); +} + +static GstCaps * +gst_decklink2_sink_get_caps (GstBaseSink * sink, GstCaps * filter) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + GstDeckLink2SinkPrivate *priv = self->priv; + GstCaps *caps; + GstCaps *ret; + std::lock_guard < std::mutex > lk (priv->lock); + + if (!self->output) { + GST_DEBUG_OBJECT (self, "Output is not configured yet"); + caps = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (self)); + } else { + caps = gst_decklink2_output_get_caps (self->output, self->display_mode, + self->video_format); + } + + if (!caps) { + GST_WARNING_OBJECT (self, "Couldn't get caps"); + caps = gst_caps_new_empty (); + } else if (self->output) { + guint max_ch; + GValue ch_list = G_VALUE_INIT; + GValue ch_val = G_VALUE_INIT; + + max_ch = gst_decklink2_output_get_max_audio_channels (self->output); + + caps = gst_caps_make_writable (caps); + + g_value_init (&ch_list, GST_TYPE_LIST); + + g_value_init (&ch_val, G_TYPE_INT); + g_value_set_int (&ch_val, 0); + gst_value_list_append_and_take_value (&ch_list, &ch_val); + + g_value_init (&ch_val, G_TYPE_INT); + g_value_set_int (&ch_val, 2); + gst_value_list_append_and_take_value (&ch_list, &ch_val); + + if (max_ch >= 8) { + g_value_init (&ch_val, G_TYPE_INT); + g_value_set_int (&ch_val, 8); + gst_value_list_append_and_take_value (&ch_list, &ch_val); + } + + if (max_ch >= 16) { + g_value_init (&ch_val, G_TYPE_INT); + g_value_set_int (&ch_val, 16); + gst_value_list_append_and_take_value (&ch_list, &ch_val); + } + + gst_caps_set_value (caps, "audio-channels", &ch_list); + g_value_unset (&ch_list); + } + + if (filter) { + ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + } else { + ret = caps; + } + + GST_LOG_OBJECT (self, "Returning caps %" GST_PTR_FORMAT, ret); + + return ret; +} + +static gboolean +gst_decklink2_sink_set_caps (GstBaseSink * sink, GstCaps * caps) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + HRESULT hr; + GstVideoInfo info; + GstDeckLink2DisplayMode mode; + GstStructure *config; + GstAllocationParams params = { (GstMemoryFlags) 0, 15, 0, 0 }; + GstStructure *s; + GstAudioFormat audio_format = GST_AUDIO_FORMAT_UNKNOWN; + const gchar *audio_format_str; + gint audio_channels = 0; + BMDAudioSampleType audio_sample_type = bmdAudioSampleType16bitInteger; + + GST_DEBUG_OBJECT (self, "Set caps %" GST_PTR_FORMAT, caps); + + if (!self->output) { + GST_ERROR_OBJECT (self, "output has not been configured yet"); + return FALSE; + } + + if (!gst_video_info_from_caps (&info, caps)) { + GST_ERROR_OBJECT (self, "Invalid caps"); + return FALSE; + } + + if (!gst_decklink2_output_get_display_mode (self->output, &info, &mode)) { + GST_ERROR_OBJECT (self, "Couldn't get display mode"); + return FALSE; + } + + self->video_info = info; + + s = gst_caps_get_structure (caps, 0); + audio_format_str = gst_structure_get_string (s, "audio-format"); + if (audio_format_str) + audio_format = gst_audio_format_from_string (audio_format_str); + gst_structure_get_int (s, "audio-channels", &audio_channels); + + if (audio_format == GST_AUDIO_FORMAT_S16LE) { + audio_sample_type = bmdAudioSampleType16bitInteger; + } else if (audio_format == GST_AUDIO_FORMAT_S32LE) { + audio_sample_type = bmdAudioSampleType32bitInteger; + } else { + audio_channels = 0; + } + + if (self->configured) { + if (self->selected_mode.mode == mode.mode && + self->audio_sample_type == audio_sample_type && + self->audio_channels == audio_channels) { + return TRUE; + } + + GST_DEBUG_OBJECT (self, "Configuration changed"); + gst_decklink2_output_stop (self->output); + self->configured = FALSE; + } + + self->selected_mode = mode; + self->audio_sample_type = audio_sample_type; + self->audio_channels = audio_channels; + + /* The timecode_format itself is used when we embed the actual timecode data + * into the frame. Now we only need to know which of the two standards the + * timecode format will adhere to: VITC or RP188, and send the appropriate + * flag to EnableVideoOutput. The exact format is specified later. + * + * Note that this flag will have no effect in practice if the video stream + * does not contain timecode metadata. + */ + BMDVideoOutputFlags output_flags; + if (self->timecode_format == bmdTimecodeVITC || + self->timecode_format == bmdTimecodeVITCField2) { + output_flags = bmdVideoOutputVITC; + } else { + output_flags = bmdVideoOutputRP188; + } + + if (self->caption_line > 0 || self->afd_bar_line > 0) + output_flags = (BMDVideoOutputFlags) (output_flags | bmdVideoOutputVANC); + + GST_DEBUG_OBJECT (self, "Configuring output, mode %" GST_FOURCC_FORMAT + ", audio-sample-type %d, audio-channles %d", + GST_DECKLINK2_FOURCC_ARGS (self->selected_mode.mode), + self->audio_sample_type, self->audio_channels); + + hr = gst_decklink2_output_configure (self->output, self->n_preroll_frames, + self->min_buffered_frames, self->max_buffered_frames, + &self->selected_mode, output_flags, self->profile_id, self->keyer_mode, + (guint8) self->keyer_level, self->mapping_format, + self->audio_sample_type, self->audio_channels); + if (hr != S_OK) { + GST_ERROR_OBJECT (self, "Couldn't configure output"); + return FALSE; + } + + if (self->fallback_pool) { + gst_buffer_pool_set_active (self->fallback_pool, FALSE); + gst_object_unref (self->fallback_pool); + } + + self->fallback_pool = gst_video_buffer_pool_new (); + config = gst_buffer_pool_get_config (self->fallback_pool); + gst_buffer_pool_config_set_params (config, caps, info.size, 0, 0); + gst_buffer_pool_config_set_allocator (config, NULL, ¶ms); + + if (!gst_buffer_pool_set_config (self->fallback_pool, config)) { + GST_ERROR_OBJECT (self, "Couldn't set pool config"); + goto error; + } + + if (!gst_buffer_pool_set_active (self->fallback_pool, TRUE)) { + GST_ERROR_OBJECT (self, "Couldn't set active state to pool"); + goto error; + } + + self->configured = TRUE; + + return TRUE; + +error: + gst_clear_object (&self->fallback_pool); + + return FALSE; +} + +static gboolean +gst_decklink2_sink_propose_allocation (GstBaseSink * sink, GstQuery * query) +{ + GstCaps *caps; + GstVideoInfo info; + GstBufferPool *pool; + guint size; + + gst_query_parse_allocation (query, &caps, NULL); + + if (!caps) + return FALSE; + + if (!gst_video_info_from_caps (&info, caps)) + return FALSE; + + size = GST_VIDEO_INFO_SIZE (&info); + if (gst_query_get_n_allocation_pools (query) == 0) { + GstStructure *structure; + GstAllocator *allocator = NULL; + GstAllocationParams params = { (GstMemoryFlags) 0, 15, 0, 0 }; + + if (gst_query_get_n_allocation_params (query) > 0) + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + else + gst_query_add_allocation_param (query, allocator, ¶ms); + + pool = gst_video_buffer_pool_new (); + + structure = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (structure, caps, size, 0, 0); + gst_buffer_pool_config_set_allocator (structure, allocator, ¶ms); + + if (allocator) + gst_object_unref (allocator); + + if (!gst_buffer_pool_set_config (pool, structure)) { + GST_ERROR_OBJECT (sink, "Couldn't set pool config"); + gst_object_unref (pool); + return FALSE; + } + + gst_query_add_allocation_pool (query, pool, size, 0, 0); + gst_object_unref (pool); + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); + } + + return TRUE; +} + +static gboolean +gst_decklink2_sink_start (GstBaseSink * sink) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + GstDeckLink2SinkPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + GST_DEBUG_OBJECT (self, "Start"); + + self->output = gst_decklink2_acquire_output (self->device_number, + self->persistent_id); + + if (!self->output) { + GST_ERROR_OBJECT (self, "Couldn't acquire output object"); + return FALSE; + } + + if (self->n_preroll_frames < self->min_buffered_frames || + self->n_preroll_frames > self->max_buffered_frames || + self->max_buffered_frames < self->min_buffered_frames) { + GST_WARNING_OBJECT (self, "Invalid buffering configuration"); + self->n_preroll_frames = DEFAULT_N_PREROLL_FRAMES; + self->min_buffered_frames = DEFAULT_MIN_BUFFERED_FRAMES; + self->max_buffered_frames = DEFAULT_MAX_BUFFERED_FRAMES; + } + + memset (&self->selected_mode, 0, sizeof (GstDeckLink2DisplayMode)); + self->audio_sample_type = bmdAudioSampleType16bitInteger; + self->audio_channels = 0; + self->configured = FALSE; + + return TRUE; +} + +static gboolean +gst_decklink2_sink_stop (GstBaseSink * sink) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + GstDeckLink2SinkPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + GST_DECKLINK2_CLEAR_COM (self->prepared_frame); + + if (self->output) { + gst_decklink2_output_stop (self->output); + gst_decklink2_release_output (self->output); + self->output = NULL; + } + + if (self->fallback_pool) { + gst_buffer_pool_set_active (self->fallback_pool, FALSE); + gst_clear_object (&self->fallback_pool); + } + + return TRUE; +} + +static gboolean +gst_decklink2_sink_unlock_stop (GstBaseSink * sink) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + + GST_DECKLINK2_CLEAR_COM (self->prepared_frame); + + return TRUE; +} + +static gboolean +buffer_is_pbo_memory (GstBuffer * buffer) +{ + GstMemory *mem; + + mem = gst_buffer_peek_memory (buffer, 0); + if (mem->allocator + && g_strcmp0 (mem->allocator->mem_type, "GLMemoryPBO") == 0) + return TRUE; + return FALSE; +} + +static IDeckLinkVideoFrame * +gst_decklink2_sink_upload_frame (GstDeckLink2Sink * self, GstBuffer * buffer) +{ + GstBuffer *uploaded_buffer = buffer; + + if (buffer_is_pbo_memory (buffer)) { + GstVideoFrame other_frame; + GstVideoFrame vframe; + GstBuffer *fallback; + + if (!gst_video_frame_map (&vframe, &self->video_info, buffer, GST_MAP_READ)) { + GST_ERROR_OBJECT (self, "Failed to map video frame"); + return NULL; + } + + GstFlowReturn ret = gst_buffer_pool_acquire_buffer (self->fallback_pool, + &fallback, NULL); + if (ret != GST_FLOW_OK) { + GST_ERROR_OBJECT (self, "Couldn't acquire fallback buffer"); + gst_video_frame_unmap (&vframe); + return NULL; + } + + if (!gst_video_frame_map (&other_frame, + &self->video_info, fallback, GST_MAP_WRITE)) { + GST_ERROR_OBJECT (self, "Couldn't map fallback buffer"); + gst_video_frame_unmap (&vframe); + gst_buffer_unref (fallback); + return NULL; + } + + if (!gst_video_frame_copy (&other_frame, &vframe)) { + GST_ERROR_OBJECT (self, "Couldn't copy to fallback buffer"); + gst_video_frame_unmap (&vframe); + gst_video_frame_unmap (&other_frame); + gst_buffer_unref (fallback); + return NULL; + } + + gst_video_frame_unmap (&vframe); + gst_video_frame_unmap (&other_frame); + + gst_buffer_copy_into (fallback, buffer, GST_BUFFER_COPY_META, 0, -1); + uploaded_buffer = fallback; + } + + IDeckLinkVideoFrame *frame = + gst_decklink2_output_upload (self->output, &self->video_info, + uploaded_buffer, self->caption_line, self->afd_bar_line); + /* frame will hold buffer */ + if (uploaded_buffer != buffer) + gst_buffer_unref (uploaded_buffer); + + return frame; +} + +static GstFlowReturn +gst_decklink2_sink_prepare (GstBaseSink * sink, GstBuffer * buffer) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + + GST_DECKLINK2_CLEAR_COM (self->prepared_frame); + + self->prepared_frame = gst_decklink2_sink_upload_frame (self, buffer); + if (!self->prepared_frame) { + GST_ERROR_OBJECT (self, "Couldn't upload frame"); + return GST_FLOW_ERROR; + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) +{ + GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + HRESULT hr; + GstBuffer *audio_buf = NULL; + GstMapInfo info; + guint8 *audio_data = NULL; + gsize audio_data_size = 0; + + if (!self->prepared_frame) { + GST_ERROR_OBJECT (self, "No prepared frame"); + return GST_FLOW_ERROR; + } + + if (self->audio_channels > 0) { + GstDeckLink2AudioMeta *meta = gst_buffer_get_decklink2_audio_meta (buffer); + if (meta) + audio_buf = gst_sample_get_buffer (meta->sample); + + if (audio_buf) { + if (!gst_buffer_map (audio_buf, &info, GST_MAP_READ)) { + GST_ERROR_OBJECT (self, "Couldn't map audio buffer"); + return GST_FLOW_ERROR; + } + + audio_data = info.data; + audio_data_size = info.size; + } else { + GST_DEBUG_OBJECT (self, "Received buffer without audio meta"); + } + } + + GST_LOG_OBJECT (self, "schedule frame %p with audio buffer size %" + G_GSIZE_FORMAT, self->prepared_frame, audio_data_size); + + hr = gst_decklink2_output_schedule_stream (self->output, + self->prepared_frame, audio_data, audio_data_size); + + if (audio_buf) + gst_buffer_unmap (audio_buf, &info); + + if (hr != S_OK) { + GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), + ("Failed to schedule frame: 0x%x", (guint) hr)); + return GST_FLOW_ERROR; + } + + return GST_FLOW_OK; +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.h new file mode 100644 index 0000000000..3b0f9e3347 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.h @@ -0,0 +1,34 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_SINK (gst_decklink2_sink_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Sink, gst_decklink2_sink, + GST, DECKLINK2_SINK, GstBaseSink); + +GST_ELEMENT_REGISTER_DECLARE (decklink2sink); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp new file mode 100644 index 0000000000..e3a0a8b565 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -0,0 +1,674 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2src.h" +#include "gstdecklink2utils.h" +#include "gstdecklink2object.h" + +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_decklink2_src_debug); +#define GST_CAT_DEFAULT gst_decklink2_src_debug + +enum +{ + PROP_0, + PROP_MODE, + PROP_DEVICE_NUMBER, + PROP_PERSISTENT_ID, + PROP_VIDEO_CONNECTION, + PROP_AUDIO_CONNECTION, + PROP_VIDEO_FORMAT, + PROP_AUDIO_CHANNELS, + PROP_PROFILE_ID, + PROP_TIMECODE_FORMAT, + PROP_OUTPUT_CC, + PROP_OUTPUT_AFD_BAR, + PROP_BUFFER_SIZE, + PROP_SIGNAL, +}; + +#define DEFAULT_MODE bmdModeUnknown +#define DEFAULT_DEVICE_NUMBER 0 +#define DEFAULT_PERSISTENT_ID -1 +#define DEFAULT_VIDEO_CONNECTION bmdVideoConnectionUnspecified +#define DEFAULT_AUDIO_CONNECTION bmdAudioConnectionUnspecified +#define DEFAULT_VIDEO_FORMAT bmdFormat8BitYUV +#define DEFAULT_PROFILE_ID bmdProfileDefault +#define DEFAULT_TIMECODE_FORMAT bmdTimecodeRP188Any +#define DEFAULT_OUTPUT_CC FALSE +#define DEFAULT_OUTPUT_AFD_BAR FALSE +#define DEFAULT_BUFFER_SIZE 5 +#define DEFAULT_AUDIO_CHANNELS GST_DECKLINK2_AUDIO_CHANNELS_2 + +struct GstDeckLink2SrcPrivate +{ + std::mutex lock; +}; + +struct _GstDeckLink2Src +{ + GstPushSrc parent; + + GstDeckLink2SrcPrivate *priv; + + GstVideoInfo video_info; + + GstDeckLink2Input *input; + GstDeckLink2DisplayMode selected_mode; + GstCaps *selected_caps; + gboolean is_gap_buf; + + gboolean running; + + /* properties */ + BMDDisplayMode display_mode; + gint device_number; + gint64 persistent_id; + BMDVideoConnection video_conn; + BMDAudioConnection audio_conn; + BMDPixelFormat video_format; + GstDeckLink2AudioChannels audio_channels; + BMDProfileID profile_id; + BMDTimecodeFormat timecode_format; + gboolean output_cc; + gboolean output_afd_bar; + guint buffer_size; +}; + +static void gst_decklink2_src_finalize (GObject * object); +static void gst_decklink2_src_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_decklink2_src_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static GstCaps *gst_decklink2_src_get_caps (GstBaseSrc * src, GstCaps * filter); +static gboolean gst_decklink2_src_set_caps (GstBaseSrc * src, GstCaps * caps); +static gboolean gst_decklink2_src_query (GstBaseSrc * src, GstQuery * query); +static gboolean gst_decklink2_src_start (GstBaseSrc * src); +static gboolean gst_decklink2_src_stop (GstBaseSrc * src); +static gboolean gst_decklink2_src_unlock (GstBaseSrc * src); +static gboolean gst_decklink2_src_unlock_stop (GstBaseSrc * src); + +static GstFlowReturn gst_decklink2_src_create (GstPushSrc * src, + GstBuffer ** buffer); + +#define gst_decklink2_src_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2Src, gst_decklink2_src, GST_TYPE_PUSH_SRC); +GST_ELEMENT_REGISTER_DEFINE (decklink2src, "decklink2src", + GST_RANK_NONE, GST_TYPE_DECKLINK2_SRC); + +static void +gst_decklink2_src_class_init (GstDeckLink2SrcClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass); + GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); + GstCaps *templ_caps; + + object_class->finalize = gst_decklink2_src_finalize; + object_class->set_property = gst_decklink2_src_set_property; + object_class->get_property = gst_decklink2_src_get_property; + + gst_decklink2_src_install_properties (object_class); + + templ_caps = gst_decklink2_get_default_template_caps (); + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps)); + gst_caps_unref (templ_caps); + + gst_element_class_set_static_metadata (element_class, + "Decklink2 Source", "Video/Audio/Source/Hardware", "Decklink2 Source", + "Seungha Yang "); + + basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink2_src_get_caps); + basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_decklink2_src_set_caps); + basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink2_src_query); + basesrc_class->start = GST_DEBUG_FUNCPTR (gst_decklink2_src_start); + basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_decklink2_src_stop); + basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink2_src_unlock); + basesrc_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_decklink2_src_unlock_stop); + + pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_decklink2_src_create); + + GST_DEBUG_CATEGORY_INIT (gst_decklink2_src_debug, "decklink2src", + 0, "decklink2src"); + + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_MODE, (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_VIDEO_CONNECTION, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_AUDIO_CONNECTION, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_VIDEO_FORMAT, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_AUDIO_CHANNELS, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_PROFILE_ID, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_DECKLINK2_TIMECODE_FORMAT, + (GstPluginAPIFlags) 0); +} + +static void +gst_decklink2_src_init (GstDeckLink2Src * self) +{ + self->display_mode = DEFAULT_MODE; + self->device_number = DEFAULT_DEVICE_NUMBER; + self->persistent_id = DEFAULT_PERSISTENT_ID; + self->video_conn = DEFAULT_VIDEO_CONNECTION; + self->audio_conn = DEFAULT_AUDIO_CONNECTION; + self->video_format = DEFAULT_VIDEO_FORMAT; + self->profile_id = DEFAULT_PROFILE_ID; + self->audio_channels = DEFAULT_AUDIO_CHANNELS; + self->timecode_format = DEFAULT_TIMECODE_FORMAT; + self->output_cc = DEFAULT_OUTPUT_CC; + self->output_afd_bar = DEFAULT_OUTPUT_AFD_BAR; + self->buffer_size = DEFAULT_BUFFER_SIZE; + self->is_gap_buf = FALSE; + + self->priv = new GstDeckLink2SrcPrivate (); + + gst_base_src_set_live (GST_BASE_SRC (self), TRUE); + gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME); +} + +static void +gst_decklink2_src_finalize (GObject * object) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (object); + + delete self->priv; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_decklink2_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (object); + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + switch (prop_id) { + case PROP_MODE: + self->display_mode = (BMDDisplayMode) g_value_get_enum (value); + break; + case PROP_DEVICE_NUMBER: + self->device_number = g_value_get_int (value); + break; + case PROP_PERSISTENT_ID: + self->persistent_id = g_value_get_int64 (value); + break; + case PROP_VIDEO_CONNECTION: + self->video_conn = (BMDVideoConnection) g_value_get_enum (value); + break; + case PROP_AUDIO_CONNECTION: + self->audio_conn = (BMDAudioConnection) g_value_get_enum (value); + break; + case PROP_VIDEO_FORMAT: + self->video_format = (BMDPixelFormat) g_value_get_enum (value); + break; + case PROP_AUDIO_CHANNELS: + self->audio_channels = + (GstDeckLink2AudioChannels) g_value_get_enum (value); + break; + case PROP_PROFILE_ID: + self->profile_id = (BMDProfileID) g_value_get_enum (value); + break; + case PROP_TIMECODE_FORMAT: + self->timecode_format = (BMDTimecodeFormat) g_value_get_enum (value); + break; + case PROP_OUTPUT_CC: + self->output_cc = g_value_get_boolean (value); + break; + case PROP_OUTPUT_AFD_BAR: + self->output_afd_bar = g_value_get_boolean (value); + break; + case PROP_BUFFER_SIZE: + self->buffer_size = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_decklink2_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (object); + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + switch (prop_id) { + case PROP_MODE: + g_value_set_enum (value, self->display_mode); + break; + case PROP_DEVICE_NUMBER: + g_value_set_int (value, self->device_number); + break; + case PROP_PERSISTENT_ID: + g_value_set_int64 (value, self->persistent_id); + break; + case PROP_VIDEO_CONNECTION: + g_value_set_enum (value, self->video_conn); + break; + case PROP_AUDIO_CONNECTION: + g_value_set_enum (value, self->audio_conn); + break; + case PROP_VIDEO_FORMAT: + g_value_set_enum (value, self->video_format); + break; + case PROP_AUDIO_CHANNELS: + g_value_set_enum (value, self->audio_channels); + break; + case PROP_PROFILE_ID: + g_value_set_enum (value, self->profile_id); + break; + case PROP_TIMECODE_FORMAT: + g_value_set_enum (value, self->timecode_format); + break; + case PROP_OUTPUT_CC: + g_value_set_boolean (value, self->output_cc); + break; + case PROP_OUTPUT_AFD_BAR: + g_value_set_boolean (value, self->output_afd_bar); + break; + case PROP_BUFFER_SIZE: + g_value_set_uint (value, self->buffer_size); + break; + case PROP_SIGNAL: + { + gboolean has_signal = FALSE; + if (self->input) + has_signal = gst_decklink2_input_has_signal (self->input); + + g_value_set_boolean (value, has_signal); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstCaps * +gst_decklink2_src_get_caps (GstBaseSrc * src, GstCaps * filter) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstDeckLink2SrcPrivate *priv = self->priv; + GstCaps *caps; + GstCaps *ret; + std::lock_guard < std::mutex > lk (priv->lock); + + if (!self->input) + return GST_BASE_SRC_CLASS (parent_class)->get_caps (src, filter); + + if (self->selected_caps) { + caps = gst_caps_ref (self->selected_caps); + } else { + caps = gst_decklink2_input_get_caps (self->input, self->display_mode, + self->video_format); + } + + if (!caps) { + GST_WARNING_OBJECT (self, "Couldn't get caps"); + caps = gst_caps_new_empty (); + } + + if (filter) { + ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + } else { + ret = caps; + } + + GST_DEBUG_OBJECT (self, "Returning caps %" GST_PTR_FORMAT, ret); + + return ret; +} + +static gboolean +gst_decklink2_src_set_caps (GstBaseSrc * src, GstCaps * caps) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstDeckLink2SrcPrivate *priv = self->priv; + BMDPixelFormat pixel_format; + std::lock_guard < std::mutex > lk (priv->lock); + + GST_DEBUG_OBJECT (self, "Set caps %" GST_PTR_FORMAT, caps); + + if (!self->input) { + GST_WARNING_OBJECT (self, + "Couldn't accept caps without configured input object"); + return FALSE; + } + + if (self->running) + return TRUE; + + if (!gst_video_info_from_caps (&self->video_info, caps)) { + GST_WARNING_OBJECT (self, "Invalid caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + + if (!gst_decklink2_input_get_display_mode (self->input, &self->video_info, + &self->selected_mode)) { + GST_ERROR_OBJECT (self, "Not a supported caps"); + return FALSE; + } + + gst_clear_caps (&self->selected_caps); + pixel_format = + gst_decklink2_pixel_format_from_video_format (GST_VIDEO_INFO_FORMAT + (&self->video_info)); + self->selected_caps = + gst_decklink2_input_get_caps (self->input, self->selected_mode.mode, + pixel_format); + + if (!self->selected_caps) { + GST_ERROR_OBJECT (self, "Couldn't get caps from selected mode"); + return FALSE; + } + + return TRUE; +} + +static gboolean +gst_decklink2_src_query (GstBaseSrc * src, GstQuery * query) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstDeckLink2SrcPrivate *priv = self->priv; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + std::lock_guard < std::mutex > lk (priv->lock); + gint fps_n, fps_d; + GstClockTime min, max; + if (self->selected_mode.fps_n > 0 && self->selected_mode.fps_d > 0) { + fps_n = self->selected_mode.fps_n; + fps_d = self->selected_mode.fps_d; + } else { + fps_n = 30; + fps_d = 1; + } + + min = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); + max = self->buffer_size * min; + gst_query_set_latency (query, TRUE, min, max); + return TRUE; + } + default: + break; + } + + return GST_BASE_SRC_CLASS (parent_class)->query (src, query); +} + +static gboolean +gst_decklink2_src_start (GstBaseSrc * src) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + self->running = FALSE; + memset (&self->selected_mode, 0, sizeof (GstDeckLink2DisplayMode)); + + gst_clear_caps (&self->selected_caps); + self->input = gst_decklink2_acquire_input (self->device_number, + self->persistent_id); + + if (!self->input) { + GST_ERROR_OBJECT (self, "Couldn't acquire input object"); + return FALSE; + } + + return TRUE; +} + +static gboolean +gst_decklink2_src_stop (GstBaseSrc * src) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + if (self->input) { + gst_decklink2_input_stop (self->input); + gst_decklink2_release_input (self->input); + self->input = NULL; + } + + gst_clear_caps (&self->selected_caps); + memset (&self->selected_mode, 0, sizeof (GstDeckLink2DisplayMode)); + + self->running = FALSE; + + return TRUE; +} + +static gboolean +gst_decklink2_src_unlock (GstBaseSrc * src) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + if (self->input) + gst_decklink2_input_set_flushing (self->input, TRUE); + + return TRUE; +} + +static gboolean +gst_decklink2_src_unlock_stop (GstBaseSrc * src) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + if (self->input) + gst_decklink2_input_set_flushing (self->input, FALSE); + + return TRUE; +} + +static gboolean +gst_decklink2_src_run (GstDeckLink2Src * self) +{ + HRESULT hr; + GstDeckLink2InputVideoConfig video_config; + GstDeckLink2InputAudioConfig audio_config; + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + if (self->running) + return TRUE; + + if (!self->input) { + GST_ERROR_OBJECT (self, "Input object was not configured"); + return FALSE; + } + + video_config.connection = self->video_conn; + video_config.display_mode = self->selected_mode; + video_config.pixel_format = self->video_format; + video_config.auto_detect = self->display_mode == bmdModeUnknown; + video_config.output_cc = self->output_cc; + video_config.output_afd_bar = self->output_afd_bar; + + audio_config.connection = self->audio_conn; + audio_config.sample_type = bmdAudioSampleType32bitInteger; + audio_config.channels = self->audio_channels; + + hr = gst_decklink2_input_start (self->input, GST_ELEMENT (self), + self->profile_id, self->buffer_size, &video_config, &audio_config); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't start stream, hr: 0x%x", (guint) hr); + return FALSE; + } + + self->running = TRUE; + return TRUE; +} + +static GstFlowReturn +gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) +{ + GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); + GstSample *sample; + GstCaps *caps; + GstFlowReturn ret; + GstDeckLink2SrcPrivate *priv = self->priv; + gboolean is_gap_buf = FALSE; + + if (!gst_decklink2_src_run (self)) { + GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), + ("Failed to start stream")); + return GST_FLOW_ERROR; + } + + ret = gst_decklink2_input_get_sample (self->input, &sample); + if (ret != GST_FLOW_OK) + return ret; + + std::unique_lock < std::mutex > lk (priv->lock); + caps = gst_sample_get_caps (sample); + if (caps && !gst_caps_is_equal (caps, self->selected_caps)) { + GST_DEBUG_OBJECT (self, "Set updated caps %" GST_PTR_FORMAT, caps); + gst_caps_replace (&self->selected_caps, caps); + lk.unlock (); + if (!gst_pad_set_caps (GST_BASE_SRC_PAD (self), caps)) { + GST_ERROR_OBJECT (self, "Couldn't set caps"); + gst_sample_unref (sample); + return GST_FLOW_NOT_NEGOTIATED; + } + } + + *buffer = gst_sample_get_buffer (sample); + if (GST_BUFFER_FLAG_IS_SET (*buffer, GST_BUFFER_FLAG_GAP)) + is_gap_buf = TRUE; + + if (is_gap_buf != self->is_gap_buf) { + self->is_gap_buf = is_gap_buf; + g_object_notify (G_OBJECT (self), "signal"); + } + + gst_buffer_ref (*buffer); + gst_sample_unref (sample); + + return GST_FLOW_OK; +} + +void +gst_decklink2_src_install_properties (GObjectClass * object_class) +{ + GParamFlags param_flags = (GParamFlags) (G_PARAM_READWRITE | + GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_property (object_class, PROP_MODE, + g_param_spec_enum ("mode", "Playback Mode", + "Video Mode to use for playback", + GST_TYPE_DECKLINK2_MODE, DEFAULT_MODE, param_flags)); + + g_object_class_install_property (object_class, PROP_DEVICE_NUMBER, + g_param_spec_int ("device-number", "Device number", + "Output device instance to use", 0, G_MAXINT, DEFAULT_DEVICE_NUMBER, + param_flags)); + + g_object_class_install_property (object_class, PROP_PERSISTENT_ID, + g_param_spec_int64 ("persistent-id", "Persistent id", + "Output device instance to use. Higher priority than \"device-number\".", + DEFAULT_PERSISTENT_ID, G_MAXINT64, DEFAULT_PERSISTENT_ID, + param_flags)); + + g_object_class_install_property (object_class, PROP_VIDEO_CONNECTION, + g_param_spec_enum ("video-connection", "Video Connection", + "Video input connection to use", + GST_TYPE_DECKLINK2_VIDEO_CONNECTION, DEFAULT_VIDEO_CONNECTION, + param_flags)); + + g_object_class_install_property (object_class, PROP_AUDIO_CONNECTION, + g_param_spec_enum ("audio-connection", "Audio Connection", + "Audio input connection to use", + GST_TYPE_DECKLINK2_AUDIO_CONNECTION, DEFAULT_AUDIO_CONNECTION, + param_flags)); + + g_object_class_install_property (object_class, PROP_VIDEO_FORMAT, + g_param_spec_enum ("video-format", "Video format", + "Video format type to use for playback", + GST_TYPE_DECKLINK2_VIDEO_FORMAT, DEFAULT_VIDEO_FORMAT, param_flags)); + + g_object_class_install_property (object_class, PROP_AUDIO_CHANNELS, + g_param_spec_enum ("audio-channels", "Audio Channels", + "Audio Channels", + GST_TYPE_DECKLINK2_AUDIO_CHANNELS, DEFAULT_AUDIO_CHANNELS, + param_flags)); + + g_object_class_install_property (object_class, PROP_PROFILE_ID, + g_param_spec_enum ("profile", "Profile", + "Certain DeckLink devices such as the DeckLink 8K Pro, the DeckLink " + "Quad 2 and the DeckLink Duo 2 support multiple profiles to " + "configure the capture and playback behavior of its sub-devices." + "For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared " + "between any 2 sub-devices that utilize the same connectors. For the " + "DeckLink 8K Pro, a profile is shared between all 4 sub-devices. Any " + "sub-devices that share a profile are considered to be part of the " + "same profile group." + "DeckLink Duo 2 support configuration of the duplex mode of " + "individual sub-devices.", + GST_TYPE_DECKLINK2_PROFILE_ID, DEFAULT_PROFILE_ID, param_flags)); + + g_object_class_install_property (object_class, PROP_TIMECODE_FORMAT, + g_param_spec_enum ("timecode-format", "Timecode format", + "Timecode format type to use for playback", + GST_TYPE_DECKLINK2_TIMECODE_FORMAT, DEFAULT_TIMECODE_FORMAT, + param_flags)); + + g_object_class_install_property (object_class, PROP_OUTPUT_CC, + g_param_spec_boolean ("output-cc", "Output Closed Caption", + "Extract and output CC as GstMeta (if present)", + DEFAULT_OUTPUT_CC, param_flags)); + + g_object_class_install_property (object_class, PROP_OUTPUT_AFD_BAR, + g_param_spec_boolean ("output-afd-bar", "Output AFD/Bar data", + "Extract and output AFD/Bar as GstMeta (if present)", + DEFAULT_OUTPUT_AFD_BAR, param_flags)); + + g_object_class_install_property (object_class, PROP_BUFFER_SIZE, + g_param_spec_uint ("buffer-size", "Buffer Size", + "Size of internal buffer in number of video frames", 1, + 16, DEFAULT_BUFFER_SIZE, param_flags)); + + g_object_class_install_property (object_class, PROP_SIGNAL, + g_param_spec_boolean ("signal", "Signal", + "True if there is a valid input signal available", + FALSE, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h new file mode 100644 index 0000000000..2b4b5803ab --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h @@ -0,0 +1,36 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_SRC (gst_decklink2_src_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2Src, gst_decklink2_src, + GST, DECKLINK2_SRC, GstPushSrc); + +GST_ELEMENT_REGISTER_DECLARE (decklink2src); + +void gst_decklink2_src_install_properties (GObjectClass * object_class); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp new file mode 100644 index 0000000000..3fc331def5 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp @@ -0,0 +1,206 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2srcbin.h" +#include "gstdecklink2src.h" +#include "gstdecklink2utils.h" + +GST_DEBUG_CATEGORY_STATIC (gst_decklink2_src_bin_debug); +#define GST_CAT_DEFAULT gst_decklink2_src_bin_debug + +static GstStaticPadTemplate audio_template = GST_STATIC_PAD_TEMPLATE ("audio", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("audio/x-raw, format = (string) { S16LE, S32LE }, " + "rate = (int) 48000, channels = (int) { 2, 8, 16 }, " + "layout = (string) interleaved")); + + +struct _GstDeckLink2SrcBin +{ + GstBin parent; + + GstElement *src; + GstElement *demux; +}; + +static void gst_decklink2_src_bin_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_decklink2_src_bin_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static void on_signal (GObject * object, GParamSpec * pspec, GstElement * self); +static void on_pad_added (GstElement * demux, GstPad * pad, + GstDeckLink2SrcBin * self); +static void on_pad_removed (GstElement * demux, GstPad * pad, + GstDeckLink2SrcBin * self); +static void on_no_more_pads (GstElement * demux, GstDeckLink2SrcBin * self); + +#define gst_decklink2_src_bin_parent_class parent_class +G_DEFINE_TYPE (GstDeckLink2SrcBin, gst_decklink2_src_bin, GST_TYPE_BIN); +GST_ELEMENT_REGISTER_DEFINE (decklink2srcbin, "decklink2srcbin", + GST_RANK_NONE, GST_TYPE_DECKLINK2_SRC_BIN); + +static void +gst_decklink2_src_bin_class_init (GstDeckLink2SrcBinClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstCaps *templ_caps; + + object_class->set_property = gst_decklink2_src_bin_set_property; + object_class->get_property = gst_decklink2_src_bin_get_property; + + gst_decklink2_src_install_properties (object_class); + + templ_caps = gst_decklink2_get_default_template_caps (); + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("video", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps)); + gst_caps_unref (templ_caps); + + gst_element_class_add_static_pad_template (element_class, &audio_template); + + gst_element_class_set_static_metadata (element_class, + "Decklink2 Source Bin", "Video/Audio/Source/Hardware", + "Decklink2 Source Bin", "Seungha Yang "); + + GST_DEBUG_CATEGORY_INIT (gst_decklink2_src_bin_debug, "decklink2srcbin", + 0, "decklink2srcbin"); +} + +static void +gst_decklink2_src_bin_init (GstDeckLink2SrcBin * self) +{ + GstPad *pad; + GstPad *gpad; + + self->src = gst_element_factory_make ("decklink2src", NULL); + self->demux = gst_element_factory_make ("decklink2demux", NULL); + + gst_bin_add_many (GST_BIN (self), self->src, self->demux, NULL); + gst_element_link (self->src, self->demux); + + pad = gst_element_get_static_pad (self->demux, "video"); + gpad = gst_ghost_pad_new ("video", pad); + gst_object_unref (pad); + gst_element_add_pad (GST_ELEMENT (self), gpad); + + g_signal_connect (self->src, "notify::signal", G_CALLBACK (on_signal), self); + + g_signal_connect (self->demux, "pad-added", G_CALLBACK (on_pad_added), self); + g_signal_connect (self->demux, + "pad-removed", G_CALLBACK (on_pad_removed), self); + g_signal_connect (self->demux, "no-more-pads", + G_CALLBACK (on_no_more_pads), self); + + gst_bin_set_suppressed_flags (GST_BIN (self), + (GstElementFlags) (GST_ELEMENT_FLAG_SOURCE | GST_ELEMENT_FLAG_SINK)); + GST_OBJECT_FLAG_SET (self, GST_ELEMENT_FLAG_SOURCE); +} + +static void +gst_decklink2_src_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeckLink2SrcBin *self = GST_DECKLINK2_SRC_BIN (object); + + g_object_set_property (G_OBJECT (self->src), pspec->name, value); +} + +static void +gst_decklink2_src_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeckLink2SrcBin *self = GST_DECKLINK2_SRC_BIN (object); + + g_object_get_property (G_OBJECT (self->src), pspec->name, value); +} + +static gboolean +copy_sticky_events (GstPad * pad, GstEvent ** event, GstPad * gpad) +{ + gst_pad_store_sticky_event (gpad, *event); + + return TRUE; +} + +static void +on_signal (GObject * object, GParamSpec * pspec, GstElement * self) +{ + g_object_notify (G_OBJECT (self), "signal"); +} + +static void +on_pad_added (GstElement * demux, GstPad * pad, GstDeckLink2SrcBin * self) +{ + GstPad *gpad; + gchar *pad_name; + + GST_DEBUG_OBJECT (self, "Pad added %" GST_PTR_FORMAT, pad); + + if (!GST_PAD_IS_SRC (pad)) + return; + + pad_name = gst_pad_get_name (pad); + if (g_strcmp0 (pad_name, "audio") != 0) { + g_free (pad_name); + return; + } + + g_free (pad_name); + + gpad = gst_ghost_pad_new ("audio", pad); + g_object_set_data (G_OBJECT (pad), "decklink2srcbin.ghostpad", gpad); + + gst_pad_set_active (gpad, TRUE); + gst_pad_sticky_events_foreach (pad, + (GstPadStickyEventsForeachFunction) copy_sticky_events, gpad); + gst_element_add_pad (GST_ELEMENT (self), gpad); +} + +static void +on_pad_removed (GstElement * demux, GstPad * pad, GstDeckLink2SrcBin * self) +{ + GstPad *gpad; + + GST_DEBUG_OBJECT (self, "Pad removed %" GST_PTR_FORMAT, pad); + + if (!GST_PAD_IS_SRC (pad)) + return; + + gpad = (GstPad *) g_object_get_data (G_OBJECT (pad), + "decklink2srcbin.ghostpad"); + if (!gpad) { + GST_DEBUG_OBJECT (self, "No ghost pad found"); + return; + } + + gst_element_remove_pad (GST_ELEMENT (self), gpad); +} + +static void +on_no_more_pads (GstElement * demux, GstDeckLink2SrcBin * self) +{ + gst_element_no_more_pads (GST_ELEMENT (self)); +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.h new file mode 100644 index 0000000000..1503332787 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.h @@ -0,0 +1,34 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DECKLINK2_SRC_BIN (gst_decklink2_src_bin_get_type()) +G_DECLARE_FINAL_TYPE (GstDeckLink2SrcBin, gst_decklink2_src_bin, + GST, DECKLINK2_SRC_BIN, GstBin); + +GST_ELEMENT_REGISTER_DECLARE (decklink2srcbin); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp new file mode 100644 index 0000000000..3a930ab223 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp @@ -0,0 +1,1228 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdecklink2utils.h" +#include "gstdecklink2object.h" +#include +#include +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (gst_decklink2_debug); +#define GST_CAT_DEFAULT gst_decklink2_debug + +static guint api_version_major = 0; +static guint api_version_minor = 0; +static guint api_version_sub = 0; +static guint api_version_extra = 0; + +#ifdef G_OS_WIN32 +static GThread *win32_com_thread = NULL; +/* *INDENT-OFF* */ +static std::mutex com_init_lock; +static std::mutex com_deinit_lock; +static std::condition_variable com_init_cond; +static std::condition_variable com_deinit_cond; +/* *INDENT-ON* */ +static bool com_thread_running = false; +static bool exit_com_thread = false; + +static gpointer +gst_decklink2_win32_com_thread (gpointer user_data) +{ + std::unique_lock < std::mutex > init_lk (com_init_lock); + + CoInitializeEx (0, COINIT_MULTITHREADED); + com_thread_running = true; + com_init_cond.notify_all (); + init_lk.unlock (); + + std::unique_lock < std::mutex > deinit_lk (com_deinit_lock); + while (!exit_com_thread) { + com_deinit_cond.wait (deinit_lk); + } + CoUninitialize (); + + return NULL; +} + +static IDeckLinkAPIInformation * +CreateDeckLinkAPIInformationInstance (void) +{ + IDeckLinkAPIInformation *info = NULL; + + CoCreateInstance (CLSID_CDeckLinkAPIInformation, NULL, CLSCTX_ALL, + IID_IDeckLinkAPIInformation, (void **) &info); + + return info; +} +#endif + +gboolean +gst_decklink2_init_once (void) +{ + static gboolean ret = FALSE; + GST_DECKLINK2_CALL_ONCE_BEGIN { + IDeckLinkAPIInformation *info = NULL; + gint64 version = 0; + HRESULT hr; + +#ifdef G_OS_WIN32 + std::unique_lock < std::mutex > lk (com_init_lock); + win32_com_thread = g_thread_new ("GstDeckLink2Win32", + gst_decklink2_win32_com_thread, NULL); + while (!com_thread_running) + com_init_cond.wait (lk); +#endif + + info = CreateDeckLinkAPIInformationInstance (); + if (!info) + return; + + hr = info->GetInt (BMDDeckLinkAPIVersion, &version); + if (gst_decklink2_result (hr)) { + api_version_major = (version & 0xff000000) >> 24; + api_version_minor = (version & 0xff0000) >> 16; + api_version_sub = (version & 0xff00) >> 8; + api_version_extra = version & 0xff; + ret = TRUE; + } + + info->Release (); + } + GST_DECKLINK2_CALL_ONCE_END; + + return ret; +} + +void +gst_decklink2_deinit (void) +{ + gst_decklink2_object_deinit (); +#ifdef G_OS_WIN32 + std::unique_lock < std::mutex > deinit_lk (com_deinit_lock); + if (win32_com_thread) { + exit_com_thread = true; + com_deinit_cond.notify_all (); + deinit_lk.unlock (); + g_thread_join (win32_com_thread); + win32_com_thread = NULL; + } +#endif +} + +gboolean +gst_decklink2_get_api_version (guint * major, guint * minor, guint * sub, + guint * extra) +{ + if (!gst_decklink2_init_once ()) + return FALSE; + + if (major) + *major = api_version_major; + if (minor) + *minor = api_version_minor; + if (sub) + *sub = api_version_sub; + if (extra) + *extra = api_version_extra; + + return TRUE; +} + +GstDeckLink2APILevel +gst_decklink2_get_api_level (void) +{ + static GstDeckLink2APILevel level = GST_DECKLINK2_API_LEVEL_UNKNOWN; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + guint major, minor, sub; + if (!gst_decklink2_get_api_version (&major, &minor, &sub, NULL)) + return; + + if (major >= 12) { + level = GST_DECKLINK2_API_LEVEL_LATEST; + return; + } else if (major == 11) { + if (minor > 5 || (minor == 5 && sub >= 1)) { + level = GST_DECKLINK2_API_LEVEL_11_5_1; + } else if (minor == 4) { + level = GST_DECKLINK2_API_LEVEL_11_4; + } else { + level = GST_DECKLINK2_API_LEVEL_10_11; + } + } else if (major == 10 && minor >= 11) { + level = GST_DECKLINK2_API_LEVEL_10_11; + } + } + GST_DECKLINK2_CALL_ONCE_END; + + return level; +} + +const gchar * +gst_decklink2_api_level_to_string (GstDeckLink2APILevel level) +{ + switch (level) { + case GST_DECKLINK2_API_LEVEL_10_11: + return "10.11"; + case GST_DECKLINK2_API_LEVEL_11_4: + return "11.4"; + case GST_DECKLINK2_API_LEVEL_11_5_1: + return "11.5.1"; + case GST_DECKLINK2_API_LEVEL_LATEST: + return "latest"; + default: + break; + } + + return "unknown"; +} + +GType +gst_decklink2_mode_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue modes[] = { + {bmdModeUnknown, "Automatic detection", "auto"}, + + {bmdModeNTSC, "NTSC SD 60i", "ntsc"}, + {bmdModeNTSC2398, "NTSC SD 60i (24 fps)", "ntsc2398"}, + {bmdModePAL, "PAL SD 50i", "pal"}, + {bmdModeNTSCp, "NTSC SD 60p", "ntsc-p"}, + {bmdModePALp, "PAL SD 50p", "pal-p"}, + + {bmdModeNTSC_W, "NTSC SD 60i Widescreen", "ntsc-widescreen"}, + {bmdModeNTSC2398_W, "NTSC SD 60i Widescreen (24 fps)", + "ntsc2398-widescreen"}, + {bmdModePAL_W, "PAL SD 50i Widescreen", "pal-widescreen"}, + {bmdModeNTSCp_W, "NTSC SD 60p Widescreen", "ntsc-p-widescreen"}, + {bmdModePALp_W, "PAL SD 50p Widescreen", "pal-p-widescreen"}, + + {bmdModeHD1080p2398, "HD1080 23.98p", "1080p2398"}, + {bmdModeHD1080p24, "HD1080 24p", "1080p24"}, + {bmdModeHD1080p25, "HD1080 25p", "1080p25"}, + {bmdModeHD1080p2997, "HD1080 29.97p", "1080p2997"}, + {bmdModeHD1080p30, "HD1080 30p", "1080p30"}, + {bmdModeHD1080p50, "HD1080 50p", "1080p50"}, + {bmdModeHD1080p5994, "HD1080 59.94p", "1080p5994"}, + {bmdModeHD1080p6000, "HD1080 60p", "1080p60"}, + {bmdModeHD1080i50, "HD1080 50i", "1080i50"}, + {bmdModeHD1080i5994, "HD1080 59.94i", "1080i5994"}, + {bmdModeHD1080i6000, "HD1080 60i", "1080i60"}, + + {bmdModeHD720p50, "HD720 50p", "720p50"}, + {bmdModeHD720p5994, "HD720 59.94p", "720p5994"}, + {bmdModeHD720p60, "HD720 60p", "720p60"}, + + {bmdMode2k2398, "2k 23.98p", "1556p2398"}, + {bmdMode2k24, "2k 24p", "1556p24"}, + {bmdMode2k25, "2k 25p", "1556p25"}, + + {bmdMode2kDCI2398, "2k dci 23.98p", "2kdcip2398"}, + {bmdMode2kDCI24, "2k dci 24p", "2kdcip24"}, + {bmdMode2kDCI25, "2k dci 25p", "2kdcip25"}, + {bmdMode2kDCI2997, "2k dci 29.97p", "2kdcip2997"}, + {bmdMode2kDCI30, "2k dci 30p", "2kdcip30"}, + {bmdMode2kDCI50, "2k dci 50p", "2kdcip50"}, + {bmdMode2kDCI5994, "2k dci 59.94p", "2kdcip5994"}, + {bmdMode2kDCI60, "2k dci 60p", "2kdcip60"}, + + {bmdMode4K2160p2398, "4k 23.98p", "2160p2398"}, + {bmdMode4K2160p24, "4k 24p", "2160p24"}, + {bmdMode4K2160p25, "4k 25p", "2160p25"}, + {bmdMode4K2160p2997, "4k 29.97p", "2160p2997"}, + {bmdMode4K2160p30, "4k 30p", "2160p30"}, + {bmdMode4K2160p50, "4k 50p", "2160p50"}, + {bmdMode4K2160p5994, "4k 59.94p", "2160p5994"}, + {bmdMode4K2160p60, "4k 60p", "2160p60"}, + + {bmdMode4kDCI2398, "4k dci 23.98p", "4kdcip2398"}, + {bmdMode4kDCI24, "4k dci 24p", "4kdcip24"}, + {bmdMode4kDCI25, "4k dci 25p", "4kdcip25"}, + {bmdMode4kDCI2997, "4k dci 29.97p", "4kdcip2997"}, + {bmdMode4kDCI30, "4k dci 30p", "4kdcip30"}, + {bmdMode4kDCI50, "4k dci 50p", "4kdcip50"}, + {bmdMode4kDCI5994, "4k dci 59.94p", "4kdcip5994"}, + {bmdMode4kDCI60, "4k dci 60p", "4kdcip60"}, + + {bmdMode8K4320p2398, "8k 23.98p", "8kp2398"}, + {bmdMode8K4320p24, "8k 24p", "8kp24"}, + {bmdMode8K4320p25, "8k 25p", "8kp25"}, + {bmdMode8K4320p2997, "8k 29.97p", "8kp2997"}, + {bmdMode8K4320p30, "8k 30p", "8kp30"}, + {bmdMode8K4320p50, "8k 50p", "8kp50"}, + {bmdMode8K4320p5994, "8k 59.94p", "8kp5994"}, + {bmdMode8K4320p60, "8k 60p", "8kp60"}, + + {bmdMode8kDCI2398, "8k dci 23.98p", "8kdcip2398"}, + {bmdMode8kDCI24, "8k dci 24p", "8kdcip24"}, + {bmdMode8kDCI25, "8k dci 25p", "8kdcip25"}, + {bmdMode8kDCI2997, "8k dci 29.97p", "8kdcip2997"}, + {bmdMode8kDCI30, "8k dci 30p", "8kdcip30"}, + {bmdMode8kDCI50, "8k dci 50p", "8kdcip50"}, + {bmdMode8kDCI5994, "8k dci 59.94p", "8kdcip5994"}, + {bmdMode8kDCI60, "8k dci 60p", "8kdcip60"}, + + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2Mode", modes); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_video_format_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue formats[] = { + {bmdFormatUnspecified, "Auto", "auto"}, + {bmdFormat8BitYUV, "bmdFormat8BitYUV", "8bit-yuv"}, + {bmdFormat10BitYUV, "bmdFormat10BitYUV", "10bit-yuv"}, + {bmdFormat8BitARGB, "bmdFormat8BitARGB", "8bit-argb"}, + {bmdFormat8BitBGRA, "bmdFormat8BitBGRA", "8bit-bgra"}, + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2VideoFormat", formats); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_profile_id_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue profiles[] = { + {bmdProfileDefault, "Default, don't change profile", + "default"}, + {bmdProfileOneSubDeviceFullDuplex, + "One sub-device, Full-Duplex", "one-sub-device-full"}, + {bmdProfileOneSubDeviceHalfDuplex, + "One sub-device, Half-Duplex", "one-sub-device-half"}, + {bmdProfileTwoSubDevicesFullDuplex, + "Two sub-devices, Full-Duplex", "two-sub-devices-full"}, + {bmdProfileTwoSubDevicesHalfDuplex, + "Two sub-devices, Half-Duplex", "two-sub-devices-half"}, + {bmdProfileFourSubDevicesHalfDuplex, + "Four sub-devices, Half-Duplex", "four-sub-devices-half"}, + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2ProfileId", profiles); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_keyer_mode_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue modes[] = { + {GST_DECKLINK2_KEYER_MODE_OFF, "Off", "off"}, + {GST_DECKLINK2_KEYER_MODE_INTERNAL, "Internal", "internal"}, + {GST_DECKLINK2_KEYER_MODE_EXTERNAL, "External", "external"}, + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2KeyerMode", modes); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_mapping_format_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue formats[] = { + {GST_DECKLINK2_MAPPING_FORMAT_DEFAULT, + "Default, don't change mapping format", + "default"}, + {GST_DECKLINK2_MAPPING_FORMAT_LEVEL_A, "Level A", "level-a"}, + {GST_DECKLINK2_MAPPING_FORMAT_LEVEL_B, "Level B", "level-b"}, + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2MappingFormat", formats); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_timecode_format_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue formats[] = { + {bmdTimecodeRP188VITC1, "bmdTimecodeRP188VITC1", "rp188vitc1"}, + {bmdTimecodeRP188VITC2, "bmdTimecodeRP188VITC2", "rp188vitc2"}, + {bmdTimecodeRP188LTC, "bmdTimecodeRP188LTC", "rp188ltc"}, + {bmdTimecodeRP188Any, "bmdTimecodeRP188Any", "rp188any"}, + {bmdTimecodeVITC, "bmdTimecodeVITC", "vitc"}, + {bmdTimecodeVITCField2, "bmdTimecodeVITCField2", "vitcfield2"}, + {bmdTimecodeSerial, "bmdTimecodeSerial", "serial"}, + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2TimecodeFormat", formats); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_video_connection_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue connections[] = { + {bmdVideoConnectionUnspecified, "Auto", "auto"}, + {bmdVideoConnectionSDI, "SDI", "sdi"}, + {bmdVideoConnectionHDMI, "HDMI", "hdmi"}, + {bmdVideoConnectionOpticalSDI, "Optical SDI", "optical-sdi"}, + {bmdVideoConnectionComponent, "Component", "component"}, + {bmdVideoConnectionComposite, "Composite", "composite"}, + {bmdVideoConnectionSVideo, "S-Video", "svideo"}, + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2VideoConnection", connections); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_audio_connection_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue connections[] = { + {bmdAudioConnectionUnspecified, "Auto", "auto"}, + {bmdAudioConnectionEmbedded, "SDI/HDMI embedded audio", "embedded"}, + {bmdAudioConnectionAESEBU, "AES/EBU", "aes"}, + {bmdAudioConnectionAnalog, "Analog", "analog"}, + {bmdAudioConnectionAnalogXLR, "Analog (XLR)", "analog-xlr"}, + {bmdAudioConnectionAnalogRCA, "Analog (RCA)", "analog-rca"}, +#if 0 + {bmdAudioConnectionMicrophone, "Microphone", "microphone"}, + {bmdAudioConnectionHeadphones, "Headpones", "headphones"}, +#endif + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2AudioConnection", connections); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +GType +gst_decklink2_audio_channels_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const GEnumValue channles[] = { + {GST_DECKLINK2_AUDIO_CHANNELS_DISABLED, "Disabled", "disabled"}, + {GST_DECKLINK2_AUDIO_CHANNELS_2, "2 Channels", "2"}, + {GST_DECKLINK2_AUDIO_CHANNELS_8, "8 Channels", "8"}, + {GST_DECKLINK2_AUDIO_CHANNELS_16, "16 Channels", "16"}, + {GST_DECKLINK2_AUDIO_CHANNELS_MAX, "Maximum channels supported", "max"}, + {0, NULL, NULL} + }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstDeckLink2AudioChannels", channles); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +#define NTSC 10, 11, FALSE +#define PAL 12, 11, TRUE +#define NTSC_WS 40, 33, FALSE +#define PAL_WS 16, 11, TRUE +#define HD 1, 1, TRUE +#define UHD 1, 1, TRUE + +static const GstDeckLink2DisplayMode all_modes[] = { + {bmdModeUnknown, 0, 0, 0, 0, FALSE, 0, 0, 0}, + /* SD Modes */ + {bmdModeNTSC, 720, 486, 30000, 1001, TRUE, NTSC}, + {bmdModeNTSC2398, 720, 486, 24000, 1001, TRUE, NTSC}, + {bmdModePAL, 720, 576, 25, 1, TRUE, PAL}, + {bmdModeNTSCp, 720, 486, 30000, 1001, FALSE, NTSC}, + {bmdModePALp, 720, 576, 25, 1, FALSE, PAL}, + + /* Custom wide modes */ + {bmdModeNTSC_W, 720, 486, 30000, 1001, TRUE, NTSC_WS}, + {bmdModeNTSC2398_W, 720, 486, 24000, 1001, TRUE, NTSC_WS}, + {bmdModePAL_W, 720, 576, 25, 1, TRUE, PAL_WS}, + {bmdModeNTSCp_W, 720, 486, 30000, 1001, FALSE, NTSC_WS}, + {bmdModePALp_W, 720, 576, 25, 1, FALSE, PAL_WS}, + + /* HD 1080 Modes */ + {bmdModeHD1080p2398, 1920, 1080, 24000, 1001, FALSE, HD}, + {bmdModeHD1080p24, 1920, 1080, 24, 1, FALSE, HD}, + {bmdModeHD1080p25, 1920, 1080, 25, 1, FALSE, HD}, + {bmdModeHD1080p2997, 1920, 1080, 30000, 1001, FALSE, HD}, + {bmdModeHD1080p30, 1920, 1080, 30, 1, FALSE, HD}, + /* FIXME: + * bmdModeHD1080p4795 + * bmdModeHD1080p48 + */ + {bmdModeHD1080p50, 1920, 1080, 50, 1, FALSE, HD}, + {bmdModeHD1080p5994, 1920, 1080, 60000, 1001, FALSE, HD}, + {bmdModeHD1080p6000, 1920, 1080, 60, 1, FALSE, HD}, + /* FIXME: + * bmdModeHD1080p9590 + * bmdModeHD1080p96 + * bmdModeHD1080p100 + * bmdModeHD1080p11988 + * bmdModeHD1080p120 + */ + {bmdModeHD1080i50, 1920, 1080, 25, 1, TRUE, HD}, + {bmdModeHD1080i5994, 1920, 1080, 30000, 1001, TRUE, HD}, + {bmdModeHD1080i6000, 1920, 1080, 30, 1, TRUE, HD}, + + /* HD 720 Modes */ + {bmdModeHD720p50, 1280, 720, 50, 1, FALSE, HD}, + {bmdModeHD720p5994, 1280, 720, 60000, 1001, FALSE, HD}, + {bmdModeHD720p60, 1280, 720, 60, 1, FALSE, HD}, + + /* 2K Modes */ + {bmdMode2k2398, 2048, 1556, 24000, 1001, FALSE, HD}, + {bmdMode2k24, 2048, 1556, 24, 1, FALSE, HD}, + {bmdMode2k25, 2048, 1556, 25, 1, FALSE, HD}, + + /* 2K DCI Modes */ + {bmdMode2kDCI2398, 2048, 1080, 24000, 1001, FALSE, HD}, + {bmdMode2kDCI24, 2048, 1080, 24, 1, FALSE, HD}, + {bmdMode2kDCI25, 2048, 1080, 25, 1, FALSE, HD}, + {bmdMode2kDCI2997, 2048, 1080, 30000, 1001, FALSE, HD}, + {bmdMode2kDCI30, 2048, 1080, 30, 1, FALSE, HD}, + /* FIXME: + * bmdMode2kDCI4795 + * bmdMode2kDCI48 + */ + {bmdMode2kDCI50, 2048, 1080, 50, 1, FALSE, HD}, + {bmdMode2kDCI5994, 2048, 1080, 60000, 1001, FALSE, HD}, + {bmdMode2kDCI60, 2048, 1080, 60, 1, FALSE, HD}, + /* FIXME: + * bmdMode2kDCI9590 + * bmdMode2kDCI96 + * bmdMode2kDCI100 + * bmdMode2kDCI11988 + * bmdMode2kDCI120 + */ + + /* 4K UHD Modes */ + {bmdMode4K2160p2398, 3840, 2160, 24000, 1001, FALSE, UHD}, + {bmdMode4K2160p24, 3840, 2160, 24, 1, FALSE, UHD}, + {bmdMode4K2160p25, 3840, 2160, 25, 1, FALSE, UHD}, + {bmdMode4K2160p2997, 3840, 2160, 30000, 1001, FALSE, UHD}, + {bmdMode4K2160p30, 3840, 2160, 30, 1, FALSE, UHD}, + /* FIXME: + * bmdMode4K2160p4795 + * bmdMode4K2160p48 + */ + {bmdMode4K2160p50, 3840, 2160, 50, 1, FALSE, UHD}, + {bmdMode4K2160p5994, 3840, 2160, 60000, 1001, FALSE, UHD}, + {bmdMode4K2160p60, 3840, 2160, 60, 1, FALSE, UHD}, + /* FIXME: + * bmdMode4K2160p9590 + * bmdMode4K2160p96 + * bmdMode4K2160p100 + * bmdMode4K2160p11988 + * bmdMode4K2160p120 + */ + + /* 4K DCI Modes */ + {bmdMode4kDCI2398, 4096, 2160, 24000, 1001, FALSE, UHD}, + {bmdMode4kDCI24, 4096, 2160, 24, 1, FALSE, UHD}, + {bmdMode4kDCI25, 4096, 2160, 25, 1, FALSE, UHD}, + {bmdMode4kDCI2997, 4096, 2160, 30000, 1001, FALSE, UHD}, + {bmdMode4kDCI30, 4096, 2160, 30, 1, FALSE, UHD}, + /* FIXME: + * bmdMode4kDCI4795 + * bmdMode4kDCI48 + */ + {bmdMode4kDCI50, 4096, 2160, 50, 1, FALSE, UHD}, + {bmdMode4kDCI5994, 4096, 2160, 60000, 1001, FALSE, UHD}, + {bmdMode4kDCI60, 4096, 2160, 60, 1, FALSE, UHD}, + /* FIXME: + * bmdMode4kDCI9590 + * bmdMode4kDCI96 + * bmdMode4kDCI100 + * bmdMode4kDCI11988 + * bmdMode4kDCI120 + */ + + /* 8K UHD Modes */ + {bmdMode8K4320p2398, 7680, 4320, 24000, 1001, FALSE, UHD}, + {bmdMode8K4320p24, 7680, 4320, 24, 1, FALSE, UHD}, + {bmdMode8K4320p25, 7680, 4320, 25, 1, FALSE, UHD}, + {bmdMode8K4320p2997, 7680, 4320, 30000, 1001, FALSE, UHD}, + {bmdMode8K4320p30, 7680, 4320, 30, 1, FALSE, UHD}, + /* FIXME: + * bmdMode8K4320p4795 + * bmdMode8K4320p48 + */ + {bmdMode8K4320p50, 7680, 4320, 50, 1, FALSE, UHD}, + {bmdMode8K4320p5994, 7680, 4320, 60000, 1001, FALSE, UHD}, + {bmdMode8K4320p60, 7680, 4320, 60, 1, FALSE, UHD}, + + /* 8K DCI Modes */ + {bmdMode8kDCI2398, 8192, 4320, 24000, 1001, FALSE, UHD}, + {bmdMode8kDCI24, 8192, 4320, 24, 1, FALSE, UHD}, + {bmdMode8kDCI25, 8192, 4320, 25, 1, FALSE, UHD}, + {bmdMode8kDCI2997, 8192, 4320, 30000, 1001, FALSE, UHD}, + {bmdMode8kDCI30, 8192, 4320, 30, 1, FALSE, UHD}, + /* FIXME: + * bmdMode8kDCI4795 + * bmdMode8kDCI48 + */ + {bmdMode8kDCI50, 8192, 4320, 50, 1, FALSE, UHD}, + {bmdMode8kDCI5994, 8192, 4320, 60000, 1001, FALSE, UHD}, + {bmdMode8kDCI60, 8192, 4320, 60, 1, FALSE, UHD}, + + /* FIXME: Add PC modes */ +}; + +static const struct +{ + BMDPixelFormat format; + gint bpp; + GstVideoFormat vformat; +} formats[] = { + {bmdFormatUnspecified, 0, GST_VIDEO_FORMAT_UNKNOWN}, + {bmdFormat8BitYUV, 2, GST_VIDEO_FORMAT_UYVY}, + {bmdFormat10BitYUV, 4, GST_VIDEO_FORMAT_v210}, + {bmdFormat8BitARGB, 4, GST_VIDEO_FORMAT_ARGB}, + {bmdFormat8BitBGRA, 4, GST_VIDEO_FORMAT_BGRA}, +}; + +GstVideoFormat +gst_decklink2_video_format_from_pixel_format (BMDPixelFormat format) +{ + switch (format) { + case bmdFormat8BitYUV: + return GST_VIDEO_FORMAT_UYVY; + case bmdFormat10BitYUV: + return GST_VIDEO_FORMAT_v210; + case bmdFormat8BitARGB: + return GST_VIDEO_FORMAT_ARGB; + case bmdFormat8BitBGRA: + return GST_VIDEO_FORMAT_BGRA; + default: + break; + } + + return GST_VIDEO_FORMAT_UNKNOWN; +} + +BMDPixelFormat +gst_decklink2_pixel_format_from_video_format (GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_UYVY: + return bmdFormat8BitYUV; + case GST_VIDEO_FORMAT_v210: + return bmdFormat10BitYUV; + case GST_VIDEO_FORMAT_ARGB: + return bmdFormat8BitARGB; + case GST_VIDEO_FORMAT_BGRA: + return bmdFormat8BitBGRA; + default: + break; + } + + return bmdFormatUnspecified; +} + + +static const gchar * +gst_decklink2_pixel_format_to_string (BMDPixelFormat format) +{ + switch (format) { + case bmdFormat8BitYUV: + return "UYVY"; + case bmdFormat10BitYUV: + return "v210"; + case bmdFormat8BitARGB: + return "ARGB"; + case bmdFormat8BitBGRA: + return "BGRA"; + default: + g_assert_not_reached (); + break; + } + + return ""; +} + +static GstStructure * +gst_decklink2_mode_get_structure (const GstDeckLink2DisplayMode * mode, + BMDPixelFormat f) +{ + GstStructure *s = gst_structure_new ("video/x-raw", + "width", G_TYPE_INT, mode->width, + "height", G_TYPE_INT, mode->height, + "pixel-aspect-ratio", GST_TYPE_FRACTION, mode->par_n, mode->par_d, + "interlace-mode", G_TYPE_STRING, + mode->interlaced ? "interleaved" : "progressive", + "framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d, NULL); + + switch (f) { + case bmdFormatUnspecified: + { + GValue format_values = G_VALUE_INIT; + + g_value_init (&format_values, GST_TYPE_LIST); + for (guint i = 1; i < G_N_ELEMENTS (formats); i++) { + GValue f = G_VALUE_INIT; + + g_value_init (&f, G_TYPE_STRING); + g_value_set_static_string (&f, + gst_decklink2_pixel_format_to_string (formats[i].format)); + gst_value_list_append_and_take_value (&format_values, &f); + } + + gst_structure_set_value (s, "format", &format_values); + g_value_unset (&format_values); + break; + } + case bmdFormat8BitYUV: + gst_structure_set (s, "format", G_TYPE_STRING, "UYVY", NULL); + break; + case bmdFormat10BitYUV: + gst_structure_set (s, "format", G_TYPE_STRING, "v210", NULL); + break; + case bmdFormat8BitARGB: + gst_structure_set (s, "format", G_TYPE_STRING, "ARGB", NULL); + break; + case bmdFormat8BitBGRA: + gst_structure_set (s, "format", G_TYPE_STRING, "BGRA", NULL); + break; + default: + GST_WARNING ("format not supported %d", f); + gst_structure_free (s); + s = NULL; + break; + } + + return s; +} + +static GstCaps * +gst_decklink2_mode_get_all_format_caps (const GstDeckLink2DisplayMode * mode) +{ + GstCaps *caps; + GstStructure *s; + + if (!mode) + return NULL; + + caps = gst_caps_new_empty (); + s = gst_decklink2_mode_get_structure (mode, bmdFormatUnspecified); + return gst_caps_merge_structure (caps, s); +} + +static gboolean +gst_decklink2_get_display_mode (BMDDisplayMode mode, + GstDeckLink2DisplayMode * display_mode) +{ + for (guint i = 0; i < G_N_ELEMENTS (all_modes); i++) { + if (mode == all_modes[i].mode) { + *display_mode = all_modes[i]; + return TRUE; + } + } + + return FALSE; +} + +BMDDisplayMode +gst_decklink2_get_real_display_mode (BMDDisplayMode mode) +{ + switch (mode) { + case bmdModeNTSC_W: + return bmdModeNTSC; + case bmdModeNTSC2398_W: + return bmdModeNTSC2398; + case bmdModePAL_W: + return bmdModePAL; + case bmdModeNTSCp_W: + return bmdModeNTSCp; + case bmdModePALp_W: + return bmdModePALp; + default: + break; + } + + return mode; +} + +GstCaps * +gst_decklink2_build_caps (GstObject * io_object, + IDeckLinkDisplayModeIterator * iter, BMDDisplayMode requested_mode, + BMDPixelFormat format, GstDeckLink2DoesSupportVideoMode func) +{ + HRESULT hr = S_OK; + GstCaps *caps = NULL; + BMDDisplayMode real_mode = + gst_decklink2_get_real_display_mode (requested_mode); + + GST_LOG_OBJECT (io_object, "Building caps, mode: %" GST_FOURCC_FORMAT + ", format: %" GST_FOURCC_FORMAT, + GST_DECKLINK2_FOURCC_ARGS (requested_mode), + GST_DECKLINK2_FOURCC_ARGS (format)); + + do { + IDeckLinkDisplayMode *mode = NULL; + BMDDisplayMode bdm_mode; + GstDeckLink2DisplayMode gst_mode; + std::vector < std::string > formats; + GstStructure *s; + GstStructure *s_wide = NULL; + const gchar *format_str; + + hr = iter->Next (&mode); + if (hr != S_OK) + break; + + bdm_mode = mode->GetDisplayMode (); + if (requested_mode != bmdModeUnknown) { + if (real_mode != bdm_mode) + goto next; + + if (!gst_decklink2_get_display_mode (requested_mode, &gst_mode)) { + GST_WARNING_OBJECT (io_object, "Couldn't get mode"); + goto next; + } + } else if (!gst_decklink2_get_display_mode (bdm_mode, &gst_mode)) { + goto next; + } + + if (format == bmdFormatUnspecified) { + if (func (io_object, bdm_mode, bmdFormat8BitYUV)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat8BitYUV); + formats.push_back (format_str); + } + + if (func (io_object, bdm_mode, bmdFormat10BitYUV)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat10BitYUV); + formats.push_back (format_str); + } + + if (func (io_object, bdm_mode, bmdFormat8BitARGB)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat8BitARGB); + formats.push_back (format_str); + } + + if (func (io_object, bdm_mode, bmdFormat8BitBGRA)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat8BitBGRA); + formats.push_back (format_str); + } + } else if (func (io_object, bdm_mode, format)) { + format_str = gst_decklink2_pixel_format_to_string (format); + formats.push_back (format_str); + } + + if (formats.empty ()) + goto next; + + if (!caps) + caps = gst_caps_new_empty (); + + gst_mode.width = (gint) mode->GetWidth (); + gst_mode.height = (gint) mode->GetHeight (); + + s = gst_structure_new ("video/x-raw", + "width", G_TYPE_INT, gst_mode.width, + "height", G_TYPE_INT, gst_mode.height, + "pixel-aspect-ratio", GST_TYPE_FRACTION, gst_mode.par_n, gst_mode.par_d, + "interlace-mode", G_TYPE_STRING, + gst_mode.interlaced ? "interleaved" : "progressive", + "framerate", GST_TYPE_FRACTION, gst_mode.fps_n, gst_mode.fps_d, NULL); + + if (gst_mode.interlaced) { + BMDFieldDominance field; + + field = mode->GetFieldDominance (); + if (field == bmdLowerFieldFirst) + gst_mode.tff = FALSE; + else if (field == bmdUpperFieldFirst) + gst_mode.tff = TRUE; + + if (gst_mode.tff) { + gst_structure_set (s, + "field-order", G_TYPE_STRING, "top-field-first", NULL); + } else { + gst_structure_set (s, + "field-order", G_TYPE_STRING, "bottom-field-first", NULL); + } + } + + if (formats.size () == 1) { + gst_structure_set (s, "format", G_TYPE_STRING, formats[0].c_str (), NULL); + } else { + GValue format_values = G_VALUE_INIT; + + g_value_init (&format_values, GST_TYPE_LIST); + + /* *INDENT-OFF* */ + for (const auto & iter: formats) { + GValue f = G_VALUE_INIT; + + g_value_init (&f, G_TYPE_STRING); + g_value_set_string (&f, iter.c_str ()); + gst_value_list_append_and_take_value (&format_values, &f); + } + /* *INDENT-ON* */ + + gst_structure_set_value (s, "format", &format_values); + g_value_unset (&format_values); + } + + /* Add custom wide mode */ + if (requested_mode == bmdModeUnknown) { + switch (bdm_mode) { + case bmdModeNTSC: + case bmdModeNTSC2398: + case bmdModeNTSCp: + s_wide = gst_structure_copy (s); + gst_structure_set (s_wide, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 40, 33, NULL); + break; + case bmdModePAL: + case bmdModePALp: + s_wide = gst_structure_copy (s); + gst_structure_set (s_wide, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 16, 11, NULL); + break; + default: + break; + } + } + + gst_caps_append_structure (caps, s); + if (s_wide) + gst_caps_append_structure (caps, s_wide); + + next: + mode->Release (); + } while (gst_decklink2_result (hr)); + + return caps; +} + +GstCaps * +gst_decklink2_build_template_caps (GstObject * io_object, + IDeckLinkDisplayModeIterator * iter, GstDeckLink2DoesSupportVideoMode func, + GArray * format_table) +{ + HRESULT hr = S_OK; + GstCaps *caps = NULL; + + do { + IDeckLinkDisplayMode *mode = NULL; + BMDDisplayMode bdm_mode; + GstDeckLink2DisplayMode gst_mode; + GstDeckLink2DisplayMode gst_mode_wide; + std::vector < std::string > formats; + GstStructure *s; + GstStructure *s_wide = NULL; + const gchar *format_str; + + hr = iter->Next (&mode); + if (hr != S_OK) + break; + + bdm_mode = mode->GetDisplayMode (); + if (!gst_decklink2_get_display_mode (bdm_mode, &gst_mode)) + goto next; + + if (func (io_object, bdm_mode, bmdFormat8BitYUV)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat8BitYUV); + formats.push_back (format_str); + } + + if (func (io_object, bdm_mode, bmdFormat10BitYUV)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat10BitYUV); + formats.push_back (format_str); + } + + if (func (io_object, bdm_mode, bmdFormat8BitARGB)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat8BitARGB); + formats.push_back (format_str); + } + + if (func (io_object, bdm_mode, bmdFormat8BitBGRA)) { + format_str = gst_decklink2_pixel_format_to_string (bmdFormat8BitBGRA); + formats.push_back (format_str); + } + + if (formats.empty ()) + goto next; + + if (!caps) + caps = gst_caps_new_empty (); + + gst_mode.width = (gint) mode->GetWidth (); + gst_mode.height = (gint) mode->GetHeight (); + if (gst_mode.interlaced) { + BMDFieldDominance field; + + field = mode->GetFieldDominance (); + if (field == bmdLowerFieldFirst) + gst_mode.tff = FALSE; + else if (field == bmdUpperFieldFirst) + gst_mode.tff = TRUE; + } + + s = gst_structure_new ("video/x-raw", + "width", G_TYPE_INT, gst_mode.width, + "height", G_TYPE_INT, gst_mode.height, + "pixel-aspect-ratio", GST_TYPE_FRACTION, gst_mode.par_n, gst_mode.par_d, + "interlace-mode", G_TYPE_STRING, + gst_mode.interlaced ? "interleaved" : "progressive", + "framerate", GST_TYPE_FRACTION, gst_mode.fps_n, gst_mode.fps_d, NULL); + + if (gst_mode.interlaced) { + if (gst_mode.tff) { + gst_structure_set (s, + "field-order", G_TYPE_STRING, "top-field-first", NULL); + } else { + gst_structure_set (s, + "field-order", G_TYPE_STRING, "bottom-field-first", NULL); + } + } + + if (formats.size () == 1) { + gst_structure_set (s, "format", G_TYPE_STRING, formats[0].c_str (), NULL); + } else { + GValue format_values = G_VALUE_INIT; + + g_value_init (&format_values, GST_TYPE_LIST); + + /* *INDENT-OFF* */ + for (const auto & iter: formats) { + GValue f = G_VALUE_INIT; + + g_value_init (&f, G_TYPE_STRING); + g_value_set_string (&f, iter.c_str ()); + gst_value_list_append_and_take_value (&format_values, &f); + } + /* *INDENT-ON* */ + + gst_structure_set_value (s, "format", &format_values); + g_value_unset (&format_values); + } + + /* Add custom wide mode */ + switch (bdm_mode) { + case bmdModeNTSC: + case bmdModeNTSC2398: + case bmdModeNTSCp: + gst_mode_wide = gst_mode; + gst_mode_wide.par_n = 40; + gst_mode_wide.par_d = 33; + s_wide = gst_structure_copy (s); + gst_structure_set (s_wide, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 40, 33, NULL); + break; + case bmdModePAL: + case bmdModePALp: + gst_mode_wide = gst_mode; + gst_mode_wide.par_n = 16; + gst_mode_wide.par_d = 11; + s_wide = gst_structure_copy (s); + gst_structure_set (s_wide, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 16, 11, NULL); + break; + default: + break; + } + + gst_caps_append_structure (caps, s); + g_array_append_val (format_table, gst_mode); + + if (s_wide) { + gst_caps_append_structure (caps, s_wide); + g_array_append_val (format_table, gst_mode_wide); + } + + next: + mode->Release (); + } while (gst_decklink2_result (hr)); + + return caps; +} + +GstCaps * +gst_decklink2_get_default_template_caps (void) +{ + static GstCaps *template_caps = NULL; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + template_caps = gst_caps_new_empty (); + + for (guint i = 1; i < G_N_ELEMENTS (all_modes); i++) { + GstCaps *other; + + other = gst_decklink2_mode_get_all_format_caps (&all_modes[i]); + template_caps = gst_caps_merge (template_caps, other); + } + + GST_MINI_OBJECT_FLAG_SET (template_caps, + GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); + } + GST_DECKLINK2_CALL_ONCE_END; + + return gst_caps_ref (template_caps); +} + +GstCaps * +gst_decklink2_get_caps_from_mode (const GstDeckLink2DisplayMode * mode) +{ + GstCaps *caps = gst_caps_new_simple ("video/x-raw", + "width", G_TYPE_INT, mode->width, + "height", G_TYPE_INT, mode->height, + "pixel-aspect-ratio", GST_TYPE_FRACTION, mode->par_n, mode->par_d, + "interlace-mode", G_TYPE_STRING, + mode->interlaced ? "interleaved" : "progressive", + "framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d, + NULL); + + if (mode->interlaced) { + if (mode->tff) { + gst_caps_set_simple (caps, + "field-order", G_TYPE_STRING, "top-field-first", NULL); + } else { + gst_caps_set_simple (caps, + "field-order", G_TYPE_STRING, "bottom-field-first", NULL); + } + } + + return caps; +} + +GType +gst_decklink2_audio_meta_api_get_type (void) +{ + static GType type = G_TYPE_INVALID; + static const gchar *tags[] = { NULL }; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + type = gst_meta_api_type_register ("GstDeckLink2AudioMetaAPI", tags); + } GST_DECKLINK2_CALL_ONCE_END; + + return type; +} + +static gboolean +gst_decklink2_audio_meta_transform (GstBuffer * dest, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstDeckLink2AudioMeta *dmeta, *smeta; + + if (GST_META_TRANSFORM_IS_COPY (type)) { + smeta = (GstDeckLink2AudioMeta *) meta; + + dmeta = gst_buffer_add_decklink2_audio_meta (dest, smeta->sample); + if (!dmeta) + return FALSE; + } else { + /* return FALSE, if transform type is not supported */ + return FALSE; + } + return TRUE; +} + +static gboolean +gst_decklink2_audio_meta_init (GstMeta * meta, gpointer params, + GstBuffer * buffer) +{ + GstDeckLink2AudioMeta *dmeta = (GstDeckLink2AudioMeta *) meta; + + dmeta->sample = NULL; + + return TRUE; +} + +static void +gst_decklink2_audio_meta_free (GstMeta * meta, GstBuffer * buffer) +{ + GstDeckLink2AudioMeta *dmeta = (GstDeckLink2AudioMeta *) meta; + + if (dmeta->sample) + gst_sample_unref (dmeta->sample); +} + +const GstMetaInfo * +gst_decklink2_audio_meta_get_info (void) +{ + static GstMetaInfo *meta_info = NULL; + + GST_DECKLINK2_CALL_ONCE_BEGIN { + const GstMetaInfo *m = gst_meta_register (GST_DECKLINK2_AUDIO_META_API_TYPE, + "GstDeckLink2AudioMeta", + sizeof (GstDeckLink2AudioMeta), + gst_decklink2_audio_meta_init, + gst_decklink2_audio_meta_free, + gst_decklink2_audio_meta_transform); + meta_info = (GstMetaInfo *) m; + } + GST_DECKLINK2_CALL_ONCE_END; + + return meta_info; +} + +GstDeckLink2AudioMeta * +gst_buffer_add_decklink2_audio_meta (GstBuffer * buffer, + GstSample * audio_sample) +{ + GstDeckLink2AudioMeta *meta; + + g_return_val_if_fail (buffer != NULL, NULL); + g_return_val_if_fail (audio_sample != NULL, NULL); + + meta = (GstDeckLink2AudioMeta *) gst_buffer_add_meta (buffer, + GST_DECKLINK2_AUDIO_META_INFO, NULL); + + meta->sample = gst_sample_ref (audio_sample); + + return meta; +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h new file mode 100644 index 0000000000..5b4784ef93 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h @@ -0,0 +1,334 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#pragma once + +#include +#include +#include + +#ifdef G_OS_WIN32 +#include +#ifndef INITGUID +#include +#endif /* INITGUID */ +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* G_OS_WIN32 */ + +#include + +#if defined(G_OS_WIN32) +#define dlbool_t BOOL +#define dlstring_t BSTR +#elif defined(__APPLE__) +#define dlbool_t bool +#define dlstring_t CFStringRef +#else +#define dlbool_t bool +#define dlstring_t const char* +#endif + +G_BEGIN_DECLS + +typedef struct _GstDeckLink2AudioMeta GstDeckLink2AudioMeta; +typedef struct _GstDeckLink2DisplayMode GstDeckLink2DisplayMode; + +typedef enum +{ + GST_DECKLINK2_API_LEVEL_UNKNOWN, + GST_DECKLINK2_API_LEVEL_10_11, + GST_DECKLINK2_API_LEVEL_11_4, + GST_DECKLINK2_API_LEVEL_11_5_1, + GST_DECKLINK2_API_LEVEL_LATEST, +} GstDeckLink2APILevel; + +/* defines custom display mode for wide screen */ +#define bmdModeNTSC_W ((BMDDisplayMode) 0x4E545343) /* 'NTSC' */ +#define bmdModeNTSC2398_W ((BMDDisplayMode) 0x4E543233) /* 'NT23' */ +#define bmdModePAL_W ((BMDDisplayMode) 0x50414C20) /* 'PAL ' */ +#define bmdModeNTSCp_W ((BMDDisplayMode) 0x4E545350) /* 'NTSP' */ +#define bmdModePALp_W ((BMDDisplayMode) 0x50414C50) /* 'PALP' */ + +#define GST_TYPE_DECKLINK2_MODE (gst_decklink2_mode_get_type ()) +GType gst_decklink2_mode_get_type (void); + +#define GST_TYPE_DECKLINK2_VIDEO_FORMAT (gst_decklink2_video_format_get_type ()) +GType gst_decklink2_video_format_get_type (void); + +#define bmdProfileDefault ((BMDProfileID) 0) +#define GST_TYPE_DECKLINK2_PROFILE_ID (gst_decklink2_profile_id_get_type ()) +GType gst_decklink2_profile_id_get_type (void); + +typedef enum +{ + GST_DECKLINK2_KEYER_MODE_OFF, + GST_DECKLINK2_KEYER_MODE_INTERNAL, + GST_DECKLINK2_KEYER_MODE_EXTERNAL +} GstDeckLink2KeyerMode; +#define GST_TYPE_DECKLINK2_KEYER_MODE (gst_decklink2_keyer_mode_get_type ()) +GType gst_decklink2_keyer_mode_get_type (void); + +typedef enum +{ + GST_DECKLINK2_MAPPING_FORMAT_DEFAULT, + GST_DECKLINK2_MAPPING_FORMAT_LEVEL_A, /* bmdDeckLinkConfigSMPTELevelAOutput = true */ + GST_DECKLINK2_MAPPING_FORMAT_LEVEL_B, /* bmdDeckLinkConfigSMPTELevelAOutput = false */ +} GstDeckLink2MappingFormat; +#define GST_TYPE_DECKLINK2_MAPPING_FORMAT (gst_decklink2_mapping_format_get_type ()) +GType gst_decklink2_mapping_format_get_type (void); + +#define GST_TYPE_DECKLINK2_TIMECODE_FORMAT (gst_decklink2_timecode_format_get_type ()) +GType gst_decklink2_timecode_format_get_type (void); + +#define GST_TYPE_DECKLINK2_VIDEO_CONNECTION (gst_decklink2_video_connection_get_type ()) +GType gst_decklink2_video_connection_get_type (void); + +#define bmdAudioConnectionUnspecified ((BMDAudioConnection) 0) +#define GST_TYPE_DECKLINK2_AUDIO_CONNECTION (gst_decklink2_audio_connection_get_type ()) +GType gst_decklink2_audio_connection_get_type (void); + +typedef enum +{ + GST_DECKLINK2_AUDIO_CHANNELS_DISABLED = -1, + GST_DECKLINK2_AUDIO_CHANNELS_MAX = 0, + GST_DECKLINK2_AUDIO_CHANNELS_2 = 2, + GST_DECKLINK2_AUDIO_CHANNELS_8 = 8, + GST_DECKLINK2_AUDIO_CHANNELS_16 = 16, +} GstDeckLink2AudioChannels; +#define GST_TYPE_DECKLINK2_AUDIO_CHANNELS (gst_decklink2_audio_channels_get_type ()) +GType gst_decklink2_audio_channels_get_type (void); + +struct _GstDeckLink2DisplayMode +{ + BMDDisplayMode mode; + gint width; + gint height; + gint fps_n; + gint fps_d; + gboolean interlaced; + gint par_n; + gint par_d; + gboolean tff; +}; + +gboolean gst_decklink2_init_once (void); + +void gst_decklink2_deinit (void); + +gboolean gst_decklink2_get_api_version (guint * major, + guint * minor, + guint * sub, + guint * extra); + +GstDeckLink2APILevel gst_decklink2_get_api_level (void); + +const gchar * gst_decklink2_api_level_to_string (GstDeckLink2APILevel level); + +GstCaps * gst_decklink2_get_default_template_caps (void); + +BMDDisplayMode gst_decklink2_get_real_display_mode (BMDDisplayMode mode); + +typedef gboolean (*GstDeckLink2DoesSupportVideoMode) (GstObject * object, + BMDDisplayMode mode, + BMDPixelFormat format); + +GstCaps * gst_decklink2_build_caps (GstObject * io_object, + IDeckLinkDisplayModeIterator * iter, + BMDDisplayMode requested_mode, + BMDPixelFormat format, + GstDeckLink2DoesSupportVideoMode func); + +GstCaps * gst_decklink2_build_template_caps (GstObject * io_object, + IDeckLinkDisplayModeIterator * iter, + GstDeckLink2DoesSupportVideoMode func, + GArray * format_table); + +GstCaps * gst_decklink2_get_caps_from_mode (const GstDeckLink2DisplayMode * mode); + + +GstVideoFormat gst_decklink2_video_format_from_pixel_format (BMDPixelFormat format); + +BMDPixelFormat gst_decklink2_pixel_format_from_video_format (GstVideoFormat format); + + +struct _GstDeckLink2AudioMeta +{ + GstMeta meta; + + GstSample *sample; +}; + +GType gst_decklink2_audio_meta_api_get_type (void); +#define GST_DECKLINK2_AUDIO_META_API_TYPE (gst_decklink2_audio_meta_api_get_type()) + +const GstMetaInfo *gst_decklink2_audio_meta_get_info (void); +#define GST_DECKLINK2_AUDIO_META_INFO (gst_decklink2_audio_meta_get_info()) + +#define gst_buffer_get_decklink2_audio_meta(b) \ + ((GstDeckLink2AudioMeta*)gst_buffer_get_meta((b),GST_DECKLINK2_AUDIO_META_API_TYPE)) + +GstDeckLink2AudioMeta * gst_buffer_add_decklink2_audio_meta (GstBuffer * buffer, + GstSample * audio_sample); + +#ifndef GST_DISABLE_GST_DEBUG +static inline gboolean +_gst_decklink2_result (HRESULT hr, GstDebugCategory * cat, const gchar * file, + const gchar * function, gint line) +{ + if (hr == S_OK) + return TRUE; + +#ifdef G_OS_WIN32 + { + gchar *error_text = g_win32_error_message ((guint) hr); + gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line, NULL, + "DeckLink call failed: 0x%x (%s)", (guint) hr, + GST_STR_NULL (error_text)); + g_free (error_text); + } +#else + gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line, NULL, + "DeckLink call failed: 0x%x", (guint) hr); +#endif /* G_OS_WIN32 */ + + return FALSE; +} + +#define gst_decklink2_result(hr) \ + _gst_decklink2_result (hr, GST_CAT_DEFAULT, __FILE__, GST_FUNCTION, __LINE__) +#else /* GST_DISABLE_GST_DEBUG */ +static inline gboolean +gst_decklink2_result (HRESULT hr) +{ + if (hr == S_OK) + return TRUE; + + return FALSE; +} +#endif /* GST_DISABLE_GST_DEBUG */ + +#define GST_DECKLINK2_PRINT_CHAR(c) \ + g_ascii_isprint(c) ? (c) : '.' + +#define GST_DECKLINK2_FOURCC_ARGS(fourcc) \ + GST_DECKLINK2_PRINT_CHAR(((fourcc) >> 24) & 0xff), \ + GST_DECKLINK2_PRINT_CHAR(((fourcc) >> 16) & 0xff), \ + GST_DECKLINK2_PRINT_CHAR(((fourcc) >> 8) & 0xff), \ + GST_DECKLINK2_PRINT_CHAR((fourcc) & 0xff) + +G_END_DECLS + +#ifdef __cplusplus +#include +#include +#include +#include + +#define GST_DECKLINK2_CALL_ONCE_BEGIN \ + static std::once_flag __once_flag; \ + std::call_once (__once_flag, [&]() + +#define GST_DECKLINK2_CALL_ONCE_END ) + +#define GST_DECKLINK2_CLEAR_COM(obj) G_STMT_START { \ + if (obj) { \ + (obj)->Release (); \ + (obj) = NULL; \ + } \ + } G_STMT_END + +#ifndef G_OS_WIN32 +#include +inline bool operator==(REFIID a, REFIID b) +{ + if (memcmp (&a, &b, sizeof (REFIID)) != 0) + return false; + + return true; +} +#endif + +#if defined(G_OS_WIN32) +const std::function DeleteString = SysFreeString; + +const std::function DlToStdString = [](dlstring_t dl_str) -> std::string +{ + int wlen = ::SysStringLen(dl_str); + int mblen = ::WideCharToMultiByte(CP_ACP, 0, (wchar_t*)dl_str, wlen, NULL, 0, NULL, NULL); + + std::string ret_str(mblen, '\0'); + mblen = ::WideCharToMultiByte(CP_ACP, 0, (wchar_t*)dl_str, wlen, &ret_str[0], mblen, NULL, NULL); + + return ret_str; +}; + +const std::function StdToDlString = [](std::string std_str) -> dlstring_t +{ + int wlen = ::MultiByteToWideChar(CP_ACP, 0, std_str.data(), (int)std_str.length(), NULL, 0); + + dlstring_t ret_str = ::SysAllocStringLen(NULL, wlen); + ::MultiByteToWideChar(CP_ACP, 0, std_str.data(), (int)std_str.length(), ret_str, wlen); + + return ret_str; +}; +#elif defined(__APPLE__) +const auto DeleteString = CFRelease; + +const auto DlToStdString = [](dlstring_t dl_str) -> std::string +{ + std::string returnString(""); + char stringBuffer[1024]; + if (CFStringGetCString(dl_str, stringBuffer, 1024, kCFStringEncodingUTF8)) + returnString = stringBuffer; + return returnString; +}; + +const auto StdToDlString = [](std::string std_str) -> dlstring_t +{ + return CFStringCreateWithCString(kCFAllocatorMalloc, std_str.c_str(), kCFStringEncodingUTF8); +}; +#else +#include + +const std::function DeleteString = [](dlstring_t dl_str) +{ + free((void*)dl_str); +}; + +const std::function DlToStdString = [](dlstring_t dl_str) -> std::string +{ + return dl_str; +}; + +const std::function StdToDlString = [](std::string std_str) -> dlstring_t +{ + return strcpy((char*)malloc(std_str.length()+1), std_str.c_str()); +}; +#endif +#endif /* __cplusplus */ diff --git a/subprojects/gst-plugins-bad/sys/decklink2/meson.build b/subprojects/gst-plugins-bad/sys/decklink2/meson.build new file mode 100644 index 0000000000..5cc329fffe --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/meson.build @@ -0,0 +1,96 @@ +decklink2_sources = [ + 'gstdecklink2combiner.cpp', + 'gstdecklink2demux.cpp', + 'gstdecklink2deviceprovider.cpp', + 'gstdecklink2input.cpp', + 'gstdecklink2object.cpp', + 'gstdecklink2output.cpp', + 'gstdecklink2sink.cpp', + 'gstdecklink2src.cpp', + 'gstdecklink2srcbin.cpp', + 'gstdecklink2utils.cpp', + 'plugin.cpp', +] + +decklink2_sdk = [] +decklink2_deps = [] +decklink2_extra_args = ['-DGST_USE_UNSTABLE_API'] +decklink2_ldflags = [] +decklink2_incl = [] +decklink2_option = get_option('decklink2') + +if decklink2_option.disabled() + subdir_done() +endif + +# Build SDK headers using midl compiler on Windows +if host_system == 'windows' + midl = find_program('midl', required: decklink2_option) + if not midl.found() + subdir_done() + endif + + if host_machine.cpu_family() == 'x86' + midl_env = 'win32' + elif host_machine.cpu_family() == 'x86_64' + midl_env = 'win64' + else + # ARM64 support? + if decklink2_option.enabled() + error(host_machine.cpu_family() + ' is not supported') + endif + subdir_done() + endif + + decklink2_sdk = custom_target('DeckLinkAPI.h', + output : ['DeckLinkAPI_i.c', 'DeckLinkAPI.h'], + input : 'win/DeckLinkAPI.idl', + command : [midl, '/h', 'DeckLinkAPI.h', + '/env', midl_env, + '/target', 'NT50', + '/notlb', + '/out', meson.current_build_dir(), + '@INPUT@'] + ) +else + libdl = cc.find_library('dl', required: decklink2_option) + have_pthread_h = cc.has_header('pthread.h', required: decklink2_option) + if not libdl.found() or not have_pthread_h + subdir_done() + endif + + decklink2_extra_args += cc.get_supported_arguments([ + '-Wno-missing-declarations', + ]) + + decklink2_deps += [libdl, dependency('threads')] + if host_system == 'linux' + decklink2_sdk += ['linux/DeckLinkAPIDispatch.cpp', + 'linux/DeckLinkAPIDispatch_v10_11.cpp'] + decklink2_incl = include_directories('linux') + elif host_system in ['darwin', 'ios'] + decklink2_sdk += ['mac/DeckLinkAPIDispatch.cpp', + 'mac/DeckLinkAPIDispatch_v10_11.cpp'] + decklink2_ldflags += ['-Wl,-framework,CoreFoundation'] + decklink2_incl = include_directories('mac') + else + if decklink2_option.enabled() + error('Host system "@0@" is not supported'.format(host_system)) + endif + subdir_done() + endif +endif + +decklink2 = library('gstdecklink2', + decklink2_sources + decklink2_sdk, + c_args : gst_plugins_bad_args + decklink2_extra_args, + cpp_args : gst_plugins_bad_args + decklink2_extra_args, + link_args : decklink2_ldflags + noseh_link_args, + include_directories : [configinc] + decklink2_incl, + dependencies : [gstvideo_dep, gstaudio_dep, gstbase_dep, gst_dep] + decklink2_deps, + override_options : ['cpp_std=c++14'], + install : true, + install_dir : plugins_install_dir, +) + +plugins += [decklink2] \ No newline at end of file diff --git a/subprojects/gst-plugins-bad/sys/decklink2/plugin.cpp b/subprojects/gst-plugins-bad/sys/decklink2/plugin.cpp new file mode 100644 index 0000000000..0503200192 --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/decklink2/plugin.cpp @@ -0,0 +1,74 @@ +/* + * GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * plugin-decklink2: + * + * Since: 1.24 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gstdecklink2combiner.h" +#include "gstdecklink2demux.h" +#include "gstdecklink2deviceprovider.h" +#include "gstdecklink2sink.h" +#include "gstdecklink2src.h" +#include "gstdecklink2srcbin.h" +#include "gstdecklink2utils.h" + +GST_DEBUG_CATEGORY (gst_decklink2_debug); + +static void +plugin_deinit (gpointer data) +{ + gst_decklink2_deinit (); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_decklink2_debug, "decklink2", 0, "decklink2"); + + gst_decklink2_init_once (); + + GST_ELEMENT_REGISTER (decklink2combiner, plugin); + GST_ELEMENT_REGISTER (decklink2demux, plugin); + GST_ELEMENT_REGISTER (decklink2sink, plugin); + GST_ELEMENT_REGISTER (decklink2src, plugin); + GST_ELEMENT_REGISTER (decklink2srcbin, plugin); + + GST_DEVICE_PROVIDER_REGISTER (decklink2deviceprovider, plugin); + + g_object_set_data_full (G_OBJECT (plugin), + "plugin-decklink2-shutdown", (gpointer) "shutdown-data", + (GDestroyNotify) plugin_deinit); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + decklink2, + "Blackmagic Decklink plugin", + plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/subprojects/gst-plugins-bad/sys/meson.build b/subprojects/gst-plugins-bad/sys/meson.build index 57370ace62..65f8d0bc5d 100644 --- a/subprojects/gst-plugins-bad/sys/meson.build +++ b/subprojects/gst-plugins-bad/sys/meson.build @@ -8,6 +8,7 @@ subdir('d3d11') subdir('d3d12') subdir('d3dvideosink') subdir('decklink') +subdir('decklink2') subdir('directsound') subdir('directshow') subdir('dvb') From 44ff95f1dbbf2c9ae0754f2f571c5b98949ebed7 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 2 Jun 2023 00:16:49 +0900 Subject: [PATCH 14/82] aggregator: Add gst_aggregator_ensure_mandatory_events() method ... so that subclasses can push sticky-events dependent events --- .../gstreamer/libs/gst/base/gstaggregator.c | 17 +++++++++++++++++ .../gstreamer/libs/gst/base/gstaggregator.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/subprojects/gstreamer/libs/gst/base/gstaggregator.c b/subprojects/gstreamer/libs/gst/base/gstaggregator.c index 01f1e79503..bd4f071b5d 100644 --- a/subprojects/gstreamer/libs/gst/base/gstaggregator.c +++ b/subprojects/gstreamer/libs/gst/base/gstaggregator.c @@ -4314,3 +4314,20 @@ gst_aggregator_set_force_live (GstAggregator * self, gboolean force_live) { self->priv->force_live = force_live; } + +/** + * gst_aggregator_ensure_mandatory_events: + * @self: The #GstAggregator + * + * This method will push mandatory events such as stream-start, caps, + * and segment if needed. + * + * Since: 1.24 + */ +void +gst_aggregator_ensure_mandatory_events (GstAggregator * self) +{ + g_return_if_fail (GST_IS_AGGREGATOR (self)); + + gst_aggregator_push_mandatory_events (self, FALSE); +} diff --git a/subprojects/gstreamer/libs/gst/base/gstaggregator.h b/subprojects/gstreamer/libs/gst/base/gstaggregator.h index 4d330e6f44..4203d5c5d0 100644 --- a/subprojects/gstreamer/libs/gst/base/gstaggregator.h +++ b/subprojects/gstreamer/libs/gst/base/gstaggregator.h @@ -524,6 +524,9 @@ GST_BASE_API void gst_aggregator_set_force_live (GstAggregator *self, gboolean force_live); +GST_BASE_API +void gst_aggregator_ensure_mandatory_events (GstAggregator * self); + /** * GstAggregatorStartTimeSelection: * @GST_AGGREGATOR_START_TIME_SELECTION_ZERO: Start at running time 0. From ae58acff6c468f9405b9380ca2b648c7f39ea243 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 2 Jun 2023 00:19:06 +0900 Subject: [PATCH 15/82] streamselector: Add new input stream selector element Adding GstAggregator based input-selector-like elements. streamselector element behaves similar to input-selector element, but active pad selection is done via "active" property of streamselector's sink pads. And input streams will be synchronized by using active pad's segment (same as "sync-mode=active-segment" of input-selector). In addition to streamselector element, streamselectorbin is added which consists of clocksync and streamselector elements. The streamselectorbin supports "sync-mode" property identical to that of input-selector. --- subprojects/gst-plugins-bad/gst/meson.build | 1 + .../gst/streamselector/gststreamselector.c | 807 ++++++++++++++++++ .../gst/streamselector/gststreamselector.h | 37 + .../gst/streamselector/gststreamselectorbin.c | 519 +++++++++++ .../gst/streamselector/gststreamselectorbin.h | 36 + .../gst/streamselector/meson.build | 15 + .../gst/streamselector/plugin.c | 46 + subprojects/gst-plugins-bad/meson.options | 1 + .../tests/examples/meson.build | 1 + .../tests/examples/streamselector/meson.build | 6 + .../examples/streamselector/streamselector.c | 125 +++ 11 files changed, 1594 insertions(+) create mode 100644 subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c create mode 100644 subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.h create mode 100644 subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c create mode 100644 subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.h create mode 100644 subprojects/gst-plugins-bad/gst/streamselector/meson.build create mode 100644 subprojects/gst-plugins-bad/gst/streamselector/plugin.c create mode 100644 subprojects/gst-plugins-bad/tests/examples/streamselector/meson.build create mode 100644 subprojects/gst-plugins-bad/tests/examples/streamselector/streamselector.c diff --git a/subprojects/gst-plugins-bad/gst/meson.build b/subprojects/gst-plugins-bad/gst/meson.build index 92a2529b8e..24bd198cc7 100644 --- a/subprojects/gst-plugins-bad/gst/meson.build +++ b/subprojects/gst-plugins-bad/gst/meson.build @@ -12,6 +12,7 @@ foreach plugin : ['accurip', 'adpcmdec', 'adpcmenc', 'aiff', 'asfmux', 'rawparse', 'removesilence', 'rist', 'rtmp2', 'rtp', 'sdp', 'segmentclip', 'siren', 'smooth', 'speed', 'subenc', 'switchbin', 'tensordecoders', 'timecode', 'transcode', 'unixfd', 'videofilters', + 'streamselector', 'videoframe_audiolevel', 'videoparsers', 'videosignal', 'vmnc'] subdir(plugin) diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c new file mode 100644 index 0000000000..1298ce48b0 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c @@ -0,0 +1,807 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-streamselector + * @title: streamselector + * + * Direct one out of N input streams to the output pad. + * + * Since: 1.24 + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gststreamselector.h" + +GST_DEBUG_CATEGORY_STATIC (stream_selector_debug); +#define GST_CAT_DEFAULT stream_selector_debug + +enum +{ + PROP_PAD_0, + PROP_PAD_ACTIVE, +}; + +struct _GstStreamSelectorPad +{ + GstAggregatorPad parent; + + GstCaps *caps; + GstEvent *tag_event; + gboolean active; + gboolean discont; +}; + +static void gst_stream_selector_pad_dispose (GObject * object); +static void gst_stream_selector_pad_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_stream_selector_pad_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static GstFlowReturn gst_stream_selector_pad_flush (GstAggregatorPad * pad, + GstAggregator * agg); +static void gst_stream_selector_set_active_pad (GstStreamSelector * self, + GstStreamSelectorPad * pad, gboolean active); + +#define gst_stream_selector_pad_parent_class pad_parent_class +G_DEFINE_TYPE (GstStreamSelectorPad, gst_stream_selector_pad, + GST_TYPE_AGGREGATOR_PAD); + +static void +gst_stream_selector_pad_class_init (GstStreamSelectorPadClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstAggregatorPadClass *aggpad_class = GST_AGGREGATOR_PAD_CLASS (klass); + + object_class->dispose = gst_stream_selector_pad_dispose; + object_class->set_property = gst_stream_selector_pad_set_property; + object_class->get_property = gst_stream_selector_pad_get_property; + + g_object_class_install_property (object_class, + PROP_PAD_ACTIVE, g_param_spec_boolean ("active", + "Active", "Active state of the pad", FALSE, + GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + aggpad_class->flush = GST_DEBUG_FUNCPTR (gst_stream_selector_pad_flush); +} + +static void +gst_stream_selector_pad_init (GstStreamSelectorPad * self) +{ +} + +static void +gst_stream_selector_pad_dispose (GObject * object) +{ + GstStreamSelectorPad *self = GST_STREAM_SELECTOR_PAD (object); + + gst_clear_caps (&self->caps); + + G_OBJECT_CLASS (pad_parent_class)->dispose (object); +} + +static void +gst_stream_selector_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstStreamSelectorPad *pad = GST_STREAM_SELECTOR_PAD (object); + GstStreamSelector *self = (GstStreamSelector *) + gst_object_get_parent (GST_OBJECT_CAST (object)); + + if (!self) { + GST_WARNING_OBJECT (pad, "No parent"); + return; + } + + switch (prop_id) { + case PROP_PAD_ACTIVE: + gst_stream_selector_set_active_pad (self, + pad, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + gst_object_unref (self); +} + +static void +gst_stream_selector_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstStreamSelectorPad *pad = GST_STREAM_SELECTOR_PAD (object); + + switch (prop_id) { + case PROP_PAD_ACTIVE: + g_value_set_boolean (value, pad->active); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +gst_stream_selector_pad_flush (GstAggregatorPad * pad, GstAggregator * agg) +{ + GstStreamSelectorPad *self = GST_STREAM_SELECTOR_PAD (pad); + + gst_clear_event (&self->tag_event); + + return GST_FLOW_OK; +} + +static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_0, + PROP_IGNORE_INACTIVE_PADS, +}; + +struct _GstStreamSelector +{ + GstAggregator parent; + + /* Current active pad, updated on aggregate() */ + GstStreamSelectorPad *active_pad; +}; + +static void gst_stream_selector_child_proxy_init (gpointer g_iface, + gpointer iface_data); +static void gst_stream_selector_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_stream_selector_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static GstPad *gst_stream_selector_request_new_pad (GstElement * elem, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); +static void gst_stream_selector_release_pad (GstElement * elem, GstPad * pad); +static gboolean gst_stream_selector_start (GstAggregator * agg); +static gboolean gst_stream_selector_stop (GstAggregator * agg); +static gboolean gst_stream_selector_sink_query (GstAggregator * agg, + GstAggregatorPad * pad, GstQuery * query); +static gboolean gst_stream_selector_sink_event (GstAggregator * agg, + GstAggregatorPad * pad, GstEvent * event); +static gboolean gst_stream_selector_src_query (GstAggregator * agg, + GstQuery * query); +static GstFlowReturn gst_stream_selector_aggregate (GstAggregator * agg, + gboolean timeout); + +#define gst_stream_selector_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstStreamSelector, gst_stream_selector, + GST_TYPE_AGGREGATOR, G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY, + gst_stream_selector_child_proxy_init)); +GST_ELEMENT_REGISTER_DEFINE (streamselector, "streamselector", + GST_RANK_NONE, GST_TYPE_STREAM_SELECTOR); + +static void +gst_stream_selector_class_init (GstStreamSelectorClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstAggregatorClass *agg_class = GST_AGGREGATOR_CLASS (klass); + + object_class->set_property = gst_stream_selector_set_property; + object_class->get_property = gst_stream_selector_get_property; + + g_object_class_install_property (object_class, + PROP_IGNORE_INACTIVE_PADS, g_param_spec_boolean ("ignore-inactive-pads", + "Ignore inactive pads", + "Avoid timing out waiting for inactive pads", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + element_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_stream_selector_request_new_pad); + element_class->release_pad = + GST_DEBUG_FUNCPTR (gst_stream_selector_release_pad); + + gst_element_class_add_static_pad_template_with_gtype (element_class, + &sink_templ, GST_TYPE_STREAM_SELECTOR_PAD); + gst_element_class_add_static_pad_template_with_gtype (element_class, + &src_templ, GST_TYPE_AGGREGATOR_PAD); + + gst_element_class_set_static_metadata (element_class, "Stream Selector", + "Generic", "N-to-1 input stream selector", + "Seungha Yang "); + + agg_class->start = GST_DEBUG_FUNCPTR (gst_stream_selector_start); + agg_class->stop = GST_DEBUG_FUNCPTR (gst_stream_selector_stop); + agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_stream_selector_sink_query); + agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_stream_selector_sink_event); + agg_class->src_query = GST_DEBUG_FUNCPTR (gst_stream_selector_src_query); + agg_class->aggregate = GST_DEBUG_FUNCPTR (gst_stream_selector_aggregate); + agg_class->get_next_time = + GST_DEBUG_FUNCPTR (gst_aggregator_simple_get_next_time); + agg_class->negotiate = NULL; + + gst_type_mark_as_plugin_api (GST_TYPE_STREAM_SELECTOR_PAD, 0); + + GST_DEBUG_CATEGORY_INIT (stream_selector_debug, "streamselector", 0, + "streamselector"); +} + +static void +gst_stream_selector_init (GstStreamSelector * self) +{ +} + +static void +gst_stream_selector_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + case PROP_IGNORE_INACTIVE_PADS: + gst_aggregator_set_ignore_inactive_pads (GST_AGGREGATOR (object), + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_stream_selector_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + case PROP_IGNORE_INACTIVE_PADS: + g_value_set_boolean (value, + gst_aggregator_get_ignore_inactive_pads (GST_AGGREGATOR (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GObject * +gst_stream_selector_child_proxy_get_child_by_index (GstChildProxy * proxy, + guint index) +{ + GstElement *elem = GST_ELEMENT_CAST (proxy); + GObject *obj = NULL; + + GST_OBJECT_LOCK (elem); + obj = (GObject *) g_list_nth_data (elem->sinkpads, index); + if (obj) + gst_object_ref (obj); + GST_OBJECT_UNLOCK (elem); + + return obj; +} + +static guint +gst_stream_selector_child_proxy_get_children_count (GstChildProxy * proxy) +{ + GstElement *elem = GST_ELEMENT_CAST (proxy); + guint count = 0; + + GST_OBJECT_LOCK (elem); + count = elem->numsinkpads; + GST_OBJECT_UNLOCK (elem); + + return count; +} + +static void +gst_stream_selector_child_proxy_init (gpointer g_iface, gpointer iface_data) +{ + GstChildProxyInterface *iface = (GstChildProxyInterface *) g_iface; + + iface->get_child_by_index = + gst_stream_selector_child_proxy_get_child_by_index; + iface->get_children_count = + gst_stream_selector_child_proxy_get_children_count; +} + +static void +gst_stream_selector_reset (GstAggregator * agg) +{ + GstElement *elem = GST_ELEMENT_CAST (agg); + GstStreamSelector *self = GST_STREAM_SELECTOR (agg); + GList *iter; + + /* Clear all except for active state */ + GST_OBJECT_LOCK (self); + for (iter = elem->sinkpads; iter; iter = g_list_next (iter)) { + GstStreamSelectorPad *pad = GST_STREAM_SELECTOR_PAD (iter->data); + gst_clear_caps (&pad->caps); + gst_clear_event (&pad->tag_event); + pad->discont = FALSE; + } + GST_OBJECT_UNLOCK (self); + + gst_clear_object (&self->active_pad); +} + +static gboolean +gst_stream_selector_start (GstAggregator * agg) +{ + gst_stream_selector_reset (agg); + + return TRUE; +} + +static gboolean +gst_stream_selector_stop (GstAggregator * agg) +{ + gst_stream_selector_reset (agg); + + return TRUE; +} + +static void +gst_stream_selector_update_active_pad_unlocked (GstStreamSelector * self) +{ + GstElement *elem = GST_ELEMENT_CAST (self); + GstPad *first = NULL; + GstPad *active = NULL; + GstStreamSelectorPad *spad; + GList *iter; + + for (iter = elem->sinkpads; iter; iter = g_list_next (iter)) { + GstPad *pad = GST_PAD_CAST (iter->data); + spad = GST_STREAM_SELECTOR_PAD (pad); + + if (!first) + first = pad; + + if (!active && spad->active) + active = pad; + } + + if (!active && first) { + spad = GST_STREAM_SELECTOR_PAD (first); + spad->active = TRUE; + } +} + +static void +gst_stream_selector_update_active_pad (GstStreamSelector * self) +{ + GST_OBJECT_LOCK (self); + gst_stream_selector_update_active_pad_unlocked (self); + GST_OBJECT_UNLOCK (self); +} + +static void +gst_stream_selector_set_active_pad (GstStreamSelector * self, + GstStreamSelectorPad * pad, gboolean active) +{ + GstElement *elem = GST_ELEMENT_CAST (self); + GList *iter; + + GST_OBJECT_LOCK (self); + if (!active) { + pad->active = FALSE; + gst_stream_selector_update_active_pad_unlocked (self); + } else { + for (iter = elem->sinkpads; iter; iter = g_list_next (iter)) { + GstStreamSelectorPad *other = GST_STREAM_SELECTOR_PAD (iter->data); + other->active = FALSE; + } + + pad->active = TRUE; + } + + GST_OBJECT_UNLOCK (self); +} + +static GstPad * +gst_stream_selector_get_active_pad_unlocked (GstStreamSelector * self) +{ + GstElement *elem = GST_ELEMENT_CAST (self); + GList *iter; + GstPad *pad = NULL; + + for (iter = elem->sinkpads; iter; iter = g_list_next (iter)) { + GstStreamSelectorPad *spad = GST_STREAM_SELECTOR_PAD (iter->data); + if (spad->active) { + pad = gst_object_ref (spad); + break; + } + } + + return pad; +} + +static GstPad * +gst_stream_selector_get_active_pad (GstStreamSelector * self) +{ + GstPad *pad; + + GST_OBJECT_LOCK (self); + pad = gst_stream_selector_get_active_pad_unlocked (self); + GST_OBJECT_UNLOCK (self); + + return pad; +} + +static GstPad * +gst_stream_selector_request_new_pad (GstElement * elem, GstPadTemplate * templ, + const gchar * name, const GstCaps * caps) +{ + GstStreamSelector *self = GST_STREAM_SELECTOR (elem); + GstPad *pad; + + pad = GST_ELEMENT_CLASS (parent_class)->request_new_pad (elem, templ, name, + caps); + if (!pad) + return NULL; + + gst_stream_selector_update_active_pad (self); + + gst_child_proxy_child_added (GST_CHILD_PROXY (elem), G_OBJECT (pad), + GST_OBJECT_NAME (pad)); + + return pad; +} + +static void +gst_stream_selector_release_pad (GstElement * elem, GstPad * pad) +{ + GstStreamSelector *self = GST_STREAM_SELECTOR (elem); + + gst_child_proxy_child_removed (GST_CHILD_PROXY (elem), + G_OBJECT (pad), GST_OBJECT_NAME (pad)); + + GST_ELEMENT_CLASS (parent_class)->release_pad (elem, pad); + + gst_stream_selector_update_active_pad (self); +} + +static gboolean +gst_stream_selector_sink_query (GstAggregator * agg, GstAggregatorPad * pad, + GstQuery * query) +{ + GstStreamSelector *self = GST_STREAM_SELECTOR (agg); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_ALLOCATION: + { + GstPad *active = gst_stream_selector_get_active_pad (self); + if (!active) + break; + + if (active == GST_PAD_CAST (pad)) { + gboolean ret = gst_pad_query_default (active, GST_OBJECT_CAST (self), + query); + gst_object_unref (active); + return ret; + } + gst_object_unref (active); + return FALSE; + } + case GST_QUERY_CAPS: + case GST_QUERY_ACCEPT_CAPS: + return gst_pad_peer_query (agg->srcpad, query); + break; + default: + break; + } + + return GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, pad, query); +} + +static gboolean +gst_stream_selector_sink_event (GstAggregator * agg, GstAggregatorPad * pad, + GstEvent * event) +{ + GstStreamSelector *self = GST_STREAM_SELECTOR (agg); + GstStreamSelectorPad *spad = GST_STREAM_SELECTOR_PAD (pad); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START: + { + gst_clear_caps (&spad->caps); + gst_clear_event (&spad->tag_event); + break; + } + case GST_EVENT_CAPS: + { + GstCaps *caps; + GstPad *active; + + gst_event_parse_caps (event, &caps); + gst_caps_replace (&spad->caps, caps); + + active = gst_stream_selector_get_active_pad (self); + if (active) { + if (active == GST_PAD_CAST (pad)) + gst_aggregator_set_src_caps (agg, caps); + gst_object_unref (active); + } + break; + } + case GST_EVENT_SEGMENT: + { + GstPad *active; + const GstSegment *segment; + + gst_event_parse_segment (event, &segment); + + if (segment->format != GST_FORMAT_TIME) { + GST_ERROR_OBJECT (self, "Non-TIME format segment is not supported"); + return FALSE; + } + + active = gst_stream_selector_get_active_pad (self); + if (!active) + break; + + if (active == GST_PAD_CAST (pad)) + gst_aggregator_update_segment (agg, segment); + + gst_object_unref (active); + break; + } + case GST_EVENT_TAG: + { + /* aggregator will drop tag event. Store the tag here and send later + * on aggregate() */ + gst_clear_event (&spad->tag_event); + spad->tag_event = event; + return TRUE; + } + default: + break; + } + + return GST_AGGREGATOR_CLASS (parent_class)->sink_event (agg, pad, event); +} + +static gboolean +gst_stream_selector_src_query (GstAggregator * agg, GstQuery * query) +{ + GstStreamSelector *self = GST_STREAM_SELECTOR (agg); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + GstPad *active = gst_stream_selector_get_active_pad (self); + if (active) { + gboolean ret = gst_pad_peer_query (active, query); + gst_object_unref (active); + return ret; + } + break; + } + default: + break; + } + + return GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query); +} + +static GstClockTime +gst_stream_selector_get_pad_running_time (GstStreamSelector * self, + GstAggregatorPad * pad) +{ + GstClockTime running_time = GST_CLOCK_TIME_NONE; + GstClockTime running_time_end = GST_CLOCK_TIME_NONE; + GstClockTime timestamp; + GstBuffer *buf; + + buf = gst_aggregator_pad_peek_buffer (pad); + if (!buf) + return GST_CLOCK_TIME_NONE; + + timestamp = GST_BUFFER_PTS (buf); + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) + timestamp = GST_BUFFER_DTS (buf); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + running_time = gst_segment_to_running_time (&pad->segment, + GST_FORMAT_TIME, timestamp); + } + + if (GST_CLOCK_TIME_IS_VALID (running_time)) { + if (GST_BUFFER_DURATION_IS_VALID (buf)) + running_time_end = running_time + GST_BUFFER_DURATION (buf); + else + running_time_end = running_time; + } + + gst_buffer_unref (buf); + + return running_time_end; +} + +static GstFlowReturn +gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) +{ + GstElement *elem = GST_ELEMENT_CAST (agg); + GstStreamSelector *self = GST_STREAM_SELECTOR (agg); + GstBuffer *buf = NULL; + GstStreamSelectorPad *active_pad = NULL; + GstAggregatorPad *active_agg_pad; + GstAggregatorPad *srcpad = GST_AGGREGATOR_PAD_CAST (agg->srcpad); + gboolean active_changed = FALSE; + GList *iter; + GstClockTime running_time = GST_CLOCK_TIME_NONE; + GstClockTime running_time_end = GST_CLOCK_TIME_NONE; + GstClockTime output_running_time = GST_CLOCK_TIME_NONE; + GstClockTime timestamp; + gboolean active_eos = FALSE; + gboolean have_non_eos_pad = FALSE; + + GST_OBJECT_LOCK (self); + active_pad = (GstStreamSelectorPad *) + gst_stream_selector_get_active_pad_unlocked (self); + if (!active_pad) { + GST_WARNING_OBJECT (self, "No current active pad"); + goto need_data; + } + + if (active_pad != self->active_pad) { + gst_clear_object (&self->active_pad); + self->active_pad = gst_object_ref (active_pad); + active_changed = TRUE; + } + + active_agg_pad = GST_AGGREGATOR_PAD_CAST (active_pad); + + buf = gst_aggregator_pad_pop_buffer (active_agg_pad); + if (!buf) { + if (gst_aggregator_pad_is_eos (active_agg_pad)) { + GST_DEBUG_OBJECT (self, "Active pad is EOS"); + active_eos = TRUE; + } else { + GST_DEBUG_OBJECT (self, "active pad is not ready"); + goto need_data; + } + } + + if (buf) { + timestamp = GST_BUFFER_PTS (buf); + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) + timestamp = GST_BUFFER_DTS (buf); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + running_time = gst_segment_to_running_time (&active_agg_pad->segment, + GST_FORMAT_TIME, timestamp); + } + + if (GST_CLOCK_TIME_IS_VALID (running_time)) { + if (GST_BUFFER_DURATION_IS_VALID (buf)) + running_time_end = running_time + GST_BUFFER_DURATION (buf); + else + running_time_end = running_time; + } + + GST_LOG_OBJECT (self, "Current running time %" GST_TIME_FORMAT " - %" + GST_TIME_FORMAT, GST_TIME_ARGS (running_time), + GST_TIME_ARGS (running_time_end)); + } + + output_running_time = gst_segment_to_running_time (&srcpad->segment, + GST_FORMAT_TIME, srcpad->segment.position); + + for (iter = elem->sinkpads; iter; iter = g_list_next (iter)) { + GstAggregatorPad *other_pad = GST_AGGREGATOR_PAD_CAST (iter->data); + GstStreamSelectorPad *other_spad = GST_STREAM_SELECTOR_PAD (other_pad); + GstClockTime other_running_time = + gst_stream_selector_get_pad_running_time (self, other_pad); + + /* Drops other pad's buffer if + * - active pad is eos + * - active pad's running time is unknown + * - or other pad's running time is unknown + * - or active pad's running time > other_pad's running time + */ + if (active_eos || !GST_CLOCK_TIME_IS_VALID (running_time_end) || + !GST_CLOCK_TIME_IS_VALID (other_running_time) || + (running_time_end > other_running_time)) { + + GST_LOG_OBJECT (other_pad, "Trying to drop non-active buffer, " + "active-eos %d, active-running-time %" GST_TIME_FORMAT + ", other-running-time %" GST_TIME_FORMAT + ", output-running-time %" GST_TIME_FORMAT, active_eos, + GST_TIME_ARGS (running_time_end), + GST_TIME_ARGS (other_running_time), + GST_TIME_ARGS (output_running_time)); + + if (gst_aggregator_pad_drop_buffer (other_pad)) + other_spad->discont = TRUE; + + if (!gst_aggregator_pad_is_eos (other_pad)) { + if (active_eos) + GST_DEBUG_OBJECT (other_pad, "Other pad is not EOS yet"); + have_non_eos_pad = TRUE; + } + } + } + GST_OBJECT_UNLOCK (self); + + if (active_changed) { + gst_aggregator_set_src_caps (agg, active_pad->caps); + gst_aggregator_update_segment (agg, &active_agg_pad->segment); + } + + if (active_pad->tag_event) { + gst_aggregator_ensure_mandatory_events (agg); + gst_pad_push_event (agg->srcpad, active_pad->tag_event); + active_pad->tag_event = NULL; + } + + if (active_eos) { + gst_object_unref (active_pad); + + if (have_non_eos_pad) { + GST_DEBUG_OBJECT (self, + "Active pad is EOS, waiting for EOS from other pads"); + return GST_AGGREGATOR_FLOW_NEED_DATA; + } + + GST_DEBUG_OBJECT (self, "All pads are EOS"); + + return GST_FLOW_EOS; + } + + srcpad->segment.position = + gst_segment_position_from_running_time (&srcpad->segment, + GST_FORMAT_TIME, running_time_end); + + /* Convert gap buffer to event */ + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP) && + GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DROPPABLE) && + gst_buffer_get_size (buf) == 0) { + GstEvent *gap; + gst_aggregator_ensure_mandatory_events (agg); + + gap = gst_event_new_gap (GST_BUFFER_PTS (buf), GST_BUFFER_DURATION (buf)); + gst_buffer_unref (buf); + + GST_DEBUG_OBJECT (self, "Sending gap event %" GST_PTR_FORMAT, gap); + gst_pad_push_event (agg->srcpad, gap); + gst_object_unref (active_pad); + + return GST_FLOW_OK; + } + + if (active_pad->discont) { + buf = gst_buffer_make_writable (buf); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + active_pad->discont = FALSE; + } + + gst_object_unref (active_pad); + + return gst_aggregator_finish_buffer (agg, buf); + +need_data: + gst_clear_object (&active_pad); + GST_OBJECT_UNLOCK (self); + + return GST_AGGREGATOR_FLOW_NEED_DATA; +} diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.h b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.h new file mode 100644 index 0000000000..e270360897 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.h @@ -0,0 +1,37 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_SELECTOR_PAD (gst_stream_selector_pad_get_type()) +G_DECLARE_FINAL_TYPE (GstStreamSelectorPad, gst_stream_selector_pad, + GST, STREAM_SELECTOR_PAD, GstAggregatorPad) + +#define GST_TYPE_STREAM_SELECTOR (gst_stream_selector_get_type()) +G_DECLARE_FINAL_TYPE (GstStreamSelector, gst_stream_selector, + GST, STREAM_SELECTOR, GstAggregator) + +GST_ELEMENT_REGISTER_DECLARE (streamselector); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c new file mode 100644 index 0000000000..417e35f844 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c @@ -0,0 +1,519 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-streamselectorbin + * @title: streamselectorbin + * + * Direct one out of N input streams to the output pad. + * + * Since: 1.24 + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gststreamselectorbin.h" +#include + +GST_DEBUG_CATEGORY_STATIC (stream_selector_bin_debug); +#define GST_CAT_DEFAULT stream_selector_bin_debug + +static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_PAD_0, + PROP_PAD_ACTIVE, +}; + +struct _GstStreamSelectorBinPad +{ + GstGhostPad parent; + + GstPad *target; +}; + +static void gst_stream_selector_bin_pad_dispose (GObject * object); +static void gst_stream_selector_bin_pad_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_stream_selector_bin_pad_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +#define gst_stream_selector_bin_pad_parent_class pad_parent_class +G_DEFINE_TYPE (GstStreamSelectorBinPad, gst_stream_selector_bin_pad, + GST_TYPE_GHOST_PAD); + +static void +gst_stream_selector_bin_pad_class_init (GstStreamSelectorBinPadClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gst_stream_selector_bin_pad_dispose; + object_class->set_property = gst_stream_selector_bin_pad_set_property; + object_class->get_property = gst_stream_selector_bin_pad_get_property; + + g_object_class_install_property (object_class, + PROP_PAD_ACTIVE, g_param_spec_boolean ("active", + "Active", "Active state of the pad", FALSE, + GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +static void +gst_stream_selector_bin_pad_init (GstStreamSelectorBinPad * self) +{ +} + +static void +gst_stream_selector_bin_pad_dispose (GObject * object) +{ + GstStreamSelectorBinPad *self = GST_STREAM_SELECTOR_BIN_PAD (object); + + gst_clear_object (&self->target); + + G_OBJECT_CLASS (pad_parent_class)->dispose (object); +} + +static void +gst_stream_selector_bin_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstStreamSelectorBinPad *self = GST_STREAM_SELECTOR_BIN_PAD (object); + + if (self->target) + g_object_set_property (G_OBJECT (self->target), pspec->name, value); +} + +static void +gst_stream_selector_bin_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstStreamSelectorBinPad *self = GST_STREAM_SELECTOR_BIN_PAD (object); + + if (self->target) + g_object_get_property (G_OBJECT (self->target), pspec->name, value); +} + +typedef enum +{ + GST_STREAM_SELECTOR_BIN_SYNC_MODE_ACTIVE_SEGMENT, + GST_STREAM_SELECTOR_BIN_SYNC_MODE_CLOCK, +} GstStreamSelectorBinSyncMode; + +#define GST_TYPE_STREAM_SELECTOR_BIN_SYNC_MODE (gst_stream_selector_bin_sync_mode_get_type()) +static GType +gst_stream_selector_bin_sync_mode_get_type (void) +{ + static GType type = 0; + static const GEnumValue sync_modes[] = { + {GST_STREAM_SELECTOR_BIN_SYNC_MODE_ACTIVE_SEGMENT, + "Sync using the current active segment", "active-segment"}, + {GST_STREAM_SELECTOR_BIN_SYNC_MODE_CLOCK, "Sync using the clock", "clock"}, + {0, NULL, NULL}, + }; + + if (g_once_init_enter (&type)) { + GType tmp = + g_enum_register_static ("GstStreamSelectorBinSyncMode", sync_modes); + + g_once_init_leave (&type, tmp); + } + + return type; +} + +typedef struct _GstStreamSelectorBinChain +{ + GstStreamSelectorBin *self; + + GstStreamSelectorBinPad *pad; + GstElement *clocksync; +} GstStreamSelectorBinChain; + +struct _GstStreamSelectorBin +{ + GstBin parent; + + GMutex lock; + + GstElement *selector; + GList *input_chains; + gboolean running; + + GstStreamSelectorBinSyncMode sync_mode; +}; + +enum +{ + PROP_0, + PROP_SYNC_MODE, + /* GstAggregator */ + PROP_LATENCY, + PROP_MIN_UPSTREAM_LATENCY, + PROP_START_TIME_SELECTION, + PROP_START_TIME, + PROP_EMIT_SIGNALS, + /* GstStreamSelector */ + PROP_IGNORE_INACTIVE_PADS, +}; + +#define DEFAULT_SYNC_MODE GST_STREAM_SELECTOR_BIN_SYNC_MODE_ACTIVE_SEGMENT +#define DEFAULT_LATENCY 0 +#define DEFAULT_MIN_UPSTREAM_LATENCY 0 +#define DEFAULT_START_TIME_SELECTION GST_AGGREGATOR_START_TIME_SELECTION_ZERO +#define DEFAULT_START_TIME (-1) +#define DEFAULT_EMIT_SIGNALS FALSE + +static void gst_stream_selector_bin_finalize (GObject * object); +static void gst_stream_selector_bin_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_stream_selector_bin_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static GstStateChangeReturn +gst_stream_selector_bin_change_state (GstElement * elem, + GstStateChange transition); +static GstPad *gst_stream_selector_bin_request_new_pad (GstElement * elem, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); +static void gst_stream_selector_bin_release_pad (GstElement * elem, + GstPad * pad); + +#define gst_stream_selector_bin_parent_class parent_class +G_DEFINE_TYPE (GstStreamSelectorBin, gst_stream_selector_bin, GST_TYPE_BIN); +GST_ELEMENT_REGISTER_DEFINE (streamselectorbin, "streamselectorbin", + GST_RANK_NONE, GST_TYPE_STREAM_SELECTOR_BIN); + +static void +gst_stream_selector_bin_class_init (GstStreamSelectorBinClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + object_class->finalize = gst_stream_selector_bin_finalize; + object_class->set_property = gst_stream_selector_bin_set_property; + object_class->get_property = gst_stream_selector_bin_get_property; + + g_object_class_install_property (object_class, PROP_SYNC_MODE, + g_param_spec_enum ("sync-mode", "Sync mode", + "Behavior in sync-streams mode", + GST_TYPE_STREAM_SELECTOR_BIN_SYNC_MODE, + DEFAULT_SYNC_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* GstAggregator */ + g_object_class_install_property (object_class, PROP_LATENCY, + g_param_spec_uint64 ("latency", "Buffer latency", + "Additional latency in live mode to allow upstream " + "to take longer to produce buffers for the current " + "position (in nanoseconds)", 0, G_MAXUINT64, + DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_MIN_UPSTREAM_LATENCY, + g_param_spec_uint64 ("min-upstream-latency", "Buffer latency", + "When sources with a higher latency are expected to be plugged " + "in dynamically after the aggregator has started playing, " + "this allows overriding the minimum latency reported by the " + "initial source(s). This is only taken into account when larger " + "than the actually reported minimum latency. (nanoseconds)", + 0, G_MAXUINT64, + DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_START_TIME_SELECTION, + g_param_spec_enum ("start-time-selection", "Start Time Selection", + "Decides which start time is output", + gst_aggregator_start_time_selection_get_type (), + DEFAULT_START_TIME_SELECTION, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_START_TIME, + g_param_spec_uint64 ("start-time", "Start Time", + "Start time to use if start-time-selection=set", 0, + G_MAXUINT64, + DEFAULT_START_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_EMIT_SIGNALS, + g_param_spec_boolean ("emit-signals", "Emit signals", + "Send signals", DEFAULT_EMIT_SIGNALS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* GstStreamSelector */ + g_object_class_install_property (object_class, + PROP_IGNORE_INACTIVE_PADS, g_param_spec_boolean ("ignore-inactive-pads", + "Ignore inactive pads", + "Avoid timing out waiting for inactive pads", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_stream_selector_bin_change_state); + element_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_stream_selector_bin_request_new_pad); + element_class->release_pad = + GST_DEBUG_FUNCPTR (gst_stream_selector_bin_release_pad); + + gst_element_class_add_static_pad_template_with_gtype (element_class, + &sink_templ, GST_TYPE_STREAM_SELECTOR_BIN_PAD); + gst_element_class_add_static_pad_template (element_class, &src_templ); + + gst_element_class_set_static_metadata (element_class, "Stream Selector Bin", + "Generic", "N-to-1 input stream selector", + "Seungha Yang "); + + gst_type_mark_as_plugin_api (GST_TYPE_STREAM_SELECTOR_BIN_PAD, 0); + gst_type_mark_as_plugin_api (GST_TYPE_STREAM_SELECTOR_BIN_SYNC_MODE, 0); + + GST_DEBUG_CATEGORY_INIT (stream_selector_bin_debug, "streamselectorbin", 0, + "streamselectorbin"); +} + +static void +gst_stream_selector_bin_init (GstStreamSelectorBin * self) +{ + GstPad *gpad; + GstPad *srcpad; + + self->selector = gst_element_factory_make ("streamselector", + "stream-selector"); + + gst_bin_add (GST_BIN_CAST (self), self->selector); + + srcpad = gst_element_get_static_pad (GST_ELEMENT_CAST (self->selector), + "src"); + gpad = gst_ghost_pad_new ("src", srcpad); + gst_object_unref (srcpad); + + gst_element_add_pad (GST_ELEMENT_CAST (self), gpad); + + self->sync_mode = DEFAULT_SYNC_MODE; + + g_mutex_init (&self->lock); +} + +static void +gst_stream_selector_bin_finalize (GObject * object) +{ + GstStreamSelectorBin *self = GST_STREAM_SELECTOR_BIN (object); + + if (self->input_chains) + g_list_free_full (self->input_chains, (GDestroyNotify) g_free); + + g_mutex_clear (&self->lock); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_stream_selector_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstStreamSelectorBin *self = GST_STREAM_SELECTOR_BIN (object); + + switch (prop_id) { + case PROP_SYNC_MODE: + { + GList *iter; + gboolean sync = FALSE; + g_mutex_lock (&self->lock); + self->sync_mode = g_value_get_enum (value); + if (self->sync_mode == GST_STREAM_SELECTOR_BIN_SYNC_MODE_CLOCK) + sync = TRUE; + + for (iter = self->input_chains; iter; iter = g_list_next (iter)) { + GstStreamSelectorBinChain *chain = iter->data; + if (chain->clocksync) + g_object_set (chain->clocksync, "sync", sync, NULL); + } + g_mutex_unlock (&self->lock); + break; + } + default: + g_object_set_property (G_OBJECT (self->selector), pspec->name, value); + break; + } +} + +static void +gst_stream_selector_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstStreamSelectorBin *self = GST_STREAM_SELECTOR_BIN (object); + + switch (prop_id) { + case PROP_SYNC_MODE: + g_mutex_lock (&self->lock); + g_value_set_enum (value, self->sync_mode); + g_mutex_unlock (&self->lock); + break; + default: + g_object_get_property (G_OBJECT (self->selector), pspec->name, value); + break; + } +} + +static GstStateChangeReturn +gst_stream_selector_bin_change_state (GstElement * elem, + GstStateChange transition) +{ + GstStreamSelectorBin *self = GST_STREAM_SELECTOR_BIN (elem); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + g_mutex_lock (&self->lock); + self->running = TRUE; + g_mutex_unlock (&self->lock); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (elem, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + g_mutex_lock (&self->lock); + self->running = FALSE; + g_mutex_unlock (&self->lock); + default: + break; + } + + return ret; +} + +static GstStreamSelectorBinChain * +gst_stream_selector_bin_chain_new (GstStreamSelectorBin * self, + GstPad * selector_pad) +{ + GstStreamSelectorBinChain *chain; + GstStreamSelectorBinPad *binpad; + GstPad *pad; + + chain = g_new0 (GstStreamSelectorBinChain, 1); + chain->self = self; + chain->clocksync = gst_element_factory_make ("clocksync", NULL); + + gst_bin_add (GST_BIN_CAST (self), chain->clocksync); + + pad = gst_element_get_static_pad (chain->clocksync, "src"); + gst_pad_link (pad, selector_pad); + gst_object_unref (pad); + + chain->pad = g_object_new (GST_TYPE_STREAM_SELECTOR_BIN_PAD, + "name", GST_OBJECT_NAME (selector_pad), "direction", GST_PAD_SINK, NULL); + + binpad = GST_STREAM_SELECTOR_BIN_PAD (chain->pad); + binpad->target = selector_pad; + + pad = gst_element_get_static_pad (chain->clocksync, "sink"); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->pad), pad); + gst_object_unref (pad); + + g_mutex_lock (&self->lock); + if (self->running) + gst_pad_set_active (GST_PAD_CAST (chain->pad), TRUE); + g_mutex_unlock (&self->lock); + + gst_element_add_pad (GST_ELEMENT_CAST (self), GST_PAD_CAST (chain->pad)); + gst_element_sync_state_with_parent (chain->clocksync); + + return chain; +} + +static void +gst_stream_selector_bin_chain_free (GstStreamSelectorBinChain * chain) +{ + GstStreamSelectorBin *self = chain->self; + + gst_element_set_locked_state (chain->clocksync, TRUE); + gst_element_set_state (chain->clocksync, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (chain->self), chain->clocksync); + + gst_element_release_request_pad (self->selector, chain->pad->target); + gst_clear_object (&chain->pad->target); + + g_free (chain); +} + +static GstPad * +gst_stream_selector_bin_request_new_pad (GstElement * elem, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps) +{ + GstStreamSelectorBin *self = GST_STREAM_SELECTOR_BIN (elem); + GstPad *selector_pad; + GstStreamSelectorBinChain *chain; + gboolean sync = FALSE; + GstPadTemplate *selector_templ; + + selector_templ = gst_element_get_pad_template (self->selector, "sink_%u"); + selector_pad = gst_element_request_pad (self->selector, selector_templ, name, caps); + if (!selector_pad) + return NULL; + + chain = gst_stream_selector_bin_chain_new (self, selector_pad); + + g_mutex_lock (&self->lock); + if (self->sync_mode == GST_STREAM_SELECTOR_BIN_SYNC_MODE_CLOCK) + sync = TRUE; + g_object_set (chain->clocksync, "sync", sync, NULL); + self->input_chains = g_list_append (self->input_chains, chain); + g_mutex_unlock (&self->lock); + + GST_DEBUG_OBJECT (chain->pad, "Created new pad"); + + return GST_PAD_CAST (chain->pad); +} + +static void +gst_stream_selector_bin_release_pad (GstElement * elem, GstPad * pad) +{ + GstStreamSelectorBin *self = GST_STREAM_SELECTOR_BIN (elem); + GList *iter; + gboolean found = FALSE; + + g_mutex_lock (&self->lock); + for (iter = self->input_chains; iter; iter = g_list_next (iter)) { + GstStreamSelectorBinChain *chain = iter->data; + + if (pad == GST_PAD_CAST (chain->pad)) { + self->input_chains = g_list_delete_link (self->input_chains, iter); + g_mutex_unlock (&self->lock); + + gst_stream_selector_bin_chain_free (chain); + found = TRUE; + break; + } + } + + if (!found) { + g_mutex_unlock (&self->lock); + GST_WARNING_OBJECT (self, "Unknown pad to release %s:%s", + GST_DEBUG_PAD_NAME (pad)); + } + + gst_element_remove_pad (elem, pad); +} diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.h b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.h new file mode 100644 index 0000000000..457b09bf98 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.h @@ -0,0 +1,36 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_SELECTOR_BIN_PAD (gst_stream_selector_bin_pad_get_type()) +G_DECLARE_FINAL_TYPE (GstStreamSelectorBinPad, gst_stream_selector_bin_pad, + GST, STREAM_SELECTOR_BIN_PAD, GstGhostPad) + +#define GST_TYPE_STREAM_SELECTOR_BIN (gst_stream_selector_bin_get_type()) +G_DECLARE_FINAL_TYPE (GstStreamSelectorBin, gst_stream_selector_bin, + GST, STREAM_SELECTOR_BIN, GstBin) + +GST_ELEMENT_REGISTER_DECLARE (streamselectorbin); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/gst/streamselector/meson.build b/subprojects/gst-plugins-bad/gst/streamselector/meson.build new file mode 100644 index 0000000000..2ef9799188 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst/streamselector/meson.build @@ -0,0 +1,15 @@ +streamselector_sources = [ + 'gststreamselector.c', + 'gststreamselectorbin.c', + 'plugin.c', +] + +gststreamselector = library('gststreamselector', + streamselector_sources, + c_args : gst_plugins_bad_args, + include_directories : [configinc], + dependencies : [gstbase_dep], + install : true, + install_dir : plugins_install_dir, +) +plugins += [gststreamselector] diff --git a/subprojects/gst-plugins-bad/gst/streamselector/plugin.c b/subprojects/gst-plugins-bad/gst/streamselector/plugin.c new file mode 100644 index 0000000000..b3ad77f185 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst/streamselector/plugin.c @@ -0,0 +1,46 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * plugin-streamselector: + * + * Since: 1.24 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gststreamselector.h" +#include "gststreamselectorbin.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_ELEMENT_REGISTER (streamselector, plugin); + GST_ELEMENT_REGISTER (streamselectorbin, plugin); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + streamselector, + "streamselector", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/subprojects/gst-plugins-bad/meson.options b/subprojects/gst-plugins-bad/meson.options index 8e388986ad..8e14ac1e79 100644 --- a/subprojects/gst-plugins-bad/meson.options +++ b/subprojects/gst-plugins-bad/meson.options @@ -64,6 +64,7 @@ option('segmentclip', type : 'feature', value : 'auto') option('siren', type : 'feature', value : 'auto') option('smooth', type : 'feature', value : 'auto') option('speed', type : 'feature', value : 'auto') +option('streamselector', type : 'feature', value : 'auto') option('subenc', type : 'feature', value : 'auto') option('switchbin', type : 'feature', value : 'auto') option('tensordecoders', type : 'feature', value : 'auto') diff --git a/subprojects/gst-plugins-bad/tests/examples/meson.build b/subprojects/gst-plugins-bad/tests/examples/meson.build index 04bdccccb3..22dbc5b3fa 100644 --- a/subprojects/gst-plugins-bad/tests/examples/meson.build +++ b/subprojects/gst-plugins-bad/tests/examples/meson.build @@ -18,6 +18,7 @@ subdir('nvcodec') subdir('opencv', if_found: opencv_dep) subdir('qsv') subdir('qt6d3d11') +subdir('streamselector') subdir('uvch264') subdir('va') subdir('vulkan') diff --git a/subprojects/gst-plugins-bad/tests/examples/streamselector/meson.build b/subprojects/gst-plugins-bad/tests/examples/streamselector/meson.build new file mode 100644 index 0000000000..ff9ef7c93a --- /dev/null +++ b/subprojects/gst-plugins-bad/tests/examples/streamselector/meson.build @@ -0,0 +1,6 @@ +executable('streamselector', + ['streamselector.c'], + include_directories : [configinc], + dependencies: [gst_dep], + c_args : gst_plugins_bad_args, + install: false) diff --git a/subprojects/gst-plugins-bad/tests/examples/streamselector/streamselector.c b/subprojects/gst-plugins-bad/tests/examples/streamselector/streamselector.c new file mode 100644 index 0000000000..ebff8ffaa1 --- /dev/null +++ b/subprojects/gst-plugins-bad/tests/examples/streamselector/streamselector.c @@ -0,0 +1,125 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GMainLoop *loop = NULL; + +typedef struct +{ + GstElement *selector; + guint active_pad_num; +} SwitchData; + +static gboolean +bus_msg (GstBus * bus, GstMessage * message, gpointer data) +{ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR:{ + GError *err; + gchar *debug; + + gst_message_parse_error (message, &err, &debug); + gst_println ("Error: %s", err->message); + g_error_free (err); + g_free (debug); + + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_EOS: + g_main_loop_quit (loop); + break; + default: + break; + } + + return TRUE; +} + +static gboolean +timer_cb (SwitchData * data) +{ + GstPad *to_active; + + if (data->active_pad_num == 0) { + to_active = gst_element_get_static_pad (data->selector, "sink_1"); + data->active_pad_num = 1; + } else { + to_active = gst_element_get_static_pad (data->selector, "sink_0"); + data->active_pad_num = 0; + } + + gst_println ("Switching to pad %d", data->active_pad_num); + + g_object_set (to_active, "active", TRUE, NULL); + + return G_SOURCE_CONTINUE; +} + +int +main (int argc, char *argv[]) +{ + GstElement *pipeline; + GstBus *bus; + SwitchData data; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + pipeline = gst_parse_launch ("streamselector name=selector ! videoconvert ! " + "videoscale ! autovideosink videotestsrc ! " + "video/x-raw,format=RGBA,width=640,height=480,framerate=30/1 ! queue ! " + "selector. videotestsrc pattern=ball ! " + "video/x-raw,format=NV12,width=320,height=240 ! queue ! " + "selector.", NULL); + + if (!pipeline) { + gst_printerrln ("Couldn't create pipeline"); + return 1; + } + + data.selector = gst_bin_get_by_name (GST_BIN (pipeline), "selector"); + data.active_pad_num = 0; + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_watch (bus, bus_msg, NULL); + gst_object_unref (bus); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + g_timeout_add_seconds (3, (GSourceFunc) timer_cb, &data); + + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (data.selector); + gst_object_unref (pipeline); + + g_main_loop_unref (loop); + + gst_deinit (); + + return 0; +} From d741a48a09f61eadce32816b146176950bddf3b6 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 7 Jun 2023 00:18:57 +0900 Subject: [PATCH 16/82] decklink2srcbin: Configure small queue between src and demux --- .../sys/decklink2/gstdecklink2srcbin.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp index 3fc331def5..591b251e17 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp @@ -94,12 +94,18 @@ gst_decklink2_src_bin_init (GstDeckLink2SrcBin * self) { GstPad *pad; GstPad *gpad; + GstElement *queue; self->src = gst_element_factory_make ("decklink2src", NULL); self->demux = gst_element_factory_make ("decklink2demux", NULL); - gst_bin_add_many (GST_BIN (self), self->src, self->demux, NULL); - gst_element_link (self->src, self->demux); + queue = gst_element_factory_make ("queue", NULL); + + g_object_set (queue, "max-size-buffers", 3, "max-size-bytes", 0, + "max-size-time", (guint64) 0, NULL); + + gst_bin_add_many (GST_BIN (self), self->src, queue, self->demux, NULL); + gst_element_link_many (self->src, queue, self->demux, NULL); pad = gst_element_get_static_pad (self->demux, "video"); gpad = gst_ghost_pad_new ("video", pad); From c8a776396a89f4184eb533dc3b1f95fc36fb8229 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 7 Jun 2023 02:44:32 +0900 Subject: [PATCH 17/82] decklink2sink: Fill audio silence when video is duplicated --- .../sys/decklink2/gstdecklink2output.cpp | 193 ++++++++++++++++-- 1 file changed, 180 insertions(+), 13 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index 01c508493d..e042a2e9d7 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -30,17 +30,167 @@ #include #include #include +#include +#include +#include GST_DEBUG_CATEGORY_STATIC (gst_decklink2_output_debug); #define GST_CAT_DEFAULT gst_decklink2_output_debug class IGstDeckLinkVideoOutputCallback; +class GstDecklink2OutputAudioBuffer +{ +public: + void Init (const gchar * debug_name, const GstAudioInfo & info, gint fps_n, + gint fps_d) + { + info_ = info; + buffer_.clear (); + video_frame_dup_drop_count_ = 0; + dup_drop_sample_offset_end_ = 0; + samples_to_drop_ = 0; + fps_n_ = fps_n; + fps_d_ = fps_d; + init_done_ = true; + if (debug_name) + debug_name_ = debug_name; + else + debug_name_ = "GstDecklink2OutputAudioBuffer"; + } + + void Deinit () + { + buffer_.clear (); + init_done_ = false; + } + + void Append (const guint8 * data, size_t size) + { + if (!data || size == 0 || !init_done_) + return; + + size_t cur_size = buffer_.size (); + size_t num_samples = size / info_.bpf; + + GST_LOG_ID (debug_name_.c_str (), "Appending %" G_GSIZE_FORMAT " samples", + num_samples); + + if (samples_to_drop_) { + GST_WARNING_ID (debug_name_.c_str (), "audio samples to drop %" + G_GUINT64_FORMAT ", new sample count %" G_GSIZE_FORMAT, + samples_to_drop_, num_samples); + + if (num_samples >= samples_to_drop_) { + size_t actual_append_samples = num_samples - samples_to_drop_; + size_t bytes_to_drop = samples_to_drop_ * info_.bpf; + samples_to_drop_ = 0; + if (actual_append_samples == 0) + return; + + data += bytes_to_drop; + size -= bytes_to_drop; + } else { + samples_to_drop_ -= num_samples; + return; + } + } + + buffer_.resize (cur_size + size); + memcpy (&buffer_[0] + cur_size, data, size); + } + + void Drop () + { + if (!init_done_) + return; + + video_frame_dup_drop_count_++; + guint64 next_sample_offset = + gst_util_uint64_scale (video_frame_dup_drop_count_, + fps_d_ * info_.rate, fps_n_); + guint64 num_samples = next_sample_offset - dup_drop_sample_offset_end_; + samples_to_drop_ += num_samples; + dup_drop_sample_offset_end_ = next_sample_offset; + + GST_WARNING_ID (debug_name_.c_str (), "Samples to drop %" G_GUINT64_FORMAT + ", total samples to drop %" G_GUINT64_FORMAT, num_samples, + samples_to_drop_); + + size_t bytes_to_drop = samples_to_drop_ * info_.bpf; + size_t cur_size = buffer_.size (); + if (cur_size >= bytes_to_drop) { + buffer_.resize (cur_size - bytes_to_drop); + samples_to_drop_ = 0; + } else { + guint64 samples_in_buffer = cur_size / info_.bpf; + samples_to_drop_ -= samples_in_buffer; + buffer_.clear (); + } + } + + void PrependSilence () + { + if (!init_done_) + return; + + video_frame_dup_drop_count_++; + guint64 next_sample_offset = + gst_util_uint64_scale (video_frame_dup_drop_count_, + fps_d_ * info_.rate, fps_n_); + guint64 num_samples = next_sample_offset - dup_drop_sample_offset_end_; + dup_drop_sample_offset_end_ = next_sample_offset; + + GST_WARNING_ID (debug_name_.c_str (), "Prepending silence %" + G_GUINT64_FORMAT " samples", num_samples); + + size_t silence_length_in_bytes = num_samples * info_.bpf; + size_t cur_size = buffer_.size (); + + buffer_.resize (cur_size + num_samples); + if (cur_size > 0) { + memmove (&buffer_[0] + silence_length_in_bytes, &buffer_[0], + cur_size); + } + + gst_audio_format_info_fill_silence (info_.finfo, &buffer_[0], + silence_length_in_bytes); + } + + guint8 *GetSamples (guint & num_samples) + { + if (!init_done_) { + num_samples = 0; + return NULL; + } + + num_samples = buffer_.size () / info_.bpf; + return &buffer_[0]; + } + + void Flush () + { + buffer_.resize (0); + } + +private: + std::vector < guint8 > buffer_; + guint64 video_frame_dup_drop_count_ = 0; + guint64 dup_drop_sample_offset_end_ = 0; + guint64 samples_to_drop_ = 0; + GstAudioInfo info_; + gint fps_n_; + gint fps_d_; + bool init_done_ = false; + std::string debug_name_; +}; + struct GstDeckLink2OutputPrivate { std::mutex extern_lock; std::mutex schedule_lock; std::condition_variable cond; + GstDecklink2OutputAudioBuffer audio_buf; }; struct _GstDeckLink2Output @@ -754,10 +904,13 @@ gst_decklink2_output_start (GstDeckLink2Output * self, static HRESULT gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, - IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size) + IDeckLinkVideoFrame * frame) { + GstDeckLink2OutputPrivate *priv = self->priv; GstClockTime next_pts, dur; HRESULT hr = E_FAIL; + guint num_samples; + guint8 *audio_buf; frame->AddRef (); GST_DECKLINK2_CLEAR_COM (self->last_frame); @@ -768,8 +921,7 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, self->selected_mode.fps_d * GST_SECOND, self->selected_mode.fps_n); dur = next_pts - self->pts; - GST_LOG_OBJECT (self, "Scheduling video frame %p, audio-buf-size %" - G_GSIZE_FORMAT, frame, audio_buf_size); + GST_LOG_OBJECT (self, "Scheduling video frame %p", frame); switch (self->api_level) { case GST_DECKLINK2_API_LEVEL_10_11: @@ -796,6 +948,8 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, return hr; } + audio_buf = priv->audio_buf.GetSamples (num_samples); + if (!self->prerolled) { if (self->n_prerolled == 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { GST_DEBUG_OBJECT (self, "Begin audio preroll"); @@ -808,11 +962,11 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, } } - if (audio_buf && audio_buf_size > 0) { - guint num_samples = audio_buf_size / self->audio_info.bpf; - + if (audio_buf && num_samples > 0) { hr = gst_decklink2_output_schedule_audio_samples (self, audio_buf, num_samples, 0, 0, NULL); + priv->audio_buf.Flush (); + if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", (guint) hr); @@ -842,11 +996,11 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, self->prerolled = TRUE; } - } else if (audio_buf && audio_buf_size > 0) { - guint num_samples = audio_buf_size / self->audio_info.bpf; - + } else if (audio_buf && num_samples > 0) { hr = gst_decklink2_output_schedule_audio_samples (self, audio_buf, num_samples, 0, 0, NULL); + priv->audio_buf.Flush (); + if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", (guint) hr); @@ -887,14 +1041,22 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, if (count > output->max_buffered) { GST_WARNING_OBJECT (output, "Skipping frame, buffered count %u > %u", count, output->max_buffered); + std::lock_guard < std::mutex > slk (priv->schedule_lock); + + /* audio and video may not be completely aligned. Add this sample + * and drop video frame duration amount of audio samples */ + priv->audio_buf.Append (audio_buf, audio_buf_size); + priv->audio_buf.Drop (); + return S_OK; } } lk.unlock (); std::lock_guard < std::mutex > slk (priv->schedule_lock); - return gst_decklink2_output_schedule_video_internal (output, frame, - audio_buf, audio_buf_size); + priv->audio_buf.Append (audio_buf, audio_buf_size); + + return gst_decklink2_output_schedule_video_internal (output, frame); } static HRESULT @@ -1755,6 +1917,11 @@ gst_decklink2_output_configure (GstDeckLink2Output * output, audio_sample_type == bmdAudioSampleType16bitInteger ? GST_AUDIO_FORMAT_S16LE : GST_AUDIO_FORMAT_S32LE, 48000, audio_channels, NULL); + + priv->audio_buf.Init (GST_OBJECT_NAME (output), output->audio_info, + output->selected_mode.fps_n, output->selected_mode.fps_d); + } else { + priv->audio_buf.Deinit (); } g_clear_pointer (&output->vbi_enc, gst_video_vbi_encoder_free); @@ -1799,8 +1966,8 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self) hr = gst_decklink2_output_get_num_bufferred (self, &count); if (gst_decklink2_result (hr) && count <= self->min_buffered) { GST_WARNING_OBJECT (self, "Underrun, buffered count %u", count); - gst_decklink2_output_schedule_video_internal (self, self->last_frame, - NULL, 0); + priv->audio_buf.PrependSilence (); + gst_decklink2_output_schedule_video_internal (self, self->last_frame); } } } From 0ec1ed0c3454b1bee709d2dd30998c63bb9fdb60 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 6 Jun 2023 02:17:18 +0900 Subject: [PATCH 18/82] streamselector: Always drop old buffers from inactive pad ... even when active pad is not ready. And send necessary stick event when active pad is changed even if the active pad does not hold buffer. --- .../gst/streamselector/gststreamselector.c | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c index 1298ce48b0..491bb9bef6 100644 --- a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c @@ -383,6 +383,8 @@ gst_stream_selector_update_active_pad_unlocked (GstStreamSelector * self) if (!active && first) { spad = GST_STREAM_SELECTOR_PAD (first); spad->active = TRUE; + + GST_DEBUG_OBJECT (spad, "New active pad"); } } @@ -412,6 +414,7 @@ gst_stream_selector_set_active_pad (GstStreamSelector * self, } pad->active = TRUE; + GST_DEBUG_OBJECT (pad, "New active pad"); } GST_OBJECT_UNLOCK (self); @@ -559,8 +562,11 @@ gst_stream_selector_sink_event (GstAggregator * agg, GstAggregatorPad * pad, if (!active) break; - if (active == GST_PAD_CAST (pad)) + if (active == GST_PAD_CAST (pad)) { + GST_DEBUG_OBJECT (active, "Pad is active, schedule update segment %" + GST_SEGMENT_FORMAT, segment); gst_aggregator_update_segment (agg, segment); + } gst_object_unref (active); break; @@ -664,24 +670,25 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) } if (active_pad != self->active_pad) { + GST_DEBUG_OBJECT (active_pad, "Updated new active pad"); gst_clear_object (&self->active_pad); self->active_pad = gst_object_ref (active_pad); active_changed = TRUE; + } else { + GST_LOG_OBJECT (active_pad, "Current active pad"); } active_agg_pad = GST_AGGREGATOR_PAD_CAST (active_pad); buf = gst_aggregator_pad_pop_buffer (active_agg_pad); - if (!buf) { - if (gst_aggregator_pad_is_eos (active_agg_pad)) { - GST_DEBUG_OBJECT (self, "Active pad is EOS"); - active_eos = TRUE; - } else { - GST_DEBUG_OBJECT (self, "active pad is not ready"); - goto need_data; - } + if (!buf && gst_aggregator_pad_is_eos (active_agg_pad)) { + GST_DEBUG_OBJECT (self, "Active pad is EOS"); + active_eos = TRUE; } + output_running_time = gst_segment_to_running_time (&srcpad->segment, + GST_FORMAT_TIME, srcpad->segment.position); + if (buf) { timestamp = GST_BUFFER_PTS (buf); if (!GST_CLOCK_TIME_IS_VALID (timestamp)) @@ -702,11 +709,10 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) GST_LOG_OBJECT (self, "Current running time %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, GST_TIME_ARGS (running_time), GST_TIME_ARGS (running_time_end)); + } else { + running_time_end = output_running_time; } - output_running_time = gst_segment_to_running_time (&srcpad->segment, - GST_FORMAT_TIME, srcpad->segment.position); - for (iter = elem->sinkpads; iter; iter = g_list_next (iter)) { GstAggregatorPad *other_pad = GST_AGGREGATOR_PAD_CAST (iter->data); GstStreamSelectorPad *other_spad = GST_STREAM_SELECTOR_PAD (other_pad); @@ -766,6 +772,10 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) GST_DEBUG_OBJECT (self, "All pads are EOS"); return GST_FLOW_EOS; + } else if (!buf) { + GST_LOG_OBJECT (self, "Active pad is not ready"); + gst_object_unref (active_pad); + return GST_AGGREGATOR_FLOW_NEED_DATA; } srcpad->segment.position = From 1b9c619e38e5207c25f18568048539fede26580a Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 13 Jun 2023 22:52:30 +0900 Subject: [PATCH 19/82] decklink2src: Add "skip-first-time" property ... so that the element can skip first N frames as requested. --- .../sys/decklink2/gstdecklink2input.cpp | 39 +++++++++++++++---- .../sys/decklink2/gstdecklink2input.h | 1 + .../sys/decklink2/gstdecklink2src.cpp | 18 ++++++++- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index d77dba9120..c99c20350b 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -384,6 +384,8 @@ struct _GstDeckLink2Input gboolean discont; gboolean audio_discont; gboolean flushing; + GstClockTime skip_first_time; + GstClockTime start_time; guint window_size; guint window_fill; @@ -1498,12 +1500,30 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, if (!clock) { GST_WARNING_OBJECT (self, "Frame arrived but we dont have configured clock"); - } else { - base_time = gst_element_get_base_time (GST_ELEMENT (self->client)); - capture_time = gst_clock_get_time (clock); - gst_object_unref (clock); - if (capture_time >= base_time) - capture_time -= base_time; + return; + } + + base_time = gst_element_get_base_time (GST_ELEMENT (self->client)); + capture_time = gst_clock_get_time (clock); + gst_object_unref (clock); + if (capture_time >= base_time) + capture_time -= base_time; + + if (!GST_CLOCK_TIME_IS_VALID (self->start_time)) + self->start_time = capture_time; + + if (GST_CLOCK_TIME_IS_VALID (self->skip_first_time)) { + GstClockTime diff = capture_time - self->start_time; + if (diff < self->skip_first_time) { + GST_DEBUG_OBJECT (self, + "Skipping frame as requested: %" GST_TIME_FORMAT " < %" + GST_TIME_FORMAT, GST_TIME_ARGS (capture_time), + GST_TIME_ARGS (self->skip_first_time + self->start_time)); + return; + } + + GST_DEBUG_OBJECT (self, "All frames were skipped as requested"); + self->skip_first_time = GST_CLOCK_TIME_NONE; } if (frame) { @@ -1856,11 +1876,13 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) gst_clear_caps (&self->selected_video_caps); gst_clear_caps (&self->selected_audio_caps); priv->signal = false; + self->skip_first_time = GST_CLOCK_TIME_NONE; + self->start_time = GST_CLOCK_TIME_NONE; } HRESULT gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, - BMDProfileID profile_id, guint buffer_size, + BMDProfileID profile_id, guint buffer_size, GstClockTime skip_first_time, const GstDeckLink2InputVideoConfig * video_config, const GstDeckLink2InputAudioConfig * audio_config) { @@ -1872,6 +1894,9 @@ gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, gst_decklink2_input_stop_unlocked (input); gst_decklink2_input_reset_time_mapping (input); + if (skip_first_time > 0 && GST_CLOCK_TIME_IS_VALID (skip_first_time)) + input->skip_first_time = skip_first_time; + if (profile_id != bmdProfileDefault) { GstDeckLink2Object *object; gchar *profile_id_str = g_enum_to_string (GST_TYPE_DECKLINK2_PROFILE_ID, diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h index 481a9a6a62..47c1b27a5b 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h @@ -61,6 +61,7 @@ HRESULT gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, BMDProfileID profile_id, guint buffer_size, + GstClockTime skip_first_time, const GstDeckLink2InputVideoConfig * video_config, const GstDeckLink2InputAudioConfig * audio_config); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index e3a0a8b565..b1d2ed1211 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -48,6 +48,7 @@ enum PROP_OUTPUT_AFD_BAR, PROP_BUFFER_SIZE, PROP_SIGNAL, + PROP_SKIP_FIRST_TIME, }; #define DEFAULT_MODE bmdModeUnknown @@ -62,6 +63,7 @@ enum #define DEFAULT_OUTPUT_AFD_BAR FALSE #define DEFAULT_BUFFER_SIZE 5 #define DEFAULT_AUDIO_CHANNELS GST_DECKLINK2_AUDIO_CHANNELS_2 +#define DEFAULT_SKIP_FIRST_TIME 0 struct GstDeckLink2SrcPrivate { @@ -96,6 +98,7 @@ struct _GstDeckLink2Src gboolean output_cc; gboolean output_afd_bar; guint buffer_size; + GstClockTime skip_first_time; }; static void gst_decklink2_src_finalize (GObject * object); @@ -251,6 +254,9 @@ gst_decklink2_src_set_property (GObject * object, guint prop_id, case PROP_BUFFER_SIZE: self->buffer_size = g_value_get_uint (value); break; + case PROP_SKIP_FIRST_TIME: + self->skip_first_time = g_value_get_uint64 (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -311,6 +317,9 @@ gst_decklink2_src_get_property (GObject * object, guint prop_id, GValue * value, g_value_set_boolean (value, has_signal); break; } + case PROP_SKIP_FIRST_TIME: + g_value_set_uint64 (value, self->skip_first_time); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -529,7 +538,8 @@ gst_decklink2_src_run (GstDeckLink2Src * self) audio_config.channels = self->audio_channels; hr = gst_decklink2_input_start (self->input, GST_ELEMENT (self), - self->profile_id, self->buffer_size, &video_config, &audio_config); + self->profile_id, self->buffer_size, self->skip_first_time, + &video_config, &audio_config); if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (self, "Couldn't start stream, hr: 0x%x", (guint) hr); return FALSE; @@ -671,4 +681,10 @@ gst_decklink2_src_install_properties (GObjectClass * object_class) g_param_spec_boolean ("signal", "Signal", "True if there is a valid input signal available", FALSE, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (object_class, PROP_SKIP_FIRST_TIME, + g_param_spec_uint64 ("skip-first-time", "Skip First Time", + "Skip that much time of initial frames after starting", 0, + G_MAXUINT64, DEFAULT_SKIP_FIRST_TIME, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); } From 217da0fbfe21ec1578dc0e1e9478bb0b5ea93c8e Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 13 Jun 2023 23:52:55 +0900 Subject: [PATCH 20/82] decklink2src: Add "restart" signal action Support restart streaming via signal action --- .../sys/decklink2/gstdecklink2input.cpp | 11 +++++- .../sys/decklink2/gstdecklink2input.h | 2 + .../sys/decklink2/gstdecklink2src.cpp | 39 ++++++++++++++++++- .../sys/decklink2/gstdecklink2src.h | 2 + .../sys/decklink2/gstdecklink2srcbin.cpp | 21 ++++++++++ 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index c99c20350b..113c59ae13 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -384,6 +384,7 @@ struct _GstDeckLink2Input gboolean discont; gboolean audio_discont; gboolean flushing; + gboolean started; GstClockTime skip_first_time; GstClockTime start_time; @@ -1878,6 +1879,7 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) priv->signal = false; self->skip_first_time = GST_CLOCK_TIME_NONE; self->start_time = GST_CLOCK_TIME_NONE; + self->started = FALSE; } HRESULT @@ -1894,6 +1896,8 @@ gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, gst_decklink2_input_stop_unlocked (input); gst_decklink2_input_reset_time_mapping (input); + input->started = TRUE; + if (skip_first_time > 0 && GST_CLOCK_TIME_IS_VALID (skip_first_time)) input->skip_first_time = skip_first_time; @@ -2065,6 +2069,8 @@ gst_decklink2_input_stop (GstDeckLink2Input * input) gst_decklink2_input_stop_unlocked (input); input->client = NULL; + + priv->cond.notify_all (); } void @@ -2083,12 +2089,15 @@ gst_decklink2_input_get_sample (GstDeckLink2Input * input, GstSample ** sample) GstDeckLink2InputPrivate *priv = input->priv; std::unique_lock < std::mutex > lk (priv->lock); - while (priv->queue.empty () && !input->flushing) + while (priv->queue.empty () && !input->flushing && input->started) priv->cond.wait (lk); if (input->flushing) return GST_FLOW_FLUSHING; + if (!input->started) + return GST_DECKLINK2_INPUT_FLOW_STOPPED; + *sample = priv->queue.front (); priv->queue.pop (); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h index 47c1b27a5b..e8ac36fc95 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h @@ -29,6 +29,8 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (GstDeckLink2Input, gst_decklink2_input, GST, DECKLINK2_INPUT, GstObject); +#define GST_DECKLINK2_INPUT_FLOW_STOPPED GST_FLOW_CUSTOM_ERROR + typedef struct _GstDeckLink2InputVideoConfig { BMDVideoConnection connection; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index b1d2ed1211..a3479163fc 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -65,6 +65,16 @@ enum #define DEFAULT_AUDIO_CHANNELS GST_DECKLINK2_AUDIO_CHANNELS_2 #define DEFAULT_SKIP_FIRST_TIME 0 +enum +{ + /* actions */ + SIGNAL_RESTART, + + SIGNAL_LAST, +}; + +static guint gst_decklink2_src_signals[SIGNAL_LAST] = { 0, }; + struct GstDeckLink2SrcPrivate { std::mutex lock; @@ -137,6 +147,11 @@ gst_decklink2_src_class_init (GstDeckLink2SrcClass * klass) gst_decklink2_src_install_properties (object_class); + gst_decklink2_src_signals[SIGNAL_RESTART] = + g_signal_new_class_handler ("restart", G_TYPE_FROM_CLASS (klass), + (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_CALLBACK (gst_decklink2_src_restart), NULL, NULL, NULL, G_TYPE_NONE, 0); + templ_caps = gst_decklink2_get_default_template_caps (); gst_element_class_add_pad_template (element_class, gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps)); @@ -559,6 +574,7 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) GstDeckLink2SrcPrivate *priv = self->priv; gboolean is_gap_buf = FALSE; +again: if (!gst_decklink2_src_run (self)) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to start stream")); @@ -566,8 +582,14 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) } ret = gst_decklink2_input_get_sample (self->input, &sample); - if (ret != GST_FLOW_OK) + if (ret != GST_FLOW_OK) { + if (ret == GST_DECKLINK2_INPUT_FLOW_STOPPED) { + GST_DEBUG_OBJECT (self, "Input was stopped for restarting"); + goto again; + } + return ret; + } std::unique_lock < std::mutex > lk (priv->lock); caps = gst_sample_get_caps (sample); @@ -688,3 +710,18 @@ gst_decklink2_src_install_properties (GObjectClass * object_class) G_MAXUINT64, DEFAULT_SKIP_FIRST_TIME, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); } + +void +gst_decklink2_src_restart (GstDeckLink2Src * self) +{ + g_return_if_fail (GST_IS_DECKLINK2_SRC (self)); + + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + if (self->input && self->running) { + GST_INFO_OBJECT (self, "Stopping input for restart"); + self->running = FALSE; + gst_decklink2_input_stop (self->input); + } +} diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h index 2b4b5803ab..8816945db3 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.h @@ -33,4 +33,6 @@ GST_ELEMENT_REGISTER_DECLARE (decklink2src); void gst_decklink2_src_install_properties (GObjectClass * object_class); +void gst_decklink2_src_restart (GstDeckLink2Src * self); + G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp index 591b251e17..8150ecb7ca 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2srcbin.cpp @@ -36,6 +36,15 @@ static GstStaticPadTemplate audio_template = GST_STATIC_PAD_TEMPLATE ("audio", "rate = (int) 48000, channels = (int) { 2, 8, 16 }, " "layout = (string) interleaved")); +enum +{ + /* actions */ + SIGNAL_RESTART, + + SIGNAL_LAST, +}; + +static guint gst_decklink2_src_bin_signals[SIGNAL_LAST] = { 0, }; struct _GstDeckLink2SrcBin { @@ -56,6 +65,7 @@ static void on_pad_added (GstElement * demux, GstPad * pad, static void on_pad_removed (GstElement * demux, GstPad * pad, GstDeckLink2SrcBin * self); static void on_no_more_pads (GstElement * demux, GstDeckLink2SrcBin * self); +static void on_restart (GstDeckLink2SrcBin * self); #define gst_decklink2_src_bin_parent_class parent_class G_DEFINE_TYPE (GstDeckLink2SrcBin, gst_decklink2_src_bin, GST_TYPE_BIN); @@ -74,6 +84,11 @@ gst_decklink2_src_bin_class_init (GstDeckLink2SrcBinClass * klass) gst_decklink2_src_install_properties (object_class); + gst_decklink2_src_bin_signals[SIGNAL_RESTART] = + g_signal_new_class_handler ("restart", G_TYPE_FROM_CLASS (klass), + (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_CALLBACK (on_restart), NULL, NULL, NULL, G_TYPE_NONE, 0); + templ_caps = gst_decklink2_get_default_template_caps (); gst_element_class_add_pad_template (element_class, gst_pad_template_new ("video", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps)); @@ -210,3 +225,9 @@ on_no_more_pads (GstElement * demux, GstDeckLink2SrcBin * self) { gst_element_no_more_pads (GST_ELEMENT (self)); } + +static void +on_restart (GstDeckLink2SrcBin * self) +{ + gst_decklink2_src_restart (GST_DECKLINK2_SRC (self->src)); +} From b8342c4ce359f47b78288101dbc703e7929671b8 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 20 Jun 2023 21:58:53 +0900 Subject: [PATCH 21/82] decklink2sink: Add auto-restart property Support automatic restart when frame dropping happens --- .../sys/decklink2/gstdecklink2output.cpp | 44 ++++++++++++--- .../sys/decklink2/gstdecklink2output.h | 5 +- .../sys/decklink2/gstdecklink2sink.cpp | 53 ++++++++++++++++--- 3 files changed, 85 insertions(+), 17 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index e042a2e9d7..d580ffe5a6 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -149,8 +149,7 @@ class GstDecklink2OutputAudioBuffer buffer_.resize (cur_size + num_samples); if (cur_size > 0) { - memmove (&buffer_[0] + silence_length_in_bytes, &buffer_[0], - cur_size); + memmove (&buffer_[0] + silence_length_in_bytes, &buffer_[0], cur_size); } gst_audio_format_info_fill_silence (info_.finfo, &buffer_[0], @@ -234,12 +233,16 @@ struct _GstDeckLink2Output gboolean configured; gboolean prerolled; + guint64 late_count; + guint64 drop_count; + guint64 underrun_count; }; static void gst_decklink2_output_dispose (GObject * object); static void gst_decklink2_output_finalize (GObject * object); static void gst_decklink2_output_on_stopped (GstDeckLink2Output * self); -static void gst_decklink2_output_on_completed (GstDeckLink2Output * self); +static void gst_decklink2_output_on_completed (GstDeckLink2Output * self, + BMDOutputFrameCompletionResult result); #define gst_decklink2_output_parent_class parent_class G_DEFINE_TYPE (GstDeckLink2Output, gst_decklink2_output, GST_TYPE_OBJECT); @@ -308,8 +311,9 @@ class IGstDeckLinkVideoOutputCallback:public IDeckLinkVideoOutputCallback } if (result == bmdOutputFrameCompleted || - result == bmdOutputFrameDisplayedLate) { - gst_decklink2_output_on_completed (output_); + result == bmdOutputFrameDisplayedLate || + result == bmdOutputFrameDropped) { + gst_decklink2_output_on_completed (output_, result); } return S_OK; @@ -1013,7 +1017,8 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, HRESULT gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, - IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size) + IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size, + guint64 * drop_count, guint64 * late_count, guint64 * underrun_count) { GstDeckLink2OutputPrivate *priv = output->priv; HRESULT hr; @@ -1022,6 +1027,10 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, g_assert (output->configured); + *drop_count = 0; + *late_count = 0; + *underrun_count = 0; + hr = gst_decklink2_output_is_running (output, &active); if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (output, "Couldn't query active state, hr: 0x%x", @@ -1056,7 +1065,12 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, std::lock_guard < std::mutex > slk (priv->schedule_lock); priv->audio_buf.Append (audio_buf, audio_buf_size); - return gst_decklink2_output_schedule_video_internal (output, frame); + hr = gst_decklink2_output_schedule_video_internal (output, frame); + *drop_count = output->drop_count; + *late_count = output->late_count; + *underrun_count = output->underrun_count; + + return hr; } static HRESULT @@ -1094,6 +1108,10 @@ gst_decklink2_output_stop_internal (GstDeckLink2Output * self) gst_decklink2_output_disable_video (self); gst_decklink2_output_set_video_callback (self, NULL); self->configured = FALSE; + self->prerolled = FALSE; + self->late_count = 0; + self->drop_count = 0; + self->underrun_count = 0; return hr; } @@ -1934,6 +1952,9 @@ gst_decklink2_output_configure (GstDeckLink2Output * output, output->cdp_hdr_sequence_cntr = 0; output->configured = TRUE; output->pts = 0; + output->drop_count = 0; + output->late_count = 0; + output->underrun_count = 0; return S_OK; @@ -1951,13 +1972,19 @@ gst_decklink2_output_on_stopped (GstDeckLink2Output * self) } static void -gst_decklink2_output_on_completed (GstDeckLink2Output * self) +gst_decklink2_output_on_completed (GstDeckLink2Output * self, + BMDOutputFrameCompletionResult result) { GstDeckLink2OutputPrivate *priv = self->priv; dlbool_t active; guint32 count = 0; std::lock_guard < std::mutex > lk (priv->schedule_lock); + if (result == bmdOutputFrameDisplayedLate) + self->late_count++; + else if (result == bmdOutputFrameDropped) + self->drop_count++; + if (!self->last_frame) return; @@ -1966,6 +1993,7 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self) hr = gst_decklink2_output_get_num_bufferred (self, &count); if (gst_decklink2_result (hr) && count <= self->min_buffered) { GST_WARNING_OBJECT (self, "Underrun, buffered count %u", count); + self->underrun_count++; priv->audio_buf.PrependSilence (); gst_decklink2_output_schedule_video_internal (self, self->last_frame); } diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h index 551fe5de68..8c81b9d67a 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h @@ -65,7 +65,10 @@ IDeckLinkVideoFrame * gst_decklink2_output_upload (GstDeckLink2Output * HRESULT gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, IDeckLinkVideoFrame * frame, guint8 *audio_buf, - gsize audio_buf_size); + gsize audio_buf_size, + guint64 * drop_count, + guint64 * late_count, + guint64 * underrun_count); HRESULT gst_decklink2_output_stop (GstDeckLink2Output * output); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp index 9d966108f1..ea59cf6475 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -49,6 +49,7 @@ enum PROP_N_PREROLL_FRAMES, PROP_MIN_BUFFERED_FRAMES, PROP_MAX_BUFFERED_FRAMES, + PROP_AUTO_RESTART }; #define DEFAULT_MODE bmdModeUnknown @@ -65,6 +66,7 @@ enum #define DEFAULT_N_PREROLL_FRAMES 7 #define DEFAULT_MIN_BUFFERED_FRAMES 3 #define DEFAULT_MAX_BUFFERED_FRAMES 14 +#define DEFAULT_AUTO_RESTART FALSE struct GstDeckLink2SinkPrivate { @@ -88,6 +90,7 @@ struct _GstDeckLink2Sink GstBufferPool *fallback_pool; IDeckLinkVideoFrame *prepared_frame; + BMDVideoOutputFlags output_flags; /* properties */ BMDDisplayMode display_mode; @@ -104,6 +107,7 @@ struct _GstDeckLink2Sink guint n_preroll_frames; guint min_buffered_frames; guint max_buffered_frames; + gboolean auto_restart; }; static void gst_decklink2_sink_set_property (GObject * object, @@ -225,6 +229,12 @@ gst_decklink2_sink_class_init (GstDeckLink2SinkClass * klass) "Max number of frames to buffer before dropping", 0, 16, DEFAULT_MAX_BUFFERED_FRAMES, param_flags)); + g_object_class_install_property (object_class, PROP_AUTO_RESTART, + g_param_spec_boolean ("auto-restart", "Auto Restart", + "Restart streaming when frame is dropped, late or underrun happens", + DEFAULT_AUTO_RESTART, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + GstCaps *templ_caps = gst_decklink2_get_default_template_caps (); templ_caps = gst_caps_make_writable (templ_caps); @@ -296,6 +306,7 @@ gst_decklink2_sink_init (GstDeckLink2Sink * self) self->n_preroll_frames = DEFAULT_N_PREROLL_FRAMES; self->min_buffered_frames = DEFAULT_MIN_BUFFERED_FRAMES; self->max_buffered_frames = DEFAULT_MAX_BUFFERED_FRAMES; + self->auto_restart = DEFAULT_AUTO_RESTART; self->priv = new GstDeckLink2SinkPrivate (); } @@ -362,6 +373,9 @@ gst_decklink2_sink_set_property (GObject * object, guint prop_id, case PROP_MAX_BUFFERED_FRAMES: self->max_buffered_frames = g_value_get_int (value); break; + case PROP_AUTO_RESTART: + self->auto_restart = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -419,6 +433,9 @@ gst_decklink2_sink_get_property (GObject * object, guint prop_id, case PROP_MAX_BUFFERED_FRAMES: g_value_set_int (value, self->max_buffered_frames); break; + case PROP_AUTO_RESTART: + g_value_set_boolean (value, self->auto_restart); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -592,16 +609,17 @@ gst_decklink2_sink_set_caps (GstBaseSink * sink, GstCaps * caps) * Note that this flag will have no effect in practice if the video stream * does not contain timecode metadata. */ - BMDVideoOutputFlags output_flags; if (self->timecode_format == bmdTimecodeVITC || self->timecode_format == bmdTimecodeVITCField2) { - output_flags = bmdVideoOutputVITC; + self->output_flags = bmdVideoOutputVITC; } else { - output_flags = bmdVideoOutputRP188; + self->output_flags = bmdVideoOutputRP188; } - if (self->caption_line > 0 || self->afd_bar_line > 0) - output_flags = (BMDVideoOutputFlags) (output_flags | bmdVideoOutputVANC); + if (self->caption_line > 0 || self->afd_bar_line > 0) { + self->output_flags = (BMDVideoOutputFlags) + (self->output_flags | bmdVideoOutputVANC); + } GST_DEBUG_OBJECT (self, "Configuring output, mode %" GST_FOURCC_FORMAT ", audio-sample-type %d, audio-channles %d", @@ -610,8 +628,8 @@ gst_decklink2_sink_set_caps (GstBaseSink * sink, GstCaps * caps) hr = gst_decklink2_output_configure (self->output, self->n_preroll_frames, self->min_buffered_frames, self->max_buffered_frames, - &self->selected_mode, output_flags, self->profile_id, self->keyer_mode, - (guint8) self->keyer_level, self->mapping_format, + &self->selected_mode, self->output_flags, self->profile_id, + self->keyer_mode, (guint8) self->keyer_level, self->mapping_format, self->audio_sample_type, self->audio_channels); if (hr != S_OK) { GST_ERROR_OBJECT (self, "Couldn't configure output"); @@ -858,6 +876,7 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) GstMapInfo info; guint8 *audio_data = NULL; gsize audio_data_size = 0; + guint64 drop_count, late_count, underrun_count; if (!self->prepared_frame) { GST_ERROR_OBJECT (self, "No prepared frame"); @@ -886,7 +905,8 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) G_GSIZE_FORMAT, self->prepared_frame, audio_data_size); hr = gst_decklink2_output_schedule_stream (self->output, - self->prepared_frame, audio_data, audio_data_size); + self->prepared_frame, audio_data, audio_data_size, &drop_count, + &late_count, &underrun_count); if (audio_buf) gst_buffer_unmap (audio_buf, &info); @@ -897,5 +917,22 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) return GST_FLOW_ERROR; } + if (self->auto_restart && (drop_count || late_count || underrun_count)) { + GST_WARNING_OBJECT (self, "Restart output, drop count: %" G_GUINT64_FORMAT + ", late cout: %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT, + drop_count, late_count, underrun_count); + + hr = gst_decklink2_output_configure (self->output, self->n_preroll_frames, + self->min_buffered_frames, self->max_buffered_frames, + &self->selected_mode, self->output_flags, self->profile_id, + self->keyer_mode, (guint8) self->keyer_level, self->mapping_format, + self->audio_sample_type, self->audio_channels); + + if (hr != S_OK) { + GST_ERROR_OBJECT (self, "Couldn't configure output"); + return GST_FLOW_OK; + } + } + return GST_FLOW_OK; } From ea4484f9e59a8e84bc76b9f7f7ddf48a13f12f23 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 20 Jun 2023 22:41:42 +0900 Subject: [PATCH 22/82] decklink2sink: Add restart signal action --- .../sys/decklink2/gstdecklink2sink.cpp | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp index ea59cf6475..c25820ce05 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -68,6 +68,16 @@ enum #define DEFAULT_MAX_BUFFERED_FRAMES 14 #define DEFAULT_AUTO_RESTART FALSE +enum +{ + /* actions */ + SIGNAL_RESTART, + + SIGNAL_LAST, +}; + +static guint gst_decklink2_sink_signals[SIGNAL_LAST] = { 0, }; + struct GstDeckLink2SinkPrivate { std::mutex lock; @@ -91,6 +101,7 @@ struct _GstDeckLink2Sink GstBufferPool *fallback_pool; IDeckLinkVideoFrame *prepared_frame; BMDVideoOutputFlags output_flags; + gboolean schedule_restart; /* properties */ BMDDisplayMode display_mode; @@ -129,6 +140,7 @@ static GstFlowReturn gst_decklink2_sink_prepare (GstBaseSink * sink, GstBuffer * buffer); static GstFlowReturn gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer); +static void gst_decklink2_sink_restart (GstDeckLink2Sink * self); #define gst_decklink2_sink_parent_class parent_class G_DEFINE_TYPE (GstDeckLink2Sink, gst_decklink2_sink, GST_TYPE_BASE_SINK); @@ -235,6 +247,12 @@ gst_decklink2_sink_class_init (GstDeckLink2SinkClass * klass) DEFAULT_AUTO_RESTART, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + gst_decklink2_sink_signals[SIGNAL_RESTART] = + g_signal_new_class_handler ("restart", G_TYPE_FROM_CLASS (klass), + (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_CALLBACK (gst_decklink2_sink_restart), + NULL, NULL, NULL, G_TYPE_NONE, 0); + GstCaps *templ_caps = gst_decklink2_get_default_template_caps (); templ_caps = gst_caps_make_writable (templ_caps); @@ -657,6 +675,10 @@ gst_decklink2_sink_set_caps (GstBaseSink * sink, GstCaps * caps) } self->configured = TRUE; + { + std::lock_guard lk (self->priv->lock); + self->schedule_restart = FALSE; + } return TRUE; @@ -770,6 +792,8 @@ gst_decklink2_sink_stop (GstBaseSink * sink) gst_clear_object (&self->fallback_pool); } + self->schedule_restart = FALSE; + return TRUE; } @@ -871,6 +895,7 @@ static GstFlowReturn gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) { GstDeckLink2Sink *self = GST_DECKLINK2_SINK (sink); + GstDeckLink2SinkPrivate *priv = self->priv; HRESULT hr; GstBuffer *audio_buf = NULL; GstMapInfo info; @@ -901,6 +926,26 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) } } + { + std::lock_guard < std::mutex > lk (priv->lock); + + if (self->schedule_restart) { + GST_DEBUG_OBJECT (self, "Restarting sink as scheduled"); + self->schedule_restart = FALSE; + + hr = gst_decklink2_output_configure (self->output, self->n_preroll_frames, + self->min_buffered_frames, self->max_buffered_frames, + &self->selected_mode, self->output_flags, self->profile_id, + self->keyer_mode, (guint8) self->keyer_level, self->mapping_format, + self->audio_sample_type, self->audio_channels); + + if (hr != S_OK) { + GST_ERROR_OBJECT (self, "Couldn't configure output"); + return GST_FLOW_OK; + } + } + } + GST_LOG_OBJECT (self, "schedule frame %p with audio buffer size %" G_GSIZE_FORMAT, self->prepared_frame, audio_data_size); @@ -936,3 +981,13 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) return GST_FLOW_OK; } + +static void +gst_decklink2_sink_restart (GstDeckLink2Sink * self) +{ + GstDeckLink2SinkPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + GST_DEBUG_OBJECT (self, "Schedule restart"); + self->schedule_restart = TRUE; +} \ No newline at end of file From ba0312f62678d361f8b8511fedcc4e7e8deb44f5 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 15 Jun 2023 19:39:57 +0900 Subject: [PATCH 23/82] decklink2: Update for CFStringRef to std::string converision --- .../sys/decklink2/gstdecklink2utils.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h index 5b4784ef93..abd176d7db 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.h @@ -302,11 +302,13 @@ const auto DeleteString = CFRelease; const auto DlToStdString = [](dlstring_t dl_str) -> std::string { - std::string returnString(""); - char stringBuffer[1024]; - if (CFStringGetCString(dl_str, stringBuffer, 1024, kCFStringEncodingUTF8)) - returnString = stringBuffer; - return returnString; + CFIndex len; + CFStringGetBytes(dl_str, CFRangeMake(0, CFStringGetLength(dl_str)), + kCFStringEncodingUTF8, 0, FALSE, NULL, 0, &len); + std::string ret_str (len, '\0'); + CFStringGetCString (dl_str, &ret_str[0], len, kCFStringEncodingUTF8); + + return ret_str; }; const auto StdToDlString = [](std::string std_str) -> dlstring_t From 11b3af8798823263a304bfb76ffe2e568d4d94b6 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 15 Jun 2023 20:13:15 +0900 Subject: [PATCH 24/82] decklink2src: Use GstQueueArray instead of std::queue Avoid heap allocation in capture thread --- .../sys/decklink2/gstdecklink2input.cpp | 65 ++++++++++++------- .../sys/decklink2/gstdecklink2input.h | 5 +- .../sys/decklink2/gstdecklink2src.cpp | 19 +++--- 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 113c59ae13..787658c8b1 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -29,6 +29,7 @@ #include #include #include +#include GST_DEBUG_CATEGORY_STATIC (gst_decklink2_input_debug); #define GST_CAT_DEFAULT gst_decklink2_input_debug @@ -317,6 +318,12 @@ class IGstDeckLinkInputCallback:public IDeckLinkInputCallback GstDeckLink2Input *input_; }; +struct GstDecklink2InputData +{ + GstBuffer *buffer; + GstCaps *caps; +}; + struct TimeMapping { GstClockTime xbase; @@ -334,7 +341,6 @@ struct GstDeckLink2InputPrivate std::mutex lock; std::condition_variable cond; - std::queue < GstSample * >queue; std::atomic < bool >signal; }; @@ -373,6 +379,8 @@ struct _GstDeckLink2Input guint64 audio_offset; GstAdapter *audio_buf; + GstQueueArray *queue; + GstDeckLink2DisplayMode selected_mode; BMDPixelFormat pixel_format; GstElement *client; @@ -414,6 +422,13 @@ static void gst_decklink2_input_finalize (GObject * object); static HRESULT gst_decklink2_input_set_allocator (GstDeckLink2Input * input, IDeckLinkMemoryAllocator * allocator); +static void +gst_decklink2_input_data_clear (GstDecklink2InputData * data) +{ + gst_clear_buffer (&data->buffer); + gst_clear_caps (&data->caps); +} + #define gst_decklink2_input_parent_class parent_class G_DEFINE_TYPE (GstDeckLink2Input, gst_decklink2_input, GST_TYPE_OBJECT); @@ -436,6 +451,10 @@ gst_decklink2_input_init (GstDeckLink2Input * self) FALSE, sizeof (GstDeckLink2DisplayMode)); self->audio_buf = gst_adapter_new (); self->allocator = new IGstDeckLinkMemoryAllocator (); + self->queue = gst_queue_array_new_for_struct (sizeof (GstDecklink2InputData), + 6); + gst_queue_array_set_clear_func (self->queue, + (GDestroyNotify) gst_decklink2_input_data_clear); self->priv = new GstDeckLink2InputPrivate (); } @@ -449,6 +468,7 @@ gst_decklink2_input_dispose (GObject * object) gst_clear_caps (&self->selected_audio_caps); g_clear_pointer (&self->vbi_parser, gst_video_vbi_parser_free); g_clear_object (&self->audio_buf); + g_clear_pointer (&self->queue, gst_queue_array_free); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -1787,15 +1807,10 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, if (buffer) { GstSample *sample; gsize audio_size; - while (priv->queue.size () > self->buffer_size) { - GstBuffer *old_buf; - - sample = priv->queue.front (); - old_buf = gst_sample_get_buffer (sample); - - GST_DEBUG_OBJECT (self, "Dropping old buffer %" GST_PTR_FORMAT, old_buf); - gst_sample_unref (sample); - priv->queue.pop (); + while (gst_queue_array_get_length (self->queue) > self->buffer_size) { + GstDecklink2InputData *data = (GstDecklink2InputData *) + gst_queue_array_pop_head_struct (self->queue); + gst_decklink2_input_data_clear (data); } audio_size = gst_adapter_available (self->audio_buf); @@ -1851,11 +1866,12 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, gst_buffer_unref (audio_buf); } - sample = gst_sample_new (buffer, self->selected_video_caps, NULL, NULL); GST_LOG_OBJECT (self, "Enqueue buffer %" GST_PTR_FORMAT, buffer); - gst_buffer_unref (buffer); - priv->queue.push (sample); + GstDecklink2InputData new_data; + new_data.buffer = buffer; + new_data.caps = gst_caps_ref (self->selected_video_caps); + gst_queue_array_push_tail_struct (self->queue, &new_data); priv->cond.notify_all (); } } @@ -1869,11 +1885,7 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) gst_decklink2_input_disable_video (self); gst_decklink2_input_disable_audio (self); gst_decklink2_input_set_callback (self, NULL); - while (!priv->queue.empty ()) { - GstSample *sample = priv->queue.front (); - gst_sample_unref (sample); - priv->queue.pop (); - } + gst_queue_array_clear (self->queue); gst_clear_caps (&self->selected_video_caps); gst_clear_caps (&self->selected_audio_caps); priv->signal = false; @@ -2084,13 +2096,20 @@ gst_decklink2_input_set_flushing (GstDeckLink2Input * input, gboolean flush) } GstFlowReturn -gst_decklink2_input_get_sample (GstDeckLink2Input * input, GstSample ** sample) +gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buf, + GstCaps ** caps) { GstDeckLink2InputPrivate *priv = input->priv; std::unique_lock < std::mutex > lk (priv->lock); + GstDecklink2InputData *data; + + *buf = nullptr; + *caps = nullptr; - while (priv->queue.empty () && !input->flushing && input->started) + while (gst_queue_array_is_empty (input->queue) + && !input->flushing && input->started) { priv->cond.wait (lk); + } if (input->flushing) return GST_FLOW_FLUSHING; @@ -2098,8 +2117,10 @@ gst_decklink2_input_get_sample (GstDeckLink2Input * input, GstSample ** sample) if (!input->started) return GST_DECKLINK2_INPUT_FLOW_STOPPED; - *sample = priv->queue.front (); - priv->queue.pop (); + data = (GstDecklink2InputData *) + gst_queue_array_pop_head_struct (input->queue); + *buf = data->buffer; + *caps = data->caps; return GST_FLOW_OK; } diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h index e8ac36fc95..a47aed6ca0 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h @@ -72,8 +72,9 @@ void gst_decklink2_input_stop (GstDeckLink2Input * input); void gst_decklink2_input_set_flushing (GstDeckLink2Input * input, gboolean flush); -GstFlowReturn gst_decklink2_input_get_sample (GstDeckLink2Input * input, - GstSample ** sample); +GstFlowReturn gst_decklink2_input_get_data (GstDeckLink2Input * input, + GstBuffer ** buffer, + GstCaps ** caps); gboolean gst_decklink2_input_has_signal (GstDeckLink2Input * input); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index a3479163fc..34867a482b 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -568,8 +568,8 @@ static GstFlowReturn gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) { GstDeckLink2Src *self = GST_DECKLINK2_SRC (src); - GstSample *sample; - GstCaps *caps; + GstBuffer *buf = nullptr; + GstCaps *caps = nullptr; GstFlowReturn ret; GstDeckLink2SrcPrivate *priv = self->priv; gboolean is_gap_buf = FALSE; @@ -581,7 +581,7 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) return GST_FLOW_ERROR; } - ret = gst_decklink2_input_get_sample (self->input, &sample); + ret = gst_decklink2_input_get_data (self->input, &buf, &caps); if (ret != GST_FLOW_OK) { if (ret == GST_DECKLINK2_INPUT_FLOW_STOPPED) { GST_DEBUG_OBJECT (self, "Input was stopped for restarting"); @@ -592,20 +592,22 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) } std::unique_lock < std::mutex > lk (priv->lock); - caps = gst_sample_get_caps (sample); if (caps && !gst_caps_is_equal (caps, self->selected_caps)) { GST_DEBUG_OBJECT (self, "Set updated caps %" GST_PTR_FORMAT, caps); gst_caps_replace (&self->selected_caps, caps); lk.unlock (); if (!gst_pad_set_caps (GST_BASE_SRC_PAD (self), caps)) { GST_ERROR_OBJECT (self, "Couldn't set caps"); - gst_sample_unref (sample); + gst_clear_buffer (&buf); + gst_clear_caps (&caps); + return GST_FLOW_NOT_NEGOTIATED; } } - *buffer = gst_sample_get_buffer (sample); - if (GST_BUFFER_FLAG_IS_SET (*buffer, GST_BUFFER_FLAG_GAP)) + gst_clear_caps (&caps); + + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) is_gap_buf = TRUE; if (is_gap_buf != self->is_gap_buf) { @@ -613,8 +615,7 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) g_object_notify (G_OBJECT (self), "signal"); } - gst_buffer_ref (*buffer); - gst_sample_unref (sample); + *buffer = buf; return GST_FLOW_OK; } From d0f23db45e8a5a34f4d62d1707f552654b1dcbe2 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 21 Jun 2023 18:04:10 +0900 Subject: [PATCH 25/82] decklink2sink: Loop ScheduleAudioSamples() until all data is written SDK 12.4.2 doc says if "sampleFramesWritten" is null, it's blocking operation finished once all data is written to driver. But the behavior is not mentioned in old SDK docs. --- .../sys/decklink2/gstdecklink2output.cpp | 43 +++++++++++++------ .../sys/decklink2/gstdecklink2sink.cpp | 4 +- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index d580ffe5a6..d8fcb5e9e8 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -914,6 +914,7 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, GstClockTime next_pts, dur; HRESULT hr = E_FAIL; guint num_samples; + guint num_written; guint8 *audio_buf; frame->AddRef (); @@ -967,15 +968,22 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, } if (audio_buf && num_samples > 0) { - hr = gst_decklink2_output_schedule_audio_samples (self, - audio_buf, num_samples, 0, 0, NULL); - priv->audio_buf.Flush (); + while (num_samples > 0) { + num_written = 0; + hr = gst_decklink2_output_schedule_audio_samples (self, + audio_buf, num_samples, 0, 0, &num_written); - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", - (guint) hr); - return hr; + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", + (guint) hr); + return hr; + } + + num_samples -= num_written; + audio_buf += num_written * self->audio_info.bpf; } + + priv->audio_buf.Flush (); } self->n_prerolled++; @@ -1001,15 +1009,22 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, self->prerolled = TRUE; } } else if (audio_buf && num_samples > 0) { - hr = gst_decklink2_output_schedule_audio_samples (self, - audio_buf, num_samples, 0, 0, NULL); - priv->audio_buf.Flush (); + while (num_samples > 0) { + num_written = 0; + hr = gst_decklink2_output_schedule_audio_samples (self, + audio_buf, num_samples, 0, 0, &num_written); - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", - (guint) hr); - return hr; + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", + (guint) hr); + return hr; + } + + num_samples -= num_written; + audio_buf += num_written * self->audio_info.bpf; } + + priv->audio_buf.Flush (); } return S_OK; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp index c25820ce05..40795641a0 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -676,7 +676,7 @@ gst_decklink2_sink_set_caps (GstBaseSink * sink, GstCaps * caps) self->configured = TRUE; { - std::lock_guard lk (self->priv->lock); + std::lock_guard < std::mutex > lk (self->priv->lock); self->schedule_restart = FALSE; } @@ -990,4 +990,4 @@ gst_decklink2_sink_restart (GstDeckLink2Sink * self) GST_DEBUG_OBJECT (self, "Schedule restart"); self->schedule_restart = TRUE; -} \ No newline at end of file +} From fe19ac735d7a8cf67c2a53bca2f33bde93802e24 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 21 Jun 2023 23:10:07 +0900 Subject: [PATCH 26/82] decklink2src: Add "desync-threshold" and "no-signal-threshold" properties Once large A/V desync or no-signal frames are detected, src will automatically restart streaming --- .../sys/decklink2/gstdecklink2input.cpp | 37 +++--- .../sys/decklink2/gstdecklink2input.h | 4 +- .../sys/decklink2/gstdecklink2src.cpp | 111 +++++++++++++++--- 3 files changed, 116 insertions(+), 36 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 787658c8b1..13c166e8a4 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -395,6 +395,8 @@ struct _GstDeckLink2Input gboolean started; GstClockTime skip_first_time; GstClockTime start_time; + guint no_signal_count; + GstClockTimeDiff av_sync; guint window_size; guint window_fill; @@ -1126,6 +1128,8 @@ gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, gst_adapter_clear (self->audio_buf); self->audio_offset = INVALID_AUDIO_OFFSET; self->next_audio_offset = INVALID_AUDIO_OFFSET; + self->no_signal_count = 0; + self->av_sync = 0; gst_decklink2_input_reset_time_mapping (self); gst_decklink2_input_start_streams (self); @@ -1600,9 +1604,12 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, flags = frame->GetFlags (); if ((flags & bmdFrameHasNoInputSource) != 0) { GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_GAP); + GST_DEBUG_OBJECT (self, "No signal"); priv->signal = false; + self->no_signal_count++; } else { priv->signal = true; + self->no_signal_count = 0; if (self->output_cc || self->output_afd_bar) { extract_vbi (self, buffer, frame); @@ -1840,27 +1847,9 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, gst_buffer_add_decklink2_audio_meta (buffer, sample); gst_sample_unref (sample); - /* FIXME: make configurable? */ if (frame && packet) { - GstClockTime diff = 0; - /* Video PTS are calibrated but not for audio to make audio pts - * and duration perfect. Then audio/video may be out of sync. - * Determine resync if large gap is detected */ - if (GST_BUFFER_PTS (buffer) >= GST_BUFFER_PTS (audio_buf)) - diff = GST_BUFFER_PTS (buffer) - GST_BUFFER_PTS (audio_buf); - else - diff = GST_BUFFER_PTS (audio_buf) - GST_BUFFER_PTS (buffer); - - if (diff > 250 * GST_MSECOND) { - GST_WARNING_OBJECT (self, "Large gap detected %" GST_TIME_FORMAT - ", video pts %" GST_TIME_FORMAT ", audio pts %" GST_TIME_FORMAT - ", do resync", GST_TIME_ARGS (diff), - GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), - GST_TIME_ARGS (GST_BUFFER_PTS (audio_buf))); - self->audio_offset = INVALID_AUDIO_OFFSET; - self->next_audio_offset = INVALID_AUDIO_OFFSET; - self->audio_discont = TRUE; - } + self->av_sync = GST_CLOCK_DIFF (GST_BUFFER_PTS (buffer), + GST_BUFFER_PTS (audio_buf)); } gst_buffer_unref (audio_buf); @@ -1892,6 +1881,8 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) self->skip_first_time = GST_CLOCK_TIME_NONE; self->start_time = GST_CLOCK_TIME_NONE; self->started = FALSE; + self->no_signal_count = 0; + self->av_sync = 0; } HRESULT @@ -2097,7 +2088,7 @@ gst_decklink2_input_set_flushing (GstDeckLink2Input * input, gboolean flush) GstFlowReturn gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buf, - GstCaps ** caps) + GstCaps ** caps, GstClockTimeDiff * av_sync, guint * no_signal_count) { GstDeckLink2InputPrivate *priv = input->priv; std::unique_lock < std::mutex > lk (priv->lock); @@ -2105,6 +2096,8 @@ gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buf, *buf = nullptr; *caps = nullptr; + *av_sync = 0; + *no_signal_count = 0; while (gst_queue_array_is_empty (input->queue) && !input->flushing && input->started) { @@ -2121,6 +2114,8 @@ gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buf, gst_queue_array_pop_head_struct (input->queue); *buf = data->buffer; *caps = data->caps; + *av_sync = input->av_sync; + *no_signal_count = input->no_signal_count; return GST_FLOW_OK; } diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h index a47aed6ca0..44a827df29 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h @@ -74,7 +74,9 @@ void gst_decklink2_input_set_flushing (GstDeckLink2Input * input, GstFlowReturn gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buffer, - GstCaps ** caps); + GstCaps ** caps, + GstClockTimeDiff * av_sync, + guint * no_signal_count); gboolean gst_decklink2_input_has_signal (GstDeckLink2Input * input); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index 34867a482b..3ca56cd4c9 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -49,6 +49,8 @@ enum PROP_BUFFER_SIZE, PROP_SIGNAL, PROP_SKIP_FIRST_TIME, + PROP_DESYNC_THRESHOLD, + PROP_NO_SIGNAL_THRESHOLD, }; #define DEFAULT_MODE bmdModeUnknown @@ -64,6 +66,8 @@ enum #define DEFAULT_BUFFER_SIZE 5 #define DEFAULT_AUDIO_CHANNELS GST_DECKLINK2_AUDIO_CHANNELS_2 #define DEFAULT_SKIP_FIRST_TIME 0 +#define DEFAULT_DESYNC_THRESHOLD (250 * GST_MSECOND) +#define DEFAULT_NO_SIGNAL_THRESHOLD (10) enum { @@ -109,6 +113,8 @@ struct _GstDeckLink2Src gboolean output_afd_bar; guint buffer_size; GstClockTime skip_first_time; + GstClockTime desync_threshold; + guint no_signal_threshold; }; static void gst_decklink2_src_finalize (GObject * object); @@ -206,6 +212,8 @@ gst_decklink2_src_init (GstDeckLink2Src * self) self->output_afd_bar = DEFAULT_OUTPUT_AFD_BAR; self->buffer_size = DEFAULT_BUFFER_SIZE; self->is_gap_buf = FALSE; + self->desync_threshold = DEFAULT_DESYNC_THRESHOLD; + self->no_signal_threshold = DEFAULT_NO_SIGNAL_THRESHOLD; self->priv = new GstDeckLink2SrcPrivate (); @@ -272,6 +280,12 @@ gst_decklink2_src_set_property (GObject * object, guint prop_id, case PROP_SKIP_FIRST_TIME: self->skip_first_time = g_value_get_uint64 (value); break; + case PROP_DESYNC_THRESHOLD: + self->desync_threshold = g_value_get_uint64 (value); + break; + case PROP_NO_SIGNAL_THRESHOLD: + self->no_signal_threshold = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -335,6 +349,12 @@ gst_decklink2_src_get_property (GObject * object, guint prop_id, GValue * value, case PROP_SKIP_FIRST_TIME: g_value_set_uint64 (value, self->skip_first_time); break; + case PROP_DESYNC_THRESHOLD: + g_value_set_uint64 (value, self->desync_threshold); + break; + case PROP_NO_SIGNAL_THRESHOLD: + g_value_set_uint (value, self->no_signal_threshold); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -525,21 +545,11 @@ gst_decklink2_src_unlock_stop (GstBaseSrc * src) } static gboolean -gst_decklink2_src_run (GstDeckLink2Src * self) +gst_decklink2_src_run_unlocked (GstDeckLink2Src * self, gboolean auto_restart) { HRESULT hr; GstDeckLink2InputVideoConfig video_config; GstDeckLink2InputAudioConfig audio_config; - GstDeckLink2SrcPrivate *priv = self->priv; - std::lock_guard < std::mutex > lk (priv->lock); - - if (self->running) - return TRUE; - - if (!self->input) { - GST_ERROR_OBJECT (self, "Input object was not configured"); - return FALSE; - } video_config.connection = self->video_conn; video_config.display_mode = self->selected_mode; @@ -553,8 +563,8 @@ gst_decklink2_src_run (GstDeckLink2Src * self) audio_config.channels = self->audio_channels; hr = gst_decklink2_input_start (self->input, GST_ELEMENT (self), - self->profile_id, self->buffer_size, self->skip_first_time, - &video_config, &audio_config); + self->profile_id, self->buffer_size, + auto_restart ? 0 : self->skip_first_time, &video_config, &audio_config); if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (self, "Couldn't start stream, hr: 0x%x", (guint) hr); return FALSE; @@ -564,6 +574,23 @@ gst_decklink2_src_run (GstDeckLink2Src * self) return TRUE; } +static gboolean +gst_decklink2_src_run (GstDeckLink2Src * self) +{ + GstDeckLink2SrcPrivate *priv = self->priv; + std::lock_guard < std::mutex > lk (priv->lock); + + if (self->running) + return TRUE; + + if (!self->input) { + GST_ERROR_OBJECT (self, "Input object was not configured"); + return FALSE; + } + + return gst_decklink2_src_run_unlocked (self, FALSE); +} + static GstFlowReturn gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) { @@ -573,6 +600,8 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) GstFlowReturn ret; GstDeckLink2SrcPrivate *priv = self->priv; gboolean is_gap_buf = FALSE; + GstClockTimeDiff av_sync; + guint no_signal_count; again: if (!gst_decklink2_src_run (self)) { @@ -581,7 +610,8 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) return GST_FLOW_ERROR; } - ret = gst_decklink2_input_get_data (self->input, &buf, &caps); + ret = gst_decklink2_input_get_data (self->input, &buf, &caps, &av_sync, + &no_signal_count); if (ret != GST_FLOW_OK) { if (ret == GST_DECKLINK2_INPUT_FLOW_STOPPED) { GST_DEBUG_OBJECT (self, "Input was stopped for restarting"); @@ -617,6 +647,43 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) *buffer = buf; + if (self->desync_threshold != 0 && + GST_CLOCK_TIME_IS_VALID (self->desync_threshold)) { + GstClockTime diff; + if (av_sync >= 0) + diff = av_sync; + else + diff = -av_sync; + + GST_LOG_OBJECT (self, "Current AV sync %" GST_STIME_FORMAT, + GST_STIME_ARGS (av_sync)); + + if (diff >= self->desync_threshold) { + GST_WARNING_OBJECT (self, "Large AV desync is detected, desync %" + GST_STIME_FORMAT ", threshold %" GST_TIME_FORMAT, + GST_STIME_ARGS (av_sync), GST_TIME_ARGS (self->desync_threshold)); + + self->running = FALSE; + gst_decklink2_input_stop (self->input); + if (!gst_decklink2_src_run_unlocked (self, TRUE)) { + GST_ERROR_OBJECT (self, "Couldn't restart input"); + return GST_FLOW_ERROR; + } + } + } + + if (self->no_signal_threshold != 0 && + no_signal_count >= self->no_signal_threshold) { + GST_DEBUG_OBJECT (self, "No signal count %u, restarting", no_signal_count); + + self->running = FALSE; + gst_decklink2_input_stop (self->input); + if (!gst_decklink2_src_run_unlocked (self, TRUE)) { + GST_ERROR_OBJECT (self, "Couldn't restart input"); + return GST_FLOW_ERROR; + } + } + return GST_FLOW_OK; } @@ -710,6 +777,22 @@ gst_decklink2_src_install_properties (GObjectClass * object_class) "Skip that much time of initial frames after starting", 0, G_MAXUINT64, DEFAULT_SKIP_FIRST_TIME, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (object_class, PROP_DESYNC_THRESHOLD, + g_param_spec_uint64 ("desync-threshold", "Desync Threshold", + "Maximum allowed a/v desync threshold. " + "If larger desync is detected, streaming will be restarted " + "(0 = disable auto-restart)", 0, + G_MAXUINT64, DEFAULT_DESYNC_THRESHOLD, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (object_class, PROP_NO_SIGNAL_THRESHOLD, + g_param_spec_uint ("no-signal-threshold", "No Signal Threshold", + "Maximum allowed consecutive no-signal threshold. " + "If larger number of consecutive no-signal frames is detected, " + "streaming will be restarted (0 = disable auto-restart)", 0, + G_MAXINT32, DEFAULT_NO_SIGNAL_THRESHOLD, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); } void From 414285d89a91455331d181042dce82892f306289 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Mon, 26 Jun 2023 18:21:49 +0900 Subject: [PATCH 27/82] decklink2src: Remove no-signal-threshold property instead, do auto restart on no-signal to signal state transition --- .../sys/decklink2/gstdecklink2input.cpp | 49 +++++++++++++------ .../sys/decklink2/gstdecklink2input.h | 3 +- .../sys/decklink2/gstdecklink2src.cpp | 34 +------------ 3 files changed, 37 insertions(+), 49 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 13c166e8a4..87a17e94e9 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -337,11 +337,13 @@ struct GstDeckLink2InputPrivate GstDeckLink2InputPrivate () { signal = false; + was_restarted = false; } std::mutex lock; std::condition_variable cond; std::atomic < bool >signal; + std::atomic < bool >was_restarted; }; struct _GstDeckLink2Input @@ -395,7 +397,6 @@ struct _GstDeckLink2Input gboolean started; GstClockTime skip_first_time; GstClockTime start_time; - guint no_signal_count; GstClockTimeDiff av_sync; guint window_size; @@ -1075,6 +1076,7 @@ gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, BMDDisplayMode display_mode = mode->GetDisplayMode (); GstDeckLink2DisplayMode new_mode; GstCaps *caps; + GstDeckLink2InputPrivate *priv = self->priv; GST_DEBUG_OBJECT (self, "format changed, flags 0x%x", flags); @@ -1128,8 +1130,8 @@ gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, gst_adapter_clear (self->audio_buf); self->audio_offset = INVALID_AUDIO_OFFSET; self->next_audio_offset = INVALID_AUDIO_OFFSET; - self->no_signal_count = 0; self->av_sync = 0; + priv->was_restarted = true; gst_decklink2_input_reset_time_mapping (self); gst_decklink2_input_start_streams (self); @@ -1510,6 +1512,34 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, BMDTimeValue hw_now, dummy, dummy2; BMDTimeValue stream_time = GST_CLOCK_TIME_NONE; BMDTimeValue stream_dur; + BMDFrameFlags flags = bmdFrameFlagDefault; + + if (frame) { + if (priv->was_restarted) { + /* Ignores no-signal flag of the first frame after we do restart */ + priv->was_restarted = false; + } else { + flags = frame->GetFlags (); + if ((flags & bmdFrameHasNoInputSource) != 0) { + GST_DEBUG_OBJECT (self, "No signal"); + priv->signal = false; + } else if (!priv->signal) { + GST_INFO_OBJECT (self, "Got first frame, reset timing map"); + priv->signal = true; + priv->was_restarted = true; + gst_decklink2_input_reset_time_mapping (self); + gst_decklink2_input_stop_streams (self); + gst_decklink2_input_flush_streams (self); + gst_decklink2_input_start_streams (self); + gst_adapter_clear (self->audio_buf); + self->audio_offset = INVALID_AUDIO_OFFSET; + self->next_audio_offset = INVALID_AUDIO_OFFSET; + return; + } else { + priv->signal = true; + } + } + } std::unique_lock < std::mutex > lk (priv->lock); hr = gst_decklink2_input_get_reference_clock (self, GST_SECOND, @@ -1554,7 +1584,6 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, if (frame) { void *frame_data; gsize frame_size; - BMDFrameFlags flags; BMDTimeValue frame_time, frame_dur; IDeckLinkTimecode *timecode = NULL; GstClockTime pts, dur; @@ -1601,16 +1630,10 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, dur = GST_CLOCK_TIME_NONE; } - flags = frame->GetFlags (); - if ((flags & bmdFrameHasNoInputSource) != 0) { + if (!priv->signal) { GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_GAP); GST_DEBUG_OBJECT (self, "No signal"); - priv->signal = false; - self->no_signal_count++; } else { - priv->signal = true; - self->no_signal_count = 0; - if (self->output_cc || self->output_afd_bar) { extract_vbi (self, buffer, frame); @@ -1878,10 +1901,10 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) gst_clear_caps (&self->selected_video_caps); gst_clear_caps (&self->selected_audio_caps); priv->signal = false; + priv->was_restarted = false; self->skip_first_time = GST_CLOCK_TIME_NONE; self->start_time = GST_CLOCK_TIME_NONE; self->started = FALSE; - self->no_signal_count = 0; self->av_sync = 0; } @@ -2088,7 +2111,7 @@ gst_decklink2_input_set_flushing (GstDeckLink2Input * input, gboolean flush) GstFlowReturn gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buf, - GstCaps ** caps, GstClockTimeDiff * av_sync, guint * no_signal_count) + GstCaps ** caps, GstClockTimeDiff * av_sync) { GstDeckLink2InputPrivate *priv = input->priv; std::unique_lock < std::mutex > lk (priv->lock); @@ -2097,7 +2120,6 @@ gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buf, *buf = nullptr; *caps = nullptr; *av_sync = 0; - *no_signal_count = 0; while (gst_queue_array_is_empty (input->queue) && !input->flushing && input->started) { @@ -2115,7 +2137,6 @@ gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buf, *buf = data->buffer; *caps = data->caps; *av_sync = input->av_sync; - *no_signal_count = input->no_signal_count; return GST_FLOW_OK; } diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h index 44a827df29..6f18d43f53 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h @@ -75,8 +75,7 @@ void gst_decklink2_input_set_flushing (GstDeckLink2Input * input, GstFlowReturn gst_decklink2_input_get_data (GstDeckLink2Input * input, GstBuffer ** buffer, GstCaps ** caps, - GstClockTimeDiff * av_sync, - guint * no_signal_count); + GstClockTimeDiff * av_sync); gboolean gst_decklink2_input_has_signal (GstDeckLink2Input * input); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index 3ca56cd4c9..e2b9a97230 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -50,7 +50,6 @@ enum PROP_SIGNAL, PROP_SKIP_FIRST_TIME, PROP_DESYNC_THRESHOLD, - PROP_NO_SIGNAL_THRESHOLD, }; #define DEFAULT_MODE bmdModeUnknown @@ -67,7 +66,6 @@ enum #define DEFAULT_AUDIO_CHANNELS GST_DECKLINK2_AUDIO_CHANNELS_2 #define DEFAULT_SKIP_FIRST_TIME 0 #define DEFAULT_DESYNC_THRESHOLD (250 * GST_MSECOND) -#define DEFAULT_NO_SIGNAL_THRESHOLD (10) enum { @@ -114,7 +112,6 @@ struct _GstDeckLink2Src guint buffer_size; GstClockTime skip_first_time; GstClockTime desync_threshold; - guint no_signal_threshold; }; static void gst_decklink2_src_finalize (GObject * object); @@ -213,7 +210,6 @@ gst_decklink2_src_init (GstDeckLink2Src * self) self->buffer_size = DEFAULT_BUFFER_SIZE; self->is_gap_buf = FALSE; self->desync_threshold = DEFAULT_DESYNC_THRESHOLD; - self->no_signal_threshold = DEFAULT_NO_SIGNAL_THRESHOLD; self->priv = new GstDeckLink2SrcPrivate (); @@ -283,9 +279,6 @@ gst_decklink2_src_set_property (GObject * object, guint prop_id, case PROP_DESYNC_THRESHOLD: self->desync_threshold = g_value_get_uint64 (value); break; - case PROP_NO_SIGNAL_THRESHOLD: - self->no_signal_threshold = g_value_get_uint (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -352,9 +345,6 @@ gst_decklink2_src_get_property (GObject * object, guint prop_id, GValue * value, case PROP_DESYNC_THRESHOLD: g_value_set_uint64 (value, self->desync_threshold); break; - case PROP_NO_SIGNAL_THRESHOLD: - g_value_set_uint (value, self->no_signal_threshold); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -601,7 +591,6 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) GstDeckLink2SrcPrivate *priv = self->priv; gboolean is_gap_buf = FALSE; GstClockTimeDiff av_sync; - guint no_signal_count; again: if (!gst_decklink2_src_run (self)) { @@ -610,8 +599,7 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) return GST_FLOW_ERROR; } - ret = gst_decklink2_input_get_data (self->input, &buf, &caps, &av_sync, - &no_signal_count); + ret = gst_decklink2_input_get_data (self->input, &buf, &caps, &av_sync); if (ret != GST_FLOW_OK) { if (ret == GST_DECKLINK2_INPUT_FLOW_STOPPED) { GST_DEBUG_OBJECT (self, "Input was stopped for restarting"); @@ -672,18 +660,6 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) } } - if (self->no_signal_threshold != 0 && - no_signal_count >= self->no_signal_threshold) { - GST_DEBUG_OBJECT (self, "No signal count %u, restarting", no_signal_count); - - self->running = FALSE; - gst_decklink2_input_stop (self->input); - if (!gst_decklink2_src_run_unlocked (self, TRUE)) { - GST_ERROR_OBJECT (self, "Couldn't restart input"); - return GST_FLOW_ERROR; - } - } - return GST_FLOW_OK; } @@ -785,14 +761,6 @@ gst_decklink2_src_install_properties (GObjectClass * object_class) "(0 = disable auto-restart)", 0, G_MAXUINT64, DEFAULT_DESYNC_THRESHOLD, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property (object_class, PROP_NO_SIGNAL_THRESHOLD, - g_param_spec_uint ("no-signal-threshold", "No Signal Threshold", - "Maximum allowed consecutive no-signal threshold. " - "If larger number of consecutive no-signal frames is detected, " - "streaming will be restarted (0 = disable auto-restart)", 0, - G_MAXINT32, DEFAULT_NO_SIGNAL_THRESHOLD, - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); } void From 68f239242cee5cea342fcd78576396cd07e5d292 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 27 Jun 2023 20:03:44 +0900 Subject: [PATCH 28/82] decklink2src: Update for signal state logging --- .../sys/decklink2/gstdecklink2input.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 87a17e94e9..6b91e8afb4 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -1515,16 +1515,24 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, BMDFrameFlags flags = bmdFrameFlagDefault; if (frame) { + gboolean has_signal; + flags = frame->GetFlags (); + + if ((flags & bmdFrameHasNoInputSource) != 0) + has_signal = FALSE; + else + has_signal = TRUE; + + GST_TRACE_OBJECT (self, "Frame has signal: %d", has_signal); + if (priv->was_restarted) { /* Ignores no-signal flag of the first frame after we do restart */ priv->was_restarted = false; } else { - flags = frame->GetFlags (); - if ((flags & bmdFrameHasNoInputSource) != 0) { - GST_DEBUG_OBJECT (self, "No signal"); + if (!has_signal) { priv->signal = false; } else if (!priv->signal) { - GST_INFO_OBJECT (self, "Got first frame, reset timing map"); + GST_LOG_OBJECT (self, "Got first frame, reset timing map"); priv->signal = true; priv->was_restarted = true; gst_decklink2_input_reset_time_mapping (self); @@ -1632,7 +1640,6 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, if (!priv->signal) { GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_GAP); - GST_DEBUG_OBJECT (self, "No signal"); } else { if (self->output_cc || self->output_afd_bar) { extract_vbi (self, buffer, frame); From d680388b62b2e6ce170f8ee70f9539f4a9217662 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 30 Jun 2023 21:39:49 +0900 Subject: [PATCH 29/82] decklink2sink: Don't hold lock while stopping Driver may wait for callback thread to join() but we takes the same lock there --- .../gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index d8fcb5e9e8..c6fe341127 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -1099,6 +1099,7 @@ gst_decklink2_output_stop_internal (GstDeckLink2Output * self) std::unique_lock < std::mutex > lk (priv->schedule_lock); /* Steal last frame to avoid re-rendering */ GST_DECKLINK2_CLEAR_COM (self->last_frame); + lk.unlock (); switch (self->api_level) { case GST_DECKLINK2_API_LEVEL_10_11: @@ -1115,7 +1116,6 @@ gst_decklink2_output_stop_internal (GstDeckLink2Output * self) g_assert_not_reached (); break; } - lk.unlock (); GST_DEBUG_OBJECT (self, "StopScheduledPlayback result 0x%x", (guint) hr); From 7dcd7d33ff20d9b8ae049b777fac559a42c370b7 Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Mon, 10 Jul 2023 10:35:11 -0400 Subject: [PATCH 30/82] Flush device streams when we don't get enough audio samples from the hardware --- .../sys/decklink2/gstdecklink2input.cpp | 36 +++++-------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 6b91e8afb4..9a510c4ba2 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -1803,34 +1803,14 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, GST_WARNING_OBJECT (self, "Expected offset %" G_GUINT64_FORMAT ", received %" G_GUINT64_FORMAT, self->next_audio_offset, audio_offset); - self->audio_discont = TRUE; - - if (self->next_audio_offset > audio_offset) { - gsize trim = self->next_audio_offset - audio_offset; - gsize count; - - if (trim >= (gsize) sample_count) { - GST_WARNING_OBJECT (self, "Complately backward audio pts"); - gst_buffer_unref (audio_buf); - goto out; - } - - count = sample_count - trim; - audio_buf = gst_audio_buffer_truncate (audio_buf, self->audio_info.bpf, - trim, count); - self->next_audio_offset += count; - } else { - GstBuffer *silence; - gsize diff = audio_offset - self->next_audio_offset; - - silence = gst_buffer_new_and_alloc (diff * self->audio_info.bpf); - gst_buffer_map (silence, &map, GST_MAP_WRITE); - gst_audio_format_info_fill_silence (self->audio_info.finfo, - map.data, map.size); - gst_buffer_unmap (silence, &map); - gst_adapter_push (self->audio_buf, silence); - self->next_audio_offset += sample_count + diff; - } + gst_decklink2_input_reset_time_mapping (self); + gst_decklink2_input_stop_streams (self); + gst_decklink2_input_flush_streams (self); + gst_decklink2_input_start_streams (self); + gst_adapter_clear (self->audio_buf); + self->audio_offset = INVALID_AUDIO_OFFSET; + self->next_audio_offset = INVALID_AUDIO_OFFSET; + return; } else { GST_LOG_OBJECT (self, "Got expected audio samples"); self->next_audio_offset += sample_count; From 936274997ca1a143f3df1a276efbf2a6f192796c Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 11 Jul 2023 18:57:56 +0900 Subject: [PATCH 31/82] decklink2: Fix output audio prepend and add more logs --- .../sys/decklink2/gstdecklink2combiner.cpp | 17 +- .../sys/decklink2/gstdecklink2output.cpp | 152 ++++++++++++++++-- 2 files changed, 159 insertions(+), 10 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp index c82f3e0d03..d783380c59 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp @@ -55,6 +55,9 @@ struct _GstDeckLink2Combiner GstClockTime video_running_time; GstClockTime audio_running_time; + + guint64 num_video_buffers; + guint64 num_audio_buffers; }; static void gst_decklink2_combiner_dispose (GObject * object); @@ -376,6 +379,8 @@ gst_decklink2_combiner_reset (GstDeckLink2Combiner * self) self->audio_start_time = GST_CLOCK_TIME_NONE; self->video_running_time = GST_CLOCK_TIME_NONE; self->audio_running_time = GST_CLOCK_TIME_NONE; + self->num_video_buffers = 0; + self->num_audio_buffers = 0; } static gboolean @@ -621,12 +626,16 @@ gst_decklink2_combiner_aggregate (GstAggregator * agg, gboolean timeout) (GstBuffer *) g_steal_pointer (&audio_buf)); gst_aggregator_pad_drop_buffer (self->audio_pad); } + + self->num_audio_buffers++; } else { GST_LOG_OBJECT (self, "Pushing audio buffer to adapter, %" GST_PTR_FORMAT, audio_buf); gst_adapter_push (self->audio_buffers, (GstBuffer *) g_steal_pointer (&audio_buf)); gst_aggregator_pad_drop_buffer (self->audio_pad); + + self->num_audio_buffers++; } } @@ -644,6 +653,7 @@ gst_decklink2_combiner_aggregate (GstAggregator * agg, gboolean timeout) gst_aggregator_pad_drop_buffer (self->video_pad); video_buf = gst_buffer_make_writable (video_buf); + self->num_video_buffers++; /* Remove external audio meta if any */ meta = gst_buffer_get_decklink2_audio_meta (video_buf); @@ -669,7 +679,12 @@ gst_decklink2_combiner_aggregate (GstAggregator * agg, gboolean timeout) GST_LOG_OBJECT (self, "No audio meta"); } - GST_LOG_OBJECT (self, "Finish buffer %" GST_PTR_FORMAT, video_buf); + GST_LOG_OBJECT (self, "Finish buffer %" GST_PTR_FORMAT + ", total video/audio buffers %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ") / %" GST_TIME_FORMAT " (%" + G_GUINT64_FORMAT ")", video_buf, GST_TIME_ARGS (self->video_running_time), + self->num_video_buffers, GST_TIME_ARGS (self->audio_running_time), + self->num_audio_buffers); GST_AGGREGATOR_PAD (agg->srcpad)->segment.position = self->video_running_time; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index c6fe341127..87201644cd 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -147,7 +147,7 @@ class GstDecklink2OutputAudioBuffer size_t silence_length_in_bytes = num_samples * info_.bpf; size_t cur_size = buffer_.size (); - buffer_.resize (cur_size + num_samples); + buffer_.resize (cur_size + silence_length_in_bytes); if (cur_size > 0) { memmove (&buffer_[0] + silence_length_in_bytes, &buffer_[0], cur_size); } @@ -226,10 +226,12 @@ struct _GstDeckLink2Output guint16 cdp_hdr_sequence_cntr; guint n_prerolled; guint64 n_frames; + guint64 n_samples; guint n_preroll_frames; guint min_buffered; guint max_buffered; GstClockTime pts; + BMDTimeValue hw_time; gboolean configured; gboolean prerolled; @@ -856,7 +858,7 @@ gst_decklink2_output_is_running (GstDeckLink2Output * self, dlbool_t * active) } static HRESULT -gst_decklink2_output_get_num_bufferred (GstDeckLink2Output * self, +gst_decklink2_output_get_num_buffered (GstDeckLink2Output * self, guint32 * count) { HRESULT hr = E_FAIL; @@ -880,6 +882,60 @@ gst_decklink2_output_get_num_bufferred (GstDeckLink2Output * self, return hr; } +static HRESULT +gst_decklink2_output_get_num_buffered_audio (GstDeckLink2Output * self, + guint32 * count) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->GetBufferedAudioSampleFrameCount (count); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->GetBufferedAudioSampleFrameCount (count); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->GetBufferedAudioSampleFrameCount (count); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + +static HRESULT +gst_decklink2_output_get_reference_clock (GstDeckLink2Output * self, + BMDTimeScale scale, BMDTimeValue * hw_time, BMDTimeValue * time_in_frame, + BMDTimeValue * ticks_per_frame) +{ + HRESULT hr = E_FAIL; + + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->GetHardwareReferenceClock (scale, + hw_time, time_in_frame, ticks_per_frame); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->GetHardwareReferenceClock (scale, + hw_time, time_in_frame, ticks_per_frame); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->GetHardwareReferenceClock (scale, + hw_time, time_in_frame, ticks_per_frame); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; +} + static HRESULT gst_decklink2_output_start (GstDeckLink2Output * self, BMDTimeValue start_time, BMDTimeScale scale, double speed) @@ -906,6 +962,50 @@ gst_decklink2_output_start (GstDeckLink2Output * self, return hr; } +static HRESULT +gst_decklink2_get_current_level (GstDeckLink2Output * self, + guint * buffered_video, GstClockTime * video_running_time, + guint * buffered_audio, GstClockTime * audio_running_time, + GstClockTimeDiff * av_diff, GstClockTime * hw_time) +{ + BMDTimeValue hw_now, dummy, dummy2; + HRESULT hr = S_OK; + + *buffered_video = 0; + *buffered_audio = 0; + *video_running_time = self->pts; + *audio_running_time = GST_CLOCK_TIME_NONE; + *av_diff = GST_CLOCK_STIME_NONE; + *hw_time = GST_CLOCK_TIME_NONE; + + hr = gst_decklink2_output_get_num_buffered (self, buffered_video); + if (!gst_decklink2_result (hr)) + return hr; + + if (self->n_samples > 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { + hr = gst_decklink2_output_get_num_buffered_audio (self, buffered_audio); + if (!gst_decklink2_result (hr)) + return hr; + + *audio_running_time = gst_util_uint64_scale (self->n_samples, GST_SECOND, + self->audio_info.rate); + *av_diff = GST_CLOCK_DIFF (self->pts, *audio_running_time); + } + + if (self->prerolled) { + hr = gst_decklink2_output_get_reference_clock (self, GST_SECOND, &hw_now, + &dummy, &dummy2); + if (!gst_decklink2_result (hr)) + return hr; + + if (self->hw_time == GST_CLOCK_TIME_NONE) + self->hw_time = hw_now; + *hw_time = hw_now - self->hw_time; + } + + return S_OK; +} + static HRESULT gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, IDeckLinkVideoFrame * frame) @@ -916,6 +1016,12 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, guint num_samples; guint num_written; guint8 *audio_buf; + guint buffered_video = 0; + guint buffered_audio = 0; + GstClockTime video_running_time = GST_CLOCK_TIME_NONE; + GstClockTime audio_running_time = GST_CLOCK_TIME_NONE; + GstClockTime hw_time_gst = GST_CLOCK_TIME_NONE; + GstClockTimeDiff diff = GST_CLOCK_STIME_NONE; frame->AddRef (); GST_DECKLINK2_CLEAR_COM (self->last_frame); @@ -926,8 +1032,6 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, self->selected_mode.fps_d * GST_SECOND, self->selected_mode.fps_n); dur = next_pts - self->pts; - GST_LOG_OBJECT (self, "Scheduling video frame %p", frame); - switch (self->api_level) { case GST_DECKLINK2_API_LEVEL_10_11: hr = self->output_10_11->ScheduleVideoFrame (frame, @@ -954,6 +1058,7 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, } audio_buf = priv->audio_buf.GetSamples (num_samples); + self->n_samples += num_samples; if (!self->prerolled) { if (self->n_prerolled == 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { @@ -1027,6 +1132,19 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, priv->audio_buf.Flush (); } + hr = gst_decklink2_get_current_level (self, &buffered_video, + &video_running_time, &buffered_audio, &audio_running_time, &diff, + &hw_time_gst); + if (gst_decklink2_result (hr)) { + GST_LOG_OBJECT (self, "After schedule, video %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u) audio %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u), av-diff: %" GST_STIME_FORMAT + ", hw-time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->pts), self->n_frames, buffered_video, + GST_TIME_ARGS (audio_running_time), self->n_samples, buffered_audio, + GST_STIME_ARGS (diff), GST_TIME_ARGS (hw_time_gst)); + } + return S_OK; } @@ -1055,7 +1173,7 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, if (active) { guint32 count = 0; - hr = gst_decklink2_output_get_num_bufferred (output, &count); + hr = gst_decklink2_output_get_num_buffered (output, &count); if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (output, "Couldn't query bufferred frame count, hr: 0x%x", (guint) hr); @@ -1964,6 +2082,8 @@ gst_decklink2_output_configure (GstDeckLink2Output * output, output->min_buffered = min_buffered; output->max_buffered = max_buffered; output->n_frames = 0; + output->n_samples = 0; + output->hw_time = GST_CLOCK_TIME_NONE; output->cdp_hdr_sequence_cntr = 0; output->configured = TRUE; output->pts = 0; @@ -1992,7 +2112,6 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self, { GstDeckLink2OutputPrivate *priv = self->priv; dlbool_t active; - guint32 count = 0; std::lock_guard < std::mutex > lk (priv->schedule_lock); if (result == bmdOutputFrameDisplayedLate) @@ -2005,9 +2124,24 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self, HRESULT hr = gst_decklink2_output_is_running (self, &active); if (gst_decklink2_result (hr) && active) { - hr = gst_decklink2_output_get_num_bufferred (self, &count); - if (gst_decklink2_result (hr) && count <= self->min_buffered) { - GST_WARNING_OBJECT (self, "Underrun, buffered count %u", count); + guint buffered_video = 0; + guint buffered_audio = 0; + GstClockTime video_running_time = GST_CLOCK_TIME_NONE; + GstClockTime audio_running_time = GST_CLOCK_TIME_NONE; + GstClockTime hw_time_gst = GST_CLOCK_TIME_NONE; + GstClockTimeDiff diff = GST_CLOCK_STIME_NONE; + + hr = gst_decklink2_get_current_level (self, &buffered_video, + &video_running_time, &buffered_audio, &audio_running_time, &diff, + &hw_time_gst); + if (gst_decklink2_result (hr) && buffered_video <= self->min_buffered) { + GST_WARNING_OBJECT (self, "Underrun, video %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u) audio %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u), av-diff: %" GST_STIME_FORMAT + ", hw-time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->pts), self->n_frames, buffered_video, + GST_TIME_ARGS (audio_running_time), self->n_samples, buffered_audio, + GST_STIME_ARGS (diff), GST_TIME_ARGS (hw_time_gst)); self->underrun_count++; priv->audio_buf.PrependSilence (); gst_decklink2_output_schedule_video_internal (self, self->last_frame); From 1694e145589a5733da7126563e4fac5c98d88c10 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 14 Jul 2023 23:26:04 +0900 Subject: [PATCH 32/82] decklink2sink: Restart only when frames are dropped --- .../gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp index 40795641a0..fbc258184f 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -243,7 +243,7 @@ gst_decklink2_sink_class_init (GstDeckLink2SinkClass * klass) g_object_class_install_property (object_class, PROP_AUTO_RESTART, g_param_spec_boolean ("auto-restart", "Auto Restart", - "Restart streaming when frame is dropped, late or underrun happens", + "Restart streaming when frame is being dropped by hardware", DEFAULT_AUTO_RESTART, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); @@ -962,10 +962,11 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) return GST_FLOW_ERROR; } - if (self->auto_restart && (drop_count || late_count || underrun_count)) { + if (self->auto_restart && (drop_count + late_count > + (guint) self->n_preroll_frames)) { GST_WARNING_OBJECT (self, "Restart output, drop count: %" G_GUINT64_FORMAT - ", late cout: %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT, - drop_count, late_count, underrun_count); + ", late cout: %" G_GUINT64_FORMAT ", underrun count: %" + G_GUINT64_FORMAT, drop_count, late_count, underrun_count); hr = gst_decklink2_output_configure (self->output, self->n_preroll_frames, self->min_buffered_frames, self->max_buffered_frames, From 502321e85b1941a0e5758ce9f387727b0c4a3d7d Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 15 Jul 2023 00:29:52 +0900 Subject: [PATCH 33/82] decklink2output: Duplicate more frames on underrun ... and log actual render time with scheduled time --- .../sys/decklink2/gstdecklink2output.cpp | 1188 +++++++++-------- 1 file changed, 664 insertions(+), 524 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index 87201644cd..480121b334 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -39,6 +39,321 @@ GST_DEBUG_CATEGORY_STATIC (gst_decklink2_output_debug); class IGstDeckLinkVideoOutputCallback; +class IGstDeckLinkTimecode:public IDeckLinkTimecode +{ +public: + IGstDeckLinkTimecode (GstVideoTimeCode * timecode):ref_count_ (1) + { + g_assert (timecode); + + timecode_ = gst_video_time_code_copy (timecode); + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkTimecode) { + *object = static_cast < IDeckLinkTimecode * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkTimecode */ + BMDTimecodeBCD STDMETHODCALLTYPE GetBCD (void) + { + BMDTimecodeBCD bcd = 0; + + bcd |= (timecode_->frames % 10) << 0; + bcd |= ((timecode_->frames / 10) & 0x0f) << 4; + bcd |= (timecode_->seconds % 10) << 8; + bcd |= ((timecode_->seconds / 10) & 0x0f) << 12; + bcd |= (timecode_->minutes % 10) << 16; + bcd |= ((timecode_->minutes / 10) & 0x0f) << 20; + bcd |= (timecode_->hours % 10) << 24; + bcd |= ((timecode_->hours / 10) & 0x0f) << 28; + + if (timecode_->config.fps_n == 24 && timecode_->config.fps_d == 1) + bcd |= 0x0 << 30; + else if (timecode_->config.fps_n == 25 && timecode_->config.fps_d == 1) + bcd |= 0x1 << 30; + else if (timecode_->config.fps_n == 30 && timecode_->config.fps_d == 1001) + bcd |= 0x2 << 30; + else if (timecode_->config.fps_n == 30 && timecode_->config.fps_d == 1) + bcd |= 0x3 << 30; + + return bcd; + } + + HRESULT STDMETHODCALLTYPE + GetComponents (unsigned char *hours, unsigned char *minutes, + unsigned char *seconds, unsigned char *frames) + { + *hours = timecode_->hours; + *minutes = timecode_->minutes; + *seconds = timecode_->seconds; + *frames = timecode_->frames; + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE GetString (dlstring_t * timecode) + { + gchar *s = gst_video_time_code_to_string (timecode_); + *timecode = StdToDlString (s); + g_free (s); + + return S_OK; + } + + BMDTimecodeFlags STDMETHODCALLTYPE GetFlags (void) + { + BMDTimecodeFlags flags = (BMDTimecodeFlags) 0; + + if ((timecode_->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) != 0) + flags = (BMDTimecodeFlags) (flags | bmdTimecodeIsDropFrame); + else + flags = (BMDTimecodeFlags) (flags | bmdTimecodeFlagDefault); + + if (timecode_->field_count == 2) + flags = (BMDTimecodeFlags) (flags | bmdTimecodeFieldMark); + + return flags; + } + + HRESULT STDMETHODCALLTYPE GetTimecodeUserBits (BMDTimecodeUserBits * userBits) + { + *userBits = 0; + return S_OK; + } + +private: + virtual ~ IGstDeckLinkTimecode () { + gst_video_time_code_free (timecode_); + } + +private: + GstVideoTimeCode * timecode_; + std::atomic < ULONG > ref_count_; +}; + +class IGstDeckLinkVideoFrame:public IDeckLinkVideoFrame +{ +public: + IGstDeckLinkVideoFrame (GstVideoFrame * frame):ref_count_ (1) + { + frame_ = *frame; + } + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) + { + if (riid == IID_IDeckLinkVideoOutputCallback) { + *object = static_cast < IDeckLinkVideoFrame * >(this); + } else { + *object = NULL; + return E_NOINTERFACE; + } + + AddRef (); + + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef (void) + { + ULONG cnt = ref_count_.fetch_add (1); + + return cnt + 1; + } + + ULONG STDMETHODCALLTYPE Release (void) + { + ULONG cnt = ref_count_.fetch_sub (1); + if (cnt == 1) + delete this; + + return cnt - 1; + } + + /* IDeckLinkVideoFrame */ + long STDMETHODCALLTYPE GetWidth (void) + { + return GST_VIDEO_FRAME_WIDTH (&frame_); + } + + long STDMETHODCALLTYPE GetHeight (void) + { + return GST_VIDEO_FRAME_HEIGHT (&frame_); + } + + long STDMETHODCALLTYPE GetRowBytes (void) + { + return GST_VIDEO_FRAME_PLANE_STRIDE (&frame_, 0); + } + + BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat (void) + { + BMDPixelFormat format = bmdFormatUnspecified; + switch (GST_VIDEO_FRAME_FORMAT (&frame_)) { + case GST_VIDEO_FORMAT_UYVY: + format = bmdFormat8BitYUV; + break; + case GST_VIDEO_FORMAT_v210: + format = bmdFormat10BitYUV; + break; + case GST_VIDEO_FORMAT_ARGB: + format = bmdFormat8BitARGB; + break; + case GST_VIDEO_FORMAT_BGRA: + format = bmdFormat8BitBGRA; + break; + default: + g_assert_not_reached (); + break; + } + + return format; + } + + BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) + { + return bmdFrameFlagDefault; + } + + HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) + { + *buffer = GST_VIDEO_FRAME_PLANE_DATA (&frame_, 0); + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE + GetTimecode (BMDTimecodeFormat format, IDeckLinkTimecode ** timecode) + { + if (timecode_) { + *timecode = timecode_; + timecode_->AddRef (); + return S_OK; + } + + return S_FALSE; + } + + HRESULT STDMETHODCALLTYPE + GetAncillaryData (IDeckLinkVideoFrameAncillary ** ancillary) + { + if (ancillary_) { + *ancillary = ancillary_; + ancillary_->AddRef (); + return S_OK; + } + + return S_FALSE; + } + + /* Non-interface methods */ + HRESULT STDMETHODCALLTYPE SetTimecode (GstVideoTimeCode * timecode) + { + GST_DECKLINK2_CLEAR_COM (timecode_); + + if (timecode) + timecode_ = new IGstDeckLinkTimecode (timecode); + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE + SetAncillaryData (IDeckLinkVideoFrameAncillary * ancillary) + { + GST_DECKLINK2_CLEAR_COM (ancillary_); + + ancillary_ = ancillary; + if (ancillary_) + ancillary_->AddRef (); + + return S_OK; + } + + IGstDeckLinkVideoFrame *Clone (void) + { + IGstDeckLinkVideoFrame *cloned; + g_assert (frame_.buffer); + GstVideoFrame frame; + + if (!gst_video_frame_map (&frame, + &frame_.info, frame_.buffer, GST_MAP_READ)) { + return NULL; + } + + cloned = new IGstDeckLinkVideoFrame (&frame_); + if (ancillary_) + cloned->SetAncillaryData (ancillary_); + if (timecode_) { + timecode_->AddRef (); + cloned->timecode_ = timecode_; + } + + return cloned; + } + + void SetScheduledPts (GstClockTime pts) + { + pts_ = pts; + } + + GstClockTime GetScheduledPts (void) + { + return pts_; + } + + void SetScheduledHwTime (GstClockTime hw_time) + { + hw_time_ = hw_time; + } + + GstClockTime GetScheduledHwTime (void) + { + return hw_time_; + } + +private: + virtual ~ IGstDeckLinkVideoFrame () { + gst_video_frame_unmap (&frame_); + GST_DECKLINK2_CLEAR_COM (timecode_); + GST_DECKLINK2_CLEAR_COM (ancillary_); + } + +private: + std::atomic < ULONG > ref_count_; + GstVideoFrame frame_; + IDeckLinkTimecode *timecode_ = NULL; + IDeckLinkVideoFrameAncillary *ancillary_ = NULL; + GstClockTime pts_ = GST_CLOCK_TIME_NONE; + GstClockTime hw_time_ = GST_CLOCK_TIME_NONE; +}; + class GstDecklink2OutputAudioBuffer { public: @@ -112,13 +427,14 @@ class GstDecklink2OutputAudioBuffer guint64 num_samples = next_sample_offset - dup_drop_sample_offset_end_; samples_to_drop_ += num_samples; dup_drop_sample_offset_end_ = next_sample_offset; + size_t cur_size = buffer_.size (); + guint64 samples_in_queue = cur_size / info_.bpf; GST_WARNING_ID (debug_name_.c_str (), "Samples to drop %" G_GUINT64_FORMAT - ", total samples to drop %" G_GUINT64_FORMAT, num_samples, - samples_to_drop_); + ", total samples to drop %" G_GUINT64_FORMAT ", samples in queue %" + G_GUINT64_FORMAT, num_samples, samples_to_drop_, samples_in_queue); size_t bytes_to_drop = samples_to_drop_ * info_.bpf; - size_t cur_size = buffer_.size (); if (cur_size >= bytes_to_drop) { buffer_.resize (cur_size - bytes_to_drop); samples_to_drop_ = 0; @@ -187,7 +503,7 @@ class GstDecklink2OutputAudioBuffer struct GstDeckLink2OutputPrivate { std::mutex extern_lock; - std::mutex schedule_lock; + std::recursive_mutex schedule_lock; std::condition_variable cond; GstDecklink2OutputAudioBuffer audio_buf; }; @@ -212,7 +528,7 @@ struct _GstDeckLink2Output IDeckLinkOutput_v10_11 *output_10_11; IGstDeckLinkVideoOutputCallback *callback; - IDeckLinkVideoFrame *last_frame; + IGstDeckLinkVideoFrame *last_frame; GstCaps *caps; GArray *format_table; @@ -230,8 +546,10 @@ struct _GstDeckLink2Output guint n_preroll_frames; guint min_buffered; guint max_buffered; + guint gap_frames; GstClockTime pts; BMDTimeValue hw_time; + gboolean duplicating; gboolean configured; gboolean prerolled; @@ -245,6 +563,9 @@ static void gst_decklink2_output_finalize (GObject * object); static void gst_decklink2_output_on_stopped (GstDeckLink2Output * self); static void gst_decklink2_output_on_completed (GstDeckLink2Output * self, BMDOutputFrameCompletionResult result); +static HRESULT +gst_decklink2_output_get_completion_timestamp (GstDeckLink2Output * self, + IDeckLinkVideoFrame * frame, BMDTimeScale scale, BMDTimeValue * timestamp); #define gst_decklink2_output_parent_class parent_class G_DEFINE_TYPE (GstDeckLink2Output, gst_decklink2_output, GST_TYPE_OBJECT); @@ -293,15 +614,33 @@ class IGstDeckLinkVideoOutputCallback:public IDeckLinkVideoOutputCallback ScheduledFrameCompleted (IDeckLinkVideoFrame * frame, BMDOutputFrameCompletionResult result) { + IGstDeckLinkVideoFrame *gst_frame = (IGstDeckLinkVideoFrame *) frame; + BMDTimeValue timestamp = GST_CLOCK_TIME_NONE; + GstClockTime pts, hw_pts; + + pts = gst_frame->GetScheduledPts (); + hw_pts = gst_frame->GetScheduledHwTime (); + gst_decklink2_output_get_completion_timestamp (output_, + frame, GST_SECOND, ×tamp); + switch (result) { case bmdOutputFrameCompleted: - GST_LOG_OBJECT (output_, "Completed frame %p", frame); + GST_LOG_OBJECT (output_, "Frame %p completed timestamp %" + GST_TIME_FORMAT ", scheduled %" GST_TIME_FORMAT + " (gst pts %" GST_TIME_FORMAT ")", frame, + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (hw_pts), + GST_TIME_ARGS (pts)); break; case bmdOutputFrameDisplayedLate: - GST_WARNING_OBJECT (output_, "Late Frame %p", frame); + GST_LOG_OBJECT (output_, "Frame %p late, completed timestamp %" + GST_TIME_FORMAT ", scheduled %" GST_TIME_FORMAT + " (gst pts %" GST_TIME_FORMAT ")", frame, + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (hw_pts), + GST_TIME_ARGS (pts)); break; case bmdOutputFrameDropped: - GST_WARNING_OBJECT (output_, "Dropped Frame %p", frame); + GST_WARNING_OBJECT (output_, "Frame %p dropped, scheduled %" + GST_TIME_FORMAT, frame, GST_TIME_ARGS (pts)); break; case bmdOutputFrameFlushed: GST_LOG_OBJECT (output_, "Flushed Frame %p", frame); @@ -927,607 +1266,387 @@ gst_decklink2_output_get_reference_clock (GstDeckLink2Output * self, case GST_DECKLINK2_API_LEVEL_LATEST: hr = self->output->GetHardwareReferenceClock (scale, hw_time, time_in_frame, ticks_per_frame); - break; - default: - g_assert_not_reached (); - break; - } - - return hr; -} - -static HRESULT -gst_decklink2_output_start (GstDeckLink2Output * self, - BMDTimeValue start_time, BMDTimeScale scale, double speed) -{ - HRESULT hr = E_FAIL; - - switch (self->api_level) { - case GST_DECKLINK2_API_LEVEL_10_11: - hr = self->output_10_11->StartScheduledPlayback (start_time, - scale, speed); - break; - case GST_DECKLINK2_API_LEVEL_11_4: - hr = self->output_11_4->StartScheduledPlayback (start_time, scale, speed); - break; - case GST_DECKLINK2_API_LEVEL_11_5_1: - case GST_DECKLINK2_API_LEVEL_LATEST: - hr = self->output->StartScheduledPlayback (start_time, scale, speed); - break; - default: - g_assert_not_reached (); - break; - } - - return hr; -} - -static HRESULT -gst_decklink2_get_current_level (GstDeckLink2Output * self, - guint * buffered_video, GstClockTime * video_running_time, - guint * buffered_audio, GstClockTime * audio_running_time, - GstClockTimeDiff * av_diff, GstClockTime * hw_time) -{ - BMDTimeValue hw_now, dummy, dummy2; - HRESULT hr = S_OK; - - *buffered_video = 0; - *buffered_audio = 0; - *video_running_time = self->pts; - *audio_running_time = GST_CLOCK_TIME_NONE; - *av_diff = GST_CLOCK_STIME_NONE; - *hw_time = GST_CLOCK_TIME_NONE; - - hr = gst_decklink2_output_get_num_buffered (self, buffered_video); - if (!gst_decklink2_result (hr)) - return hr; - - if (self->n_samples > 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { - hr = gst_decklink2_output_get_num_buffered_audio (self, buffered_audio); - if (!gst_decklink2_result (hr)) - return hr; - - *audio_running_time = gst_util_uint64_scale (self->n_samples, GST_SECOND, - self->audio_info.rate); - *av_diff = GST_CLOCK_DIFF (self->pts, *audio_running_time); - } - - if (self->prerolled) { - hr = gst_decklink2_output_get_reference_clock (self, GST_SECOND, &hw_now, - &dummy, &dummy2); - if (!gst_decklink2_result (hr)) - return hr; - - if (self->hw_time == GST_CLOCK_TIME_NONE) - self->hw_time = hw_now; - *hw_time = hw_now - self->hw_time; - } - - return S_OK; -} - -static HRESULT -gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, - IDeckLinkVideoFrame * frame) -{ - GstDeckLink2OutputPrivate *priv = self->priv; - GstClockTime next_pts, dur; - HRESULT hr = E_FAIL; - guint num_samples; - guint num_written; - guint8 *audio_buf; - guint buffered_video = 0; - guint buffered_audio = 0; - GstClockTime video_running_time = GST_CLOCK_TIME_NONE; - GstClockTime audio_running_time = GST_CLOCK_TIME_NONE; - GstClockTime hw_time_gst = GST_CLOCK_TIME_NONE; - GstClockTimeDiff diff = GST_CLOCK_STIME_NONE; - - frame->AddRef (); - GST_DECKLINK2_CLEAR_COM (self->last_frame); - self->last_frame = frame; - - self->n_frames++; - next_pts = gst_util_uint64_scale (self->n_frames, - self->selected_mode.fps_d * GST_SECOND, self->selected_mode.fps_n); - dur = next_pts - self->pts; - - switch (self->api_level) { - case GST_DECKLINK2_API_LEVEL_10_11: - hr = self->output_10_11->ScheduleVideoFrame (frame, - self->pts, dur, GST_SECOND); - break; - case GST_DECKLINK2_API_LEVEL_11_4: - hr = self->output_11_4->ScheduleVideoFrame (frame, - self->pts, dur, GST_SECOND); - break; - case GST_DECKLINK2_API_LEVEL_11_5_1: - case GST_DECKLINK2_API_LEVEL_LATEST: - hr = self->output->ScheduleVideoFrame (frame, self->pts, dur, GST_SECOND); - break; - default: - g_assert_not_reached (); - break; - } - - self->pts = next_pts; - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't schedule video frame, hr: 0x%x", - (guint) hr); - return hr; - } - - audio_buf = priv->audio_buf.GetSamples (num_samples); - self->n_samples += num_samples; - - if (!self->prerolled) { - if (self->n_prerolled == 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { - GST_DEBUG_OBJECT (self, "Begin audio preroll"); - - hr = gst_decklink2_output_begin_audio_preroll (self); - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't start audio preroll, hr: 0x%x", - (guint) hr); - return hr; - } - } - - if (audio_buf && num_samples > 0) { - while (num_samples > 0) { - num_written = 0; - hr = gst_decklink2_output_schedule_audio_samples (self, - audio_buf, num_samples, 0, 0, &num_written); - - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", - (guint) hr); - return hr; - } - - num_samples -= num_written; - audio_buf += num_written * self->audio_info.bpf; - } - - priv->audio_buf.Flush (); - } - - self->n_prerolled++; - if (self->n_prerolled >= self->n_preroll_frames) { - if (GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { - hr = gst_decklink2_output_end_audio_preroll (self); - - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Audio preroll failed, hr: 0x%x", (guint) hr); - return hr; - } - } - - hr = gst_decklink2_output_start (self, 0, GST_SECOND, 1.0); - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't start playback, hr: 0x%x", - (guint) hr); - return hr; - } - - GST_DEBUG_OBJECT (self, "Prerolled, start playback"); - - self->prerolled = TRUE; - } - } else if (audio_buf && num_samples > 0) { - while (num_samples > 0) { - num_written = 0; - hr = gst_decklink2_output_schedule_audio_samples (self, - audio_buf, num_samples, 0, 0, &num_written); - - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", - (guint) hr); - return hr; - } - - num_samples -= num_written; - audio_buf += num_written * self->audio_info.bpf; - } - - priv->audio_buf.Flush (); - } - - hr = gst_decklink2_get_current_level (self, &buffered_video, - &video_running_time, &buffered_audio, &audio_running_time, &diff, - &hw_time_gst); - if (gst_decklink2_result (hr)) { - GST_LOG_OBJECT (self, "After schedule, video %" GST_TIME_FORMAT - " (%" G_GUINT64_FORMAT ", buffered %u) audio %" GST_TIME_FORMAT - " (%" G_GUINT64_FORMAT ", buffered %u), av-diff: %" GST_STIME_FORMAT - ", hw-time %" GST_TIME_FORMAT, - GST_TIME_ARGS (self->pts), self->n_frames, buffered_video, - GST_TIME_ARGS (audio_running_time), self->n_samples, buffered_audio, - GST_STIME_ARGS (diff), GST_TIME_ARGS (hw_time_gst)); - } - - return S_OK; -} - -HRESULT -gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, - IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size, - guint64 * drop_count, guint64 * late_count, guint64 * underrun_count) -{ - GstDeckLink2OutputPrivate *priv = output->priv; - HRESULT hr; - std::unique_lock < std::mutex > lk (priv->extern_lock); - dlbool_t active; - - g_assert (output->configured); - - *drop_count = 0; - *late_count = 0; - *underrun_count = 0; - - hr = gst_decklink2_output_is_running (output, &active); - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (output, "Couldn't query active state, hr: 0x%x", - (guint) hr); - return hr; - } - - if (active) { - guint32 count = 0; - hr = gst_decklink2_output_get_num_buffered (output, &count); - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (output, - "Couldn't query bufferred frame count, hr: 0x%x", (guint) hr); - return hr; - } - - if (count > output->max_buffered) { - GST_WARNING_OBJECT (output, "Skipping frame, buffered count %u > %u", - count, output->max_buffered); - std::lock_guard < std::mutex > slk (priv->schedule_lock); - - /* audio and video may not be completely aligned. Add this sample - * and drop video frame duration amount of audio samples */ - priv->audio_buf.Append (audio_buf, audio_buf_size); - priv->audio_buf.Drop (); - - return S_OK; - } + break; + default: + g_assert_not_reached (); + break; } - lk.unlock (); - - std::lock_guard < std::mutex > slk (priv->schedule_lock); - priv->audio_buf.Append (audio_buf, audio_buf_size); - - hr = gst_decklink2_output_schedule_video_internal (output, frame); - *drop_count = output->drop_count; - *late_count = output->late_count; - *underrun_count = output->underrun_count; return hr; } static HRESULT -gst_decklink2_output_stop_internal (GstDeckLink2Output * self) +gst_decklink2_output_get_completion_timestamp (GstDeckLink2Output * self, + IDeckLinkVideoFrame * frame, BMDTimeScale scale, BMDTimeValue * timestamp) { - GstDeckLink2OutputPrivate *priv = self->priv; HRESULT hr = E_FAIL; - GST_DEBUG_OBJECT (self, "Stopping"); - - std::unique_lock < std::mutex > lk (priv->schedule_lock); - /* Steal last frame to avoid re-rendering */ - GST_DECKLINK2_CLEAR_COM (self->last_frame); - lk.unlock (); - switch (self->api_level) { case GST_DECKLINK2_API_LEVEL_10_11: - hr = self->output_10_11->StopScheduledPlayback (0, NULL, 0); + hr = self->output_10_11->GetFrameCompletionReferenceTimestamp (frame, + scale, timestamp); break; case GST_DECKLINK2_API_LEVEL_11_4: - hr = self->output_11_4->StopScheduledPlayback (0, NULL, 0); + hr = self->output_11_4->GetFrameCompletionReferenceTimestamp (frame, + scale, timestamp); break; case GST_DECKLINK2_API_LEVEL_11_5_1: case GST_DECKLINK2_API_LEVEL_LATEST: - hr = self->output->StopScheduledPlayback (0, NULL, 0); + hr = self->output->GetFrameCompletionReferenceTimestamp (frame, + scale, timestamp); break; default: g_assert_not_reached (); break; } - GST_DEBUG_OBJECT (self, "StopScheduledPlayback result 0x%x", (guint) hr); - - gst_decklink2_output_disable_audio (self); - gst_decklink2_output_disable_video (self); - gst_decklink2_output_set_video_callback (self, NULL); - self->configured = FALSE; - self->prerolled = FALSE; - self->late_count = 0; - self->drop_count = 0; - self->underrun_count = 0; - return hr; } -HRESULT -gst_decklink2_output_stop (GstDeckLink2Output * output) +static HRESULT +gst_decklink2_output_start (GstDeckLink2Output * self, + BMDTimeValue start_time, BMDTimeScale scale, double speed) { - GstDeckLink2OutputPrivate *priv = output->priv; - std::lock_guard < std::mutex > lk (priv->extern_lock); + HRESULT hr = E_FAIL; - return gst_decklink2_output_stop_internal (output); + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->StartScheduledPlayback (start_time, + scale, speed); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->StartScheduledPlayback (start_time, scale, speed); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->StartScheduledPlayback (start_time, scale, speed); + break; + default: + g_assert_not_reached (); + break; + } + + return hr; } -class IGstDeckLinkTimecode:public IDeckLinkTimecode +static HRESULT +gst_decklink2_get_current_level (GstDeckLink2Output * self, + guint * buffered_video, GstClockTime * video_running_time, + guint * buffered_audio, GstClockTime * audio_running_time, + GstClockTimeDiff * av_diff, GstClockTime * hw_time, + GstClockTime * hw_now_gst) { -public: - IGstDeckLinkTimecode (GstVideoTimeCode * timecode):ref_count_ (1) - { - g_assert (timecode); - - timecode_ = gst_video_time_code_copy (timecode); - } - - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) - { - if (riid == IID_IDeckLinkTimecode) { - *object = static_cast < IDeckLinkTimecode * >(this); - } else { - *object = NULL; - return E_NOINTERFACE; - } + BMDTimeValue hw_now, dummy, dummy2; + HRESULT hr = S_OK; - AddRef (); + *buffered_video = 0; + *buffered_audio = 0; + *video_running_time = self->pts; + *audio_running_time = GST_CLOCK_TIME_NONE; + *av_diff = GST_CLOCK_STIME_NONE; + *hw_time = GST_CLOCK_TIME_NONE; - return S_OK; - } + hr = gst_decklink2_output_get_num_buffered (self, buffered_video); + if (!gst_decklink2_result (hr)) + return hr; - ULONG STDMETHODCALLTYPE AddRef (void) - { - ULONG cnt = ref_count_.fetch_add (1); + if (self->n_samples > 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { + hr = gst_decklink2_output_get_num_buffered_audio (self, buffered_audio); + if (!gst_decklink2_result (hr)) + return hr; - return cnt + 1; + *audio_running_time = gst_util_uint64_scale (self->n_samples, GST_SECOND, + self->audio_info.rate); + *av_diff = GST_CLOCK_DIFF (self->pts, *audio_running_time); } - ULONG STDMETHODCALLTYPE Release (void) - { - ULONG cnt = ref_count_.fetch_sub (1); - if (cnt == 1) - delete this; + if (self->prerolled) { + hr = gst_decklink2_output_get_reference_clock (self, GST_SECOND, &hw_now, + &dummy, &dummy2); + if (!gst_decklink2_result (hr)) + return hr; - return cnt - 1; + if (self->hw_time == GST_CLOCK_TIME_NONE) + self->hw_time = hw_now; + *hw_time = hw_now - self->hw_time; } - /* IDeckLinkTimecode */ - BMDTimecodeBCD STDMETHODCALLTYPE GetBCD (void) - { - BMDTimecodeBCD bcd = 0; + if (hw_now_gst) + *hw_now_gst = (GstClockTime) hw_now; - bcd |= (timecode_->frames % 10) << 0; - bcd |= ((timecode_->frames / 10) & 0x0f) << 4; - bcd |= (timecode_->seconds % 10) << 8; - bcd |= ((timecode_->seconds / 10) & 0x0f) << 12; - bcd |= (timecode_->minutes % 10) << 16; - bcd |= ((timecode_->minutes / 10) & 0x0f) << 20; - bcd |= (timecode_->hours % 10) << 24; - bcd |= ((timecode_->hours / 10) & 0x0f) << 28; + return S_OK; +} - if (timecode_->config.fps_n == 24 && timecode_->config.fps_d == 1) - bcd |= 0x0 << 30; - else if (timecode_->config.fps_n == 25 && timecode_->config.fps_d == 1) - bcd |= 0x1 << 30; - else if (timecode_->config.fps_n == 30 && timecode_->config.fps_d == 1001) - bcd |= 0x2 << 30; - else if (timecode_->config.fps_n == 30 && timecode_->config.fps_d == 1) - bcd |= 0x3 << 30; +static HRESULT +gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, + IGstDeckLinkVideoFrame * frame) +{ + GstDeckLink2OutputPrivate *priv = self->priv; + GstClockTime next_pts, dur; + HRESULT hr = E_FAIL; + guint num_samples; + guint num_written; + guint8 *audio_buf; + guint buffered_video = 0; + guint buffered_audio = 0; + GstClockTime video_running_time = GST_CLOCK_TIME_NONE; + GstClockTime audio_running_time = GST_CLOCK_TIME_NONE; + GstClockTime hw_time_gst = GST_CLOCK_TIME_NONE; + GstClockTime hw_now_gst = GST_CLOCK_TIME_NONE; + GstClockTimeDiff diff = GST_CLOCK_STIME_NONE; - return bcd; + hr = gst_decklink2_get_current_level (self, &buffered_video, + &video_running_time, &buffered_audio, &audio_running_time, &diff, + &hw_time_gst, &hw_now_gst); + if (gst_decklink2_result (hr)) { + GST_LOG_OBJECT (self, "Before schedule, video %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u) audio %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u), av-diff: %" GST_STIME_FORMAT + ", hw-time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->pts), self->n_frames, buffered_video, + GST_TIME_ARGS (audio_running_time), self->n_samples, buffered_audio, + GST_STIME_ARGS (diff), GST_TIME_ARGS (hw_time_gst)); } - HRESULT STDMETHODCALLTYPE - GetComponents (unsigned char *hours, unsigned char *minutes, - unsigned char *seconds, unsigned char *frames) - { - *hours = timecode_->hours; - *minutes = timecode_->minutes; - *seconds = timecode_->seconds; - *frames = timecode_->frames; + frame->AddRef (); + GST_DECKLINK2_CLEAR_COM (self->last_frame); + self->last_frame = frame; - return S_OK; - } + frame->SetScheduledPts (self->pts); + frame->SetScheduledHwTime (hw_now_gst); - HRESULT STDMETHODCALLTYPE GetString (dlstring_t * timecode) - { - gchar *s = gst_video_time_code_to_string (timecode_); - *timecode = StdToDlString (s); - g_free (s); + self->n_frames++; + next_pts = gst_util_uint64_scale (self->n_frames, + self->selected_mode.fps_d * GST_SECOND, self->selected_mode.fps_n); + dur = next_pts - self->pts; - return S_OK; + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->ScheduleVideoFrame (frame, + self->pts, dur, GST_SECOND); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->ScheduleVideoFrame (frame, + self->pts, dur, GST_SECOND); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->ScheduleVideoFrame (frame, self->pts, dur, GST_SECOND); + break; + default: + g_assert_not_reached (); + break; } - BMDTimecodeFlags STDMETHODCALLTYPE GetFlags (void) - { - BMDTimecodeFlags flags = (BMDTimecodeFlags) 0; - - if ((timecode_->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) != 0) - flags = (BMDTimecodeFlags) (flags | bmdTimecodeIsDropFrame); - else - flags = (BMDTimecodeFlags) (flags | bmdTimecodeFlagDefault); + self->pts = next_pts; + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule video frame, hr: 0x%x", + (guint) hr); + return hr; + } - if (timecode_->field_count == 2) - flags = (BMDTimecodeFlags) (flags | bmdTimecodeFieldMark); + audio_buf = priv->audio_buf.GetSamples (num_samples); + self->n_samples += num_samples; - return flags; - } + if (!self->prerolled) { + if (self->n_prerolled == 0 && GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { + GST_DEBUG_OBJECT (self, "Begin audio preroll"); - HRESULT STDMETHODCALLTYPE GetTimecodeUserBits (BMDTimecodeUserBits * userBits) - { - *userBits = 0; - return S_OK; - } + hr = gst_decklink2_output_begin_audio_preroll (self); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't start audio preroll, hr: 0x%x", + (guint) hr); + return hr; + } + } -private: - virtual ~ IGstDeckLinkTimecode () { - gst_video_time_code_free (timecode_); - } + if (audio_buf && num_samples > 0) { + while (num_samples > 0) { + num_written = 0; + hr = gst_decklink2_output_schedule_audio_samples (self, + audio_buf, num_samples, 0, 0, &num_written); -private: - GstVideoTimeCode * timecode_; - std::atomic < ULONG > ref_count_; -}; + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", + (guint) hr); + return hr; + } -class IGstDeckLinkVideoFrame:public IDeckLinkVideoFrame -{ -public: - IGstDeckLinkVideoFrame (GstVideoFrame * frame):ref_count_ (1) - { - frame_ = *frame; - } + num_samples -= num_written; + audio_buf += num_written * self->audio_info.bpf; + } - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) - { - if (riid == IID_IDeckLinkVideoOutputCallback) { - *object = static_cast < IDeckLinkVideoFrame * >(this); - } else { - *object = NULL; - return E_NOINTERFACE; + priv->audio_buf.Flush (); } - AddRef (); + self->n_prerolled++; + if (self->n_prerolled >= self->n_preroll_frames) { + if (GST_AUDIO_INFO_IS_VALID (&self->audio_info)) { + hr = gst_decklink2_output_end_audio_preroll (self); - return S_OK; - } + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Audio preroll failed, hr: 0x%x", (guint) hr); + return hr; + } + } - ULONG STDMETHODCALLTYPE AddRef (void) - { - ULONG cnt = ref_count_.fetch_add (1); + hr = gst_decklink2_output_start (self, 0, GST_SECOND, 1.0); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't start playback, hr: 0x%x", + (guint) hr); + return hr; + } - return cnt + 1; - } + GST_DEBUG_OBJECT (self, "Prerolled, start playback"); - ULONG STDMETHODCALLTYPE Release (void) - { - ULONG cnt = ref_count_.fetch_sub (1); - if (cnt == 1) - delete this; + self->prerolled = TRUE; + } + } else if (audio_buf && num_samples > 0) { + while (num_samples > 0) { + num_written = 0; + hr = gst_decklink2_output_schedule_audio_samples (self, + audio_buf, num_samples, 0, 0, &num_written); - return cnt - 1; - } + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", + (guint) hr); + return hr; + } - /* IDeckLinkVideoFrame */ - long STDMETHODCALLTYPE GetWidth (void) - { - return GST_VIDEO_FRAME_WIDTH (&frame_); - } + num_samples -= num_written; + audio_buf += num_written * self->audio_info.bpf; + } - long STDMETHODCALLTYPE GetHeight (void) - { - return GST_VIDEO_FRAME_HEIGHT (&frame_); + priv->audio_buf.Flush (); } - long STDMETHODCALLTYPE GetRowBytes (void) - { - return GST_VIDEO_FRAME_PLANE_STRIDE (&frame_, 0); - } + return S_OK; +} - BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat (void) - { - BMDPixelFormat format = bmdFormatUnspecified; - switch (GST_VIDEO_FRAME_FORMAT (&frame_)) { - case GST_VIDEO_FORMAT_UYVY: - format = bmdFormat8BitYUV; - break; - case GST_VIDEO_FORMAT_v210: - format = bmdFormat10BitYUV; - break; - case GST_VIDEO_FORMAT_ARGB: - format = bmdFormat8BitARGB; - break; - case GST_VIDEO_FORMAT_BGRA: - format = bmdFormat8BitBGRA; - break; - default: - g_assert_not_reached (); - break; - } +HRESULT +gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, + IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size, + guint64 * drop_count, guint64 * late_count, guint64 * underrun_count) +{ + GstDeckLink2OutputPrivate *priv = output->priv; + HRESULT hr; + std::unique_lock < std::mutex > lk (priv->extern_lock); + dlbool_t active; - return format; - } + g_assert (output->configured); - BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) - { - return bmdFrameFlagDefault; + *drop_count = 0; + *late_count = 0; + *underrun_count = 0; + + hr = gst_decklink2_output_is_running (output, &active); + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (output, "Couldn't query active state, hr: 0x%x", + (guint) hr); + return hr; } - HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) - { - *buffer = GST_VIDEO_FRAME_PLANE_DATA (&frame_, 0); + if (active) { + std::lock_guard < std::recursive_mutex > slk (priv->schedule_lock); + guint buffered_video = 0; + guint buffered_audio = 0; + GstClockTime video_running_time = GST_CLOCK_TIME_NONE; + GstClockTime audio_running_time = GST_CLOCK_TIME_NONE; + GstClockTime hw_time_gst = GST_CLOCK_TIME_NONE; + GstClockTimeDiff diff = GST_CLOCK_STIME_NONE; - return S_OK; - } + hr = gst_decklink2_get_current_level (output, &buffered_video, + &video_running_time, &buffered_audio, &audio_running_time, &diff, + &hw_time_gst, NULL); - HRESULT STDMETHODCALLTYPE - GetTimecode (BMDTimecodeFormat format, IDeckLinkTimecode ** timecode) - { - if (timecode_) { - *timecode = timecode_; - timecode_->AddRef (); - return S_OK; + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (output, + "Couldn't query bufferred frame count, hr: 0x%x", (guint) hr); + return hr; } - return S_FALSE; - } + if (buffered_video > output->max_buffered) { + GST_WARNING_OBJECT (output, "Skipping frame, video %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u) audio %" GST_TIME_FORMAT + " (%" G_GUINT64_FORMAT ", buffered %u), av-diff: %" GST_STIME_FORMAT + ", hw-time %" GST_TIME_FORMAT, + GST_TIME_ARGS (output->pts), output->n_frames, buffered_video, + GST_TIME_ARGS (audio_running_time), output->n_samples, buffered_audio, + GST_STIME_ARGS (diff), GST_TIME_ARGS (hw_time_gst)); + + /* audio and video may not be completely aligned. Add this sample + * and drop video frame duration amount of audio samples */ + priv->audio_buf.Append (audio_buf, audio_buf_size); + priv->audio_buf.Drop (); - HRESULT STDMETHODCALLTYPE - GetAncillaryData (IDeckLinkVideoFrameAncillary ** ancillary) - { - if (ancillary_) { - *ancillary = ancillary_; - ancillary_->AddRef (); return S_OK; } - - return S_FALSE; } + lk.unlock (); - /* Non-interface methods */ - HRESULT STDMETHODCALLTYPE SetTimecode (GstVideoTimeCode * timecode) - { - GST_DECKLINK2_CLEAR_COM (timecode_); + std::lock_guard < std::recursive_mutex > slk (priv->schedule_lock); + priv->audio_buf.Append (audio_buf, audio_buf_size); - if (timecode) - timecode_ = new IGstDeckLinkTimecode (timecode); + hr = gst_decklink2_output_schedule_video_internal (output, + (IGstDeckLinkVideoFrame *) frame); + *drop_count = output->drop_count; + *late_count = output->late_count; + *underrun_count = output->underrun_count; - return S_OK; - } + return hr; +} - HRESULT STDMETHODCALLTYPE - SetAncillaryData (IDeckLinkVideoFrameAncillary * ancillary) - { - GST_DECKLINK2_CLEAR_COM (ancillary_); +static HRESULT +gst_decklink2_output_stop_internal (GstDeckLink2Output * self) +{ + GstDeckLink2OutputPrivate *priv = self->priv; + HRESULT hr = E_FAIL; - ancillary_ = ancillary; - if (ancillary_) - ancillary_->AddRef (); + GST_DEBUG_OBJECT (self, "Stopping"); - return S_OK; - } + std::unique_lock < std::recursive_mutex > lk (priv->schedule_lock); + /* Steal last frame to avoid re-rendering */ + GST_DECKLINK2_CLEAR_COM (self->last_frame); + lk.unlock (); -private: - virtual ~ IGstDeckLinkVideoFrame () { - gst_video_frame_unmap (&frame_); - GST_DECKLINK2_CLEAR_COM (timecode_); - GST_DECKLINK2_CLEAR_COM (ancillary_); + switch (self->api_level) { + case GST_DECKLINK2_API_LEVEL_10_11: + hr = self->output_10_11->StopScheduledPlayback (0, NULL, 0); + break; + case GST_DECKLINK2_API_LEVEL_11_4: + hr = self->output_11_4->StopScheduledPlayback (0, NULL, 0); + break; + case GST_DECKLINK2_API_LEVEL_11_5_1: + case GST_DECKLINK2_API_LEVEL_LATEST: + hr = self->output->StopScheduledPlayback (0, NULL, 0); + break; + default: + g_assert_not_reached (); + break; } -private: - std::atomic < ULONG > ref_count_; - GstVideoFrame frame_; - IDeckLinkTimecode *timecode_ = NULL; - IDeckLinkVideoFrameAncillary *ancillary_ = NULL; -}; + GST_DEBUG_OBJECT (self, "StopScheduledPlayback result 0x%x", (guint) hr); + + gst_decklink2_output_disable_audio (self); + gst_decklink2_output_disable_video (self); + gst_decklink2_output_set_video_callback (self, NULL); + self->configured = FALSE; + self->prerolled = FALSE; + self->late_count = 0; + self->drop_count = 0; + self->underrun_count = 0; + + return hr; +} + +HRESULT +gst_decklink2_output_stop (GstDeckLink2Output * output) +{ + GstDeckLink2OutputPrivate *priv = output->priv; + std::lock_guard < std::mutex > lk (priv->extern_lock); + + return gst_decklink2_output_stop_internal (output); +} /* Copied from ext/closedcaption/gstccconverter.c */ /* Converts raw CEA708 cc_data and an optional timecode into CDP */ @@ -2090,6 +2209,12 @@ gst_decklink2_output_configure (GstDeckLink2Output * output, output->drop_count = 0; output->late_count = 0; output->underrun_count = 0; + output->gap_frames = 1; + if (max_buffered > min_buffered) { + guint gap = (max_buffered - min_buffered) / 2; + output->gap_frames = MAX (2, gap); + } + output->duplicating = FALSE; return S_OK; @@ -2113,7 +2238,7 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self, GstDeckLink2OutputPrivate *priv = self->priv; dlbool_t active; - std::lock_guard < std::mutex > lk (priv->schedule_lock); + std::lock_guard < std::recursive_mutex > lk (priv->schedule_lock); if (result == bmdOutputFrameDisplayedLate) self->late_count++; else if (result == bmdOutputFrameDropped) @@ -2129,11 +2254,12 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self, GstClockTime video_running_time = GST_CLOCK_TIME_NONE; GstClockTime audio_running_time = GST_CLOCK_TIME_NONE; GstClockTime hw_time_gst = GST_CLOCK_TIME_NONE; + GstClockTime dummy; GstClockTimeDiff diff = GST_CLOCK_STIME_NONE; hr = gst_decklink2_get_current_level (self, &buffered_video, &video_running_time, &buffered_audio, &audio_running_time, &diff, - &hw_time_gst); + &hw_time_gst, &dummy); if (gst_decklink2_result (hr) && buffered_video <= self->min_buffered) { GST_WARNING_OBJECT (self, "Underrun, video %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT ", buffered %u) audio %" GST_TIME_FORMAT @@ -2143,8 +2269,22 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self, GST_TIME_ARGS (audio_running_time), self->n_samples, buffered_audio, GST_STIME_ARGS (diff), GST_TIME_ARGS (hw_time_gst)); self->underrun_count++; - priv->audio_buf.PrependSilence (); - gst_decklink2_output_schedule_video_internal (self, self->last_frame); + if (self->duplicating) + return; + + self->duplicating = TRUE; + for (guint i = 0; i < self->gap_frames; i++) { + IGstDeckLinkVideoFrame *copy = self->last_frame->Clone (); + if (!copy) { + GST_ERROR_OBJECT (self, "Couldn't clone last frame"); + copy = self->last_frame; + self->last_frame->AddRef (); + } + priv->audio_buf.PrependSilence (); + gst_decklink2_output_schedule_video_internal (self, copy); + copy->Release (); + } + self->duplicating = FALSE; } } } From 0e92f082a9e32385b073d368b3ad54d86fa3acfd Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 28 Jul 2023 02:25:55 +0900 Subject: [PATCH 34/82] decklink2output: Calculate audio sample timestamp Calculate audio sample timestamp in samplerate unit (i.e., total number of audio samples) and pass it to driver, instead of zero timestamp/scale --- .../sys/decklink2/gstdecklink2output.cpp | 76 ++++++++++++------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index 480121b334..c1b19737ff 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -365,6 +365,7 @@ class GstDecklink2OutputAudioBuffer video_frame_dup_drop_count_ = 0; dup_drop_sample_offset_end_ = 0; samples_to_drop_ = 0; + pos_ = 0; fps_n_ = fps_n; fps_d_ = fps_d; init_done_ = true; @@ -472,7 +473,7 @@ class GstDecklink2OutputAudioBuffer silence_length_in_bytes); } - guint8 *GetSamples (guint & num_samples) + guint8 *GetSamples (guint & num_samples, guint64 & sample_pos) { if (!init_done_) { num_samples = 0; @@ -480,12 +481,35 @@ class GstDecklink2OutputAudioBuffer } num_samples = buffer_.size () / info_.bpf; + sample_pos = pos_; return &buffer_[0]; } - void Flush () + void Flush (guint samples) { - buffer_.resize (0); + if (samples == 0 || buffer_.empty ()) + return; + + size_t cur_size = buffer_.size (); + size_t cur_samples = cur_size / info_.bpf; + size_t flush_size; + guint64 flush_samples; + bool clear_all = false; + + if (cur_samples <= samples) { + flush_size = cur_size; + flush_samples = cur_samples; + clear_all = true; + } else { + flush_size = samples * info_.bpf; + flush_samples = samples; + } + + pos_ += flush_samples; + if (clear_all) + buffer_.resize (0); + else + buffer_.erase (buffer_.begin (), buffer_.begin () + flush_size); } private: @@ -493,6 +517,7 @@ class GstDecklink2OutputAudioBuffer guint64 video_frame_dup_drop_count_ = 0; guint64 dup_drop_sample_offset_end_ = 0; guint64 samples_to_drop_ = 0; + guint64 pos_ = 0; GstAudioInfo info_; gint fps_n_; gint fps_d_; @@ -1383,6 +1408,7 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, { GstDeckLink2OutputPrivate *priv = self->priv; GstClockTime next_pts, dur; + guint64 audio_pos; HRESULT hr = E_FAIL; guint num_samples; guint num_written; @@ -1445,7 +1471,7 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, return hr; } - audio_buf = priv->audio_buf.GetSamples (num_samples); + audio_buf = priv->audio_buf.GetSamples (num_samples, audio_pos); self->n_samples += num_samples; if (!self->prerolled) { @@ -1460,24 +1486,21 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, } } - if (audio_buf && num_samples > 0) { - while (num_samples > 0) { - num_written = 0; - hr = gst_decklink2_output_schedule_audio_samples (self, - audio_buf, num_samples, 0, 0, &num_written); - - if (!gst_decklink2_result (hr)) { - GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", - (guint) hr); - return hr; - } + while (audio_buf && num_samples > 0) { + num_written = 0; + hr = gst_decklink2_output_schedule_audio_samples (self, + audio_buf, num_samples, audio_pos, self->audio_info.rate, + &num_written); - num_samples -= num_written; - audio_buf += num_written * self->audio_info.bpf; + if (!gst_decklink2_result (hr)) { + GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", + (guint) hr); + return hr; } - priv->audio_buf.Flush (); - } + priv->audio_buf.Flush (num_written); + audio_buf = priv->audio_buf.GetSamples (num_samples, audio_pos); + }; self->n_prerolled++; if (self->n_prerolled >= self->n_preroll_frames) { @@ -1501,11 +1524,12 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, self->prerolled = TRUE; } - } else if (audio_buf && num_samples > 0) { - while (num_samples > 0) { + } else { + while (audio_buf && num_samples > 0) { num_written = 0; hr = gst_decklink2_output_schedule_audio_samples (self, - audio_buf, num_samples, 0, 0, &num_written); + audio_buf, num_samples, audio_pos, self->audio_info.rate, + &num_written); if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (self, "Couldn't schedule audio sample, hr: 0x%x", @@ -1513,11 +1537,9 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, return hr; } - num_samples -= num_written; - audio_buf += num_written * self->audio_info.bpf; - } - - priv->audio_buf.Flush (); + priv->audio_buf.Flush (num_written); + audio_buf = priv->audio_buf.GetSamples (num_samples, audio_pos); + }; } return S_OK; From 2db49184bc6e383b9bd1a2dc20d8cf861fe4eaf6 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 28 Jul 2023 21:42:23 +0900 Subject: [PATCH 35/82] decklink2sink: Add output-stats property --- .../sys/decklink2/gstdecklink2output.cpp | 64 +++++++++++++------ .../sys/decklink2/gstdecklink2output.h | 22 ++++++- .../sys/decklink2/gstdecklink2sink.cpp | 50 +++++++++++++-- 3 files changed, 109 insertions(+), 27 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index c1b19737ff..f205fd23ab 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -381,10 +381,10 @@ class GstDecklink2OutputAudioBuffer init_done_ = false; } - void Append (const guint8 * data, size_t size) + guint64 Append (const guint8 * data, size_t size) { if (!data || size == 0 || !init_done_) - return; + return 0; size_t cur_size = buffer_.size (); size_t num_samples = size / info_.bpf; @@ -402,24 +402,26 @@ class GstDecklink2OutputAudioBuffer size_t bytes_to_drop = samples_to_drop_ * info_.bpf; samples_to_drop_ = 0; if (actual_append_samples == 0) - return; + return num_samples; data += bytes_to_drop; size -= bytes_to_drop; } else { samples_to_drop_ -= num_samples; - return; + return num_samples; } } buffer_.resize (cur_size + size); memcpy (&buffer_[0] + cur_size, data, size); + + return num_samples; } - void Drop () + guint64 Drop () { if (!init_done_) - return; + return 0; video_frame_dup_drop_count_++; guint64 next_sample_offset = @@ -444,12 +446,14 @@ class GstDecklink2OutputAudioBuffer samples_to_drop_ -= samples_in_buffer; buffer_.clear (); } + + return num_samples; } - void PrependSilence () + guint64 PrependSilence () { if (!init_done_) - return; + return 0; video_frame_dup_drop_count_++; guint64 next_sample_offset = @@ -471,6 +475,8 @@ class GstDecklink2OutputAudioBuffer gst_audio_format_info_fill_silence (info_.finfo, &buffer_[0], silence_length_in_bytes); + + return num_samples; } guint8 *GetSamples (guint & num_samples, guint64 & sample_pos) @@ -581,6 +587,10 @@ struct _GstDeckLink2Output guint64 late_count; guint64 drop_count; guint64 underrun_count; + guint64 overrun_count; + guint64 duplicate_count; + guint64 dropped_sample_count; + guint64 silent_sample_count; }; static void gst_decklink2_output_dispose (GObject * object); @@ -1548,7 +1558,7 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, HRESULT gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size, - guint64 * drop_count, guint64 * late_count, guint64 * underrun_count) + GstDecklink2OutputStats *stats) { GstDeckLink2OutputPrivate *priv = output->priv; HRESULT hr; @@ -1557,10 +1567,6 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, g_assert (output->configured); - *drop_count = 0; - *late_count = 0; - *underrun_count = 0; - hr = gst_decklink2_output_is_running (output, &active); if (!gst_decklink2_result (hr)) { GST_ERROR_OBJECT (output, "Couldn't query active state, hr: 0x%x", @@ -1587,6 +1593,21 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, return hr; } + stats->buffered_video = buffered_video; + stats->buffered_audio = buffered_audio; + stats->video_running_time = video_running_time; + stats->audio_running_time = audio_running_time; + stats->hw_time = hw_time_gst; + stats->scheduled_video_frames = output->n_frames; + stats->scheduled_audio_samples = output->n_samples; + stats->late_count = output->late_count; + stats->drop_count = output->drop_count; + stats->overrun_count = output->overrun_count; + stats->underrun_count = output->underrun_count; + stats->duplicate_count = output->duplicate_count; + stats->silent_sample_count = output->silent_sample_count; + stats->dropped_sample_count = output->dropped_sample_count; + if (buffered_video > output->max_buffered) { GST_WARNING_OBJECT (output, "Skipping frame, video %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT ", buffered %u) audio %" GST_TIME_FORMAT @@ -1599,7 +1620,8 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, /* audio and video may not be completely aligned. Add this sample * and drop video frame duration amount of audio samples */ priv->audio_buf.Append (audio_buf, audio_buf_size); - priv->audio_buf.Drop (); + output->dropped_sample_count += priv->audio_buf.Drop (); + output->overrun_count++; return S_OK; } @@ -1611,9 +1633,6 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, hr = gst_decklink2_output_schedule_video_internal (output, (IGstDeckLinkVideoFrame *) frame); - *drop_count = output->drop_count; - *late_count = output->late_count; - *underrun_count = output->underrun_count; return hr; } @@ -1657,6 +1676,10 @@ gst_decklink2_output_stop_internal (GstDeckLink2Output * self) self->late_count = 0; self->drop_count = 0; self->underrun_count = 0; + self->overrun_count = 0; + self->duplicate_count = 0; + self->dropped_sample_count = 0; + self->silent_sample_count = 0; return hr; } @@ -2231,6 +2254,10 @@ gst_decklink2_output_configure (GstDeckLink2Output * output, output->drop_count = 0; output->late_count = 0; output->underrun_count = 0; + output->overrun_count = 0; + output->duplicate_count = 0; + output->dropped_sample_count = 0; + output->silent_sample_count = 0; output->gap_frames = 1; if (max_buffered > min_buffered) { guint gap = (max_buffered - min_buffered) / 2; @@ -2302,9 +2329,10 @@ gst_decklink2_output_on_completed (GstDeckLink2Output * self, copy = self->last_frame; self->last_frame->AddRef (); } - priv->audio_buf.PrependSilence (); + self->silent_sample_count += priv->audio_buf.PrependSilence (); gst_decklink2_output_schedule_video_internal (self, copy); copy->Release (); + self->duplicate_count++; } self->duplicating = FALSE; } diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h index 8c81b9d67a..3e349f82b9 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h @@ -29,6 +29,24 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (GstDeckLink2Output, gst_decklink2_output, GST, DECKLINK2_OUTPUT, GstObject); +typedef struct +{ + guint buffered_video; + guint buffered_audio; + GstClockTime video_running_time; + GstClockTime audio_running_time; + GstClockTime hw_time; + guint64 scheduled_video_frames; + guint64 scheduled_audio_samples; + guint64 late_count; + guint64 drop_count; + guint64 overrun_count; + guint64 underrun_count; + guint64 duplicate_count; + guint64 dropped_sample_count; + guint64 silent_sample_count; +} GstDecklink2OutputStats; + GstDeckLink2Output * gst_decklink2_output_new (IDeckLink * device, GstDeckLink2APILevel api_level); @@ -66,9 +84,7 @@ HRESULT gst_decklink2_output_schedule_stream (GstDeckLink2Output IDeckLinkVideoFrame * frame, guint8 *audio_buf, gsize audio_buf_size, - guint64 * drop_count, - guint64 * late_count, - guint64 * underrun_count); + GstDecklink2OutputStats *stats); HRESULT gst_decklink2_output_stop (GstDeckLink2Output * output); diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp index fbc258184f..7e787494fe 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -49,7 +49,8 @@ enum PROP_N_PREROLL_FRAMES, PROP_MIN_BUFFERED_FRAMES, PROP_MAX_BUFFERED_FRAMES, - PROP_AUTO_RESTART + PROP_AUTO_RESTART, + PROP_OUTPUT_STATS, }; #define DEFAULT_MODE bmdModeUnknown @@ -119,6 +120,8 @@ struct _GstDeckLink2Sink guint min_buffered_frames; guint max_buffered_frames; gboolean auto_restart; + + GstDecklink2OutputStats stats; }; static void gst_decklink2_sink_set_property (GObject * object, @@ -247,6 +250,11 @@ gst_decklink2_sink_class_init (GstDeckLink2SinkClass * klass) DEFAULT_AUTO_RESTART, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + g_object_class_install_property (object_class, PROP_OUTPUT_STATS, + g_param_spec_boxed ("output-stats", "Output Statistics", + "Output Statistics", GST_TYPE_STRUCTURE, + (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + gst_decklink2_sink_signals[SIGNAL_RESTART] = g_signal_new_class_handler ("restart", G_TYPE_FROM_CLASS (klass), (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), @@ -454,6 +462,31 @@ gst_decklink2_sink_get_property (GObject * object, guint prop_id, case PROP_AUTO_RESTART: g_value_set_boolean (value, self->auto_restart); break; + case PROP_OUTPUT_STATS: + { + GstStructure *s; + GstDecklink2OutputStats *stats = &self->stats; + + s = gst_structure_new ("output-stats", + "buffered-video", G_TYPE_UINT, stats->buffered_video, + "buffered-audio", G_TYPE_UINT, stats->buffered_audio, + "video-running-time", G_TYPE_UINT64, stats->video_running_time, + "audio-running-time", G_TYPE_UINT64, stats->audio_running_time, + "hardware-time", G_TYPE_UINT64, stats->hw_time, + "scheduled-video-frames", G_TYPE_UINT64, stats->scheduled_video_frames, + "scheduled-audio-samples", G_TYPE_UINT64, stats->scheduled_audio_samples, + "dropped-frames", G_TYPE_UINT64, stats->drop_count, + "dropped-samples", G_TYPE_UINT64, stats->dropped_sample_count, + "late-count", G_TYPE_UINT64, stats->late_count, + "overrun-count", G_TYPE_UINT64, stats->overrun_count, + "underrun-count", G_TYPE_UINT64, stats->underrun_count, + "duplicated-frames", G_TYPE_UINT64, stats->duplicate_count, + "silent-samples", G_TYPE_UINT64, stats->silent_sample_count, + NULL); + g_value_take_boxed (value, s); + + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -747,6 +780,8 @@ gst_decklink2_sink_start (GstBaseSink * sink) GST_DEBUG_OBJECT (self, "Start"); + memset (&self->stats, 0, sizeof (GstDecklink2OutputStats)); + self->output = gst_decklink2_acquire_output (self->device_number, self->persistent_id); @@ -901,7 +936,7 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) GstMapInfo info; guint8 *audio_data = NULL; gsize audio_data_size = 0; - guint64 drop_count, late_count, underrun_count; + GstDecklink2OutputStats stats = { 0, }; if (!self->prepared_frame) { GST_ERROR_OBJECT (self, "No prepared frame"); @@ -950,8 +985,7 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) G_GSIZE_FORMAT, self->prepared_frame, audio_data_size); hr = gst_decklink2_output_schedule_stream (self->output, - self->prepared_frame, audio_data, audio_data_size, &drop_count, - &late_count, &underrun_count); + self->prepared_frame, audio_data, audio_data_size, &stats); if (audio_buf) gst_buffer_unmap (audio_buf, &info); @@ -962,11 +996,12 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) return GST_FLOW_ERROR; } - if (self->auto_restart && (drop_count + late_count > + if (self->auto_restart && (stats.drop_count + stats.late_count > (guint) self->n_preroll_frames)) { GST_WARNING_OBJECT (self, "Restart output, drop count: %" G_GUINT64_FORMAT ", late cout: %" G_GUINT64_FORMAT ", underrun count: %" - G_GUINT64_FORMAT, drop_count, late_count, underrun_count); + G_GUINT64_FORMAT, stats.drop_count, stats.late_count, + stats.underrun_count); hr = gst_decklink2_output_configure (self->output, self->n_preroll_frames, self->min_buffered_frames, self->max_buffered_frames, @@ -980,6 +1015,9 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) } } + std::lock_guard < std::mutex > lk (priv->lock); + self->stats = stats; + return GST_FLOW_OK; } From 9add04c0aced3492a99bb702434b9a520715c144 Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Fri, 28 Jul 2023 20:37:19 -0400 Subject: [PATCH 36/82] Set audio output mode to bmdAudioSampleRate48kHz --- .../gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index f205fd23ab..abef5346ec 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -2224,7 +2224,7 @@ gst_decklink2_output_configure (GstDeckLink2Output * output, if (audio_channels > 0) { GST_DEBUG_OBJECT (output, "Enabling audio"); hr = gst_decklink2_output_enable_audio (output, bmdAudioSampleRate48kHz, - audio_sample_type, audio_channels, bmdAudioOutputStreamContinuous); + audio_sample_type, audio_channels, bmdAudioOutputStreamTimestamped); if (!gst_decklink2_result (hr)) goto error; From ea130a4fa835a268a15ee514431b549038667ffc Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 29 Jul 2023 00:01:57 +0900 Subject: [PATCH 37/82] decklink2sink: Add buffered audio and video time to ouptput-stats --- .../sys/decklink2/gstdecklink2output.cpp | 9 +++++++- .../sys/decklink2/gstdecklink2output.h | 2 ++ .../sys/decklink2/gstdecklink2sink.cpp | 22 ++++++++++--------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index abef5346ec..57a0a3261f 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -1558,7 +1558,7 @@ gst_decklink2_output_schedule_video_internal (GstDeckLink2Output * self, HRESULT gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, IDeckLinkVideoFrame * frame, guint8 * audio_buf, gsize audio_buf_size, - GstDecklink2OutputStats *stats) + GstDecklink2OutputStats * stats) { GstDeckLink2OutputPrivate *priv = output->priv; HRESULT hr; @@ -1597,6 +1597,13 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, stats->buffered_audio = buffered_audio; stats->video_running_time = video_running_time; stats->audio_running_time = audio_running_time; + stats->buffered_video_time = gst_util_uint64_scale (buffered_video, + output->selected_mode.fps_d * GST_SECOND, output->selected_mode.fps_n); + stats->buffered_audio_time = 0; + if (GST_AUDIO_INFO_IS_VALID (&output->audio_info)) { + stats->buffered_audio_time = gst_util_uint64_scale (buffered_audio, + GST_SECOND, output->audio_info.rate); + } stats->hw_time = hw_time_gst; stats->scheduled_video_frames = output->n_frames; stats->scheduled_audio_samples = output->n_samples; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h index 3e349f82b9..f2e8eecc4e 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.h @@ -36,6 +36,8 @@ typedef struct GstClockTime video_running_time; GstClockTime audio_running_time; GstClockTime hw_time; + GstClockTime buffered_video_time; + GstClockTime buffered_audio_time; guint64 scheduled_video_frames; guint64 scheduled_audio_samples; guint64 late_count; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp index 7e787494fe..7e6c9ef04b 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -470,19 +470,21 @@ gst_decklink2_sink_get_property (GObject * object, guint prop_id, s = gst_structure_new ("output-stats", "buffered-video", G_TYPE_UINT, stats->buffered_video, "buffered-audio", G_TYPE_UINT, stats->buffered_audio, + "buffered-video-time", G_TYPE_UINT64, stats->buffered_video_time, + "buffered-audio-time", G_TYPE_UINT64, stats->buffered_audio_time, "video-running-time", G_TYPE_UINT64, stats->video_running_time, "audio-running-time", G_TYPE_UINT64, stats->audio_running_time, "hardware-time", G_TYPE_UINT64, stats->hw_time, - "scheduled-video-frames", G_TYPE_UINT64, stats->scheduled_video_frames, - "scheduled-audio-samples", G_TYPE_UINT64, stats->scheduled_audio_samples, - "dropped-frames", G_TYPE_UINT64, stats->drop_count, - "dropped-samples", G_TYPE_UINT64, stats->dropped_sample_count, - "late-count", G_TYPE_UINT64, stats->late_count, - "overrun-count", G_TYPE_UINT64, stats->overrun_count, - "underrun-count", G_TYPE_UINT64, stats->underrun_count, - "duplicated-frames", G_TYPE_UINT64, stats->duplicate_count, - "silent-samples", G_TYPE_UINT64, stats->silent_sample_count, - NULL); + "scheduled-video-frames", G_TYPE_UINT64, + stats->scheduled_video_frames, "scheduled-audio-samples", + G_TYPE_UINT64, stats->scheduled_audio_samples, "dropped-frames", + G_TYPE_UINT64, stats->drop_count, "dropped-samples", G_TYPE_UINT64, + stats->dropped_sample_count, "late-count", G_TYPE_UINT64, + stats->late_count, "overrun-count", G_TYPE_UINT64, + stats->overrun_count, "underrun-count", G_TYPE_UINT64, + stats->underrun_count, "duplicated-frames", G_TYPE_UINT64, + stats->duplicate_count, "silent-samples", G_TYPE_UINT64, + stats->silent_sample_count, NULL); g_value_take_boxed (value, s); break; From c9b001d334774ac90e65650a0ef3ae5088656fb1 Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Mon, 31 Jul 2023 20:47:03 -0500 Subject: [PATCH 38/82] ceiling latency for awscombiner --- .../gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp index d783380c59..487299be78 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp @@ -204,7 +204,7 @@ gst_decklink2_combiner_sink_event (GstAggregator * agg, fps_d = 1; } - latency = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); + latency = gst_util_uint64_scale_ceil (GST_SECOND, fps_d, fps_n); gst_aggregator_set_latency (agg, latency, latency); gst_aggregator_set_src_caps (agg, caps); From 06343d882280525a0c2f5ded8f0bf2e59dad3c74 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 1 Aug 2023 21:34:24 +0900 Subject: [PATCH 39/82] decklink2combiner: Don't aggregate multiple audio buffers Instead, upstream should provide perfect stream --- .../sys/decklink2/gstdecklink2combiner.cpp | 324 ++++++++---------- 1 file changed, 136 insertions(+), 188 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp index 487299be78..cd4d800721 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2combiner.cpp @@ -24,6 +24,7 @@ #include "gstdecklink2combiner.h" #include "gstdecklink2utils.h" +#include GST_DEBUG_CATEGORY_STATIC (gst_decklink2_combiner_debug); #define GST_CAT_DEFAULT gst_decklink2_combiner_debug @@ -48,8 +49,6 @@ struct _GstDeckLink2Combiner GstVideoInfo video_info; GstAudioInfo audio_info; - GstAdapter *audio_buffers; - GstClockTime video_start_time; GstClockTime audio_start_time; @@ -60,7 +59,6 @@ struct _GstDeckLink2Combiner guint64 num_audio_buffers; }; -static void gst_decklink2_combiner_dispose (GObject * object); static gboolean gst_decklink2_combiner_sink_event (GstAggregator * agg, GstAggregatorPad * pad, GstEvent * event); static gboolean gst_decklink2_combiner_sink_query (GstAggregator * agg, @@ -81,13 +79,10 @@ GST_ELEMENT_REGISTER_DEFINE (decklink2combiner, "decklink2combiner", static void gst_decklink2_combiner_class_init (GstDeckLink2CombinerClass * klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstAggregatorClass *agg_class = GST_AGGREGATOR_CLASS (klass); GstCaps *templ_caps; - object_class->dispose = gst_decklink2_combiner_dispose; - gst_element_class_add_static_pad_template_with_gtype (element_class, &audio_template, GST_TYPE_AGGREGATOR_PAD); @@ -140,18 +135,6 @@ gst_decklink2_combiner_init (GstDeckLink2Combiner * self) GST_PAD_SINK, "template", templ, NULL); gst_object_unref (templ); gst_element_add_pad (GST_ELEMENT_CAST (self), GST_PAD_CAST (self->audio_pad)); - - self->audio_buffers = gst_adapter_new (); -} - -static void -gst_decklink2_combiner_dispose (GObject * object) -{ - GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (object); - - g_clear_object (&self->audio_buffers); - - G_OBJECT_CLASS (parent_class)->dispose (object); } static gboolean @@ -370,8 +353,6 @@ gst_decklink2_combiner_reset (GstDeckLink2Combiner * self) gst_clear_caps (&self->video_caps); gst_clear_caps (&self->audio_caps); - gst_adapter_clear (self->audio_buffers); - gst_video_info_init (&self->video_info); gst_audio_info_init (&self->audio_info); @@ -468,187 +449,166 @@ gst_decklink2_combiner_aggregate (GstAggregator * agg, gboolean timeout) GstDeckLink2Combiner *self = GST_DECKLINK2_COMBINER (agg); GstBuffer *video_buf = NULL; GstBuffer *audio_buf = NULL; - gsize audio_buf_size; GstDeckLink2AudioMeta *meta; GstClockTime video_running_time = GST_CLOCK_TIME_NONE; GstClockTime video_running_time_end = GST_CLOCK_TIME_NONE; + GstClockTime audio_running_time, audio_running_time_end; + GstSample *audio_sample; + + if (gst_aggregator_pad_is_eos (self->video_pad) && + gst_aggregator_pad_is_eos (self->audio_pad)) { + GST_DEBUG_OBJECT (self, "All EOS"); + return GST_FLOW_EOS; + } video_buf = gst_aggregator_pad_peek_buffer (self->video_pad); if (!video_buf) { - if (gst_aggregator_pad_is_eos (self->video_pad)) { - /* Follow video stream's timeline */ - GST_DEBUG_OBJECT (self, "Video pad is EOS"); - return GST_FLOW_EOS; - } + GST_LOG_OBJECT (self, "Waiting for video"); + goto need_data; + } - /* Need to know video start time */ - if (!GST_CLOCK_TIME_IS_VALID (self->video_start_time)) { - GST_LOG_OBJECT (self, "Waiting for first video buffer"); - goto again; - } + /* Drop empty buffer */ + if (gst_buffer_get_size (video_buf) == 0) { + GST_LOG_OBJECT (self, "Dropping empty video buffer"); + gst_aggregator_pad_drop_buffer (self->video_pad); + goto need_data; + } - GST_LOG_OBJECT (self, "Video is not ready"); + video_running_time = video_running_time_end = + gst_segment_to_running_time (&self->video_pad->segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (video_buf)); + if (GST_BUFFER_DURATION_IS_VALID (video_buf)) { + video_running_time_end += GST_BUFFER_DURATION (video_buf); + } else if (self->video_info.fps_n > 0 && self->video_info.fps_d > 0) { + video_running_time_end += gst_util_uint64_scale_int (GST_SECOND, + self->video_info.fps_d, self->video_info.fps_n); } else { - /* Drop empty buffer */ - if (gst_buffer_get_size (video_buf) == 0) { - GST_LOG_OBJECT (self, "Dropping empty video buffer"); - gst_aggregator_pad_drop_buffer (self->video_pad); - goto again; - } - - video_running_time = video_running_time_end = - gst_segment_to_running_time (&self->video_pad->segment, - GST_FORMAT_TIME, GST_BUFFER_PTS (video_buf)); - if (GST_BUFFER_DURATION_IS_VALID (video_buf)) { - video_running_time_end += GST_BUFFER_DURATION (video_buf); - } else if (self->video_info.fps_n > 0 && self->video_info.fps_d > 0) { - video_running_time_end += gst_util_uint64_scale_int (GST_SECOND, - self->video_info.fps_d, self->video_info.fps_n); - } else { - /* XXX: shouldn't happen */ - video_running_time_end = video_running_time; - } - - if (!GST_CLOCK_TIME_IS_VALID (self->video_start_time)) { - self->video_start_time = video_running_time; - GST_DEBUG_OBJECT (self, "Video start time %" GST_TIME_FORMAT, - GST_TIME_ARGS (self->video_start_time)); - } + /* XXX: shouldn't happen */ + video_running_time_end = video_running_time; + } - self->video_running_time = video_running_time_end; + if (!GST_CLOCK_TIME_IS_VALID (self->video_start_time)) { + self->video_start_time = video_running_time; + GST_DEBUG_OBJECT (self, "Video start time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->video_start_time)); } + self->video_running_time = video_running_time_end; + audio_buf = gst_aggregator_pad_peek_buffer (self->audio_pad); if (!audio_buf) { - if (gst_adapter_available (self->audio_buffers) == 0 && - !gst_aggregator_pad_is_eos (self->audio_pad) && - self->audio_running_time < self->video_running_time) { - GST_LOG_OBJECT (self, "Waiting for audio buffer"); - goto again; - } - } else if (gst_buffer_get_size (audio_buf) == 0) { + GST_LOG_OBJECT (self, "Waiting for audio buffer"); + goto need_data; + } + + if (gst_buffer_get_size (audio_buf) == 0) { GST_LOG_OBJECT (self, "Dropping empty audio buffer"); gst_aggregator_pad_drop_buffer (self->audio_pad); - goto again; + goto need_data; + } + + audio_running_time = gst_segment_to_running_time (&self->audio_pad->segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (audio_buf)); + if (GST_BUFFER_DURATION_IS_VALID (audio_buf)) { + audio_running_time_end = audio_running_time + + GST_BUFFER_DURATION (audio_buf); } else { - GstClockTime audio_running_time, audio_running_time_end; - - audio_running_time = gst_segment_to_running_time (&self->audio_pad->segment, - GST_FORMAT_TIME, GST_BUFFER_PTS (audio_buf)); - if (GST_BUFFER_DURATION_IS_VALID (audio_buf)) { - audio_running_time_end = audio_running_time + - GST_BUFFER_DURATION (audio_buf); - } else { - audio_running_time_end = gst_util_uint64_scale (GST_SECOND, - gst_buffer_get_size (audio_buf), - self->audio_info.rate * self->audio_info.bpf); - audio_running_time_end += audio_running_time; - } + audio_running_time_end = gst_util_uint64_scale (GST_SECOND, + gst_buffer_get_size (audio_buf), + self->audio_info.rate * self->audio_info.bpf); + audio_running_time_end += audio_running_time; + } - self->audio_running_time = audio_running_time_end; + self->audio_running_time = audio_running_time_end; - /* Do initial video/audio align */ - if (!GST_CLOCK_TIME_IS_VALID (self->audio_start_time)) { - GST_DEBUG_OBJECT (self, "Initial audio running time %" GST_TIME_FORMAT, - GST_TIME_ARGS (audio_running_time)); + /* Do initial video/audio align */ + if (!GST_CLOCK_TIME_IS_VALID (self->audio_start_time)) { + GST_DEBUG_OBJECT (self, "Initial audio running time %" GST_TIME_FORMAT, + GST_TIME_ARGS (audio_running_time)); - if (audio_running_time_end <= self->video_start_time) { - GST_DEBUG_OBJECT (self, "audio running-time end %" GST_TIME_FORMAT - " < video-start-time %" GST_TIME_FORMAT, - GST_TIME_ARGS (self->video_start_time), - GST_TIME_ARGS (audio_running_time_end)); - /* completely outside */ + if (audio_running_time_end <= self->video_start_time) { + GST_DEBUG_OBJECT (self, "audio running-time end %" GST_TIME_FORMAT + " < video-start-time %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->video_start_time), + GST_TIME_ARGS (audio_running_time_end)); + /* completely outside */ + gst_aggregator_pad_drop_buffer (self->audio_pad); + goto need_data; + } else if (audio_running_time < self->video_start_time && + audio_running_time_end >= self->video_start_time) { + /* partial overlap */ + GstClockTime diff; + gsize in_samples, diff_samples; + GstAudioMeta *meta; + GstBuffer *trunc_buf; + + meta = gst_buffer_get_audio_meta (audio_buf); + in_samples = meta ? meta->samples : + gst_buffer_get_size (audio_buf) / self->audio_info.bpf; + + diff = self->video_start_time - audio_running_time; + diff_samples = gst_util_uint64_scale (diff, + self->audio_info.rate, GST_SECOND); + + GST_DEBUG_OBJECT (self, "Truncate initial audio buffer duration %" + GST_TIME_FORMAT, GST_TIME_ARGS (diff)); + + trunc_buf = gst_audio_buffer_truncate ( + (GstBuffer *) g_steal_pointer (&audio_buf), + self->audio_info.bpf, diff_samples, in_samples - diff_samples); + gst_aggregator_pad_drop_buffer (self->audio_pad); + if (!trunc_buf) { + GST_DEBUG_OBJECT (self, "Empty truncated buffer"); gst_aggregator_pad_drop_buffer (self->audio_pad); - goto again; - } else if (audio_running_time < self->video_start_time && - audio_running_time_end >= self->video_start_time) { - /* partial overlap */ - GstClockTime diff; - gsize in_samples, diff_samples; - GstAudioMeta *meta; - GstBuffer *trunc_buf; - - meta = gst_buffer_get_audio_meta (audio_buf); - in_samples = meta ? meta->samples : - gst_buffer_get_size (audio_buf) / self->audio_info.bpf; - - diff = self->video_start_time - audio_running_time; - diff_samples = gst_util_uint64_scale (diff, - self->audio_info.rate, GST_SECOND); + goto need_data; + } - GST_DEBUG_OBJECT (self, "Truncate initial audio buffer duration %" - GST_TIME_FORMAT, GST_TIME_ARGS (diff)); + self->audio_start_time = self->video_start_time; + audio_buf = trunc_buf; + } else if (audio_running_time >= self->video_start_time) { + /* fill silence if needed */ + GstClockTime diff; + gsize diff_samples; - trunc_buf = gst_audio_buffer_truncate ( - (GstBuffer *) g_steal_pointer (&audio_buf), - self->audio_info.bpf, diff_samples, in_samples - diff_samples); - gst_aggregator_pad_drop_buffer (self->audio_pad); - if (!trunc_buf) { - GST_DEBUG_OBJECT (self, "Empty truncated buffer"); - gst_aggregator_pad_drop_buffer (self->audio_pad); - goto again; - } + diff = audio_running_time - self->video_start_time; + if (diff > 0) { + gsize fill_size; - self->audio_start_time = self->video_start_time; - gst_adapter_push (self->audio_buffers, trunc_buf); - } else if (audio_running_time >= self->video_start_time) { - /* fill silence if needed */ - GstClockTime diff; - gsize diff_samples; - - diff = audio_running_time - self->video_start_time; - if (diff > 0) { - gsize fill_size; - - diff_samples = gst_util_uint64_scale (diff, - self->audio_info.rate, GST_SECOND); - - fill_size = diff_samples * self->audio_info.bpf; - if (fill_size > 0) { - GstBuffer *fill_buf; - GstMapInfo map; - - GST_DEBUG_OBJECT (self, "Fill initial %" G_GSIZE_FORMAT - " audio samples", diff_samples); - - fill_buf = gst_buffer_new_and_alloc (fill_size); - gst_buffer_map (fill_buf, &map, GST_MAP_WRITE); - gst_audio_format_info_fill_silence (self->audio_info.finfo, - map.data, map.size); - gst_buffer_unmap (fill_buf, &map); - gst_adapter_push (self->audio_buffers, fill_buf); - } - } - - self->audio_start_time = self->video_start_time; + diff_samples = gst_util_uint64_scale (diff, + self->audio_info.rate, GST_SECOND); - gst_adapter_push (self->audio_buffers, - (GstBuffer *) g_steal_pointer (&audio_buf)); - gst_aggregator_pad_drop_buffer (self->audio_pad); + fill_size = diff_samples * self->audio_info.bpf; + if (fill_size > 0) { + GstBuffer *fill_buf; + GstMapInfo map; + GstMapInfo origin_map; + + GST_DEBUG_OBJECT (self, "Fill initial %" G_GSIZE_FORMAT + " audio samples", diff_samples); + + gst_buffer_map (audio_buf, &origin_map, GST_MAP_READ); + + fill_buf = gst_buffer_new_and_alloc (fill_size + origin_map.size); + gst_buffer_map (fill_buf, &map, GST_MAP_WRITE); + gst_audio_format_info_fill_silence (self->audio_info.finfo, + map.data, fill_size); + memcpy ((guint8 *) map.data + fill_size, + origin_map.data, origin_map.size); + gst_buffer_unmap (fill_buf, &map); + gst_buffer_unmap (audio_buf, &origin_map); + gst_buffer_unref (audio_buf); + audio_buf = fill_buf; + } } - self->num_audio_buffers++; - } else { - GST_LOG_OBJECT (self, "Pushing audio buffer to adapter, %" GST_PTR_FORMAT, - audio_buf); - gst_adapter_push (self->audio_buffers, - (GstBuffer *) g_steal_pointer (&audio_buf)); + self->audio_start_time = self->video_start_time; gst_aggregator_pad_drop_buffer (self->audio_pad); - - self->num_audio_buffers++; } - } - if (!video_buf) { - GST_LOG_OBJECT (self, "Waiting for video"); - goto again; - } else if (!gst_aggregator_pad_is_eos (self->audio_pad) && - self->audio_running_time < self->video_running_time) { - GST_LOG_OBJECT (self, "Waiting for audio, audio running time %" - GST_TIME_FORMAT " < video running time %" GST_TIME_FORMAT, - GST_TIME_ARGS (self->audio_running_time), - GST_TIME_ARGS (self->video_running_time)); - goto again; + self->num_audio_buffers++; + } else { + gst_aggregator_pad_drop_buffer (self->audio_pad); + self->num_audio_buffers++; } gst_aggregator_pad_drop_buffer (self->video_pad); @@ -662,22 +622,10 @@ gst_decklink2_combiner_aggregate (GstAggregator * agg, gboolean timeout) gst_buffer_remove_meta (video_buf, GST_META_CAST (meta)); } - audio_buf_size = gst_adapter_available (self->audio_buffers); - if (audio_buf_size > 0) { - GstSample *audio_sample; - - audio_buf = gst_adapter_take_buffer (self->audio_buffers, audio_buf_size); - audio_sample = gst_sample_new (audio_buf, self->audio_caps, NULL, NULL); - - GST_LOG_OBJECT (self, "Adding meta with size %" G_GSIZE_FORMAT, - gst_buffer_get_size (audio_buf)); - gst_buffer_unref (audio_buf); - - gst_buffer_add_decklink2_audio_meta (video_buf, audio_sample); - gst_sample_unref (audio_sample); - } else { - GST_LOG_OBJECT (self, "No audio meta"); - } + audio_sample = gst_sample_new (audio_buf, self->audio_caps, NULL, NULL); + gst_buffer_unref (audio_buf); + gst_buffer_add_decklink2_audio_meta (video_buf, audio_sample); + gst_sample_unref (audio_sample); GST_LOG_OBJECT (self, "Finish buffer %" GST_PTR_FORMAT ", total video/audio buffers %" GST_TIME_FORMAT @@ -690,7 +638,7 @@ gst_decklink2_combiner_aggregate (GstAggregator * agg, gboolean timeout) return gst_aggregator_finish_buffer (agg, video_buf); -again: +need_data: gst_clear_buffer (&video_buf); gst_clear_buffer (&audio_buf); From bb0b210ef2498a74cbb4c9707a7aa76a90410d4c Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 1 Aug 2023 21:36:29 +0900 Subject: [PATCH 40/82] decklink2output: Update audio drop logic Upstream should provide a/v aligned stream. Remove append/drop audio on overrun logic. And duplicate frame up to 2 frames on underrun --- .../sys/decklink2/gstdecklink2output.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index 57a0a3261f..c594259f20 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -1623,12 +1623,11 @@ gst_decklink2_output_schedule_stream (GstDeckLink2Output * output, GST_TIME_ARGS (output->pts), output->n_frames, buffered_video, GST_TIME_ARGS (audio_running_time), output->n_samples, buffered_audio, GST_STIME_ARGS (diff), GST_TIME_ARGS (hw_time_gst)); - - /* audio and video may not be completely aligned. Add this sample - * and drop video frame duration amount of audio samples */ - priv->audio_buf.Append (audio_buf, audio_buf_size); - output->dropped_sample_count += priv->audio_buf.Drop (); output->overrun_count++; + if (audio_buf_size > 0 && GST_AUDIO_INFO_IS_VALID (&output->audio_info)) { + gsize dropped_samples = audio_buf_size / output->audio_info.bpf; + output->dropped_sample_count += dropped_samples; + } return S_OK; } @@ -2268,7 +2267,8 @@ gst_decklink2_output_configure (GstDeckLink2Output * output, output->gap_frames = 1; if (max_buffered > min_buffered) { guint gap = (max_buffered - min_buffered) / 2; - output->gap_frames = MAX (2, gap); + if (gap >= 2) + output->gap_frames = 2; } output->duplicating = FALSE; From a43ede1db20b89965c3510c52dc8c082b2f04ffe Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sun, 6 Aug 2023 01:13:47 +0900 Subject: [PATCH 41/82] streamselector: Don't try to drop buffer of the current active pad --- .../gst-plugins-bad/gst/streamselector/gststreamselector.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c index 491bb9bef6..f7df41556f 100644 --- a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c @@ -716,7 +716,12 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) for (iter = elem->sinkpads; iter; iter = g_list_next (iter)) { GstAggregatorPad *other_pad = GST_AGGREGATOR_PAD_CAST (iter->data); GstStreamSelectorPad *other_spad = GST_STREAM_SELECTOR_PAD (other_pad); - GstClockTime other_running_time = + GstClockTime other_running_time; + + if (other_spad == active_pad) + continue; + + other_running_time = gst_stream_selector_get_pad_running_time (self, other_pad); /* Drops other pad's buffer if From f7406148e19607053657d8fea2bbd17ba72ace30 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sun, 6 Aug 2023 02:20:14 +0900 Subject: [PATCH 42/82] streamselector: Fix busy waiting Increase time position so that aggregator can wait a bit --- .../gst/streamselector/gststreamselector.c | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c index f7df41556f..84d7d93e69 100644 --- a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselector.c @@ -50,6 +50,7 @@ struct _GstStreamSelectorPad GstEvent *tag_event; gboolean active; gboolean discont; + GstClockTime duration; }; static void gst_stream_selector_pad_dispose (GObject * object); @@ -88,6 +89,7 @@ gst_stream_selector_pad_class_init (GstStreamSelectorPadClass * klass) static void gst_stream_selector_pad_init (GstStreamSelectorPad * self) { + self->duration = GST_CLOCK_TIME_NONE; } static void @@ -534,10 +536,21 @@ gst_stream_selector_sink_event (GstAggregator * agg, GstAggregatorPad * pad, { GstCaps *caps; GstPad *active; + GstStructure *s; + gint fps_n, fps_d; gst_event_parse_caps (event, &caps); gst_caps_replace (&spad->caps, caps); + s = gst_caps_get_structure (caps, 0); + if (gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d) + && fps_n > 0 && fps_d > 0) { + GST_DEBUG_OBJECT (pad, "Framerate %d / %d", fps_n, fps_d); + spad->duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); + } else { + spad->duration = GST_CLOCK_TIME_NONE; + } + active = gst_stream_selector_get_active_pad (self); if (active) { if (active == GST_PAD_CAST (pad)) @@ -660,12 +673,14 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) GstClockTime timestamp; gboolean active_eos = FALSE; gboolean have_non_eos_pad = FALSE; + GstClockTime advance_dur = GST_CLOCK_TIME_NONE; GST_OBJECT_LOCK (self); active_pad = (GstStreamSelectorPad *) gst_stream_selector_get_active_pad_unlocked (self); if (!active_pad) { GST_WARNING_OBJECT (self, "No current active pad"); + GST_OBJECT_UNLOCK (self); goto need_data; } @@ -678,6 +693,8 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) GST_LOG_OBJECT (active_pad, "Current active pad"); } + advance_dur = active_pad->duration; + active_agg_pad = GST_AGGREGATOR_PAD_CAST (active_pad); buf = gst_aggregator_pad_pop_buffer (active_agg_pad); @@ -779,8 +796,7 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) return GST_FLOW_EOS; } else if (!buf) { GST_LOG_OBJECT (self, "Active pad is not ready"); - gst_object_unref (active_pad); - return GST_AGGREGATOR_FLOW_NEED_DATA; + goto need_data; } srcpad->segment.position = @@ -810,13 +826,22 @@ gst_stream_selector_aggregate (GstAggregator * agg, gboolean timeout) active_pad->discont = FALSE; } + GST_LOG_OBJECT (active_pad, "Finishing buffer %" GST_PTR_FORMAT + ", running time %" GST_TIME_FORMAT, buf, + GST_TIME_ARGS (running_time_end)); + gst_object_unref (active_pad); return gst_aggregator_finish_buffer (agg, buf); need_data: + if (srcpad->segment.position != -1) { + if (GST_CLOCK_TIME_IS_VALID (advance_dur)) + srcpad->segment.position += advance_dur; + else + srcpad->segment.position += GST_MSECOND; + } gst_clear_object (&active_pad); - GST_OBJECT_UNLOCK (self); return GST_AGGREGATOR_FLOW_NEED_DATA; } From 68efb9831f4a1bc24b510c2a38d570f097ac4278 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 14 Sep 2023 20:33:17 +0900 Subject: [PATCH 43/82] streamselectorbin: Add sync-only-inactive property If enabled and sync-mode=clock, only inactive streams will be synchronized with clock --- .../gst/streamselector/gststreamselectorbin.c | 85 +++++++++++++++---- 1 file changed, 69 insertions(+), 16 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c index 417e35f844..8ef3235fa6 100644 --- a/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c +++ b/subprojects/gst-plugins-bad/gst/streamselector/gststreamselectorbin.c @@ -47,6 +47,8 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); +static void gst_stream_selector_bin_update_sync (GstStreamSelectorBin * self); + enum { PROP_PAD_0, @@ -58,6 +60,7 @@ struct _GstStreamSelectorBinPad GstGhostPad parent; GstPad *target; + GstStreamSelectorBin *bin; }; static void gst_stream_selector_bin_pad_dispose (GObject * object); @@ -107,8 +110,11 @@ gst_stream_selector_bin_pad_set_property (GObject * object, guint prop_id, { GstStreamSelectorBinPad *self = GST_STREAM_SELECTOR_BIN_PAD (object); - if (self->target) + if (self->target) { g_object_set_property (G_OBJECT (self->target), pspec->name, value); + if (prop_id == PROP_PAD_ACTIVE) + gst_stream_selector_bin_update_sync (self->bin); + } } static void @@ -168,12 +174,14 @@ struct _GstStreamSelectorBin gboolean running; GstStreamSelectorBinSyncMode sync_mode; + gboolean sync_only_inactive; }; enum { PROP_0, PROP_SYNC_MODE, + PROP_SYNC_ONLY_INACTIVE, /* GstAggregator */ PROP_LATENCY, PROP_MIN_UPSTREAM_LATENCY, @@ -190,6 +198,7 @@ enum #define DEFAULT_START_TIME_SELECTION GST_AGGREGATOR_START_TIME_SELECTION_ZERO #define DEFAULT_START_TIME (-1) #define DEFAULT_EMIT_SIGNALS FALSE +#define DEFAULT_SYNC_ONLY_INACTIVE FALSE static void gst_stream_selector_bin_finalize (GObject * object); static void gst_stream_selector_bin_set_property (GObject * object, @@ -225,6 +234,12 @@ gst_stream_selector_bin_class_init (GstStreamSelectorBinClass * klass) GST_TYPE_STREAM_SELECTOR_BIN_SYNC_MODE, DEFAULT_SYNC_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_SYNC_ONLY_INACTIVE, + g_param_spec_boolean ("sync-only-inactive", "Sync Only Inactive", + "Synchronize only inactive stream with clock when \"sync-mode=clock\"", + DEFAULT_SYNC_ONLY_INACTIVE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* GstAggregator */ g_object_class_install_property (object_class, PROP_LATENCY, g_param_spec_uint64 ("latency", "Buffer latency", @@ -309,6 +324,7 @@ gst_stream_selector_bin_init (GstStreamSelectorBin * self) gst_element_add_pad (GST_ELEMENT_CAST (self), gpad); self->sync_mode = DEFAULT_SYNC_MODE; + self->sync_only_inactive = DEFAULT_SYNC_ONLY_INACTIVE; g_mutex_init (&self->lock); } @@ -326,6 +342,40 @@ gst_stream_selector_bin_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +gst_stream_selector_bin_update_sync_unlocked (GstStreamSelectorBin * self) +{ + GList *iter; + if (self->sync_mode != GST_STREAM_SELECTOR_BIN_SYNC_MODE_CLOCK) { + for (iter = self->input_chains; iter; iter = g_list_next (iter)) { + GstStreamSelectorBinChain *chain = iter->data; + g_object_set (chain->clocksync, "sync", FALSE, NULL); + } + } else { + if (self->sync_only_inactive) { + for (iter = self->input_chains; iter; iter = g_list_next (iter)) { + GstStreamSelectorBinChain *chain = iter->data; + gboolean is_active; + g_object_get (chain->pad->target, "active", &is_active, NULL); + g_object_set (chain->clocksync, "sync", !is_active, NULL); + } + } else { + for (iter = self->input_chains; iter; iter = g_list_next (iter)) { + GstStreamSelectorBinChain *chain = iter->data; + g_object_set (chain->clocksync, "sync", TRUE, NULL); + } + } + } +} + +static void +gst_stream_selector_bin_update_sync (GstStreamSelectorBin * self) +{ + g_mutex_lock (&self->lock); + gst_stream_selector_bin_update_sync_unlocked (self); + g_mutex_unlock (&self->lock); +} + static void gst_stream_selector_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -335,18 +385,17 @@ gst_stream_selector_bin_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_SYNC_MODE: { - GList *iter; - gboolean sync = FALSE; g_mutex_lock (&self->lock); self->sync_mode = g_value_get_enum (value); - if (self->sync_mode == GST_STREAM_SELECTOR_BIN_SYNC_MODE_CLOCK) - sync = TRUE; - - for (iter = self->input_chains; iter; iter = g_list_next (iter)) { - GstStreamSelectorBinChain *chain = iter->data; - if (chain->clocksync) - g_object_set (chain->clocksync, "sync", sync, NULL); - } + gst_stream_selector_bin_update_sync_unlocked (self); + g_mutex_unlock (&self->lock); + break; + } + case PROP_SYNC_ONLY_INACTIVE: + { + g_mutex_lock (&self->lock); + self->sync_only_inactive = g_value_get_boolean (value); + gst_stream_selector_bin_update_sync_unlocked (self); g_mutex_unlock (&self->lock); break; } @@ -368,6 +417,11 @@ gst_stream_selector_bin_get_property (GObject * object, guint prop_id, g_value_set_enum (value, self->sync_mode); g_mutex_unlock (&self->lock); break; + case PROP_SYNC_ONLY_INACTIVE: + g_mutex_lock (&self->lock); + g_value_set_boolean (value, self->sync_only_inactive); + g_mutex_unlock (&self->lock); + break; default: g_object_get_property (G_OBJECT (self->selector), pspec->name, value); break; @@ -428,6 +482,7 @@ gst_stream_selector_bin_chain_new (GstStreamSelectorBin * self, binpad = GST_STREAM_SELECTOR_BIN_PAD (chain->pad); binpad->target = selector_pad; + binpad->bin = self; pad = gst_element_get_static_pad (chain->clocksync, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->pad), pad); @@ -466,21 +521,19 @@ gst_stream_selector_bin_request_new_pad (GstElement * elem, GstStreamSelectorBin *self = GST_STREAM_SELECTOR_BIN (elem); GstPad *selector_pad; GstStreamSelectorBinChain *chain; - gboolean sync = FALSE; GstPadTemplate *selector_templ; selector_templ = gst_element_get_pad_template (self->selector, "sink_%u"); - selector_pad = gst_element_request_pad (self->selector, selector_templ, name, caps); + selector_pad = + gst_element_request_pad (self->selector, selector_templ, name, caps); if (!selector_pad) return NULL; chain = gst_stream_selector_bin_chain_new (self, selector_pad); g_mutex_lock (&self->lock); - if (self->sync_mode == GST_STREAM_SELECTOR_BIN_SYNC_MODE_CLOCK) - sync = TRUE; - g_object_set (chain->clocksync, "sync", sync, NULL); self->input_chains = g_list_append (self->input_chains, chain); + gst_stream_selector_bin_update_sync_unlocked (self); g_mutex_unlock (&self->lock); GST_DEBUG_OBJECT (chain->pad, "Created new pad"); From d116d44fc1c2e9ded57ce11ac0e79c59cfc90983 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 4 Nov 2023 00:32:22 +0900 Subject: [PATCH 44/82] decklink2src: Validate frame resolution and formats ... and fix some deadlocks --- .../sys/decklink2/gstdecklink2input.cpp | 64 +++++++++++++++---- .../sys/decklink2/gstdecklink2src.cpp | 8 ++- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 9a510c4ba2..8d55e36400 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -373,6 +373,7 @@ struct _GstDeckLink2Input GArray *format_table; GstCaps *selected_video_caps; GstAudioInfo audio_info; + GstVideoInfo video_info; guint max_audio_channels; GstCaps *selected_audio_caps; gboolean auto_detect; @@ -1115,16 +1116,18 @@ gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, GST_DEBUG_OBJECT (self, "Updated caps %" GST_PTR_FORMAT, caps); - self->selected_mode = new_mode; - self->pixel_format = pixel_format; - gst_decklink2_input_pause_streams (self); gst_decklink2_input_enable_video (self, display_mode, pixel_format, bmdVideoInputEnableFormatDetection); gst_decklink2_input_flush_streams (self); + std::lock_guard < std::mutex > lk (priv->lock); + self->selected_mode = new_mode; + self->pixel_format = pixel_format; + gst_clear_caps (&self->selected_video_caps); self->selected_video_caps = caps; + gst_video_info_from_caps (&self->video_info, self->selected_video_caps); self->aspect_ratio_flag = -1; self->discont = TRUE; gst_adapter_clear (self->audio_buf); @@ -1495,6 +1498,22 @@ gst_decklink2_input_update_time_mapping (GstDeckLink2Input * self, } } +static void +gst_decklink2_input_do_restart (GstDeckLink2Input * self) +{ + GstDeckLink2InputPrivate *priv = self->priv; + + priv->was_restarted = true; + gst_decklink2_input_reset_time_mapping (self); + gst_decklink2_input_stop_streams (self); + gst_decklink2_input_flush_streams (self); + gst_adapter_clear (self->audio_buf); + self->audio_offset = INVALID_AUDIO_OFFSET; + self->next_audio_offset = INVALID_AUDIO_OFFSET; + + gst_decklink2_input_start_streams (self); +} + static void gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, IDeckLinkVideoInputFrame * frame, IDeckLinkAudioInputPacket * packet) @@ -1534,14 +1553,7 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, } else if (!priv->signal) { GST_LOG_OBJECT (self, "Got first frame, reset timing map"); priv->signal = true; - priv->was_restarted = true; - gst_decklink2_input_reset_time_mapping (self); - gst_decklink2_input_stop_streams (self); - gst_decklink2_input_flush_streams (self); - gst_decklink2_input_start_streams (self); - gst_adapter_clear (self->audio_buf); - self->audio_offset = INVALID_AUDIO_OFFSET; - self->next_audio_offset = INVALID_AUDIO_OFFSET; + gst_decklink2_input_do_restart (self); return; } else { priv->signal = true; @@ -1595,6 +1607,7 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, BMDTimeValue frame_time, frame_dur; IDeckLinkTimecode *timecode = NULL; GstClockTime pts, dur; + BMDPixelFormat pixel_format; hr = frame->GetBytes (&frame_data); if (!gst_decklink2_result (hr)) { @@ -1602,7 +1615,32 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, return; } - frame_size = frame->GetHeight () * frame->GetRowBytes (); + pixel_format = frame->GetPixelFormat (); + if (pixel_format != self->pixel_format) { + lk.unlock (); + + GST_DEBUG_OBJECT (self, "Unexpected pixel format change %d -> %d", + self->pixel_format, pixel_format); + + gst_decklink2_input_do_restart (self); + return; + } + + auto frame_width = frame->GetWidth (); + auto frame_height = frame->GetHeight (); + if (self->video_info.width != (gint) frame_width || + self->video_info.height != (gint) frame_height) { + lk.unlock (); + + GST_WARNING_OBJECT (self, "Unexpected resolution change %dx%d -> %dx%d", + self->video_info.width, self->video_info.height, + (gint) frame_width, (gint) frame_height); + + gst_decklink2_input_do_restart (self); + return; + } + + frame_size = frame_height * frame->GetRowBytes (); buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, frame_data, frame_size, 0, frame_size, frame, (GDestroyNotify) gst_decklink2_frame_free); @@ -2004,6 +2042,8 @@ gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, goto error; } + gst_video_info_from_caps (&input->video_info, input->selected_video_caps); + input->auto_detect = video_config->auto_detect; input->aspect_ratio_flag = -1; input->audio_offset = INVALID_AUDIO_OFFSET; diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index e2b9a97230..9c8a094f69 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -358,10 +358,12 @@ gst_decklink2_src_get_caps (GstBaseSrc * src, GstCaps * filter) GstDeckLink2SrcPrivate *priv = self->priv; GstCaps *caps; GstCaps *ret; - std::lock_guard < std::mutex > lk (priv->lock); + std::unique_lock < std::mutex > lk (priv->lock); - if (!self->input) + if (!self->input) { + lk.unlock (); return GST_BASE_SRC_CLASS (parent_class)->get_caps (src, filter); + } if (self->selected_caps) { caps = gst_caps_ref (self->selected_caps); @@ -630,7 +632,9 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) if (is_gap_buf != self->is_gap_buf) { self->is_gap_buf = is_gap_buf; + lk.unlock (); g_object_notify (G_OBJECT (self), "signal"); + lk.lock (); } *buffer = buf; From 282cc97fc8aa5a15049184a55f919a560c31c6d1 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Mon, 4 Dec 2023 23:49:44 +0900 Subject: [PATCH 45/82] decklink2sink: Add desync-threshold property Similar to decklink2src, adding a property to restart stream if desync is detected --- .../sys/decklink2/gstdecklink2sink.cpp | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp index 7e6c9ef04b..fa21333a17 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2sink.cpp @@ -51,6 +51,7 @@ enum PROP_MAX_BUFFERED_FRAMES, PROP_AUTO_RESTART, PROP_OUTPUT_STATS, + PROP_DESYNC_THRESHOLD, }; #define DEFAULT_MODE bmdModeUnknown @@ -68,6 +69,7 @@ enum #define DEFAULT_MIN_BUFFERED_FRAMES 3 #define DEFAULT_MAX_BUFFERED_FRAMES 14 #define DEFAULT_AUTO_RESTART FALSE +#define DEFAULT_DESYNC_THRESHOLD (250 * GST_MSECOND) enum { @@ -120,6 +122,7 @@ struct _GstDeckLink2Sink guint min_buffered_frames; guint max_buffered_frames; gboolean auto_restart; + GstClockTime desync_threshold; GstDecklink2OutputStats stats; }; @@ -255,6 +258,14 @@ gst_decklink2_sink_class_init (GstDeckLink2SinkClass * klass) "Output Statistics", GST_TYPE_STRUCTURE, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + g_object_class_install_property (object_class, PROP_DESYNC_THRESHOLD, + g_param_spec_uint64 ("desync-threshold", "Desync Threshold", + "Maximum allowed a/v desync threshold. " + "If larger desync is detected, streaming will be restarted " + "(0 = disable auto-restart)", 0, + G_MAXUINT64, DEFAULT_DESYNC_THRESHOLD, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + gst_decklink2_sink_signals[SIGNAL_RESTART] = g_signal_new_class_handler ("restart", G_TYPE_FROM_CLASS (klass), (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), @@ -333,6 +344,7 @@ gst_decklink2_sink_init (GstDeckLink2Sink * self) self->min_buffered_frames = DEFAULT_MIN_BUFFERED_FRAMES; self->max_buffered_frames = DEFAULT_MAX_BUFFERED_FRAMES; self->auto_restart = DEFAULT_AUTO_RESTART; + self->desync_threshold = DEFAULT_DESYNC_THRESHOLD; self->priv = new GstDeckLink2SinkPrivate (); } @@ -402,6 +414,9 @@ gst_decklink2_sink_set_property (GObject * object, guint prop_id, case PROP_AUTO_RESTART: self->auto_restart = g_value_get_boolean (value); break; + case PROP_DESYNC_THRESHOLD: + self->desync_threshold = g_value_get_uint64 (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -489,6 +504,9 @@ gst_decklink2_sink_get_property (GObject * object, guint prop_id, break; } + case PROP_DESYNC_THRESHOLD: + g_value_set_uint64 (value, self->desync_threshold); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -939,6 +957,7 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) guint8 *audio_data = NULL; gsize audio_data_size = 0; GstDecklink2OutputStats stats = { 0, }; + gboolean do_restart = FALSE; if (!self->prepared_frame) { GST_ERROR_OBJECT (self, "No prepared frame"); @@ -998,13 +1017,36 @@ gst_decklink2_sink_render (GstBaseSink * sink, GstBuffer * buffer) return GST_FLOW_ERROR; } + if (self->audio_channels > 0 && self->desync_threshold != 0 && + GST_CLOCK_TIME_IS_VALID (self->desync_threshold)) { + GstClockTime diff; + + if (stats.buffered_audio_time > stats.buffered_video_time) + diff = stats.buffered_audio_time - stats.buffered_video_time; + else + diff = stats.buffered_video_time - stats.buffered_audio_time; + + if (diff >= self->desync_threshold) { + GST_WARNING_OBJECT (self, "Restart output, buffered video: %" + GST_TIME_FORMAT ", buffered audio: %" GST_TIME_FORMAT + ", threshold %" GST_TIME_FORMAT, + GST_TIME_ARGS (stats.buffered_video_time), + GST_TIME_ARGS (stats.buffered_audio_time), + GST_TIME_ARGS (self->desync_threshold)); + do_restart = TRUE; + } + } + if (self->auto_restart && (stats.drop_count + stats.late_count > (guint) self->n_preroll_frames)) { GST_WARNING_OBJECT (self, "Restart output, drop count: %" G_GUINT64_FORMAT ", late cout: %" G_GUINT64_FORMAT ", underrun count: %" G_GUINT64_FORMAT, stats.drop_count, stats.late_count, stats.underrun_count); + do_restart = TRUE; + } + if (do_restart) { hr = gst_decklink2_output_configure (self->output, self->n_preroll_frames, self->min_buffered_frames, self->max_buffered_frames, &self->selected_mode, self->output_flags, self->profile_id, From cab2791d7b64aaddb660f55480b05c5b79a5528c Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 7 Dec 2023 18:39:56 +0900 Subject: [PATCH 46/82] decklink2src: Fix mutex usage --- subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index 9c8a094f69..d693e3ff4b 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -623,6 +623,7 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) return GST_FLOW_NOT_NEGOTIATED; } + lk.lock (); } gst_clear_caps (&caps); From 19e00114635b43c9751ed092a6fc37136c7d8c7e Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 7 Dec 2023 18:57:55 +0900 Subject: [PATCH 47/82] decklink2src: Release mutex while stopping Stop API will wait for callback function thread which takes mutex too. Release the mutex while stopping --- .../sys/decklink2/gstdecklink2input.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 8d55e36400..55f53b8dcc 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -338,12 +338,14 @@ struct GstDeckLink2InputPrivate { signal = false; was_restarted = false; + stopping = false; } std::mutex lock; std::condition_variable cond; std::atomic < bool >signal; std::atomic < bool >was_restarted; + std::atomic stopping; }; struct _GstDeckLink2Input @@ -1079,6 +1081,9 @@ gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, GstCaps *caps; GstDeckLink2InputPrivate *priv = self->priv; + if (priv->stopping) + return S_OK; + GST_DEBUG_OBJECT (self, "format changed, flags 0x%x", flags); if ((flags & bmdDetectedVideoInputRGB444) != 0) { @@ -1918,10 +1923,16 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) { GstDeckLink2InputPrivate *priv = self->priv; + /* Temporarily unlock mutex. below API call may be blocked by callback thread + * which takes our mutex too */ + priv->stopping = true; + priv->lock.unlock (); gst_decklink2_input_stop_streams (self); gst_decklink2_input_disable_video (self); gst_decklink2_input_disable_audio (self); gst_decklink2_input_set_callback (self, NULL); + priv->lock.lock (); + priv->stopping = false; gst_queue_array_clear (self->queue); gst_clear_caps (&self->selected_video_caps); gst_clear_caps (&self->selected_audio_caps); From 3fb0cba1ea8b007ea83f682e474745cf1f90f705 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 14 Dec 2023 19:27:50 +0900 Subject: [PATCH 48/82] decklink2: Validate video buffer size --- .../sys/decklink2/gstdecklink2demux.cpp | 24 ++++++++++++ .../sys/decklink2/gstdecklink2src.cpp | 38 +++++++++++++++---- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp index 53f35c99af..34ecd7b2f8 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2demux.cpp @@ -43,9 +43,12 @@ struct _GstDeckLink2Demux GstPad *sink_pad; GstPad *video_pad; GstPad *audio_pad; + GstVideoInfo video_info; GstFlowCombiner *flow_combiner; GstCaps *audio_caps; + + guint drop_count; }; static void gst_decklink2_demux_finalize (GObject * object); @@ -132,6 +135,7 @@ gst_decklink2_demux_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: gst_clear_caps (&self->audio_caps); + self->drop_count = 0; break; default: break; @@ -163,6 +167,7 @@ gst_decklink2_demux_chain (GstPad * sinkpad, GstObject * parent, GstDeckLink2AudioMeta *meta; GstSample *audio_sample = NULL; GstFlowReturn ret; + gsize buf_size; meta = gst_buffer_get_decklink2_audio_meta (inbuf); if (meta) { @@ -230,6 +235,23 @@ gst_decklink2_demux_chain (GstPad * sinkpad, GstObject * parent, } out: + buf_size = gst_buffer_get_size (inbuf); + if (buf_size < self->video_info.size) { + GST_WARNING_OBJECT (self, "Too small buffer size %" G_GSIZE_FORMAT + " < %" G_GSIZE_FORMAT, buf_size, self->video_info.size); + gst_buffer_unref (inbuf); + self->drop_count++; + + if (self->drop_count > 30) { + GST_ERROR_OBJECT (self, "Too many buffers were dropped"); + return GST_FLOW_ERROR; + } + + return GST_FLOW_OK; + } + + self->drop_count = 0; + GST_LOG_OBJECT (self, "Pushing video buffer %" GST_PTR_FORMAT, inbuf); ret = gst_pad_push (self->video_pad, inbuf); ret = gst_flow_combiner_update_pad_flow (self->flow_combiner, @@ -262,6 +284,8 @@ gst_decklink2_demux_sink_event (GstPad * sinkpad, GstObject * parent, gst_event_parse_caps (event, &caps); GST_DEBUG_OBJECT (self, "Forwarding %" GST_PTR_FORMAT, caps); + gst_video_info_from_caps (&self->video_info, caps); + return gst_pad_push_event (self->video_pad, event); } case GST_EVENT_FLUSH_STOP: diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index d693e3ff4b..b2185c3acc 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -593,8 +593,15 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) GstDeckLink2SrcPrivate *priv = self->priv; gboolean is_gap_buf = FALSE; GstClockTimeDiff av_sync; + guint retry_count = 0; + gsize buf_size; again: + if (retry_count > 30) { + GST_ERROR_OBJECT (self, "Too many buffers were dropped"); + return GST_FLOW_ERROR; + } + if (!gst_decklink2_src_run (self)) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to start stream")); @@ -605,17 +612,26 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) if (ret != GST_FLOW_OK) { if (ret == GST_DECKLINK2_INPUT_FLOW_STOPPED) { GST_DEBUG_OBJECT (self, "Input was stopped for restarting"); + retry_count++; goto again; } return ret; } - std::unique_lock < std::mutex > lk (priv->lock); - if (caps && !gst_caps_is_equal (caps, self->selected_caps)) { + if (!caps) { + GST_WARNING_OBJECT (self, "Buffer without caps"); + gst_clear_buffer (&buf); + retry_count++; + goto again; + } + + priv->lock.lock (); + if (!gst_caps_is_equal (caps, self->selected_caps)) { GST_DEBUG_OBJECT (self, "Set updated caps %" GST_PTR_FORMAT, caps); gst_caps_replace (&self->selected_caps, caps); - lk.unlock (); + gst_video_info_from_caps (&self->video_info, caps); + priv->lock.unlock (); if (!gst_pad_set_caps (GST_BASE_SRC_PAD (self), caps)) { GST_ERROR_OBJECT (self, "Couldn't set caps"); gst_clear_buffer (&buf); @@ -623,9 +639,9 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) return GST_FLOW_NOT_NEGOTIATED; } - lk.lock (); + } else { + priv->lock.unlock (); } - gst_clear_caps (&caps); if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) @@ -633,11 +649,19 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) if (is_gap_buf != self->is_gap_buf) { self->is_gap_buf = is_gap_buf; - lk.unlock (); g_object_notify (G_OBJECT (self), "signal"); - lk.lock (); } + buf_size = gst_buffer_get_size (buf); + if (buf_size < self->video_info.size) { + GST_WARNING_OBJECT (self, "Too small buffer size %" G_GSIZE_FORMAT + " < %" G_GSIZE_FORMAT, buf_size, self->video_info.size); + gst_clear_buffer (&buf); + retry_count++; + goto again; + } + + std::unique_lock < std::mutex > lk (priv->lock); *buffer = buf; if (self->desync_threshold != 0 && From 634f8bdf9ef12841ccb61ee4d2332ef7936387ff Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 14 Dec 2023 22:43:35 +0900 Subject: [PATCH 49/82] decklink2src: Implement soft restart Instead of stopping stream, do pause, flush, and reset time mapping. --- .../sys/decklink2/gstdecklink2input.cpp | 35 +++++++++++++++---- .../sys/decklink2/gstdecklink2input.h | 2 ++ .../sys/decklink2/gstdecklink2src.cpp | 12 ++----- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 55f53b8dcc..3ad5d4f706 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -339,6 +339,7 @@ struct GstDeckLink2InputPrivate signal = false; was_restarted = false; stopping = false; + need_restart = false; } std::mutex lock; @@ -346,6 +347,7 @@ struct GstDeckLink2InputPrivate std::atomic < bool >signal; std::atomic < bool >was_restarted; std::atomic stopping; + std::atomic need_restart; }; struct _GstDeckLink2Input @@ -1503,20 +1505,27 @@ gst_decklink2_input_update_time_mapping (GstDeckLink2Input * self, } } +/* Must be called with lock taken */ static void gst_decklink2_input_do_restart (GstDeckLink2Input * self) { GstDeckLink2InputPrivate *priv = self->priv; + GST_DEBUG_OBJECT (self, "Restaring input"); + priv->was_restarted = true; - gst_decklink2_input_reset_time_mapping (self); - gst_decklink2_input_stop_streams (self); + priv->need_restart = false; + priv->lock.unlock (); + gst_decklink2_input_pause_streams (self); gst_decklink2_input_flush_streams (self); + gst_decklink2_input_start_streams (self); + priv->lock.lock (); + + gst_decklink2_input_reset_time_mapping (self); gst_adapter_clear (self->audio_buf); + gst_queue_array_clear (self->queue); self->audio_offset = INVALID_AUDIO_OFFSET; self->next_audio_offset = INVALID_AUDIO_OFFSET; - - gst_decklink2_input_start_streams (self); } static void @@ -1538,6 +1547,7 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, BMDTimeValue stream_dur; BMDFrameFlags flags = bmdFrameFlagDefault; + std::unique_lock < std::mutex > lk (priv->lock); if (frame) { gboolean has_signal; flags = frame->GetFlags (); @@ -1566,7 +1576,13 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, } } - std::unique_lock < std::mutex > lk (priv->lock); + /* Restart requested, flush everything */ + if (priv->need_restart) { + GST_DEBUG_OBJECT (self, "Restring as requested"); + gst_decklink2_input_do_restart (self); + return; + } + hr = gst_decklink2_input_get_reference_clock (self, GST_SECOND, &hw_now, &dummy, &dummy2); if (!gst_decklink2_result (hr)) { @@ -1622,7 +1638,6 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, pixel_format = frame->GetPixelFormat (); if (pixel_format != self->pixel_format) { - lk.unlock (); GST_DEBUG_OBJECT (self, "Unexpected pixel format change %d -> %d", self->pixel_format, pixel_format); @@ -1635,7 +1650,6 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, auto frame_height = frame->GetHeight (); if (self->video_info.width != (gint) frame_width || self->video_info.height != (gint) frame_height) { - lk.unlock (); GST_WARNING_OBJECT (self, "Unexpected resolution change %dx%d -> %dx%d", self->video_info.width, self->video_info.height, @@ -1938,6 +1952,7 @@ gst_decklink2_input_stop_unlocked (GstDeckLink2Input * self) gst_clear_caps (&self->selected_audio_caps); priv->signal = false; priv->was_restarted = false; + priv->need_restart = false; self->skip_first_time = GST_CLOCK_TIME_NONE; self->start_time = GST_CLOCK_TIME_NONE; self->started = FALSE; @@ -2125,6 +2140,12 @@ gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, return E_FAIL; } +void +gst_decklink2_input_schedule_restart (GstDeckLink2Input * input) +{ + input->priv->need_restart = true; +} + void gst_decklink2_input_stop (GstDeckLink2Input * input) { diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h index 6f18d43f53..80aa39c102 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.h @@ -67,6 +67,8 @@ HRESULT gst_decklink2_input_start (GstDeckLink2Input * input, const GstDeckLink2InputVideoConfig * video_config, const GstDeckLink2InputAudioConfig * audio_config); +void gst_decklink2_input_schedule_restart (GstDeckLink2Input * input); + void gst_decklink2_input_stop (GstDeckLink2Input * input); void gst_decklink2_input_set_flushing (GstDeckLink2Input * input, diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp index b2185c3acc..10705adf9f 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2src.cpp @@ -680,12 +680,7 @@ gst_decklink2_src_create (GstPushSrc * src, GstBuffer ** buffer) GST_STIME_FORMAT ", threshold %" GST_TIME_FORMAT, GST_STIME_ARGS (av_sync), GST_TIME_ARGS (self->desync_threshold)); - self->running = FALSE; - gst_decklink2_input_stop (self->input); - if (!gst_decklink2_src_run_unlocked (self, TRUE)) { - GST_ERROR_OBJECT (self, "Couldn't restart input"); - return GST_FLOW_ERROR; - } + gst_decklink2_input_schedule_restart (self->input); } } @@ -801,8 +796,7 @@ gst_decklink2_src_restart (GstDeckLink2Src * self) std::lock_guard < std::mutex > lk (priv->lock); if (self->input && self->running) { - GST_INFO_OBJECT (self, "Stopping input for restart"); - self->running = FALSE; - gst_decklink2_input_stop (self->input); + GST_INFO_OBJECT (self, "Scheduling restart"); + gst_decklink2_input_schedule_restart (self->input); } } From 8ac14f829f654598862e8bd9bbf55bab5caf2b0c Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 4 Apr 2024 01:50:20 +0900 Subject: [PATCH 50/82] decklink2: Fix caps to mode conversion Build format list with custom mode preserved, instead of real mode --- .../sys/decklink2/gstdecklink2utils.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp index 3a930ab223..276795499e 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2utils.cpp @@ -1054,9 +1054,26 @@ gst_decklink2_build_template_caps (GstObject * io_object, /* Add custom wide mode */ switch (bdm_mode) { case bmdModeNTSC: + gst_mode_wide = gst_mode; + gst_mode_wide.mode = bmdModeNTSC_W; + gst_mode_wide.par_n = 40; + gst_mode_wide.par_d = 33; + s_wide = gst_structure_copy (s); + gst_structure_set (s_wide, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 40, 33, NULL); + break; case bmdModeNTSC2398: + gst_mode_wide = gst_mode; + gst_mode_wide.mode = bmdModeNTSC2398_W; + gst_mode_wide.par_n = 40; + gst_mode_wide.par_d = 33; + s_wide = gst_structure_copy (s); + gst_structure_set (s_wide, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 40, 33, NULL); + break; case bmdModeNTSCp: gst_mode_wide = gst_mode; + gst_mode_wide.mode = bmdModeNTSCp_W; gst_mode_wide.par_n = 40; gst_mode_wide.par_d = 33; s_wide = gst_structure_copy (s); @@ -1064,8 +1081,17 @@ gst_decklink2_build_template_caps (GstObject * io_object, "pixel-aspect-ratio", GST_TYPE_FRACTION, 40, 33, NULL); break; case bmdModePAL: + gst_mode_wide = gst_mode; + gst_mode_wide.mode = bmdModePAL_W; + gst_mode_wide.par_n = 16; + gst_mode_wide.par_d = 11; + s_wide = gst_structure_copy (s); + gst_structure_set (s_wide, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 16, 11, NULL); + break; case bmdModePALp: gst_mode_wide = gst_mode; + gst_mode_wide.mode = bmdModePALp_W; gst_mode_wide.par_n = 16; gst_mode_wide.par_d = 11; s_wide = gst_structure_copy (s); From 6392d4b1557924699613c9b578440eaecf640011 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 17 May 2024 23:03:19 +0900 Subject: [PATCH 51/82] filesrc: Don't abort on _get_osfhandle() _get_osfhandle() expects valid fd and CRT will abort program if given paramerter is invalid. The fd can be invalidated in various way, file was deleted by other process after we open a file. To avoid it, our own exception handler must be installed so that _get_osfhandle() can return INVALID_HANDLE_VALUE if fd is invalid. --- subprojects/gstreamer/plugins/elements/gstfilesrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.c b/subprojects/gstreamer/plugins/elements/gstfilesrc.c index 3b1eb495fb..5f734ec763 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.c @@ -481,7 +481,7 @@ gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size) #ifdef G_OS_WIN32 { - HANDLE h = (HANDLE) _get_osfhandle (_fileno (src->fp)); + HANDLE h = gst_file_src_win32_get_osfhandle (src->fd); LARGE_INTEGER file_size; if (h == INVALID_HANDLE_VALUE) @@ -529,7 +529,7 @@ gst_file_src_start (GstBaseSrc * basesrc) #ifdef G_OS_WIN32 { - HANDLE h = (HANDLE) _get_osfhandle (_fileno (src->fp)); + HANDLE h = gst_file_src_win32_get_osfhandle (src->fd); FILE_STANDARD_INFO file_info; if (h == INVALID_HANDLE_VALUE) From 6dc6ce634158b621e27f098ef4c559b7a2849e15 Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Fri, 17 May 2024 13:49:50 -0400 Subject: [PATCH 52/82] fix cherry-pick --- subprojects/gstreamer/plugins/elements/gstfilesrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.c b/subprojects/gstreamer/plugins/elements/gstfilesrc.c index 5f734ec763..d150b413e2 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.c @@ -481,7 +481,7 @@ gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size) #ifdef G_OS_WIN32 { - HANDLE h = gst_file_src_win32_get_osfhandle (src->fd); + HANDLE h = gst_file_src_win32_get_osfhandle (src->fp); LARGE_INTEGER file_size; if (h == INVALID_HANDLE_VALUE) @@ -529,7 +529,7 @@ gst_file_src_start (GstBaseSrc * basesrc) #ifdef G_OS_WIN32 { - HANDLE h = gst_file_src_win32_get_osfhandle (src->fd); + HANDLE h = gst_file_src_win32_get_osfhandle (src->fp); FILE_STANDARD_INFO file_info; if (h == INVALID_HANDLE_VALUE) From b31c07e05233b92b9eeaebcb8b3b972bd4195ef3 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Mon, 20 May 2024 20:16:50 +0900 Subject: [PATCH 53/82] filesrc: Fix build --- .../gstreamer/plugins/elements/gstfilesrc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/subprojects/gstreamer/plugins/elements/gstfilesrc.c b/subprojects/gstreamer/plugins/elements/gstfilesrc.c index d150b413e2..192088126f 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesrc.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesrc.c @@ -444,21 +444,27 @@ gst_file_src_win32_iph (wchar_t const *exp, wchar_t const *func, } static HANDLE -gst_file_src_win32_get_osfhandle (int fd) +gst_file_src_win32_get_osfhandle (FILE * fp) { HANDLE handle; + int fd; _invalid_parameter_handler old_iph = _set_thread_local_invalid_parameter_handler (gst_file_src_win32_iph); - handle = (HANDLE) _get_osfhandle (fd); + fd = _fileno (fp); + if (fd == -1) { + handle = INVALID_HANDLE_VALUE; + } else { + handle = (HANDLE) _get_osfhandle (fd); + } _set_thread_local_invalid_parameter_handler (old_iph); return handle; } #else /* HAVE__SET_THREAD_LOCAL_INVALID_PARAMETER_HANDLER */ static HANDLE -gst_file_src_win32_get_osfhandle (int fd) +gst_file_src_win32_get_osfhandle (FILE * fp) { - return (HANDLE) _get_osfhandle (fd); + return (HANDLE) _get_osfhandle (_fileno (fp)); } #endif /* HAVE__SET_THREAD_LOCAL_INVALID_PARAMETER_HANDLER */ #endif /* G_OS_WIN32 */ From 7ed825625542c6bf8a1023407a93fe960c8e5f4f Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Tue, 11 Jun 2024 10:47:10 -0400 Subject: [PATCH 54/82] [TEST] - Test default max decode threads at 2 --- subprojects/gst-libav/ext/libav/gstavviddec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gst-libav/ext/libav/gstavviddec.c b/subprojects/gst-libav/ext/libav/gstavviddec.c index e21f3e1558..fb3546b5f3 100644 --- a/subprojects/gst-libav/ext/libav/gstavviddec.c +++ b/subprojects/gst-libav/ext/libav/gstavviddec.c @@ -46,7 +46,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); #define DEFAULT_LOWRES 0 #define DEFAULT_SKIPFRAME 0 #define DEFAULT_DIRECT_RENDERING TRUE -#define DEFAULT_MAX_THREADS 0 +#define DEFAULT_MAX_THREADS 2 #define DEFAULT_OUTPUT_CORRUPT TRUE #define REQUIRED_POOL_MAX_BUFFERS 32 #define DEFAULT_STRIDE_ALIGN 31 From 242088cdb6eed157b9f3f8e1e05e7fe92421804c Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Tue, 18 Jun 2024 07:32:16 -0400 Subject: [PATCH 55/82] Revert "[TEST] - Test default max decode threads at 2" This reverts commit 2e354f6090e355d28768dd1fb1fe479eb174d88b. --- subprojects/gst-libav/ext/libav/gstavviddec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gst-libav/ext/libav/gstavviddec.c b/subprojects/gst-libav/ext/libav/gstavviddec.c index fb3546b5f3..e21f3e1558 100644 --- a/subprojects/gst-libav/ext/libav/gstavviddec.c +++ b/subprojects/gst-libav/ext/libav/gstavviddec.c @@ -46,7 +46,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); #define DEFAULT_LOWRES 0 #define DEFAULT_SKIPFRAME 0 #define DEFAULT_DIRECT_RENDERING TRUE -#define DEFAULT_MAX_THREADS 2 +#define DEFAULT_MAX_THREADS 0 #define DEFAULT_OUTPUT_CORRUPT TRUE #define REQUIRED_POOL_MAX_BUFFERS 32 #define DEFAULT_STRIDE_ALIGN 31 From e61a7229059d87af9d79255518e1810d346199d6 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 8 Aug 2024 06:23:47 +0900 Subject: [PATCH 56/82] timecodestamper: Add running-time source mode Add a new source mode "running-time". This mode will convert buffer running time into timecode --- subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c b/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c index 61f3a60ff1..60bed86265 100644 --- a/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c +++ b/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c @@ -2009,6 +2009,10 @@ gst_timecodestamper_transform_ip (GstBaseTransform * vfilter, timecodestamper->fps_n, timecodestamper->fps_d * GST_SECOND); guint field_count = 0; +<<<<<<< HEAD +======= + /* TODO: how to get field count from running time? */ +>>>>>>> 95898190d8 (timecodestamper: Add running-time source mode) if (timecodestamper->interlace_mode != GST_VIDEO_INTERLACE_MODE_PROGRESSIVE) { field_count = 1; From 77455c02b8e85512228ecc87512ca5f9a646d9dc Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Sun, 1 Dec 2024 12:46:49 -0500 Subject: [PATCH 57/82] Fix rebase --- subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c b/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c index 60bed86265..61f3a60ff1 100644 --- a/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c +++ b/subprojects/gst-plugins-bad/gst/timecode/gsttimecodestamper.c @@ -2009,10 +2009,6 @@ gst_timecodestamper_transform_ip (GstBaseTransform * vfilter, timecodestamper->fps_n, timecodestamper->fps_d * GST_SECOND); guint field_count = 0; -<<<<<<< HEAD -======= - /* TODO: how to get field count from running time? */ ->>>>>>> 95898190d8 (timecodestamper: Add running-time source mode) if (timecodestamper->interlace_mode != GST_VIDEO_INTERLACE_MODE_PROGRESSIVE) { field_count = 1; From 6bef836c3cabf33f5fbfba43dd6fc83a31e36fc4 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 4 Nov 2024 11:11:56 +0100 Subject: [PATCH 58/82] line21dec: Handle the case where there is only one line of CC There are some streams out there that only have valid content on a single line (i.e. a single field). Part-of: --- .../gst/closedcaption/gstline21dec.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/closedcaption/gstline21dec.c b/subprojects/gst-plugins-bad/gst/closedcaption/gstline21dec.c index 4e5b7702c6..661711af27 100644 --- a/subprojects/gst-plugins-bad/gst/closedcaption/gstline21dec.c +++ b/subprojects/gst-plugins-bad/gst/closedcaption/gstline21dec.c @@ -490,6 +490,7 @@ gst_line_21_decoder_scan (GstLine21Decoder * self, GstVideoFrame * frame) gint i; vbi_sliced sliced[52]; gboolean found = FALSE; + gboolean dual_lines = TRUE; guint8 *data; if (self->mode == GST_LINE_21_DECODER_MODE_DROP && @@ -511,13 +512,14 @@ gst_line_21_decoder_scan (GstLine21Decoder * self, GstVideoFrame * frame) for (; i < self->max_line_probes && i < GST_VIDEO_FRAME_HEIGHT (frame); i++) { gint n_lines; data = get_video_data (self, frame, i); - /* Scan until we get n_lines == 2 */ + /* Scan until we get n_lines == 2 (or 1 if only 1 line present) */ n_lines = vbi_raw_decode (&self->zvbi_decoder, data, sliced); GST_DEBUG_OBJECT (self, "i:%d n_lines:%d", i, n_lines); - if (n_lines == 2) { - GST_DEBUG_OBJECT (self, "Found 2 CC lines at offset %d", i); + if (n_lines == 2 || n_lines == 1) { + GST_DEBUG_OBJECT (self, "Found %d CC lines at offset %d", n_lines, i); self->line21_offset = i; found = TRUE; + dual_lines = n_lines == 2; break; } else if (i == self->line21_offset) { /* Otherwise if this was the previously probed line offset, @@ -550,9 +552,11 @@ gst_line_21_decoder_scan (GstLine21Decoder * self, GstVideoFrame * frame) ccdata[0] |= (base_line1 < i ? i - base_line1 : 0) & 0x1f; ccdata[1] = sliced[0].data[0]; ccdata[2] = sliced[0].data[1]; - ccdata[3] |= (base_line2 < i ? i - base_line2 : 0) & 0x1f; - ccdata[4] = sliced[1].data[0]; - ccdata[5] = sliced[1].data[1]; + if (dual_lines) { + ccdata[3] |= (base_line2 < i ? i - base_line2 : 0) & 0x1f; + ccdata[4] = sliced[1].data[0]; + ccdata[5] = sliced[1].data[1]; + } gst_buffer_add_video_caption_meta (frame->buffer, GST_VIDEO_CAPTION_TYPE_CEA608_S334_1A, ccdata, 6); GST_TRACE_OBJECT (self, From 3e50c8d79f392668779577f6aecdd0ba6952326c Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Fri, 6 Dec 2024 06:25:16 -0500 Subject: [PATCH 59/82] Add warning about if there is audio with no video from decklink2src --- .../gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 3ad5d4f706..8b99af57ec 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -1806,6 +1806,10 @@ gst_decklink2_input_on_frame_arrived (GstDeckLink2Input * self, goto out; } + if (!frame) { + GST_WARNING_OBJECT (self, "Received audio packet without video frame. This indicates video processing is not fast enough."); + } + long sample_count = packet->GetSampleFrameCount (); if (sample_count == 0) { GST_DEBUG_OBJECT (self, "Empty audio packet"); From f347240ff5d1d9038b85cb915871df72e9ca99d7 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 8 Jan 2025 23:01:20 +0900 Subject: [PATCH 60/82] decklink2src: Respect requested video-format Use requested video-format in case of auto detect mode as well --- .../sys/decklink2/gstdecklink2input.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index 8b99af57ec..aed54b1d39 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -390,6 +390,7 @@ struct _GstDeckLink2Input GstDeckLink2DisplayMode selected_mode; BMDPixelFormat pixel_format; + BMDPixelFormat requested_pixel_format; GstElement *client; gboolean output_cc; gboolean output_afd_bar; @@ -1071,6 +1072,15 @@ gst_decklink2_input_reset_time_mapping (GstDeckLink2Input * self) self->next_time_mapping.den = 1; } +static inline gboolean +is_yuv_pixel_format (BMDPixelFormat format) +{ + if (format == bmdFormat8BitYUV || format == bmdFormat10BitYUV) + return TRUE; + + return FALSE; +} + static HRESULT gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode * mode, @@ -1115,6 +1125,13 @@ gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, return E_INVALIDARG; } + if (self->requested_pixel_format != pixel_format && + is_yuv_pixel_format (self->requested_pixel_format) && + is_yuv_pixel_format (pixel_format)) { + GST_DEBUG_OBJECT (self, "Updating format as requested"); + pixel_format = self->requested_pixel_format; + } + video_format = gst_decklink2_video_format_from_pixel_format (pixel_format); caps = gst_decklink2_get_caps_from_mode (&new_mode); @@ -2061,7 +2078,8 @@ gst_decklink2_input_start (GstDeckLink2Input * input, GstElement * client, input->client = client; input->selected_mode = video_config->display_mode; - input->pixel_format = video_config->pixel_format; + input->pixel_format = input->requested_pixel_format = + video_config->pixel_format; input->output_cc = video_config->output_cc; input->output_afd_bar = video_config->output_afd_bar; input->buffer_size = buffer_size; From 8831ce4898b806650c11c9698101e2f490e9ff19 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 11 Feb 2025 03:26:25 +0900 Subject: [PATCH 61/82] decklink2src: Avoid unnecessary restart on format change callback If detected format is compatible with previous format, do not restart stream --- .../sys/decklink2/gstdecklink2input.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp index aed54b1d39..2faa03682a 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2input.cpp @@ -1140,6 +1140,17 @@ gst_decklink2_input_on_format_changed (GstDeckLink2Input * self, GST_DEBUG_OBJECT (self, "Updated caps %" GST_PTR_FORMAT, caps); + { + std::lock_guard < std::mutex > lk (priv->lock); + if (self->selected_video_caps && + gst_caps_is_equal (self->selected_video_caps, caps) && + self->pixel_format == pixel_format) { + GST_DEBUG_OBJECT (self, "Format not changed, skipping enable video"); + gst_caps_unref (caps); + return S_OK; + } + } + gst_decklink2_input_pause_streams (self); gst_decklink2_input_enable_video (self, display_mode, pixel_format, bmdVideoInputEnableFormatDetection); From b662620b1f61d8938d510b8d06d14a7b74e827dc Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 20 Feb 2025 15:30:31 +0900 Subject: [PATCH 62/82] decklink2output: Fix out of bounds read --- .../gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index c594259f20..afb1560149 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -488,6 +488,10 @@ class GstDecklink2OutputAudioBuffer num_samples = buffer_.size () / info_.bpf; sample_pos = pos_; + + if (num_samples == 0) + return NULL; + return &buffer_[0]; } From 587b726db16304a6ddeec55b62b74538659eb426 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 7 Aug 2025 21:19:59 +0900 Subject: [PATCH 63/82] avviddec: Drop frame on resolution mismatch ... instead of crashing --- subprojects/gst-libav/ext/libav/gstavviddec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-libav/ext/libav/gstavviddec.c b/subprojects/gst-libav/ext/libav/gstavviddec.c index e21f3e1558..3a5a88cd5a 100644 --- a/subprojects/gst-libav/ext/libav/gstavviddec.c +++ b/subprojects/gst-libav/ext/libav/gstavviddec.c @@ -2136,9 +2136,10 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, GstVideoInfo *info = &ffmpegdec->output_state->info; if (vmeta->width != GST_VIDEO_INFO_WIDTH (info) || vmeta->height != GST_VIDEO_INFO_HEIGHT (info)) { - g_error ("video meta uses %dx%d instead of %dx%d", + GST_ERROR_OBJECT (ffmpegdec, "video meta uses %dx%d instead of %dx%d", vmeta->width, vmeta->height, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info)); + GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (output_frame); } } } From df078457f15064b6ef21a41fb3b59dfac0291caa Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 10 Sep 2025 17:12:46 +0900 Subject: [PATCH 64/82] decodebin3: Add decoder-factory-sort signal Introduce a new "decoder-factory-sort" signal, similar to the "autoplug-sort" signal in (uri)decodebin. This allows applications to reorder the list of candidate decoder factories based on their own preferences --- .../gst/playback/gstdecodebin3.c | 112 ++++++++++++++++-- .../gst/playback/gsturidecodebin3.c | 77 ++++++++++++ 2 files changed, 176 insertions(+), 13 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/playback/gstdecodebin3.c b/subprojects/gst-plugins-base/gst/playback/gstdecodebin3.c index 7286570d13..0b822ea3ba 100644 --- a/subprojects/gst-plugins-base/gst/playback/gstdecodebin3.c +++ b/subprojects/gst-plugins-base/gst/playback/gstdecodebin3.c @@ -321,6 +321,10 @@ struct _GstDecodebin3Class gint (*select_stream) (GstDecodebin3 * dbin, GstStreamCollection * collection, GstStream * stream); + + /* signal fired to sort the factories */ + GValueArray *(*decoder_factory_sort) (GstDecodebin3 * dbin, + GstCaps * caps, GValueArray * factories); }; /* Input of decodebin, controls input pad and parsebin */ @@ -453,6 +457,7 @@ enum { SIGNAL_SELECT_STREAM, SIGNAL_ABOUT_TO_FINISH, + SIGNAL_DECODER_FACTORY_SORT, LAST_SIGNAL }; static guint gst_decodebin3_signals[LAST_SIGNAL] = { 0 }; @@ -569,6 +574,13 @@ gst_decodebin3_select_stream (GstDecodebin3 * dbin, return -1; } +static GValueArray * +gst_decodebin3_decoder_factory_sort (GstDecodebin3 * dbin, + GstCaps * caps, GValueArray * factories) +{ + return NULL; +} + static GstPad *gst_decodebin3_request_new_pad (GstElement * element, GstPadTemplate * temp, const gchar * name, const GstCaps * caps); static void gst_decodebin3_release_pad (GstElement * element, GstPad * pad); @@ -638,6 +650,21 @@ _gst_int_accumulator (GSignalInvocationHint * ihint, return FALSE; } +static gboolean +_gst_array_hasvalue_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gpointer array; + + array = g_value_get_boxed (handler_return); + g_value_set_boxed (return_accu, array); + + if (array != NULL) + return FALSE; + + return TRUE; +} + static void gst_decodebin3_class_init (GstDecodebin3Class * klass) { @@ -687,6 +714,37 @@ gst_decodebin3_class_init (GstDecodebin3Class * klass) g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstDecodeBin3::decoder-factory-sort: + * @decodebin: a #GstDecodebin3 + * @caps: a #GstCaps. + * @factories: A #GValueArray of possible #GstElementFactory to use. + * + * Once decodebin3 has found the possible decoder #GstElementFactory objects + * to try for @caps, this signal is emitted. The purpose of the signal is for + * the application to perform additional sorting or filtering on the decoder + * factory array. + * + * The callee should copy and modify @factories or return %NULL if the + * order should not change. + * + * > Invocation of signal handlers stops after one signal handler has + * > returned something else than %NULL. Signal handlers are invoked in + * > the order they were connected in. + * > Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * > signal, they will never be invoked! + * + * Returns: A new sorted array of decoder #GstElementFactory objects. + * + * Since: 1.28 + */ + gst_decodebin3_signals[SIGNAL_DECODER_FACTORY_SORT] = + g_signal_new ("decoder-factory-sort", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDecodebin3Class, decoder_factory_sort), + _gst_array_hasvalue_accumulator, NULL, + NULL, G_TYPE_VALUE_ARRAY, 2, GST_TYPE_CAPS, + G_TYPE_VALUE_ARRAY | G_SIGNAL_TYPE_STATIC_SCOPE); element_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_decodebin3_request_new_pad); @@ -717,6 +775,7 @@ gst_decodebin3_class_init (GstDecodebin3Class * klass) bin_klass->handle_message = gst_decodebin3_handle_message; klass->select_stream = gst_decodebin3_select_stream; + klass->decoder_factory_sort = gst_decodebin3_decoder_factory_sort; } static void @@ -3713,17 +3772,31 @@ gst_decodebin_input_link_to_slot (DecodebinInputStream * input_stream) slot->input = input_stream; } -static GList * +static GValueArray * create_decoder_factory_list (GstDecodebin3 * dbin, GstCaps * caps) { - GList *res; + GList *list, *tmp; + GValueArray *result; g_mutex_lock (&dbin->factories_lock); gst_decode_bin_update_factories_list (dbin); - res = gst_element_factory_list_filter (dbin->decoder_factories, + list = gst_element_factory_list_filter (dbin->decoder_factories, caps, GST_PAD_SINK, TRUE); g_mutex_unlock (&dbin->factories_lock); - return res; + + result = g_value_array_new (g_list_length (list)); + for (tmp = list; tmp; tmp = tmp->next) { + GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data); + GValue val = G_VALUE_INIT; + + g_value_init (&val, G_TYPE_OBJECT); + g_value_set_object (&val, factory); + g_value_array_append (result, &val); + g_value_unset (&val); + } + gst_plugin_feature_list_free (list); + + return result; } static GstPadProbeReturn @@ -3848,7 +3921,9 @@ db_output_stream_setup_decoder (DecodebinOutputStream * output, gboolean ret = TRUE; GstDecodebin3 *dbin = output->dbin; MultiQueueSlot *slot = output->slot; - GList *factories, *next_factory; + GValueArray *factories = NULL; + GValueArray *result = NULL; + guint i; GST_DEBUG_OBJECT (dbin, "output %s:%s caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME (output->src_pad), new_caps); @@ -3859,20 +3934,28 @@ db_output_stream_setup_decoder (DecodebinOutputStream * output, goto done; } - factories = next_factory = create_decoder_factory_list (dbin, new_caps); - if (!next_factory) { + factories = create_decoder_factory_list (dbin, new_caps); + g_signal_emit (dbin, gst_decodebin3_signals[SIGNAL_DECODER_FACTORY_SORT], 0, + new_caps, factories, &result); + if (result) { + g_value_array_free (factories); + factories = result; + } + + if (factories->n_values == 0) { GST_DEBUG ("Could not find an element for caps %" GST_PTR_FORMAT, new_caps); g_assert (output->decoder == NULL); ret = FALSE; goto missing_decoder; } - while (next_factory) { + for (i = 0; i < factories->n_values; i++) { CandidateDecoder *candidate = NULL; + GstElementFactory *factory = + g_value_get_object (g_value_array_get_nth (factories, i)); /* If we don't have a decoder yet, instantiate one */ - output->decoder = gst_element_factory_create ( - (GstElementFactory *) next_factory->data, NULL); + output->decoder = gst_element_factory_create (factory, NULL); GST_DEBUG ("Trying decoder %" GST_PTR_FORMAT, output->decoder); if (output->decoder == NULL) @@ -3928,16 +4011,14 @@ db_output_stream_setup_decoder (DecodebinOutputStream * output, if (candidate) remove_candidate_decoder (dbin, candidate); - if (!next_factory->next) { + if (i + 1 == factories->n_values) { ret = FALSE; if (output->decoder == NULL) goto missing_decoder; goto cleanup; } - next_factory = next_factory->next; } } - gst_plugin_feature_list_free (factories); done: if (output->type & GST_STREAM_TYPE_VIDEO && slot->drop_probe_id == 0) { @@ -3956,6 +4037,8 @@ db_output_stream_setup_decoder (DecodebinOutputStream * output, if (output->decoder) gst_element_sync_state_with_parent (output->decoder); + g_clear_pointer (&factories, g_value_array_free); + return ret; missing_decoder: @@ -3989,6 +4072,9 @@ db_output_stream_setup_decoder (DecodebinOutputStream * output, gst_bin_remove ((GstBin *) dbin, output->decoder); output->decoder = NULL; } + + g_clear_pointer (&factories, g_value_array_free); + return ret; } } diff --git a/subprojects/gst-plugins-base/gst/playback/gsturidecodebin3.c b/subprojects/gst-plugins-base/gst/playback/gsturidecodebin3.c index 9ca023f773..8c64e9cda4 100644 --- a/subprojects/gst-plugins-base/gst/playback/gsturidecodebin3.c +++ b/subprojects/gst-plugins-base/gst/playback/gsturidecodebin3.c @@ -251,6 +251,7 @@ struct _GstURIDecodeBin3 gulong db_pad_removed_id; gulong db_select_stream_id; gulong db_about_to_finish_id; + gulong db_decoder_factory_sort_id; /* 1 if shutting down */ gint shutdown; @@ -269,12 +270,23 @@ gst_uridecodebin3_select_stream (GstURIDecodeBin3 * dbin, return -1; } +static GValueArray * +gst_uridecodebin3_decoder_factory_sort (GstURIDecodeBin3 * dbin, + GstCaps * caps, GValueArray * factories) +{ + return NULL; +} + struct _GstURIDecodeBin3Class { GstBinClass parent_class; gint (*select_stream) (GstURIDecodeBin3 * dbin, GstStreamCollection * collection, GstStream * stream); + + /* signal fired to sort the factories */ + GValueArray *(*decoder_factory_sort) (GstURIDecodeBin3 * dbin, + GstCaps * caps, GValueArray * factories); }; GST_DEBUG_CATEGORY_STATIC (gst_uri_decode_bin3_debug); @@ -286,6 +298,7 @@ enum SIGNAL_SELECT_STREAM, SIGNAL_SOURCE_SETUP, SIGNAL_ABOUT_TO_FINISH, + SIGNAL_DECODER_FACTORY_SORT, LAST_SIGNAL }; @@ -405,6 +418,20 @@ _gst_int_accumulator (GSignalInvocationHint * ihint, return FALSE; } +static gboolean +_gst_array_hasvalue_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gpointer array; + + array = g_value_get_boxed (handler_return); + g_value_set_boxed (return_accu, array); + + if (array != NULL) + return FALSE; + + return TRUE; +} static void gst_uri_decode_bin3_class_init (GstURIDecodeBin3Class * klass) @@ -573,6 +600,37 @@ gst_uri_decode_bin3_class_init (GstURIDecodeBin3Class * klass) g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstURIDecodeBin3::decoder-factory-sort: + * @decodebin: a #GstURIDecodebin3 + * @caps: a #GstCaps. + * @factories: A #GValueArray of possible #GstElementFactory to use. + * + * Once decodebin3 has found the possible decoder #GstElementFactory objects + * to try for @caps, this signal is emitted. The purpose of the signal is for + * the application to perform additional sorting or filtering on the decoder + * factory array. + * + * The callee should copy and modify @factories or return %NULL if the + * order should not change. + * + * > Invocation of signal handlers stops after one signal handler has + * > returned something else than %NULL. Signal handlers are invoked in + * > the order they were connected in. + * > Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * > signal, they will never be invoked! + * + * Returns: A new sorted array of decoder #GstElementFactory objects. + * + * Since: 1.28 + */ + gst_uri_decode_bin3_signals[SIGNAL_DECODER_FACTORY_SORT] = + g_signal_new ("decoder-factory-sort", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstURIDecodeBin3Class, decoder_factory_sort), + _gst_array_hasvalue_accumulator, NULL, + NULL, G_TYPE_VALUE_ARRAY, 2, GST_TYPE_CAPS, + G_TYPE_VALUE_ARRAY | G_SIGNAL_TYPE_STATIC_SCOPE); gst_element_class_add_static_pad_template (gstelement_class, &video_src_template); @@ -593,6 +651,7 @@ gst_uri_decode_bin3_class_init (GstURIDecodeBin3Class * klass) gstbin_class->handle_message = gst_uri_decode_bin3_handle_message; klass->select_stream = gst_uridecodebin3_select_stream; + klass->decoder_factory_sort = gst_uridecodebin3_decoder_factory_sort; } static void @@ -885,6 +944,21 @@ db_about_to_finish_cb (GstElement * decodebin, GstURIDecodeBin3 * uridecodebin) emit_and_handle_about_to_finish (uridecodebin, uridecodebin->output_item); } +static GValueArray * +db_decoder_factory_sort_cb (GstElement * decodebin, + GstCaps * caps, GValueArray * factories, GstURIDecodeBin3 * uridecodebin) +{ + GValueArray *result; + + g_signal_emit (uridecodebin, + gst_uri_decode_bin3_signals[SIGNAL_DECODER_FACTORY_SORT], 0, caps, + factories, &result); + + GST_DEBUG_OBJECT (uridecodebin, "decoder-factory-sort returned %p", result); + + return result; +} + static void gst_uri_decode_bin3_init (GstURIDecodeBin3 * dec) { @@ -915,6 +989,9 @@ gst_uri_decode_bin3_init (GstURIDecodeBin3 * dec) dec->db_about_to_finish_id = g_signal_connect (dec->decodebin, "about-to-finish", G_CALLBACK (db_about_to_finish_cb), dec); + dec->db_decoder_factory_sort_id = + g_signal_connect (dec->decodebin, "decoder-factory-sort", + G_CALLBACK (db_decoder_factory_sort_cb), dec); GST_OBJECT_FLAG_SET (dec, GST_ELEMENT_FLAG_SOURCE); gst_bin_set_suppressed_flags (GST_BIN (dec), From 4ee6153ba43b9ffdee21005393611dd9df62bd98 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 4 Nov 2025 16:44:49 +0900 Subject: [PATCH 65/82] videoaggregator: Remove input interlace-mode and alpha restrictions Previously, videoaggregator enforced consistent input interlace-mode, but this makes little sense from a base class perspective because: * Subclasses (e.g. compositor) may perform rescaling or cropping. Even without rescaling, if the target position's vertical start offset is not aligned to an even number, blending already happens between mismatched field positions, resulting in suboptimal image quality. Therefore, enforcing a consistent interlace-mode provides little real benefit. * For best image quality, blending should always occur in progressive mode, though performing pre-deinterlacing can either be the user's responsibility or be handled internally by subclasses if desired. Similarly, input formats with an alpha channel are now allowed even when the output format does not have one. Filtering out alpha-capable input formats in such cases is unnecessary, since subclasses like compositor and d3d12compositor can already handle this properly. --- .../gst-libs/gst/video/gstvideoaggregator.c | 174 ------------------ 1 file changed, 174 deletions(-) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c index 2d8a17dbd2..6f34a328ac 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c @@ -1392,29 +1392,6 @@ gst_video_aggregator_default_negotiated_src_caps (GstAggregator * agg, return ret; } -static gboolean -gst_video_aggregator_get_sinkpads_interlace_mode (GstVideoAggregator * vagg, - GstVideoAggregatorPad * skip_pad, GstVideoInterlaceMode * mode) -{ - GList *walk; - - GST_OBJECT_LOCK (vagg); - for (walk = GST_ELEMENT (vagg)->sinkpads; walk; walk = g_list_next (walk)) { - GstVideoAggregatorPad *vaggpad = walk->data; - - if (skip_pad && vaggpad == skip_pad) - continue; - if (vaggpad->info.finfo - && GST_VIDEO_INFO_FORMAT (&vaggpad->info) != GST_VIDEO_FORMAT_UNKNOWN) { - *mode = GST_VIDEO_INFO_INTERLACE_MODE (&vaggpad->info); - GST_OBJECT_UNLOCK (vagg); - return TRUE; - } - } - GST_OBJECT_UNLOCK (vagg); - return FALSE; -} - static gboolean gst_video_aggregator_pad_sink_setcaps (GstPad * pad, GstObject * parent, GstCaps * caps) @@ -1435,30 +1412,6 @@ gst_video_aggregator_pad_sink_setcaps (GstPad * pad, GstObject * parent, } GST_VIDEO_AGGREGATOR_LOCK (vagg); - { - GstVideoInterlaceMode pads_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; - gboolean has_mode = FALSE; - - /* get the current output setting or fallback to other pads settings */ - if (GST_VIDEO_INFO_FORMAT (&vagg->info) != GST_VIDEO_FORMAT_UNKNOWN) { - pads_mode = GST_VIDEO_INFO_INTERLACE_MODE (&vagg->info); - has_mode = TRUE; - } else { - has_mode = - gst_video_aggregator_get_sinkpads_interlace_mode (vagg, vaggpad, - &pads_mode); - } - - if (has_mode) { - if (pads_mode != GST_VIDEO_INFO_INTERLACE_MODE (&info)) { - GST_ERROR_OBJECT (pad, - "got input caps %" GST_PTR_FORMAT ", but current caps are %" - GST_PTR_FORMAT, caps, vagg->priv->current_caps); - GST_VIDEO_AGGREGATOR_UNLOCK (vagg); - return FALSE; - } - } - } if (!vaggpad->info.finfo || GST_VIDEO_INFO_FORMAT (&vaggpad->info) == GST_VIDEO_FORMAT_UNKNOWN) { @@ -1484,116 +1437,6 @@ gst_video_aggregator_pad_sink_setcaps (GstPad * pad, GstObject * parent, return ret; } -static gboolean -gst_video_aggregator_caps_has_alpha (GstCaps * caps) -{ - guint size = gst_caps_get_size (caps); - guint i; - - for (i = 0; i < size; i++) { - GstStructure *s = gst_caps_get_structure (caps, i); - const GValue *formats = gst_structure_get_value (s, "format"); - - if (formats) { - const GstVideoFormatInfo *info; - - if (GST_VALUE_HOLDS_LIST (formats)) { - guint list_size = gst_value_list_get_size (formats); - guint index; - - for (index = 0; index < list_size; index++) { - const GValue *list_item = gst_value_list_get_value (formats, index); - info = - gst_video_format_get_info (gst_video_format_from_string - (g_value_get_string (list_item))); - if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) - return TRUE; - } - - } else if (G_VALUE_HOLDS_STRING (formats)) { - info = - gst_video_format_get_info (gst_video_format_from_string - (g_value_get_string (formats))); - if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) - return TRUE; - - } else { - g_assert_not_reached (); - GST_WARNING ("Unexpected type for video 'format' field: %s", - G_VALUE_TYPE_NAME (formats)); - } - - } else { - return TRUE; - } - } - return FALSE; -} - -static GstCaps * -_get_non_alpha_caps (GstCaps * caps) -{ - GstCaps *result; - guint i, size; - - size = gst_caps_get_size (caps); - result = gst_caps_new_empty (); - for (i = 0; i < size; i++) { - GstStructure *s = gst_caps_get_structure (caps, i); - const GValue *formats = gst_structure_get_value (s, "format"); - GValue new_formats = { 0, }; - gboolean has_format = FALSE; - - /* FIXME what to do if formats are missing? */ - if (formats) { - const GstVideoFormatInfo *info; - - if (GST_VALUE_HOLDS_LIST (formats)) { - guint list_size = gst_value_list_get_size (formats); - guint index; - - g_value_init (&new_formats, GST_TYPE_LIST); - - for (index = 0; index < list_size; index++) { - const GValue *list_item = gst_value_list_get_value (formats, index); - - info = - gst_video_format_get_info (gst_video_format_from_string - (g_value_get_string (list_item))); - if (!GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) { - has_format = TRUE; - gst_value_list_append_value (&new_formats, list_item); - } - } - - } else if (G_VALUE_HOLDS_STRING (formats)) { - info = - gst_video_format_get_info (gst_video_format_from_string - (g_value_get_string (formats))); - if (!GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) { - has_format = TRUE; - gst_value_init_and_copy (&new_formats, formats); - } - - } else { - g_assert_not_reached (); - GST_WARNING ("Unexpected type for video 'format' field: %s", - G_VALUE_TYPE_NAME (formats)); - } - - if (has_format) { - s = gst_structure_copy (s); - gst_structure_take_value_static_str (s, "format", &new_formats); - gst_caps_append_structure_full (result, s, - gst_caps_features_copy (gst_caps_get_features (caps, i))); - } - - } - } - - return result; -} - static GstCaps * gst_video_aggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, GstCaps * filter) @@ -1605,9 +1448,6 @@ gst_video_aggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, gint i, n; GstAggregator *agg = GST_AGGREGATOR (vagg); GstPad *srcpad = GST_PAD (agg->srcpad); - gboolean has_alpha; - GstVideoInterlaceMode interlace_mode; - gboolean has_interlace_mode; template_caps = gst_pad_get_pad_template_caps (srcpad); @@ -1615,11 +1455,6 @@ gst_video_aggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, srccaps = gst_pad_peer_query_caps (srcpad, template_caps); srccaps = gst_caps_make_writable (srccaps); - has_alpha = gst_video_aggregator_caps_has_alpha (srccaps); - - has_interlace_mode = - gst_video_aggregator_get_sinkpads_interlace_mode (vagg, NULL, - &interlace_mode); n = gst_caps_get_size (srccaps); for (i = 0; i < n; i++) { @@ -1633,10 +1468,6 @@ gst_video_aggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, gst_structure_remove_fields (s, "colorimetry", "chroma-site", "format", "pixel-aspect-ratio", NULL); } - - if (has_interlace_mode) - gst_structure_set_static_str (s, "interlace-mode", G_TYPE_STRING, - gst_video_interlace_mode_to_string (interlace_mode), NULL); } if (filter) { @@ -1647,11 +1478,6 @@ gst_video_aggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, } sink_template_caps = gst_pad_get_pad_template_caps (pad); - if (!has_alpha) { - GstCaps *tmp = _get_non_alpha_caps (sink_template_caps); - gst_caps_unref (sink_template_caps); - sink_template_caps = tmp; - } { GstCaps *intersect = gst_caps_intersect (returned_caps, sink_template_caps); From 9738938f4a58f40d50343c8a2c0198c73a06ee22 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 6 Nov 2025 17:48:48 +0900 Subject: [PATCH 66/82] videoaggregator: Actually accept differnt interlace-mode --- .../gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c index 6f34a328ac..8f97f52897 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c @@ -1468,6 +1468,8 @@ gst_video_aggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, gst_structure_remove_fields (s, "colorimetry", "chroma-site", "format", "pixel-aspect-ratio", NULL); } + + gst_structure_remove_fields (s, "interlace-mode", NULL); } if (filter) { @@ -2805,6 +2807,8 @@ gst_video_aggregator_pad_sink_acceptcaps (GstPad * pad, gst_structure_remove_fields (s, "colorimetry", "chroma-site", "format", "pixel-aspect-ratio", NULL); } + + gst_structure_remove_fields (s, "interlace-mode", NULL); } ret = gst_caps_can_intersect (caps, accepted_caps); From 97ab75321d8ac6f69c98da4e29a0b24bd2e7718b Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 6 Jan 2026 18:26:06 +0900 Subject: [PATCH 67/82] overlaycomposition: Add support for blending upstream composition By this commit, overlaycomposition will be able to blend upstream overlay-compositions with video frames if downstream does not support the meta. Summary of changes * Port to basetransform * Notify upstream that overlay-composition meta is always supported by this element during negotiation. Then decision whether blending is needed or not will be made by this element --- .../gstoverlaycomposition.c | 924 ++++++++---------- .../gstoverlaycomposition.h | 24 +- 2 files changed, 397 insertions(+), 551 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c index 713ca52a9f..0bed856b29 100644 --- a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c +++ b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c @@ -1,5 +1,6 @@ /* GStreamer * Copyright (C) 2018 Sebastian Dröge + * Copyright (C) 2022 Seungha Yang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,7 +22,9 @@ * SECTION:element-overlaycomposition * * The overlaycomposition element renders an overlay using an application - * provided draw function. + * provided draw function and/or blends already attached + * `GstVideoOverlayComposition` meta with incoming buffer if downstream does not + * support the `GstVideoOverlayComposition` meta. * * ## Example code * @@ -39,11 +42,25 @@ GST_DEBUG_CATEGORY_STATIC (gst_overlay_composition_debug); #define GST_CAT_DEFAULT gst_overlay_composition_debug -#define OVERLAY_COMPOSITION_CAPS GST_VIDEO_CAPS_MAKE (GST_VIDEO_OVERLAY_COMPOSITION_BLEND_FORMATS) - -#define ALL_CAPS OVERLAY_COMPOSITION_CAPS ";" \ +#define TEMPLATE_CAPS \ + GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY "," \ + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, \ + GST_VIDEO_FORMATS_ALL) "; " \ + GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) "; " \ GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("ANY", GST_VIDEO_FORMATS_ANY) +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (TEMPLATE_CAPS) + ); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (TEMPLATE_CAPS) + ); + enum { SIGNAL_CAPS_CHANGED, @@ -53,70 +70,60 @@ enum static guint overlay_composition_signals[LAST_SIGNAL]; -static GstStaticCaps overlay_composition_caps = -GST_STATIC_CAPS (OVERLAY_COMPOSITION_CAPS); - -static gboolean -can_blend_caps (GstCaps * incaps) +typedef enum { - gboolean ret; - GstCaps *caps; - - caps = gst_static_caps_get (&overlay_composition_caps); - ret = gst_caps_is_subset (incaps, caps); - gst_caps_unref (caps); - - return ret; -} + OVERLAY_MODE_UNKNOWN, + OVERLAY_MODE_ADD_META, + OVERLAY_MODE_BLEND, + OVERLAY_MODE_NOT_SUPPORTED, +} OverlayMode; -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (ALL_CAPS) - ); +struct _GstOverlayComposition +{ + GstBaseTransform parent; + + GstSample *sample; + GstVideoInfo info; + guint window_width; + guint window_height; + gboolean system_memory; + gboolean downstream_supports_meta; + gboolean allocation_supports_meta; + gboolean caps_changed; + OverlayMode overlay_mode; +}; -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (ALL_CAPS) - ); +#define gst_overlay_composition_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstOverlayComposition, gst_overlay_composition, + GST_TYPE_BASE_TRANSFORM, + GST_DEBUG_CATEGORY_INIT (gst_overlay_composition_debug, + "overlaycomposition", 0, "Overlay Composition")); -#define parent_class gst_overlay_composition_parent_class -G_DEFINE_TYPE (GstOverlayComposition, gst_overlay_composition, - GST_TYPE_ELEMENT); GST_ELEMENT_REGISTER_DEFINE (overlaycomposition, "overlaycomposition", GST_RANK_NONE, GST_TYPE_OVERLAY_COMPOSITION); -static GstFlowReturn gst_overlay_composition_sink_chain (GstPad * pad, - GstObject * parent, GstBuffer * buffer); -static gboolean gst_overlay_composition_sink_event (GstPad * pad, - GstObject * parent, GstEvent * event); -static gboolean gst_overlay_composition_sink_query (GstPad * pad, - GstObject * parent, GstQuery * query); -static gboolean gst_overlay_composition_src_query (GstPad * pad, - GstObject * parent, GstQuery * query); - -static GstStateChangeReturn gst_overlay_composition_change_state (GstElement * - element, GstStateChange transition); +static gboolean gst_overlay_composition_start (GstBaseTransform * trans); +static gboolean gst_overlay_composition_stop (GstBaseTransform * trans); +static gboolean +gst_overlay_composition_propose_allocation (GstBaseTransform * trans, + GstQuery * decide_query, GstQuery * query); +static gboolean +gst_overlay_composition_decide_allocation (GstBaseTransform * trans, + GstQuery * query); +static GstCaps *gst_overlay_composition_transform_caps (GstBaseTransform * + trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter); +static gboolean gst_overlay_composition_set_caps (GstBaseTransform * trans, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_overlay_composition_transform (GstBaseTransform * + trans, GstBuffer * inbuf, GstBuffer * outbuf); +static GstFlowReturn gst_overlay_composition_generate_output (GstBaseTransform * + trans, GstBuffer ** outbuf); static void gst_overlay_composition_class_init (GstOverlayCompositionClass * klass) { - GstElementClass *gstelement_class = (GstElementClass *) klass; - - GST_DEBUG_CATEGORY_INIT (gst_overlay_composition_debug, "overlaycomposition", - 0, "Overlay Composition"); - - gst_element_class_set_static_metadata (gstelement_class, - "Overlay Composition", "Filter/Editor/Video", - "Overlay Composition", "Sebastian Dröge "); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&src_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sink_template)); - - gstelement_class->change_state = gst_overlay_composition_change_state; + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstBaseTransformClass *transform_class = GST_BASE_TRANSFORM_CLASS (klass); /** * GstOverlayComposition::draw: @@ -149,563 +156,385 @@ gst_overlay_composition_class_init (GstOverlayCompositionClass * klass) g_signal_new ("caps-changed", G_TYPE_FROM_CLASS (klass), 0, 0, NULL, NULL, NULL, G_TYPE_NONE, 3, GST_TYPE_CAPS, G_TYPE_UINT, G_TYPE_UINT); + + gst_element_class_set_static_metadata (element_class, + "Overlay Composition", "Filter/Editor/Video", + "Overlay Composition", "Sebastian Dröge "); + + gst_element_class_add_static_pad_template (element_class, &src_template); + gst_element_class_add_static_pad_template (element_class, &sink_template); + + transform_class->passthrough_on_same_caps = FALSE; + + transform_class->start = GST_DEBUG_FUNCPTR (gst_overlay_composition_start); + transform_class->stop = GST_DEBUG_FUNCPTR (gst_overlay_composition_stop); + transform_class->propose_allocation = + GST_DEBUG_FUNCPTR (gst_overlay_composition_propose_allocation); + transform_class->decide_allocation = + GST_DEBUG_FUNCPTR (gst_overlay_composition_decide_allocation); + transform_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_overlay_composition_transform_caps); + transform_class->set_caps = + GST_DEBUG_FUNCPTR (gst_overlay_composition_set_caps); + transform_class->transform = + GST_DEBUG_FUNCPTR (gst_overlay_composition_transform); + transform_class->generate_output = + GST_DEBUG_FUNCPTR (gst_overlay_composition_generate_output); } static void gst_overlay_composition_init (GstOverlayComposition * self) { - self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_chain_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_overlay_composition_sink_chain)); - gst_pad_set_event_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_overlay_composition_sink_event)); - gst_pad_set_query_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_overlay_composition_sink_query)); - GST_PAD_SET_PROXY_ALLOCATION (self->sinkpad); - gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); - - self->srcpad = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_query_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_overlay_composition_src_query)); - gst_element_add_pad (GST_ELEMENT (self), self->srcpad); } -static GstStateChangeReturn -gst_overlay_composition_change_state (GstElement * element, - GstStateChange transition) +static gboolean +gst_overlay_composition_start (GstBaseTransform * trans) { - GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (element); - GstStateChangeReturn state_ret; + GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); - switch (transition) { - default: - break; - } - - state_ret = - GST_ELEMENT_CLASS (gst_overlay_composition_parent_class)->change_state - (element, transition); - if (state_ret == GST_STATE_CHANGE_FAILURE) - return state_ret; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - memset (&self->info, 0, sizeof (self->info)); - self->window_width = self->window_height = 0; - self->attach_compo_to_buffer = FALSE; - if (self->sample) { - gst_sample_unref (self->sample); - self->sample = NULL; - } - gst_caps_replace (&self->caps, NULL); - gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); - break; - default: - break; - } + self->sample = gst_sample_new (NULL, NULL, NULL, NULL); - return state_ret; + return TRUE; } -/* Based on gstbasetextoverlay.c */ static gboolean -gst_overlay_composition_negotiate (GstOverlayComposition * self, GstCaps * caps) +gst_overlay_composition_stop (GstBaseTransform * trans) { - gboolean upstream_has_meta = FALSE; - gboolean caps_has_meta = FALSE; - gboolean alloc_has_meta = FALSE; - gboolean attach = FALSE; - gboolean ret = TRUE; - guint width, height; - GstCapsFeatures *f; - GstCaps *overlay_caps; - GstQuery *query; - guint alloc_index; - - GST_DEBUG_OBJECT (self, "performing negotiation"); + GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); - /* Clear any pending reconfigure to avoid negotiating twice */ - gst_pad_check_reconfigure (self->srcpad); + g_clear_pointer (&self->sample, gst_sample_unref); - self->window_width = self->window_height = 0; - - if (!caps) - caps = gst_pad_get_current_caps (self->sinkpad); - else - gst_caps_ref (caps); - - if (!caps || gst_caps_is_empty (caps)) - goto no_format; - - /* Check if upstream caps have meta */ - if ((f = gst_caps_get_features (caps, 0))) { - upstream_has_meta = gst_caps_features_contains (f, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - } - - /* Initialize dimensions */ - width = self->info.width; - height = self->info.height; - - if (upstream_has_meta) { - overlay_caps = gst_caps_ref (caps); - } else { - GstCaps *peercaps; - - /* BaseTransform requires caps for the allocation query to work */ - overlay_caps = gst_caps_copy (caps); - f = gst_caps_get_features (overlay_caps, 0); - gst_caps_features_add (f, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - - /* Then check if downstream accept overlay composition in caps */ - /* FIXME: We should probably check if downstream *prefers* the - * overlay meta, and only enforce usage of it if we can't handle - * the format ourselves and thus would have to drop the overlays. - * Otherwise we should prefer what downstream wants here. - */ - peercaps = gst_pad_peer_query_caps (self->srcpad, overlay_caps); - caps_has_meta = !gst_caps_is_empty (peercaps); - gst_caps_unref (peercaps); - - GST_DEBUG_OBJECT (self, "caps have overlay meta %d", caps_has_meta); - } - - if (upstream_has_meta || caps_has_meta) { - /* Send caps immediately, it's needed by GstBaseTransform to get a reply - * from allocation query */ - ret = gst_pad_set_caps (self->srcpad, overlay_caps); - - /* First check if the allocation meta has compositon */ - query = gst_query_new_allocation (overlay_caps, FALSE); + return TRUE; +} - if (!gst_pad_peer_query (self->srcpad, query)) { - /* no problem, we use the query defaults */ - GST_DEBUG_OBJECT (self, "ALLOCATION query failed"); +static gboolean +gst_overlay_composition_propose_allocation (GstBaseTransform * trans, + GstQuery * decide_query, GstQuery * query) +{ + GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); + GstCaps *caps = NULL; + GstCapsFeatures *features; - /* In case we were flushing, mark reconfigure and fail this method, - * will make it retry */ - if (GST_PAD_IS_FLUSHING (self->srcpad)) - ret = FALSE; - } + /* Always proxy allocation query (we don't need allocation) */ + if (!gst_pad_peer_query (trans->srcpad, query)) + return FALSE; - alloc_has_meta = gst_query_find_allocation_meta (query, - GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, &alloc_index); + gst_query_parse_allocation (query, &caps, NULL); + if (!caps) + return FALSE; - GST_DEBUG_OBJECT (self, "sink alloc has overlay meta %d", alloc_has_meta); + if (gst_query_get_n_allocation_pools (query) > 0) + goto done; - if (alloc_has_meta) { - const GstStructure *params; + features = gst_caps_get_features (caps, 0); + if (features && gst_caps_features_contains (features, + GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) { + GstVideoInfo info; + GstBufferPool *pool; + GstStructure *config; + guint size; - gst_query_parse_nth_allocation_meta (query, alloc_index, ¶ms); - if (params) { - if (gst_structure_get (params, "width", G_TYPE_UINT, &width, - "height", G_TYPE_UINT, &height, NULL)) { - GST_DEBUG_OBJECT (self, "received window size: %dx%d", width, height); - g_assert (width != 0 && height != 0); - } - } + if (!gst_video_info_from_caps (&info, caps)) { + GST_ERROR_OBJECT (self, "Invalid caps %" GST_PTR_FORMAT, caps); + return FALSE; } - gst_query_unref (query); - } + pool = gst_video_buffer_pool_new (); + config = gst_buffer_pool_get_config (pool); - /* Update render size if needed */ - self->window_width = width; - self->window_height = height; + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_META); + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); - /* For backward compatibility, we will prefer blitting if downstream - * allocation does not support the meta. In other case we will prefer - * attaching, and will fail the negotiation in the unlikely case we are - * force to blit, but format isn't supported. */ + size = GST_VIDEO_INFO_SIZE (&info); + gst_buffer_pool_config_set_params (config, caps, size, 0, 0); - if (upstream_has_meta) { - attach = TRUE; - } else if (caps_has_meta) { - if (alloc_has_meta) { - attach = TRUE; - } else { - /* Don't attach unless we cannot handle the format */ - attach = !can_blend_caps (caps); + if (!gst_buffer_pool_set_config (pool, config)) { + GST_ERROR_OBJECT (self, "Could not set pool config"); + gst_object_unref (pool); + return FALSE; } - } else { - ret = can_blend_caps (caps); - } - /* If we attach, then pick the overlay caps */ - if (attach) { - GST_DEBUG_OBJECT (self, "Using caps %" GST_PTR_FORMAT, overlay_caps); - /* Caps where already sent */ - } else if (ret) { - GST_DEBUG_OBJECT (self, "Using caps %" GST_PTR_FORMAT, caps); - ret = gst_pad_set_caps (self->srcpad, caps); + gst_query_add_allocation_pool (query, pool, size, 0, 0); + gst_object_unref (pool); } - self->attach_compo_to_buffer = attach; - - if (!ret) { - GST_DEBUG_OBJECT (self, "negotiation failed, schedule reconfigure"); - gst_pad_mark_reconfigure (self->srcpad); +done: + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); + /* This element always supports upstream overlay-composition meta, + * but checks if downstream provided it already, to preserve + * downstream alloc params (e.g., window width/height) */ + if (!gst_query_find_allocation_meta (query, + GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL)) { + gst_query_add_allocation_meta (query, + GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL); } - g_signal_emit (self, overlay_composition_signals[SIGNAL_CAPS_CHANGED], 0, - caps, self->window_width, self->window_height, NULL); - - gst_caps_unref (overlay_caps); - gst_caps_unref (caps); - - return ret; - -no_format: - { - if (caps) - gst_caps_unref (caps); - gst_pad_mark_reconfigure (self->srcpad); - return FALSE; - } + return TRUE; } static gboolean -gst_overlay_composition_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event) +gst_overlay_composition_decide_allocation (GstBaseTransform * trans, + GstQuery * query) { - GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent); - gboolean ret = FALSE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEGMENT: - gst_event_copy_segment (event, &self->segment); - ret = gst_pad_event_default (pad, parent, event); - break; - case GST_EVENT_CAPS:{ - GstCaps *caps; - - gst_event_parse_caps (event, &caps); - if (!gst_video_info_from_caps (&self->info, caps)) { - gst_event_unref (event); - ret = FALSE; - break; - } + GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); + guint alloc_index; - if (!gst_overlay_composition_negotiate (self, caps)) { - gst_event_unref (event); - ret = FALSE; - break; - } + self->allocation_supports_meta = FALSE; + self->overlay_mode = OVERLAY_MODE_UNKNOWN; - gst_caps_replace (&self->caps, caps); + if (gst_query_find_allocation_meta (query, + GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, &alloc_index)) { + const GstStructure *params = NULL; + guint width, height; - ret = TRUE; - gst_event_unref (event); + self->allocation_supports_meta = TRUE; - break; + gst_query_parse_nth_allocation_meta (query, alloc_index, ¶ms); + /* Hold params to forward it at propose_allocation() */ + if (params && gst_structure_get (params, "width", G_TYPE_UINT, &width, + "height", G_TYPE_UINT, &height, NULL) && width > 0 && height > 0) { + GST_INFO_OBJECT (self, "received window size: %dx%d", width, height); + + if (self->window_width != width || self->window_height != height) + self->caps_changed = TRUE; + + self->window_width = width; + self->window_height = height; } - case GST_EVENT_FLUSH_STOP: - gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); - ret = gst_pad_event_default (pad, parent, event); - break; - default: - ret = gst_pad_event_default (pad, parent, event); - break; } - return ret; + return TRUE; } -/* Based on gstbasetextoverlay.c */ -/** - * add_feature_and_intersect: - * - * Creates a new #GstCaps containing the (given caps + - * given caps feature) + (given caps intersected by the - * given filter). - * - * Returns: the new #GstCaps - */ static GstCaps * -add_feature_and_intersect (GstCaps * caps, - const gchar * feature, GstCaps * filter) +add_overlay_feature (GstCaps * caps) { - int i, caps_size; - GstCaps *new_caps; + guint i, m, n; + GstCaps *tmp; + GstCapsFeatures *system_overlay_feature = + gst_caps_features_from_string + (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY ", " + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - new_caps = gst_caps_copy (caps); + tmp = gst_caps_new_empty (); - caps_size = gst_caps_get_size (new_caps); - for (i = 0; i < caps_size; i++) { - GstCapsFeatures *features = gst_caps_get_features (new_caps, i); + n = gst_caps_get_size (caps); + for (i = 0; i < n; i++) { + GstCapsFeatures *features, *orig_features; + GstStructure *s = gst_caps_get_structure (caps, i); - if (!gst_caps_features_is_any (features)) { - gst_caps_features_add (features, feature); - } - } + orig_features = gst_caps_get_features (caps, i); - gst_caps_append (new_caps, gst_caps_intersect_full (caps, - filter, GST_CAPS_INTERSECT_FIRST)); - - return new_caps; -} - -/* Based on gstbasetextoverlay.c */ -/* intersect_by_feature: - * - * Creates a new #GstCaps based on the following filtering rule. - * - * For each individual caps contained in given caps, if the - * caps uses the given caps feature, keep a version of the caps - * with the feature and an another one without. Otherwise, intersect - * the caps with the given filter. - * - * Returns: the new #GstCaps - */ -static GstCaps * -intersect_by_feature (GstCaps * caps, const gchar * feature, GstCaps * filter) -{ - int i, caps_size; - GstCaps *new_caps; - - new_caps = gst_caps_new_empty (); - - caps_size = gst_caps_get_size (caps); - for (i = 0; i < caps_size; i++) { - GstStructure *caps_structure = gst_caps_get_structure (caps, i); - GstCapsFeatures *caps_features = - gst_caps_features_copy (gst_caps_get_features (caps, i)); - GstCaps *filtered_caps; - GstCaps *simple_caps = - gst_caps_new_full (gst_structure_copy (caps_structure), NULL); - gst_caps_set_features (simple_caps, 0, caps_features); - - if (gst_caps_features_contains (caps_features, feature)) { - gst_caps_append (new_caps, gst_caps_copy (simple_caps)); - - gst_caps_features_remove (caps_features, feature); - filtered_caps = gst_caps_ref (simple_caps); + if (gst_caps_features_is_any (orig_features)) { + features = gst_caps_features_copy (system_overlay_feature); } else { - filtered_caps = gst_caps_intersect_full (simple_caps, filter, - GST_CAPS_INTERSECT_FIRST); + m = gst_caps_features_get_size (orig_features); + if (m == 1 && gst_caps_features_contains (orig_features, + GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) { + features = gst_caps_features_copy (system_overlay_feature); + } else { + features = gst_caps_features_copy (orig_features); + if (!gst_caps_features_contains (orig_features, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) { + gst_caps_features_add (features, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); + } + } } - gst_caps_unref (simple_caps); - gst_caps_append (new_caps, filtered_caps); + gst_caps_append_structure_full (tmp, gst_structure_copy (s), features); } - return new_caps; + gst_caps_features_free (system_overlay_feature); + + return tmp; } -/* Based on gstbasetextoverlay.c */ static GstCaps * -gst_overlay_composition_sink_query_caps (GstOverlayComposition * self, - GstCaps * filter) +remove_overlay_feature (GstCaps * caps) { - GstCaps *peer_caps = NULL, *caps = NULL, *overlay_filter = NULL; + guint i, n; + GstCaps *tmp; - if (filter) { - /* filter caps + composition feature + filter caps - * filtered by the software caps. */ - GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps); - overlay_filter = add_feature_and_intersect (filter, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); - - GST_DEBUG_OBJECT (self->sinkpad, "overlay filter %" GST_PTR_FORMAT, - overlay_filter); - } - - peer_caps = gst_pad_peer_query_caps (self->srcpad, overlay_filter); - - if (overlay_filter) - gst_caps_unref (overlay_filter); - - if (peer_caps) { + tmp = gst_caps_new_empty (); - GST_DEBUG_OBJECT (self->sinkpad, "peer caps %" GST_PTR_FORMAT, peer_caps); + n = gst_caps_get_size (caps); + for (i = 0; i < n; i++) { + GstCapsFeatures *features, *orig_features; + GstStructure *s = gst_caps_get_structure (caps, i); - if (gst_caps_is_any (peer_caps)) { - /* if peer returns ANY caps, return filtered src pad template caps */ - GstCaps *tcaps = gst_pad_get_pad_template_caps (self->srcpad); - caps = gst_caps_copy (tcaps); - gst_caps_unref (tcaps); - } else { - - /* duplicate caps which contains the composition into one version with - * the meta and one without. Filter the other caps by the software caps */ - GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps); - caps = intersect_by_feature (peer_caps, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); + orig_features = gst_caps_get_features (caps, i); + features = gst_caps_features_copy (orig_features); + if (!gst_caps_features_is_any (orig_features)) { + gst_caps_features_remove (features, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); } - gst_caps_unref (peer_caps); - - } else { - /* no peer, our padtemplate is enough then */ - caps = gst_pad_get_pad_template_caps (self->sinkpad); - } - - if (filter) { - GstCaps *intersection = gst_caps_intersect_full (filter, caps, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (caps); - caps = intersection; + gst_caps_append_structure_full (tmp, gst_structure_copy (s), features); } - GST_DEBUG_OBJECT (self->sinkpad, "returning %" GST_PTR_FORMAT, caps); - - return caps; + return tmp; } -/* Based on gstbasetextoverlay.c */ static GstCaps * -gst_overlay_composition_src_query_caps (GstOverlayComposition * self, - GstCaps * filter) +gst_overlay_composition_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) { - GstCaps *peer_caps = NULL, *caps = NULL, *overlay_filter = NULL; - - if (filter) { - /* duplicate filter caps which contains the composition into one version - * with the meta and one without. Filter the other caps by the software - * caps */ - GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps); - overlay_filter = - intersect_by_feature (filter, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); - } + GstCaps *result, *tmp; - peer_caps = gst_pad_peer_query_caps (self->sinkpad, overlay_filter); + GST_LOG_OBJECT (trans, + "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps, + (direction == GST_PAD_SINK) ? "sink" : "src"); - if (overlay_filter) - gst_caps_unref (overlay_filter); + tmp = gst_caps_merge (add_overlay_feature (caps), gst_caps_ref (caps)); + if (direction == GST_PAD_SINK) + tmp = gst_caps_merge (tmp, remove_overlay_feature (caps)); - if (peer_caps) { + GST_LOG_OBJECT (trans, + "Modified caps %" GST_PTR_FORMAT " in direction %s", tmp, + (direction == GST_PAD_SINK) ? "sink" : "src"); - GST_DEBUG_OBJECT (self->srcpad, "peer caps %" GST_PTR_FORMAT, peer_caps); + if (filter) { + GST_LOG_OBJECT (trans, "Filter caps %" GST_PTR_FORMAT, filter); - if (gst_caps_is_any (peer_caps)) { + result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (tmp); + } else { + result = tmp; + } - /* if peer returns ANY caps, return filtered sink pad template caps */ - GstCaps *tcaps = gst_pad_get_pad_template_caps (self->sinkpad); - caps = gst_caps_copy (tcaps); - gst_caps_unref (tcaps); + GST_LOG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, result); - } else { + return result; +} - /* return upstream caps + composition feature + upstream caps - * filtered by the software caps. */ - GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps); - caps = add_feature_and_intersect (peer_caps, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); - } +static gboolean +gst_overlay_composition_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); + GstCapsFeatures *features; - gst_caps_unref (peer_caps); + self->system_memory = FALSE; + self->downstream_supports_meta = FALSE; - } else { - /* no peer, our padtemplate is enough then */ - caps = gst_pad_get_pad_template_caps (self->srcpad); + if (!gst_video_info_from_caps (&self->info, incaps)) { + GST_ERROR_OBJECT (self, "Invalid incaps %" GST_PTR_FORMAT, incaps); + return FALSE; } - if (filter) { - GstCaps *intersection; + features = gst_caps_get_features (incaps, 0); + if (features && gst_caps_features_contains (features, + GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) { + self->system_memory = TRUE; + } - intersection = - gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (caps); - caps = intersection; + features = gst_caps_get_features (outcaps, 0); + if (features && gst_caps_features_contains (features, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) { + self->downstream_supports_meta = TRUE; } - GST_DEBUG_OBJECT (self->srcpad, "returning %" GST_PTR_FORMAT, caps); - return caps; + gst_sample_set_caps (self->sample, incaps); + self->caps_changed = TRUE; + self->overlay_mode = OVERLAY_MODE_UNKNOWN; + + /* will be updated per decide-allocation */ + self->window_width = GST_VIDEO_INFO_WIDTH (&self->info); + self->window_height = GST_VIDEO_INFO_HEIGHT (&self->info); + + return TRUE; } -static gboolean -gst_overlay_composition_sink_query (GstPad * pad, GstObject * parent, - GstQuery * query) +/* Dummy implementation to make basetransform happy. + * generate_output() method will do the actual transform */ +static GstFlowReturn +gst_overlay_composition_transform (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer * outbuf) { - GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent); - gboolean ret = FALSE; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CAPS:{ - GstCaps *filter, *caps; - - gst_query_parse_caps (query, &filter); - caps = gst_overlay_composition_sink_query_caps (self, filter); - gst_query_set_caps_result (query, caps); - gst_caps_unref (caps); - ret = TRUE; - break; - } - default: - ret = gst_pad_query_default (pad, parent, query); - break; - } - - return ret; + return GST_FLOW_OK; } -static gboolean -gst_overlay_composition_src_query (GstPad * pad, GstObject * parent, - GstQuery * query) +static const gchar * +overlay_mode_name (OverlayMode mode) { - GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent); - gboolean ret = FALSE; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CAPS:{ - GstCaps *filter, *caps; - - gst_query_parse_caps (query, &filter); - caps = gst_overlay_composition_src_query_caps (self, filter); - gst_query_set_caps_result (query, caps); - gst_caps_unref (caps); - ret = TRUE; - break; - } - default: - ret = gst_pad_query_default (pad, parent, query); - break; + switch (mode) { + case OVERLAY_MODE_UNKNOWN: + return "unknown"; + case OVERLAY_MODE_ADD_META: + return "add-meta"; + case OVERLAY_MODE_BLEND: + return "blend"; + case OVERLAY_MODE_NOT_SUPPORTED: + return "not-supported"; } - return ret; + return "undefined"; } static GstFlowReturn -gst_overlay_composition_sink_chain (GstPad * pad, GstObject * parent, - GstBuffer * buffer) +gst_overlay_composition_generate_output (GstBaseTransform * trans, + GstBuffer ** outbuf) { - GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent); - GstVideoOverlayComposition *compo = NULL; - - if (gst_pad_check_reconfigure (self->srcpad)) { - if (!gst_overlay_composition_negotiate (self, NULL)) { - gst_pad_mark_reconfigure (self->srcpad); - gst_buffer_unref (buffer); - GST_OBJECT_LOCK (self->srcpad); - if (GST_PAD_IS_FLUSHING (self->srcpad)) { - GST_OBJECT_UNLOCK (self->srcpad); - return GST_FLOW_FLUSHING; + GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); + GstBuffer *inbuf; + GstVideoOverlayComposition *comp = NULL; + GstVideoOverlayCompositionMeta *meta; + guint i, num_rect; + GstFlowReturn ret = GST_FLOW_OK; + + inbuf = trans->queued_buf; + trans->queued_buf = NULL; + + if (!inbuf) + return GST_FLOW_OK; + + if (self->overlay_mode == OVERLAY_MODE_UNKNOWN) { + GST_DEBUG_OBJECT (self, "Deciding overlay mode, downstream-meta: %d, " + "allocation-meta: %d, system-memory: %d", + self->downstream_supports_meta, self->allocation_supports_meta, + self->system_memory); + + if (self->downstream_supports_meta) { + if (self->allocation_supports_meta || !self->system_memory) { + self->overlay_mode = OVERLAY_MODE_ADD_META; + } else { + self->overlay_mode = OVERLAY_MODE_BLEND; + } + } else { + if (self->system_memory) { + self->overlay_mode = OVERLAY_MODE_BLEND; + } else { + /* downstream does not support meta and also not system memory. + * Nothing we can do */ + GST_ELEMENT_WARNING (self, STREAM, NOT_IMPLEMENTED, (NULL), + ("Neither overlay nor blending is possible")); + self->overlay_mode = OVERLAY_MODE_NOT_SUPPORTED; } - GST_OBJECT_UNLOCK (self->srcpad); - return GST_FLOW_NOT_NEGOTIATED; } + + GST_INFO_OBJECT (self, "Selected overlay mode: %s", + overlay_mode_name (self->overlay_mode)); } - if (!self->sample) { - self->sample = gst_sample_new (buffer, self->caps, &self->segment, NULL); - } else { - self->sample = gst_sample_make_writable (self->sample); - gst_sample_set_buffer (self->sample, buffer); - gst_sample_set_caps (self->sample, self->caps); - gst_sample_set_segment (self->sample, &self->segment); + if (self->overlay_mode == OVERLAY_MODE_NOT_SUPPORTED) + goto out; + + if (self->caps_changed) { + g_signal_emit (self, overlay_composition_signals[SIGNAL_CAPS_CHANGED], 0, + gst_sample_get_caps (self->sample), self->window_width, + self->window_height, NULL); + self->caps_changed = FALSE; } + self->sample = gst_sample_make_writable (self->sample); + gst_sample_set_buffer (self->sample, inbuf); + gst_sample_set_segment (self->sample, &trans->segment); + g_signal_emit (self, overlay_composition_signals[SIGNAL_DRAW], 0, - self->sample, &compo); + self->sample, &comp); /* Don't store the buffer in the sample any longer, otherwise it will not * be writable below as we have one reference in the sample and one in @@ -714,45 +543,76 @@ gst_overlay_composition_sink_chain (GstPad * pad, GstObject * parent, * If the sample is not writable itself then the application kept an * reference itself. */ - if (gst_sample_is_writable (self->sample)) { + if (gst_sample_is_writable (self->sample)) gst_sample_set_buffer (self->sample, NULL); - } - if (!compo) { - GST_DEBUG_OBJECT (self->sinkpad, - "Application did not provide an overlay composition"); - return gst_pad_push (self->srcpad, buffer); + meta = gst_buffer_get_video_overlay_composition_meta (inbuf); + if (!comp && !meta) { + /* Nothing to do, just forward this buffer */ + goto out; } - buffer = gst_buffer_make_writable (buffer); + if (self->overlay_mode == OVERLAY_MODE_ADD_META) { + if (!comp) { + GST_DEBUG_OBJECT (self, + "Application did not provide an overlay composition"); + goto out; + } - if (self->attach_compo_to_buffer) { - GST_DEBUG_OBJECT (self->sinkpad, "Attaching as meta"); + inbuf = gst_buffer_make_writable (inbuf); + if (!meta) { + GST_DEBUG_OBJECT (self, "Attaching as meta"); - gst_buffer_add_video_overlay_composition_meta (buffer, compo); - gst_video_overlay_composition_unref (compo); - } else { + gst_buffer_add_video_overlay_composition_meta (inbuf, comp); + } else { + GST_DEBUG_OBJECT (self, "Appending to upstream overlay composition"); + + meta = gst_buffer_get_video_overlay_composition_meta (inbuf); + meta->overlay = + gst_video_overlay_composition_make_writable (meta->overlay); + + num_rect = gst_video_overlay_composition_n_rectangles (comp); + for (i = 0; i < num_rect; i++) { + GstVideoOverlayRectangle *rect = + gst_video_overlay_composition_get_rectangle (comp, i); + gst_video_overlay_composition_add_rectangle (meta->overlay, rect); + } + } + } else if (self->overlay_mode == OVERLAY_MODE_BLEND) { GstVideoFrame frame; - if (!gst_video_frame_map (&frame, &self->info, buffer, GST_MAP_READWRITE)) { - gst_video_overlay_composition_unref (compo); - goto map_failed; + inbuf = gst_buffer_make_writable (inbuf); + if (!gst_video_frame_map (&frame, &self->info, inbuf, + GST_MAP_READWRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) { + GST_ERROR_OBJECT (self, "Failed to map buffer"); + ret = GST_FLOW_ERROR; + goto out; + } + + i = 0; + while ((meta = gst_buffer_get_video_overlay_composition_meta (inbuf))) { + GST_LOG_OBJECT (self, "Blending upstream overlay meta %d", i); + gst_video_overlay_composition_blend (meta->overlay, &frame); + gst_buffer_remove_video_overlay_composition_meta (inbuf, meta); + i++; } - gst_video_overlay_composition_blend (compo, &frame); + if (comp) { + GST_LOG_OBJECT (self, "Blending application overlay"); + gst_video_overlay_composition_blend (comp, &frame); + } gst_video_frame_unmap (&frame); - gst_video_overlay_composition_unref (compo); + } else { + g_assert_not_reached (); } - return gst_pad_push (self->srcpad, buffer); +out: + if (comp) + gst_video_overlay_composition_unref (comp); -map_failed: - { - GST_ERROR_OBJECT (self->sinkpad, "Failed to map buffer"); - gst_buffer_unref (buffer); - return GST_FLOW_ERROR; - } + *outbuf = inbuf; + return ret; } static gboolean diff --git a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.h b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.h index cc92f98ded..d53c0e9381 100644 --- a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.h +++ b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.h @@ -17,34 +17,20 @@ * Boston, MA 02110-1301, USA. */ +#pragma once + #include #include - -#ifndef __GST_OVERLAY_COMPOSITION_H__ -#define __GST_OVERLAY_COMPOSITION_H__ +#include G_BEGIN_DECLS #define GST_TYPE_OVERLAY_COMPOSITION (gst_overlay_composition_get_type()) G_DECLARE_FINAL_TYPE (GstOverlayComposition, gst_overlay_composition, - GST, OVERLAY_COMPOSITION, GstElement) - -struct _GstOverlayComposition { - GstElement parent; - - GstPad *sinkpad, *srcpad; - - /* state */ - GstSample *sample; - GstSegment segment; - GstCaps *caps; - GstVideoInfo info; - guint window_width, window_height; - gboolean attach_compo_to_buffer; -}; + GST, OVERLAY_COMPOSITION, GstBaseTransform) GST_ELEMENT_REGISTER_DECLARE (overlaycomposition); G_END_DECLS -#endif /* __GST_OVERLAY_COMPOSITION_H__ */ + From 75c4a95789d9241cd702789307fc0dc4b2c5c055 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 8 Aug 2023 22:52:40 +0900 Subject: [PATCH 68/82] overlaycomposition: Implement fixate_caps() Prefer composition meta --- .../gstoverlaycomposition.c | 234 ++++++------------ 1 file changed, 80 insertions(+), 154 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c index 0bed856b29..2fb83424af 100644 --- a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c +++ b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c @@ -107,11 +107,10 @@ static gboolean gst_overlay_composition_stop (GstBaseTransform * trans); static gboolean gst_overlay_composition_propose_allocation (GstBaseTransform * trans, GstQuery * decide_query, GstQuery * query); -static gboolean -gst_overlay_composition_decide_allocation (GstBaseTransform * trans, - GstQuery * query); static GstCaps *gst_overlay_composition_transform_caps (GstBaseTransform * trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter); +static GstCaps *gst_overlay_composition_fixate_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); static gboolean gst_overlay_composition_set_caps (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps); static GstFlowReturn gst_overlay_composition_transform (GstBaseTransform * @@ -170,10 +169,10 @@ gst_overlay_composition_class_init (GstOverlayCompositionClass * klass) transform_class->stop = GST_DEBUG_FUNCPTR (gst_overlay_composition_stop); transform_class->propose_allocation = GST_DEBUG_FUNCPTR (gst_overlay_composition_propose_allocation); - transform_class->decide_allocation = - GST_DEBUG_FUNCPTR (gst_overlay_composition_decide_allocation); transform_class->transform_caps = GST_DEBUG_FUNCPTR (gst_overlay_composition_transform_caps); + transform_class->fixate_caps = + GST_DEBUG_FUNCPTR (gst_overlay_composition_fixate_caps); transform_class->set_caps = GST_DEBUG_FUNCPTR (gst_overlay_composition_set_caps); transform_class->transform = @@ -211,171 +210,65 @@ static gboolean gst_overlay_composition_propose_allocation (GstBaseTransform * trans, GstQuery * decide_query, GstQuery * query) { - GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); - GstCaps *caps = NULL; - GstCapsFeatures *features; - - /* Always proxy allocation query (we don't need allocation) */ - if (!gst_pad_peer_query (trans->srcpad, query)) + if (!GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans, + decide_query, query)) { return FALSE; - - gst_query_parse_allocation (query, &caps, NULL); - if (!caps) - return FALSE; - - if (gst_query_get_n_allocation_pools (query) > 0) - goto done; - - features = gst_caps_get_features (caps, 0); - if (features && gst_caps_features_contains (features, - GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) { - GstVideoInfo info; - GstBufferPool *pool; - GstStructure *config; - guint size; - - if (!gst_video_info_from_caps (&info, caps)) { - GST_ERROR_OBJECT (self, "Invalid caps %" GST_PTR_FORMAT, caps); - return FALSE; - } - - pool = gst_video_buffer_pool_new (); - config = gst_buffer_pool_get_config (pool); - - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_VIDEO_META); - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); - - size = GST_VIDEO_INFO_SIZE (&info); - gst_buffer_pool_config_set_params (config, caps, size, 0, 0); - - if (!gst_buffer_pool_set_config (pool, config)) { - GST_ERROR_OBJECT (self, "Could not set pool config"); - gst_object_unref (pool); - return FALSE; - } - - gst_query_add_allocation_pool (query, pool, size, 0, 0); - gst_object_unref (pool); } -done: - gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); - /* This element always supports upstream overlay-composition meta, - * but checks if downstream provided it already, to preserve - * downstream alloc params (e.g., window width/height) */ - if (!gst_query_find_allocation_meta (query, - GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL)) { - gst_query_add_allocation_meta (query, - GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL); - } + /* Passthrough */ + if (!decide_query) + return TRUE; - return TRUE; -} - -static gboolean -gst_overlay_composition_decide_allocation (GstBaseTransform * trans, - GstQuery * query) -{ - GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); - guint alloc_index; - - self->allocation_supports_meta = FALSE; - self->overlay_mode = OVERLAY_MODE_UNKNOWN; - - if (gst_query_find_allocation_meta (query, - GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, &alloc_index)) { - const GstStructure *params = NULL; - guint width, height; - - self->allocation_supports_meta = TRUE; - - gst_query_parse_nth_allocation_meta (query, alloc_index, ¶ms); - /* Hold params to forward it at propose_allocation() */ - if (params && gst_structure_get (params, "width", G_TYPE_UINT, &width, - "height", G_TYPE_UINT, &height, NULL) && width > 0 && height > 0) { - GST_INFO_OBJECT (self, "received window size: %dx%d", width, height); - - if (self->window_width != width || self->window_height != height) - self->caps_changed = TRUE; - - self->window_width = width; - self->window_height = height; - } - } - - return TRUE; + return gst_pad_peer_query (trans->srcpad, query); } static GstCaps * add_overlay_feature (GstCaps * caps) { - guint i, m, n; - GstCaps *tmp; - GstCapsFeatures *system_overlay_feature = - gst_caps_features_from_string - (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY ", " - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - - tmp = gst_caps_new_empty (); - - n = gst_caps_get_size (caps); - for (i = 0; i < n; i++) { - GstCapsFeatures *features, *orig_features; - GstStructure *s = gst_caps_get_structure (caps, i); + GstCaps *new_caps = gst_caps_new_empty (); + guint caps_size = gst_caps_get_size (caps); + guint i; - orig_features = gst_caps_get_features (caps, i); - - if (gst_caps_features_is_any (orig_features)) { - features = gst_caps_features_copy (system_overlay_feature); - } else { - m = gst_caps_features_get_size (orig_features); - if (m == 1 && gst_caps_features_contains (orig_features, - GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) { - features = gst_caps_features_copy (system_overlay_feature); - } else { - features = gst_caps_features_copy (orig_features); - if (!gst_caps_features_contains (orig_features, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) { - gst_caps_features_add (features, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - } - } + for (i = 0; i < caps_size; i++) { + GstStructure *s = gst_caps_get_structure (caps, i); + GstCapsFeatures *f = + gst_caps_features_copy (gst_caps_get_features (caps, i)); + GstCaps *c = gst_caps_new_full (gst_structure_copy (s), NULL); + + if (!gst_caps_features_is_any (f) && + !gst_caps_features_contains (f, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) { + gst_caps_features_add (f, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); } - gst_caps_append_structure_full (tmp, gst_structure_copy (s), features); + gst_caps_set_features (c, 0, f); + gst_caps_append (new_caps, c); } - gst_caps_features_free (system_overlay_feature); - - return tmp; + return new_caps; } static GstCaps * remove_overlay_feature (GstCaps * caps) { - guint i, n; - GstCaps *tmp; - - tmp = gst_caps_new_empty (); + GstCaps *new_caps = gst_caps_new_empty (); + guint caps_size = gst_caps_get_size (caps); + guint i; - n = gst_caps_get_size (caps); - for (i = 0; i < n; i++) { - GstCapsFeatures *features, *orig_features; + for (i = 0; i < caps_size; i++) { GstStructure *s = gst_caps_get_structure (caps, i); - - orig_features = gst_caps_get_features (caps, i); - features = gst_caps_features_copy (orig_features); - if (!gst_caps_features_is_any (orig_features)) { - gst_caps_features_remove (features, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - } - - gst_caps_append_structure_full (tmp, gst_structure_copy (s), features); + GstCapsFeatures *f = + gst_caps_features_copy (gst_caps_get_features (caps, i)); + GstCaps *c = gst_caps_new_full (gst_structure_copy (s), NULL); + + gst_caps_features_remove (f, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); + gst_caps_set_features (c, 0, f); + gst_caps_append (new_caps, c); } - return tmp; + return new_caps; } static GstCaps * @@ -388,13 +281,13 @@ gst_overlay_composition_transform_caps (GstBaseTransform * trans, "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps, (direction == GST_PAD_SINK) ? "sink" : "src"); - tmp = gst_caps_merge (add_overlay_feature (caps), gst_caps_ref (caps)); - if (direction == GST_PAD_SINK) - tmp = gst_caps_merge (tmp, remove_overlay_feature (caps)); - - GST_LOG_OBJECT (trans, - "Modified caps %" GST_PTR_FORMAT " in direction %s", tmp, - (direction == GST_PAD_SINK) ? "sink" : "src"); + if (direction == GST_PAD_SINK) { + tmp = add_overlay_feature (caps); + tmp = gst_caps_merge (tmp, gst_caps_ref (caps)); + } else { + tmp = remove_overlay_feature (caps); + tmp = gst_caps_merge (gst_caps_ref (caps), tmp); + } if (filter) { GST_LOG_OBJECT (trans, "Filter caps %" GST_PTR_FORMAT, filter); @@ -410,6 +303,36 @@ gst_overlay_composition_transform_caps (GstBaseTransform * trans, return result; } +static GstCaps * +gst_overlay_composition_fixate_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) +{ + GstCaps *overlay_caps = NULL; + guint i; + guint caps_size = gst_caps_get_size (othercaps); + + /* Prefer overlaycomposition caps */ + for (i = 0; i < caps_size; i++) { + GstCapsFeatures *f = gst_caps_get_features (othercaps, i); + + if (f && !gst_caps_features_is_any (f) && + gst_caps_features_contains (f, + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) { + GstStructure *s = gst_caps_get_structure (othercaps, i); + overlay_caps = gst_caps_new_full (gst_structure_copy (s), NULL); + gst_caps_set_features_simple (overlay_caps, gst_caps_features_copy (f)); + break; + } + } + + if (overlay_caps) { + gst_caps_unref (othercaps); + return gst_caps_fixate (overlay_caps); + } + + return gst_caps_fixate (othercaps); +} + static gboolean gst_overlay_composition_set_caps (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) @@ -417,6 +340,9 @@ gst_overlay_composition_set_caps (GstBaseTransform * trans, GstCaps * incaps, GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (trans); GstCapsFeatures *features; + GST_DEBUG_OBJECT (self, "Set incaps %" GST_PTR_FORMAT ", outcaps %" + GST_PTR_FORMAT, incaps, outcaps); + self->system_memory = FALSE; self->downstream_supports_meta = FALSE; From 13b9f4fa0131ccf5bd065d6c879f56535b035e60 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Mon, 1 Jul 2024 22:37:11 +0900 Subject: [PATCH 69/82] overlaycomposition: Fix transform caps We need both overlay composition meta added/removed caps. --- .../gst/overlaycomposition/gstoverlaycomposition.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c index 2fb83424af..b64ff8437c 100644 --- a/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c +++ b/subprojects/gst-plugins-base/gst/overlaycomposition/gstoverlaycomposition.c @@ -281,13 +281,8 @@ gst_overlay_composition_transform_caps (GstBaseTransform * trans, "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps, (direction == GST_PAD_SINK) ? "sink" : "src"); - if (direction == GST_PAD_SINK) { - tmp = add_overlay_feature (caps); - tmp = gst_caps_merge (tmp, gst_caps_ref (caps)); - } else { - tmp = remove_overlay_feature (caps); - tmp = gst_caps_merge (gst_caps_ref (caps), tmp); - } + tmp = gst_caps_merge (add_overlay_feature (caps), gst_caps_ref (caps)); + tmp = gst_caps_merge (tmp, remove_overlay_feature (caps)); if (filter) { GST_LOG_OBJECT (trans, "Filter caps %" GST_PTR_FORMAT, filter); From 9f37e313c96f0218d878f8d35ee70e805943db21 Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Mon, 19 Jan 2026 17:29:03 -0500 Subject: [PATCH 70/82] Use Cablecast plugins --- subprojects/gst-plugins-rs.wrap | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/subprojects/gst-plugins-rs.wrap b/subprojects/gst-plugins-rs.wrap index f41d56b701..ab64934e57 100644 --- a/subprojects/gst-plugins-rs.wrap +++ b/subprojects/gst-plugins-rs.wrap @@ -1,5 +1,4 @@ [wrap-git] directory=gst-plugins-rs -url=https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git -push-url=git@gitlab.freedesktop.org:gstreamer/gst-plugins-rs.git -revision=main +url=https://github.com/trms/gst-plugins-rs.git +revision=cbl-2026-01-15 From dbf8889d66b818acf1bfef4985cb4dc0ab1ab2d6 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Tue, 3 Mar 2026 18:46:28 +0100 Subject: [PATCH 71/82] aggregator: select new start time after flush stop --- subprojects/gstreamer/libs/gst/base/gstaggregator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/gstreamer/libs/gst/base/gstaggregator.c b/subprojects/gstreamer/libs/gst/base/gstaggregator.c index bd4f071b5d..cff03e7840 100644 --- a/subprojects/gstreamer/libs/gst/base/gstaggregator.c +++ b/subprojects/gstreamer/libs/gst/base/gstaggregator.c @@ -1697,6 +1697,7 @@ gst_aggregator_flush (GstAggregator * self) GST_OBJECT_LOCK (self); priv->send_segment = TRUE; priv->flushing = FALSE; + priv->first_buffer = TRUE; GST_OBJECT_UNLOCK (self); if (klass->flush) ret = klass->flush (self); From fad7a1493d3e405f0bd29bed7a0a57bd58688755 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 20 Aug 2024 22:55:52 +0900 Subject: [PATCH 72/82] errorignore: Add ignore-flushing property Adding new mode to ignore GST_FLOW_FLUSHING --- .../docs/plugins/gst_plugins_cache.json | 12 +++++++++++ .../gst/debugutils/gsterrorignore.c | 21 ++++++++++++++++++- .../gst/debugutils/gsterrorignore.h | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json index 6dded21748..ffbbfc0890 100644 --- a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json @@ -18811,6 +18811,18 @@ "type": "gboolean", "writable": true }, + "ignore-flushing": { + "blurb": "Whether to ignore GST_FLOW_FLUSHING", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, "ignore-notlinked": { "blurb": "Whether to ignore GST_FLOW_NOT_LINKED", "conditionally-available": false, diff --git a/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.c b/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.c index f9b6a29077..b31b6ef2eb 100644 --- a/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.c +++ b/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.c @@ -53,6 +53,7 @@ enum PROP_IGNORE_EOS, PROP_CONVERT_TO, PROP_POST_WARNINGS, + PROP_IGNORE_FLUSHING, }; static void gst_error_ignore_set_property (GObject * object, guint prop_id, @@ -151,6 +152,16 @@ gst_error_ignore_class_init (GstErrorIgnoreClass * klass) g_param_spec_boolean ("post-warnings", "Post warnings", "Whether to post warnings on first flow conversion", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstErrorIgnore:ignore-flushing: + * + * Since: 1.30 + */ + g_object_class_install_property (object_class, PROP_IGNORE_FLUSHING, + g_param_spec_boolean ("ignore-flushing", + "Ignore GST_FLOW_FLUSHING", "Whether to ignore GST_FLOW_FLUSHING", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -178,6 +189,7 @@ gst_error_ignore_init (GstErrorIgnore * self) self->ignore_notlinked = FALSE; self->ignore_notnegotiated = TRUE; self->ignore_eos = FALSE; + self->ignore_flushing = FALSE; self->convert_to = GST_FLOW_NOT_LINKED; self->post_warnings = TRUE; } @@ -207,6 +219,9 @@ gst_error_ignore_set_property (GObject * object, guint prop_id, case PROP_POST_WARNINGS: self->post_warnings = g_value_get_boolean (value); break; + case PROP_IGNORE_FLUSHING: + self->ignore_flushing = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -238,6 +253,9 @@ gst_error_ignore_get_property (GObject * object, guint prop_id, GValue * value, case PROP_POST_WARNINGS: g_value_set_boolean (value, self->post_warnings); break; + case PROP_IGNORE_FLUSHING: + g_value_set_boolean (value, self->ignore_flushing); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -286,7 +304,8 @@ gst_error_ignore_sink_chain (GstPad * pad, GstObject * parent, if ((ret == GST_FLOW_ERROR && self->ignore_error) || (ret == GST_FLOW_NOT_LINKED && self->ignore_notlinked) || (ret == GST_FLOW_EOS && self->ignore_eos) || - (ret == GST_FLOW_NOT_NEGOTIATED && self->ignore_notnegotiated)) { + (ret == GST_FLOW_NOT_NEGOTIATED && self->ignore_notnegotiated) || + (ret == GST_FLOW_FLUSHING && self->ignore_flushing)) { if (warn) { GST_ELEMENT_WARNING (self, STREAM, FAILED, diff --git a/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.h b/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.h index bc2aba6149..55f1aeefa1 100644 --- a/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.h +++ b/subprojects/gst-plugins-bad/gst/debugutils/gsterrorignore.h @@ -46,6 +46,7 @@ struct _GstErrorIgnore { gboolean ignore_notnegotiated; gboolean ignore_eos; gboolean post_warnings; + gboolean ignore_flushing; GstFlowReturn convert_to; }; From 31dab027304e21256e3bc03f2f12ddd206e765e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 6 May 2026 16:13:54 +0300 Subject: [PATCH 73/82] decklink2: Use correct IID in video frame QueryInterface() --- .../gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp index afb1560149..b30e79dec7 100644 --- a/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp +++ b/subprojects/gst-plugins-bad/sys/decklink2/gstdecklink2output.cpp @@ -169,7 +169,7 @@ class IGstDeckLinkVideoFrame:public IDeckLinkVideoFrame /* IUnknown */ HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **object) { - if (riid == IID_IDeckLinkVideoOutputCallback) { + if (riid == IID_IDeckLinkVideoFrame) { *object = static_cast < IDeckLinkVideoFrame * >(this); } else { *object = NULL; From 9e097c23efd43d3c02e49842e48597cd5c4f1345 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 10 May 2026 01:58:42 +0530 Subject: [PATCH 74/82] gstinfo: Use stack allocation for <=1KB messages It should be super low-risk to add an extra KB to the stack at all call-sites. --- subprojects/gstreamer/gst/gstinfo.c | 11 ++++++++--- subprojects/gstreamer/gst/printf/printf.c | 16 ++++++++++++++++ subprojects/gstreamer/gst/printf/printf.h | 6 ++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/subprojects/gstreamer/gst/gstinfo.c b/subprojects/gstreamer/gst/gstinfo.c index 43c09da52e..d5aa166d4a 100644 --- a/subprojects/gstreamer/gst/gstinfo.c +++ b/subprojects/gstreamer/gst/gstinfo.c @@ -345,6 +345,10 @@ struct _GstDebugMessage /* heap-allocated write area for short names */ gchar tmp_id[32]; + + /* Inline buffer @message is formatted into; vasnprintf falls back to malloc + * only if the result doesn't fit. */ + gchar inline_buf[1024]; }; struct _GstLogContext @@ -828,7 +832,8 @@ gst_debug_log_full_valist (GstDebugCategory * category, GstLogContext * ctx, } g_rw_lock_reader_unlock (&__log_func_mutex); - g_free (message.message); + if (message.message != message.inline_buf) + g_free (message.message); if (message.free_object_id) g_free (message.object_id); va_end (message.arguments); @@ -1001,8 +1006,8 @@ gst_debug_message_get (GstDebugMessage * message) if (message->message == NULL) { int len; - len = __gst_vasprintf (&message->message, message->format, - message->arguments); + len = __gst_vasprintf_buf (&message->message, message->inline_buf, + sizeof (message->inline_buf), message->format, message->arguments); if (len < 0) message->message = NULL; diff --git a/subprojects/gstreamer/gst/printf/printf.c b/subprojects/gstreamer/gst/printf/printf.c index d2bb373351..8a863b65ed 100644 --- a/subprojects/gstreamer/gst/printf/printf.c +++ b/subprojects/gstreamer/gst/printf/printf.c @@ -157,3 +157,19 @@ __gst_vasprintf (char **result, char const *format, va_list args) return length; } + +/* Format into fixed_buf if the result fits, otherwise into a freshly malloc'd + * buffer. The caller must check whether *result == fixed_buf to know whether + * to free it. */ +int +__gst_vasprintf_buf (char **result, char *fixed_buf, size_t fixed_buf_size, + char const *format, va_list args) +{ + size_t length = fixed_buf_size; + + *result = vasnprintf (fixed_buf, &length, format, args); + if (*result == NULL) + return -1; + + return length; +} diff --git a/subprojects/gstreamer/gst/printf/printf.h b/subprojects/gstreamer/gst/printf/printf.h index 18e3cf97ef..3f514f2d60 100644 --- a/subprojects/gstreamer/gst/printf/printf.h +++ b/subprojects/gstreamer/gst/printf/printf.h @@ -60,5 +60,11 @@ int __gst_vasprintf (char **result, char const *format, va_list args); +int __gst_vasprintf_buf (char **result, + char *fixed_buf, + size_t fixed_buf_size, + char const *format, + va_list args); + #endif /* __GNULIB_PRINTF_H__ */ From 9b96a3efd2eee8faea7004ba456a2456685b10e5 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 10 May 2026 03:45:43 +0530 Subject: [PATCH 75/82] gstinfo: Don't ever use %n to know how much was written The return value of snprintf will let us know that already. %n is only needed for ancient snprintf implementation that didn't do that. We do not support any of those. This allows us to use snprintf instead of sprintf which is marginally faster. --- subprojects/gstreamer/gst/printf/README | 8 +++++--- subprojects/gstreamer/gst/printf/gst-printf.h | 9 ++++----- subprojects/gstreamer/gst/printf/vasnprintf.c | 6 ------ 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/subprojects/gstreamer/gst/printf/README b/subprojects/gstreamer/gst/printf/README index c8eac3815f..b6fec6cb4c 100644 --- a/subprojects/gstreamer/gst/printf/README +++ b/subprojects/gstreamer/gst/printf/README @@ -46,9 +46,11 @@ GStreamer modifications This was imported from GLib's gnulib subdirectory. g-gnulib.h and _g_gnulib namespace has been changed to gst-printf.h and -__gst_printf namespace for GStreamer. Also #define HAVE_SNPRINTF 0 has -been changed to #undef HAVE_SNPRINTF, and HAVE_ALLOCA has been replaced -by an #if defined(alloca) || defined(GLIB_HAVE_ALLOCA_H) +__gst_printf namespace for GStreamer. HAVE_SNPRINTF is defined in +gst-printf.h (snprintf is universally available on supported platforms); +%n is never appended to the reconstructed format string passed to snprintf +so glibc's _FORTIFY_SOURCE=2 check is satisfied. HAVE_ALLOCA has been +replaced by an #if defined(alloca) || defined(GLIB_HAVE_ALLOCA_H) printf-extension.[ch] were added to provide support for custom pointer arguments (e.g. caps, events, etc.) diff --git a/subprojects/gstreamer/gst/printf/gst-printf.h b/subprojects/gstreamer/gst/printf/gst-printf.h index db5972afed..e2de1ee6c5 100644 --- a/subprojects/gstreamer/gst/printf/gst-printf.h +++ b/subprojects/gstreamer/gst/printf/gst-printf.h @@ -36,11 +36,10 @@ #define realloc g_realloc #define free g_free -/* Don't use snprintf(); we have to use sprintf instead and do our own - * length calculations, because glibc doesn't allow passing %n in a format - * string if the string is in writable memory (if glibc has been compiled - * with _FORTIFY_SOURCE=2 which seems to be the case on some distros/systems) */ -#undef HAVE_SNPRINTF +/* All platforms we support have C99 snprintf. We never append %n to the + * reconstructed format string (see vasnprintf.c), so _FORTIFY_SOURCE=2 is + * fine. */ +#define HAVE_SNPRINTF 1 /* based on glib's config.h.win32.in */ #ifdef G_OS_WIN32 diff --git a/subprojects/gstreamer/gst/printf/vasnprintf.c b/subprojects/gstreamer/gst/printf/vasnprintf.c index 4cbb295b1d..37de2c3dbc 100644 --- a/subprojects/gstreamer/gst/printf/vasnprintf.c +++ b/subprojects/gstreamer/gst/printf/vasnprintf.c @@ -692,13 +692,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) break; } *p = dp->conversion; -#ifdef HAVE_SNPRINTF - p[1] = '%'; - p[2] = 'n'; - p[3] = '\0'; -#else p[1] = '\0'; -#endif /* Construct the arguments for calling snprintf or sprintf. */ prefix_count = 0; From 10734ba69726b1a41276f928b85e7a7643d728ef Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 11 May 2026 12:49:55 +0530 Subject: [PATCH 76/82] gstinfo: Use stack allocated memory when printing on Win32 --- subprojects/gstreamer/gst/gstinfo.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/subprojects/gstreamer/gst/gstinfo.c b/subprojects/gstreamer/gst/gstinfo.c index d5aa166d4a..0eb305d7f9 100644 --- a/subprojects/gstreamer/gst/gstinfo.c +++ b/subprojects/gstreamer/gst/gstinfo.c @@ -1765,11 +1765,13 @@ static void _gst_debug_fprintf (FILE * file, const gchar * format, ...) { va_list args; + gchar inline_buf[1024]; gchar *str = NULL; gint length; va_start (args, format); - length = gst_info_vasprintf (&str, format, args); + length = __gst_vasprintf_buf (&str, inline_buf, sizeof (inline_buf), + format, args); va_end (args); if (length == 0 || !str) @@ -1793,7 +1795,8 @@ _gst_debug_fprintf (FILE * file, const gchar * format, ...) fflush (file); } - g_free (str); + if (str != inline_buf) + g_free (str); } #endif From f31e21b32e685f246fc31a1f0efefb8358895ed4 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 10 May 2026 02:46:13 +0530 Subject: [PATCH 77/82] gstinfo: Use a more optimized version of GST_TIME_ARGS This implementation is 66% faster (0.33x time) than the current variant. We call GST_TIME_ARGS one very single log message and it adds up quickly. This reduces logging time by 30% (0.7x time) for a GST_INFO() macro. --- subprojects/gstreamer/gst/gstinfo.c | 94 +++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/subprojects/gstreamer/gst/gstinfo.c b/subprojects/gstreamer/gst/gstinfo.c index 0eb305d7f9..098a0a6e26 100644 --- a/subprojects/gstreamer/gst/gstinfo.c +++ b/subprojects/gstreamer/gst/gstinfo.c @@ -146,6 +146,100 @@ static char *gst_info_printf_pointer_extension_func (const char *format, #define GST_ENABLE_FORMAT_NONLITERAL_WARNING #endif +#undef GST_TIME_ARGS +#undef GST_STIME_ARGS +#undef GST_TIME_FORMAT +#undef GST_STIME_FORMAT + +static inline int +_u32_to_dec (char *p, guint32 v) +{ + if (v == 0) { + *p = '0'; + return 1; + } + char tmp[10]; /* UINT32_MAX = 4294967295, 10 digits */ + int n = 0; + while (v) { + tmp[n++] = '0' + (v % 10); + v /= 10; + } + for (int i = 0; i < n; ++i) + p[i] = tmp[n - 1 - i]; + return n; +} + +/* Internal: writes "[H...]H:MM:SS.nnnnnnnnn" at p, returns the end pointer. + Caller guarantees ns < GST_SECOND. */ +static inline char * +_gst_write_hms_ns (char *p, guint64 sec, guint ns) +{ + guint h = (guint) (sec / 3600); /* fits in 32 bits: + max ≈ 5.12e6 (unsigned) + max ≈ 2.56e6 (signed) */ + guint r = (guint) (sec - (guint64) h * 3600); + guint m = r / 60; + guint s = r - m * 60; + + p += _u32_to_dec (p, h); + *p++ = ':'; + *p++ = '0' + (m / 10); + *p++ = '0' + (m % 10); + *p++ = ':'; + *p++ = '0' + (s / 10); + *p++ = '0' + (s % 10); + *p++ = '.'; + for (int i = 8; i >= 0; --i) { + p[i] = '0' + (ns % 10); + ns /= 10; + } + return p + 9; +} + +static inline const char * +_gst_t_str (GstClockTime t, char *buf) +{ + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (t))) { + memcpy (buf, "99:99:99.999999999", 19); /* incl. NUL */ + return buf; + } + guint64 sec = t / GST_SECOND; + guint ns = (guint) (t - sec * GST_SECOND); + *_gst_write_hms_ns (buf, sec, ns) = '\0'; + return buf; +} + +static inline const char * +_gst_st_str (GstClockTimeDiff t, char *buf) +{ + if (G_UNLIKELY (!GST_CLOCK_STIME_IS_VALID (t))) { + memcpy (buf, "+99:99:99.999999999", 20); /* incl. NUL */ + return buf; + } + char *p = buf; + guint64 abs_t; + if (t < 0) { + *p++ = '-'; + /* Unsigned negation is defined modulo 2^64 and yields the correct + magnitude even at t == G_MININT64, where -(gint64)t would be UB. + For valid inputs (t != G_MININT64) the magnitude fits in gint64 + anyway; this idiom just avoids a special case. */ + abs_t = -(guint64) t; + } else { + *p++ = '+'; + abs_t = (guint64) t; + } + guint64 sec = abs_t / GST_SECOND; + guint ns = (guint) (abs_t - sec * GST_SECOND); + *_gst_write_hms_ns (p, sec, ns) = '\0'; + return buf; +} + +#define GST_TIME_FORMAT "s" +#define GST_TIME_ARGS(t) _gst_t_str((t), (char[32]){0}) + +#define GST_STIME_FORMAT "s" +#define GST_STIME_ARGS(t) _gst_st_str((t), (char[32]){0}) #ifdef G_OS_WIN32 # define WIN32_LEAN_AND_MEAN /* prevents from including too many things */ From 9b908d4aa5c6b92b91b9a80baebc58418b06bc5e Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 11 May 2026 16:33:44 +0530 Subject: [PATCH 78/82] gstinfo: Don't use fwrite() on Windows for debug logging When setting GST_DEBUG_FILE, the file was opened with fopen() and written to with fwrite(). This required an expensive fflush() on Windows because fwrite() doesn't support line-buffered I/O. Bypass the CRT userspace buffering by submitting whole lines in a single write to the kernel. This is equivalent to line-buffered FILE writes, and is about 12% faster. --- subprojects/gstreamer/gst/gstinfo.c | 46 +++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/subprojects/gstreamer/gst/gstinfo.c b/subprojects/gstreamer/gst/gstinfo.c index 098a0a6e26..a17edb4525 100644 --- a/subprojects/gstreamer/gst/gstinfo.c +++ b/subprojects/gstreamer/gst/gstinfo.c @@ -542,6 +542,13 @@ _priv_gst_debug_file_name (const gchar * env) return name; } +#ifdef G_OS_WIN32 +/* HANDLE for the configured log file. This needs to be in static storage + * because the address allows us to check when gst_debug_log_default() is + * called with a custom FILE* pointer by the user. */ +static HANDLE _gst_debug_log_handle = INVALID_HANDLE_VALUE; +#endif + /* Initialize the debugging system */ void _priv_gst_debug_init (void) @@ -556,13 +563,37 @@ _priv_gst_debug_init (void) log_file = stdout; } else { gchar *name = _priv_gst_debug_file_name (env); +#ifdef G_OS_WIN32 + wchar_t *wname = g_utf8_to_utf16 (name, -1, NULL, NULL, NULL); + if (wname) { + /* FILE_APPEND_DATA makes the kernel append each call's buffer + * atomically, so multiple threads logging in parallel never + * interleave lines and there is no userspace lock to contend on + * FILE_SHARE_READ allows other processes to read the file. + */ + _gst_debug_log_handle = CreateFileW (wname, FILE_APPEND_DATA, + FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, + NULL); + g_free (wname); + } + if (_gst_debug_log_handle == INVALID_HANDLE_VALUE) { + g_printerr ("Could not open log file '%s' for writing: %u\n", env, + (guint) GetLastError ()); + log_file = stderr; + } else { + /* Sentinel: _gst_debug_fprintf detects this by pointer-equality and + * writes via the HANDLE instead of through the CRT FILE* layer. */ + log_file = (FILE *) & _gst_debug_log_handle; + } +#else log_file = g_fopen (name, "w"); - g_free (name); if (log_file == NULL) { g_printerr ("Could not open log file '%s' for writing: %s\n", env, g_strerror (errno)); log_file = stderr; } +#endif + g_free (name); } } else { log_file = stderr; @@ -1880,12 +1911,13 @@ _gst_debug_fprintf (FILE * file, const gchar * format, ...) g_printerr ("%s", str); } else if (file == stdout) { g_print ("%s", str); + } else if (file == (FILE *) & _gst_debug_log_handle) { + /* By default, we can bypass the CRT's buffering by using WriteFile */ + DWORD written; + WriteFile (_gst_debug_log_handle, str, (DWORD) length, &written, NULL); } else { - /* We are writing to file. Text editors/viewers should be able to - * decode valid UTF-8 string regardless of codepage setting */ + /* Cater for a custom FILE* user_data in gst_debug_add_log_function */ fwrite (str, 1, length, file); - - /* FIXME: fflush here might be redundant if setvbuf works as expected */ fflush (file); } @@ -3397,6 +3429,10 @@ _priv_gst_debug_cleanup (void) } g_rw_lock_writer_unlock (&__log_func_mutex); +#ifdef G_OS_WIN32 + CloseHandle (_gst_debug_log_handle); +#endif + #ifdef HAVE_UNWIND # ifdef HAVE_DW if (_global_dwfl) { From a6c2a9a231937dbd0c4d264bf24e4f4658ba0a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 3 May 2026 23:29:45 +0300 Subject: [PATCH 79/82] gst: Pass a strong reference to the user_data to gst_pad_start_task() Otherwise the object could get disposed while the task function is still running, leading to crashes and worse. While this technically creates a reference cycle in most cases, this is not actually a problem because the task has to be stopped before the element and pad can get disposed and anything else leads to exactly the problem this is solving. --- subprojects/gst-libav/ext/libav/gstavdemux.c | 4 ++-- subprojects/gst-plugins-bad/ext/dtls/gstdtlsenc.c | 4 ++-- subprojects/gst-plugins-bad/ext/gme/gstgme.c | 6 +++--- .../gst-plugins-bad/ext/modplug/gstmodplug.cc | 4 ++-- .../gst-plugins-bad/ext/mpeg2enc/gstmpeg2enc.cc | 2 +- subprojects/gst-plugins-bad/ext/mplex/gstmplex.cc | 4 ++-- .../gst-plugins-bad/ext/musepack/gstmusepackdec.c | 6 ++++-- .../gst-plugins-bad/ext/openjpeg/gstopenjpegdec.c | 3 ++- .../gst-plugins-bad/ext/resindvd/gstmpegdemux.c | 2 +- subprojects/gst-plugins-bad/ext/sctp/gstsctpdec.c | 9 +++++---- subprojects/gst-plugins-bad/ext/sctp/gstsctpenc.c | 6 ++++-- subprojects/gst-plugins-bad/ext/sndfile/gstsfdec.c | 5 +++-- subprojects/gst-plugins-bad/ext/sndfile/gstsfsink.c | 3 ++- .../gst-libs/gst/audio/gstnonstreamaudiodecoder.c | 4 ++-- .../gst-plugins-bad/gst-libs/gst/mse/gstmsesrc.c | 6 ++++-- subprojects/gst-plugins-bad/gst/aiff/aiffparse.c | 4 ++-- subprojects/gst-plugins-bad/gst/midi/midiparse.c | 8 +++++--- .../gst-plugins-bad/gst/mpegdemux/gstmpegdemux.c | 6 ++++-- .../gst-plugins-bad/gst/mpegtsdemux/mpegtsbase.c | 8 ++++---- subprojects/gst-plugins-bad/gst/mxf/mxfdemux.c | 11 +++++++---- subprojects/gst-plugins-bad/gst/netsim/gstnetsim.c | 3 ++- .../gst-plugins-bad/gst/rist/gstristrtxsend.c | 6 ++++-- .../sys/androidmedia/gstamcaudiodec.c | 6 ++++-- .../sys/androidmedia/gstamcvideodec.c | 6 ++++-- .../sys/androidmedia/gstamcvideoenc.c | 6 ++++-- .../gst-plugins-bad/sys/applemedia/avfassetsrc.m | 10 ++++++---- subprojects/gst-plugins-bad/sys/applemedia/vtdec.c | 3 ++- subprojects/gst-plugins-bad/sys/applemedia/vtenc.c | 3 ++- .../sys/ipcpipeline/gstipcpipelinesrc.c | 2 +- .../gst-plugins-bad/sys/uvcgadget/gstuvcsink.c | 3 ++- subprojects/gst-plugins-base/ext/ogg/gstoggdemux.c | 6 +++--- .../gst-plugins-base/gst-libs/gst/tag/gsttagdemux.c | 6 ++++-- subprojects/gst-plugins-good/ext/dv/gstdvdemux.c | 5 +++-- subprojects/gst-plugins-good/gst/avi/gstavidemux.c | 4 ++-- .../gst-plugins-good/gst/debugutils/rndbuffersize.c | 4 ++-- subprojects/gst-plugins-good/gst/flv/gstflvdemux.c | 5 +++-- .../gst/imagefreeze/gstimagefreeze.c | 5 +++-- subprojects/gst-plugins-good/gst/isomp4/qtdemux.c | 4 ++-- .../gst-plugins-good/gst/matroska/matroska-demux.c | 5 +++-- .../gst-plugins-good/gst/multifile/gstsplitmuxsrc.c | 6 ++++-- .../gst/rtpmanager/gstrtpjitterbuffer.c | 3 ++- .../gst-plugins-good/gst/rtpmanager/gstrtprtxsend.c | 3 ++- .../gst-plugins-good/gst/wavparse/gstwavparse.c | 4 ++-- .../gst-plugins-good/sys/v4l2/gstv4l2videodec.c | 3 ++- .../gst-plugins-ugly/ext/sidplay/gstsiddec.cc | 3 ++- .../gst-plugins-ugly/gst/asfdemux/gstasfdemux.c | 4 ++-- subprojects/gst-plugins-ugly/gst/realmedia/rademux.c | 6 ++++-- subprojects/gst-plugins-ugly/gst/realmedia/rmdemux.c | 4 ++-- subprojects/gstreamer/libs/gst/base/gstaggregator.c | 3 ++- subprojects/gstreamer/libs/gst/base/gstbaseparse.c | 5 +++-- subprojects/gstreamer/libs/gst/base/gstbasesink.c | 3 ++- subprojects/gstreamer/libs/gst/base/gstbasesrc.c | 8 ++++---- .../gstreamer/plugins/elements/gstdownloadbuffer.c | 7 ++++--- .../gstreamer/plugins/elements/gstmultiqueue.c | 3 ++- subprojects/gstreamer/plugins/elements/gstqueue.c | 12 +++++++----- subprojects/gstreamer/plugins/elements/gstqueue2.c | 12 +++++++----- .../gstreamer/plugins/elements/gsttypefindelement.c | 5 +++-- subprojects/gstreamer/tests/check/gst/gstelement.c | 3 ++- 58 files changed, 175 insertions(+), 119 deletions(-) diff --git a/subprojects/gst-libav/ext/libav/gstavdemux.c b/subprojects/gst-libav/ext/libav/gstavdemux.c index d530c2743d..ea0462a9c7 100644 --- a/subprojects/gst-libav/ext/libav/gstavdemux.c +++ b/subprojects/gst-libav/ext/libav/gstavdemux.c @@ -648,7 +648,7 @@ gst_ffmpegdemux_perform_seek (GstFFMpegDemux * demux, GstEvent * event) /* and restart the task in case it got paused explicitely or by * the FLUSH_START event we pushed out. */ gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_ffmpegdemux_loop, - demux->sinkpad, NULL); + gst_object_ref (demux->sinkpad), gst_object_unref); /* and release the lock again so we can continue streaming */ GST_PAD_STREAM_UNLOCK (demux->sinkpad); @@ -1965,7 +1965,7 @@ gst_ffmpegdemux_sink_activate_pull (GstPad * sinkpad, GstObject * parent, if (active) { demux->seekable = TRUE; res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ffmpegdemux_loop, - demux, NULL); + gst_object_ref (demux), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); demux->seekable = FALSE; diff --git a/subprojects/gst-plugins-bad/ext/dtls/gstdtlsenc.c b/subprojects/gst-plugins-bad/ext/dtls/gstdtlsenc.c index 4f2b38e584..e4fafca7ae 100644 --- a/subprojects/gst-plugins-bad/ext/dtls/gstdtlsenc.c +++ b/subprojects/gst-plugins-bad/ext/dtls/gstdtlsenc.c @@ -477,8 +477,8 @@ src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, self->src_ret = GST_FLOW_OK; self->send_initial_events = TRUE; success = - gst_pad_start_task (pad, (GstTaskFunction) src_task_loop, self->src, - NULL); + gst_pad_start_task (pad, (GstTaskFunction) src_task_loop, + gst_object_ref (self->src), gst_object_unref); if (!success) { GST_WARNING_OBJECT (self, "failed to activate pad task"); } diff --git a/subprojects/gst-plugins-bad/ext/gme/gstgme.c b/subprojects/gst-plugins-bad/ext/gme/gstgme.c index 15d9476ba0..e8f7f76bbd 100644 --- a/subprojects/gst-plugins-bad/ext/gme/gstgme.c +++ b/subprojects/gst-plugins-bad/ext/gme/gstgme.c @@ -258,7 +258,7 @@ gst_gme_dec_src_event (GstPad * pad, GstObject * parent, GstEvent * event) gme->seeking = TRUE; gst_pad_start_task (gme->srcpad, (GstTaskFunction) gst_gme_play, - gme->srcpad, NULL); + gst_object_ref (gme->srcpad), gst_object_unref); GST_PAD_STREAM_UNLOCK (gme->srcpad); result = TRUE; @@ -461,8 +461,8 @@ gme_setup (GstGmeDec * gme) gst_segment_init (&seg, GST_FORMAT_TIME); gst_pad_push_event (gme->srcpad, gst_event_new_segment (&seg)); - gst_pad_start_task (gme->srcpad, (GstTaskFunction) gst_gme_play, gme->srcpad, - NULL); + gst_pad_start_task (gme->srcpad, (GstTaskFunction) gst_gme_play, + gst_object_ref (gme->srcpad), gst_object_unref); gme->initialized = TRUE; gme->seeking = FALSE; diff --git a/subprojects/gst-plugins-bad/ext/modplug/gstmodplug.cc b/subprojects/gst-plugins-bad/ext/modplug/gstmodplug.cc index 4ced9f1cf5..34998829e5 100644 --- a/subprojects/gst-plugins-bad/ext/modplug/gstmodplug.cc +++ b/subprojects/gst-plugins-bad/ext/modplug/gstmodplug.cc @@ -392,7 +392,7 @@ gst_modplug_do_seek (GstModPlug * modplug, GstEvent * event) gst_util_uint64_scale_int (cur, modplug->frequency, GST_SECOND); gst_pad_start_task (modplug->sinkpad, - (GstTaskFunction) gst_modplug_loop, modplug, NULL); + (GstTaskFunction) gst_modplug_loop, gst_object_ref (modplug), gst_object_unref); GST_PAD_STREAM_UNLOCK (modplug->sinkpad); @@ -586,7 +586,7 @@ gst_modplug_sinkpad_activate_mode (GstPad * pad, GstObject * parent, case GST_PAD_MODE_PULL: if (active) { res = gst_pad_start_task (pad, (GstTaskFunction) gst_modplug_loop, - modplug, NULL); + gst_object_ref (modplug), gst_object_unref); } else { res = gst_pad_stop_task (pad); } diff --git a/subprojects/gst-plugins-bad/ext/mpeg2enc/gstmpeg2enc.cc b/subprojects/gst-plugins-bad/ext/mpeg2enc/gstmpeg2enc.cc index 73c8d8021b..1699a8b32c 100644 --- a/subprojects/gst-plugins-bad/ext/mpeg2enc/gstmpeg2enc.cc +++ b/subprojects/gst-plugins-bad/ext/mpeg2enc/gstmpeg2enc.cc @@ -717,7 +717,7 @@ gst_mpeg2enc_handle_frame (GstVideoEncoder * video_encoder, if (!enc->started) { GST_DEBUG_OBJECT (video_encoder, "handle_frame: START task"); gst_pad_start_task (video_encoder->srcpad, - (GstTaskFunction) gst_mpeg2enc_loop, enc, NULL); + (GstTaskFunction) gst_mpeg2enc_loop, gst_object_ref (enc), gst_object_unref); enc->started = TRUE; } diff --git a/subprojects/gst-plugins-bad/ext/mplex/gstmplex.cc b/subprojects/gst-plugins-bad/ext/mplex/gstmplex.cc index 6e2e5e4dbe..b5806c4df7 100644 --- a/subprojects/gst-plugins-bad/ext/mplex/gstmplex.cc +++ b/subprojects/gst-plugins-bad/ext/mplex/gstmplex.cc @@ -533,8 +533,8 @@ gst_mplex_start_task (GstMplex * mplex) if (G_UNLIKELY (mplex->srcresult == GST_FLOW_CUSTOM_SUCCESS) && mplex->job->video_tracks == mplex->num_vpads && mplex->job->audio_tracks == mplex->num_apads) { - gst_pad_start_task (mplex->srcpad, (GstTaskFunction) gst_mplex_loop, mplex, - NULL); + gst_pad_start_task (mplex->srcpad, (GstTaskFunction) gst_mplex_loop, gst_object_ref (mplex), + gst_object_unref); mplex->srcresult = GST_FLOW_OK; } } diff --git a/subprojects/gst-plugins-bad/ext/musepack/gstmusepackdec.c b/subprojects/gst-plugins-bad/ext/musepack/gstmusepackdec.c index de449294ca..3d02800d8b 100644 --- a/subprojects/gst-plugins-bad/ext/musepack/gstmusepackdec.c +++ b/subprojects/gst-plugins-bad/ext/musepack/gstmusepackdec.c @@ -233,7 +233,8 @@ gst_musepackdec_handle_seek_event (GstMusepackDec * dec, GstEvent * event) GST_DEBUG_OBJECT (dec, "seek successful"); gst_pad_start_task (dec->sinkpad, - (GstTaskFunction) gst_musepackdec_loop, dec->sinkpad, NULL); + (GstTaskFunction) gst_musepackdec_loop, gst_object_ref (dec->sinkpad), + gst_object_unref); GST_PAD_STREAM_UNLOCK (dec->sinkpad); @@ -473,7 +474,8 @@ gst_musepackdec_sink_activate_mode (GstPad * sinkpad, GstObject * parent, case GST_PAD_MODE_PULL: if (active) { result = gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_musepackdec_loop, sinkpad, NULL); + (GstTaskFunction) gst_musepackdec_loop, gst_object_ref (sinkpad), + gst_object_unref); } else { result = gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gst-plugins-bad/ext/openjpeg/gstopenjpegdec.c b/subprojects/gst-plugins-bad/ext/openjpeg/gstopenjpegdec.c index 950b06d9bf..05ed9da0e7 100644 --- a/subprojects/gst-plugins-bad/ext/openjpeg/gstopenjpegdec.c +++ b/subprojects/gst-plugins-bad/ext/openjpeg/gstopenjpegdec.c @@ -1534,7 +1534,8 @@ gst_openjpeg_dec_decode_frame_multiple (GstVideoDecoder * decoder, if (!self->started) { GST_DEBUG_OBJECT (self, "Starting task"); gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self), - (GstTaskFunction) gst_openjpeg_dec_loop, decoder, NULL); + (GstTaskFunction) gst_openjpeg_dec_loop, gst_object_ref (decoder), + gst_object_unref); self->started = TRUE; } /* Make sure to release the base class stream lock, otherwise diff --git a/subprojects/gst-plugins-bad/ext/resindvd/gstmpegdemux.c b/subprojects/gst-plugins-bad/ext/resindvd/gstmpegdemux.c index 02ce48a53f..c3e66bbeb5 100644 --- a/subprojects/gst-plugins-bad/ext/resindvd/gstmpegdemux.c +++ b/subprojects/gst-plugins-bad/ext/resindvd/gstmpegdemux.c @@ -2136,7 +2136,7 @@ gst_flups_demux_sink_activate_pull (GstPad * sinkpad, GstObject * parent, GST_DEBUG ("pull mode activated"); demux->random_access = TRUE; return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flups_demux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { demux->random_access = FALSE; return gst_pad_stop_task (sinkpad); diff --git a/subprojects/gst-plugins-bad/ext/sctp/gstsctpdec.c b/subprojects/gst-plugins-bad/ext/sctp/gstsctpdec.c index 7603912a87..e3a9086b11 100644 --- a/subprojects/gst-plugins-bad/ext/sctp/gstsctpdec.c +++ b/subprojects/gst-plugins-bad/ext/sctp/gstsctpdec.c @@ -406,7 +406,8 @@ flush_srcpad (const GValue * item, gpointer user_data) } else { gst_data_queue_set_flushing (sctpdec_pad->packet_queue, FALSE); gst_pad_start_task (GST_PAD (sctpdec_pad), - (GstTaskFunction) gst_sctp_data_srcpad_loop, sctpdec_pad, NULL); + (GstTaskFunction) gst_sctp_data_srcpad_loop, + gst_object_ref (sctpdec_pad), gst_object_unref); } } @@ -552,8 +553,8 @@ gst_sctp_dec_src_event (GstPad * pad, GstSctpDec * self, GstEvent * event) /* Unflush and start task again */ gst_data_queue_set_flushing (sctpdec_pad->packet_queue, FALSE); - gst_pad_start_task (pad, (GstTaskFunction) gst_sctp_data_srcpad_loop, pad, - NULL); + gst_pad_start_task (pad, (GstTaskFunction) gst_sctp_data_srcpad_loop, + gst_object_ref (pad), gst_object_unref); return gst_pad_event_default (pad, GST_OBJECT (self), event); } @@ -634,7 +635,7 @@ get_pad_for_stream_id (GstSctpDec * self, guint16 stream_id) GST_OBJECT_UNLOCK (self); gst_pad_start_task (new_pad, (GstTaskFunction) gst_sctp_data_srcpad_loop, - new_pad, NULL); + gst_object_ref (new_pad), gst_object_unref); gst_object_ref (new_pad); diff --git a/subprojects/gst-plugins-bad/ext/sctp/gstsctpenc.c b/subprojects/gst-plugins-bad/ext/sctp/gstsctpenc.c index c8b66be0cd..981a56af4c 100644 --- a/subprojects/gst-plugins-bad/ext/sctp/gstsctpenc.c +++ b/subprojects/gst-plugins-bad/ext/sctp/gstsctpenc.c @@ -397,7 +397,8 @@ gst_sctp_enc_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: if (ret != GST_STATE_CHANGE_FAILURE) gst_pad_start_task (self->src_pad, - (GstTaskFunction) gst_sctp_enc_srcpad_loop, self->src_pad, NULL); + (GstTaskFunction) gst_sctp_enc_srcpad_loop, + gst_object_ref (self->src_pad), gst_object_unref); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: break; @@ -820,7 +821,8 @@ gst_sctp_enc_src_event (GstPad * pad, GstObject * parent, GstEvent * event) self->src_ret = GST_FLOW_OK; GST_OBJECT_UNLOCK (self); gst_pad_start_task (self->src_pad, - (GstTaskFunction) gst_sctp_enc_srcpad_loop, self->src_pad, NULL); + (GstTaskFunction) gst_sctp_enc_srcpad_loop, + gst_object_ref (self->src_pad), gst_object_unref); ret = gst_pad_event_default (pad, parent, event); break; diff --git a/subprojects/gst-plugins-bad/ext/sndfile/gstsfdec.c b/subprojects/gst-plugins-bad/ext/sndfile/gstsfdec.c index 20a61cb5ca..5aaa0998fd 100644 --- a/subprojects/gst-plugins-bad/ext/sndfile/gstsfdec.c +++ b/subprojects/gst-plugins-bad/ext/sndfile/gstsfdec.c @@ -260,7 +260,8 @@ gst_sf_dec_do_seek (GstSFDec * self, GstEvent * event) gst_pad_push_event (self->srcpad, gst_event_new_segment (&seg)); gst_pad_start_task (self->sinkpad, - (GstTaskFunction) gst_sf_dec_loop, self, NULL); + (GstTaskFunction) gst_sf_dec_loop, gst_object_ref (self), + gst_object_unref); GST_PAD_STREAM_UNLOCK (self->sinkpad); @@ -459,7 +460,7 @@ gst_sf_dec_sink_activate_mode (GstPad * sinkpad, GstObject * parent, /* if we have a scheduler we can start the task */ GST_DEBUG_OBJECT (sinkpad, "start task"); res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_sf_dec_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gst-plugins-bad/ext/sndfile/gstsfsink.c b/subprojects/gst-plugins-bad/ext/sndfile/gstsfsink.c index bd1bb9dad4..761b9c9014 100644 --- a/subprojects/gst-plugins-bad/ext/sndfile/gstsfsink.c +++ b/subprojects/gst-plugins-bad/ext/sndfile/gstsfsink.c @@ -455,7 +455,8 @@ gst_sf_sink_activate_pull (GstBaseSink * basesink, gboolean active) if (active) { /* start task */ result = gst_pad_start_task (basesink->sinkpad, - (GstTaskFunction) gst_sf_sink_loop, basesink->sinkpad, NULL); + (GstTaskFunction) gst_sf_sink_loop, gst_object_ref (basesink->sinkpad), + gst_object_unref); } else { /* step 2, make sure streaming finishes */ result = gst_pad_stop_task (basesink->sinkpad); diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/audio/gstnonstreamaudiodecoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/audio/gstnonstreamaudiodecoder.c index e8da770d61..5acdc55da6 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/audio/gstnonstreamaudiodecoder.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/audio/gstnonstreamaudiodecoder.c @@ -1486,8 +1486,8 @@ static gboolean gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder * dec) { if (!gst_pad_start_task (dec->srcpad, - (GstTaskFunction) gst_nonstream_audio_decoder_output_task, dec, - NULL)) { + (GstTaskFunction) gst_nonstream_audio_decoder_output_task, + gst_object_ref (dec), gst_object_unref)) { GST_ERROR_OBJECT (dec, "could not start decoder output task"); return FALSE; } else diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mse/gstmsesrc.c b/subprojects/gst-plugins-bad/gst-libs/gst/mse/gstmsesrc.c index 6939514a25..3c9fbbd02f 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/mse/gstmsesrc.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/mse/gstmsesrc.c @@ -834,7 +834,8 @@ resume_all_streams (GstMseSrc * self) GstPad *pad = GST_PAD (stream->pad); if (active) { clear_flushing (GST_MSE_SRC_PAD (pad)); - gst_pad_start_task (pad, (GstTaskFunction) pad_task, pad, NULL); + gst_pad_start_task (pad, (GstTaskFunction) pad_task, gst_object_ref (pad), + gst_object_unref); } } } @@ -1111,7 +1112,8 @@ pad_activate_mode (GstMseSrcPad * pad, GstObject * parent, GstPadMode mode, } if (active) { - gst_pad_start_task (GST_PAD (pad), (GstTaskFunction) pad_task, pad, NULL); + gst_pad_start_task (GST_PAD (pad), (GstTaskFunction) pad_task, + gst_object_ref (pad), gst_object_unref); } else { set_flushing_and_signal (pad); gst_media_source_track_flush (pad->track); diff --git a/subprojects/gst-plugins-bad/gst/aiff/aiffparse.c b/subprojects/gst-plugins-bad/gst/aiff/aiffparse.c index 1e8c955b79..8609d86a18 100644 --- a/subprojects/gst-plugins-bad/gst/aiff/aiffparse.c +++ b/subprojects/gst-plugins-bad/gst/aiff/aiffparse.c @@ -526,7 +526,7 @@ gst_aiff_parse_perform_seek (GstAiffParse * aiff, GstEvent * event, aiff->segment_running = TRUE; if (!aiff->streaming) { gst_pad_start_task (aiff->sinkpad, (GstTaskFunction) gst_aiff_parse_loop, - aiff->sinkpad, NULL); + gst_object_ref (aiff->sinkpad), gst_object_unref); } GST_PAD_STREAM_UNLOCK (aiff->sinkpad); @@ -1821,7 +1821,7 @@ gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent, aiff->segment_running = TRUE; res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { aiff->segment_running = FALSE; res = gst_pad_stop_task (sinkpad); diff --git a/subprojects/gst-plugins-bad/gst/midi/midiparse.c b/subprojects/gst-plugins-bad/gst/midi/midiparse.c index 413b6f0157..2bbf796015 100644 --- a/subprojects/gst-plugins-bad/gst/midi/midiparse.c +++ b/subprojects/gst-plugins-bad/gst/midi/midiparse.c @@ -373,7 +373,8 @@ gst_midi_parse_perform_seek (GstMidiParse * midiparse, GstEvent * event) * the FLUSH_START event we pushed out. */ tres = gst_pad_start_task (midiparse->sinkpad, - (GstTaskFunction) gst_midi_parse_loop, midiparse->sinkpad, NULL); + (GstTaskFunction) gst_midi_parse_loop, + gst_object_ref (midiparse->sinkpad), gst_object_unref); if (res && !tres) res = FALSE; @@ -454,7 +455,7 @@ gst_midi_parse_activatemode (GstPad * pad, GstObject * parent, case GST_PAD_MODE_PULL: if (active) { res = gst_pad_start_task (pad, (GstTaskFunction) gst_midi_parse_loop, - pad, NULL); + gst_object_ref (pad), gst_object_unref); } else { res = gst_pad_stop_task (pad); } @@ -1384,7 +1385,8 @@ gst_midi_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) midiparse->state = GST_MIDI_PARSE_STATE_PARSE; /* now start the parsing task */ res = gst_pad_start_task (midiparse->sinkpad, - (GstTaskFunction) gst_midi_parse_loop, midiparse->sinkpad, NULL); + (GstTaskFunction) gst_midi_parse_loop, + gst_object_ref (midiparse->sinkpad), gst_object_unref); /* don't forward the event */ gst_event_unref (event); break; diff --git a/subprojects/gst-plugins-bad/gst/mpegdemux/gstmpegdemux.c b/subprojects/gst-plugins-bad/gst/mpegdemux/gstmpegdemux.c index 091a6e4d6d..0cce0bea2f 100644 --- a/subprojects/gst-plugins-bad/gst/mpegdemux/gstmpegdemux.c +++ b/subprojects/gst-plugins-bad/gst/mpegdemux/gstmpegdemux.c @@ -1416,7 +1416,8 @@ gst_ps_demux_handle_seek_pull (GstPsDemux * demux, GstEvent * event) demux->segment_seqnum = seek_seqnum; gst_pad_start_task (demux->sinkpad, - (GstTaskFunction) gst_ps_demux_loop, demux->sinkpad, NULL); + (GstTaskFunction) gst_ps_demux_loop, gst_object_ref (demux->sinkpad), + gst_object_unref); GST_PAD_STREAM_UNLOCK (demux->sinkpad); @@ -3154,7 +3155,8 @@ gst_ps_demux_sink_activate_pull (GstPad * sinkpad, GstObject * parent, GST_DEBUG ("pull mode activated"); demux->random_access = TRUE; return gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_ps_demux_loop, sinkpad, NULL); + (GstTaskFunction) gst_ps_demux_loop, gst_object_ref (sinkpad), + gst_object_unref); } else { demux->random_access = FALSE; return gst_pad_stop_task (sinkpad); diff --git a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtsbase.c b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtsbase.c index e6bc57b2ec..4ecfad1546 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtsbase.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsdemux/mpegtsbase.c @@ -2016,8 +2016,8 @@ mpegts_base_handle_seek_event (MpegTSBase * base, GstPad * pad, flush_event = NULL; } - gst_pad_start_task (base->sinkpad, (GstTaskFunction) mpegts_base_loop, base, - NULL); + gst_pad_start_task (base->sinkpad, (GstTaskFunction) mpegts_base_loop, + gst_object_ref (base), gst_object_unref); GST_PAD_STREAM_UNLOCK (base->sinkpad); return ret == GST_FLOW_OK; @@ -2074,8 +2074,8 @@ mpegts_base_sink_activate_mode (GstPad * pad, GstObject * parent, base->packetizer->calculate_skew = FALSE; gst_segment_init (&base->segment, GST_FORMAT_BYTES); res = - gst_pad_start_task (pad, (GstTaskFunction) mpegts_base_loop, base, - NULL); + gst_pad_start_task (pad, (GstTaskFunction) mpegts_base_loop, + gst_object_ref (base), gst_object_unref); } else res = gst_pad_stop_task (pad); break; diff --git a/subprojects/gst-plugins-bad/gst/mxf/mxfdemux.c b/subprojects/gst-plugins-bad/gst/mxf/mxfdemux.c index b2e0d3454b..7b84df1941 100644 --- a/subprojects/gst-plugins-bad/gst/mxf/mxfdemux.c +++ b/subprojects/gst-plugins-bad/gst/mxf/mxfdemux.c @@ -5872,7 +5872,8 @@ gst_mxf_demux_seek_pull (GstMXFDemux * demux, GstEvent * event) demux->seqnum = seqnum; gst_pad_start_task (demux->sinkpad, - (GstTaskFunction) gst_mxf_demux_loop, demux->sinkpad, NULL); + (GstTaskFunction) gst_mxf_demux_loop, gst_object_ref (demux->sinkpad), + gst_object_unref); GST_PAD_STREAM_UNLOCK (demux->sinkpad); @@ -5887,7 +5888,8 @@ gst_mxf_demux_seek_pull (GstMXFDemux * demux, GstEvent * event) unresolved_metadata: { gst_pad_start_task (demux->sinkpad, - (GstTaskFunction) gst_mxf_demux_loop, demux->sinkpad, NULL); + (GstTaskFunction) gst_mxf_demux_loop, gst_object_ref (demux->sinkpad), + gst_object_unref); GST_PAD_STREAM_UNLOCK (demux->sinkpad); GST_WARNING_OBJECT (demux, "metadata can't be resolved"); return FALSE; @@ -5904,7 +5906,8 @@ gst_mxf_demux_seek_pull (GstMXFDemux * demux, GstEvent * event) gst_mxf_demux_push_src_event (demux, e); } gst_pad_start_task (demux->sinkpad, - (GstTaskFunction) gst_mxf_demux_loop, demux->sinkpad, NULL); + (GstTaskFunction) gst_mxf_demux_loop, gst_object_ref (demux->sinkpad), + gst_object_unref); GST_PAD_STREAM_UNLOCK (demux->sinkpad); GST_WARNING_OBJECT (demux, "Requested seek position is not valid"); return FALSE; @@ -6114,7 +6117,7 @@ gst_mxf_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, if (active) { demux->random_access = TRUE; return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_mxf_demux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { demux->random_access = FALSE; return gst_pad_stop_task (sinkpad); diff --git a/subprojects/gst-plugins-bad/gst/netsim/gstnetsim.c b/subprojects/gst-plugins-bad/gst/netsim/gstnetsim.c index 48c6c64fda..0b550ab65e 100644 --- a/subprojects/gst-plugins-bad/gst/netsim/gstnetsim.c +++ b/subprojects/gst-plugins-bad/gst/netsim/gstnetsim.c @@ -165,7 +165,8 @@ gst_net_sim_src_activatemode (GstPad * pad, GstObject * parent, GST_TRACE_OBJECT (netsim, "ACT: Starting task on srcpad"); result = gst_pad_start_task (netsim->srcpad, - (GstTaskFunction) gst_net_sim_loop, netsim, NULL); + (GstTaskFunction) gst_net_sim_loop, gst_object_ref (netsim), + gst_object_unref); GST_TRACE_OBJECT (netsim, "ACT: Wait for task to start"); g_assert (!netsim->running); diff --git a/subprojects/gst-plugins-bad/gst/rist/gstristrtxsend.c b/subprojects/gst-plugins-bad/gst/rist/gstristrtxsend.c index e3083f24e0..aacdb5a0fc 100644 --- a/subprojects/gst-plugins-bad/gst/rist/gstristrtxsend.c +++ b/subprojects/gst-plugins-bad/gst/rist/gstristrtxsend.c @@ -490,7 +490,8 @@ gst_rist_rtx_send_sink_event (GstPad * pad, GstObject * parent, gst_pad_push_event (rtx->srcpad, event); gst_rist_rtx_send_set_flushing (rtx, FALSE); gst_pad_start_task (rtx->srcpad, - (GstTaskFunction) gst_rist_rtx_send_src_loop, rtx, NULL); + (GstTaskFunction) gst_rist_rtx_send_src_loop, gst_object_ref (rtx), + gst_object_unref); return TRUE; case GST_EVENT_EOS: GST_INFO_OBJECT (rtx, "Got EOS - enqueueing it"); @@ -717,7 +718,8 @@ gst_rist_rtx_send_activate_mode (GstPad * pad, GstObject * parent, if (active) { gst_rist_rtx_send_set_flushing (rtx, FALSE); ret = gst_pad_start_task (rtx->srcpad, - (GstTaskFunction) gst_rist_rtx_send_src_loop, rtx, NULL); + (GstTaskFunction) gst_rist_rtx_send_src_loop, gst_object_ref (rtx), + gst_object_unref); } else { gst_rist_rtx_send_set_flushing (rtx, TRUE); ret = gst_pad_stop_task (rtx->srcpad); diff --git a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcaudiodec.c b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcaudiodec.c index 398a6e1bd3..0f7f088f99 100644 --- a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcaudiodec.c +++ b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcaudiodec.c @@ -1005,7 +1005,8 @@ gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps) self->flushing = FALSE; self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self), - (GstTaskFunction) gst_amc_audio_dec_loop, decoder, NULL); + (GstTaskFunction) gst_amc_audio_dec_loop, gst_object_ref (decoder), + gst_object_unref); return TRUE; } @@ -1045,7 +1046,8 @@ gst_amc_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard) self->drained = TRUE; self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self), - (GstTaskFunction) gst_amc_audio_dec_loop, decoder, NULL); + (GstTaskFunction) gst_amc_audio_dec_loop, gst_object_ref (decoder), + gst_object_unref); GST_DEBUG_OBJECT (self, "Reset decoder"); } diff --git a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideodec.c b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideodec.c index 7c5a535d94..2feb79baa3 100644 --- a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideodec.c +++ b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideodec.c @@ -2047,7 +2047,8 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder, self->flushing = FALSE; self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self), - (GstTaskFunction) gst_amc_video_dec_loop, decoder, NULL); + (GstTaskFunction) gst_amc_video_dec_loop, gst_object_ref (decoder), + gst_object_unref); return TRUE; } @@ -2085,7 +2086,8 @@ gst_amc_video_dec_flush (GstVideoDecoder * decoder) self->drained = TRUE; self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self), - (GstTaskFunction) gst_amc_video_dec_loop, decoder, NULL); + (GstTaskFunction) gst_amc_video_dec_loop, gst_object_ref (decoder), + gst_object_unref); GST_DEBUG_OBJECT (self, "Flushed decoder"); diff --git a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c index b2ff33d63b..2d8eb8456e 100644 --- a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c +++ b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c @@ -1477,7 +1477,8 @@ gst_amc_video_enc_set_format (GstVideoEncoder * encoder, self->flushing = FALSE; self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self), - (GstTaskFunction) gst_amc_video_enc_loop, encoder, NULL); + (GstTaskFunction) gst_amc_video_enc_loop, gst_object_ref (encoder), + gst_object_unref); r = TRUE; @@ -1525,7 +1526,8 @@ gst_amc_video_enc_flush (GstVideoEncoder * encoder) self->drained = TRUE; self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self), - (GstTaskFunction) gst_amc_video_enc_loop, encoder, NULL); + (GstTaskFunction) gst_amc_video_enc_loop, gst_object_ref (encoder), + gst_object_unref); GST_DEBUG_OBJECT (self, "Flush encoder"); diff --git a/subprojects/gst-plugins-bad/sys/applemedia/avfassetsrc.m b/subprojects/gst-plugins-bad/sys/applemedia/avfassetsrc.m index ff9a23286f..f8a2c51372 100644 --- a/subprojects/gst-plugins-bad/sys/applemedia/avfassetsrc.m +++ b/subprojects/gst-plugins-bad/sys/applemedia/avfassetsrc.m @@ -854,14 +854,15 @@ static void gst_avf_asset_src_uri_handler_init (gpointer g_iface, goto exit; } if (AVF_ASSET_READER_HAS_SUPPORTED_AUDIO (self)) { - ret = gst_pad_start_task (self->audiopad, (GstTaskFunction) gst_avf_asset_src_read_audio, self, NULL); + ret = gst_pad_start_task (self->audiopad, (GstTaskFunction) gst_avf_asset_src_read_audio, gst_object_ref (self), gst_object_unref); if (!ret) { GST_ERROR ("Failed to start audio task"); goto exit; } } else if (AVF_ASSET_READER_HAS_AUDIO (self) && self->audiopad) { ret = gst_pad_start_task (self->audiopad, - (GstTaskFunction) gst_avf_asset_src_send_audio_eos, self, NULL); + (GstTaskFunction) gst_avf_asset_src_send_audio_eos, gst_object_ref (self), + gst_object_unref); if (!ret) { GST_ERROR ("Failed to start audio EOS task"); goto exit; @@ -869,14 +870,15 @@ static void gst_avf_asset_src_uri_handler_init (gpointer g_iface, } if (AVF_ASSET_READER_HAS_SUPPORTED_VIDEO (self)) { - ret = gst_pad_start_task (self->videopad, (GstTaskFunction)gst_avf_asset_src_read_video, self, NULL); + ret = gst_pad_start_task (self->videopad, (GstTaskFunction)gst_avf_asset_src_read_video, gst_object_ref (self), gst_object_unref); if (!ret) { GST_ERROR ("Failed to start video task"); goto exit; } } else if (AVF_ASSET_READER_HAS_VIDEO (self) && self->videopad) { ret = gst_pad_start_task (self->videopad, - (GstTaskFunction) gst_avf_asset_src_send_video_eos, self, NULL); + (GstTaskFunction) gst_avf_asset_src_send_video_eos, gst_object_ref (self), + gst_object_unref); if (!ret) { GST_ERROR ("Failed to start video EOS task"); goto exit; diff --git a/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c b/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c index b98cc63705..c04a80c565 100644 --- a/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c +++ b/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c @@ -355,7 +355,8 @@ gst_vtdec_start (GstVideoDecoder * decoder) /* Create the output task, but pause it immediately */ vtdec->pause_task = TRUE; if (!gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (decoder), - (GstTaskFunction) gst_vtdec_output_loop, vtdec, NULL)) { + (GstTaskFunction) gst_vtdec_output_loop, gst_object_ref (vtdec), + gst_object_unref)) { GST_ERROR_OBJECT (vtdec, "failed to start output thread"); return FALSE; } diff --git a/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c b/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c index 733e7288a8..b66b7c691d 100644 --- a/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c +++ b/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c @@ -870,7 +870,8 @@ gst_vtenc_start (GstVideoEncoder * enc) /* Create the output task, but pause it immediately */ self->pause_task = TRUE; if (!gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (enc), - (GstTaskFunction) gst_vtenc_output_loop, self, NULL)) { + (GstTaskFunction) gst_vtenc_output_loop, gst_object_ref (self), + gst_object_unref)) { GST_ERROR_OBJECT (self, "failed to start output thread"); return FALSE; } diff --git a/subprojects/gst-plugins-bad/sys/ipcpipeline/gstipcpipelinesrc.c b/subprojects/gst-plugins-bad/sys/ipcpipeline/gstipcpipelinesrc.c index b5267286cc..2f40ca2e10 100644 --- a/subprojects/gst-plugins-bad/sys/ipcpipeline/gstipcpipelinesrc.c +++ b/subprojects/gst-plugins-bad/sys/ipcpipeline/gstipcpipelinesrc.c @@ -362,7 +362,7 @@ gst_ipc_pipeline_src_start_loop (GstIpcPipelineSrc * src) g_mutex_unlock (&src->comm.mutex); gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_ipc_pipeline_src_loop, - src, NULL); + gst_object_ref (src), gst_object_unref); } static void diff --git a/subprojects/gst-plugins-bad/sys/uvcgadget/gstuvcsink.c b/subprojects/gst-plugins-bad/sys/uvcgadget/gstuvcsink.c index da11e3f5e6..aba1799db3 100644 --- a/subprojects/gst-plugins-bad/sys/uvcgadget/gstuvcsink.c +++ b/subprojects/gst-plugins-bad/sys/uvcgadget/gstuvcsink.c @@ -865,7 +865,8 @@ gst_uvc_sink_watch (GstUvcSink * self) } if (!gst_pad_start_task (GST_PAD (self->sinkpad), - (GstTaskFunction) gst_uvc_sink_task, self, NULL)) { + (GstTaskFunction) gst_uvc_sink_task, gst_object_ref (self), + gst_object_unref)) { GST_ELEMENT_ERROR (self, CORE, THREAD, ("Could not start pad task"), ("Could not start pad task")); return FALSE; diff --git a/subprojects/gst-plugins-base/ext/ogg/gstoggdemux.c b/subprojects/gst-plugins-base/ext/ogg/gstoggdemux.c index d6c549f84d..69d0c86d37 100644 --- a/subprojects/gst-plugins-base/ext/ogg/gstoggdemux.c +++ b/subprojects/gst-plugins-base/ext/ogg/gstoggdemux.c @@ -3723,7 +3723,7 @@ gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event) /* restart our task since it might have been stopped when we did the * flush. */ gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop, - ogg->sinkpad, NULL); + gst_object_ref (ogg->sinkpad), gst_object_unref); } /* streaming can continue now */ @@ -4063,7 +4063,7 @@ gst_ogg_demux_setup_seek_pull (GstOggDemux * ogg, GstEvent * event) gst_event_replace (&ogg->seek_event, event); gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop, - ogg->sinkpad, NULL); + gst_object_ref (ogg->sinkpad), gst_object_unref); GST_PAD_STREAM_UNLOCK (ogg->sinkpad); return TRUE; @@ -5236,7 +5236,7 @@ gst_ogg_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, ogg->pullmode = TRUE; res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ogg_demux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gst-plugins-base/gst-libs/gst/tag/gsttagdemux.c b/subprojects/gst-plugins-base/gst-libs/gst/tag/gsttagdemux.c index 16bf0015b6..95cca3380b 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/tag/gsttagdemux.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/tag/gsttagdemux.c @@ -938,7 +938,8 @@ gst_tag_demux_seek_pull (GstTagDemux * tagdemux, GstEvent * event) /* restart our task since it might have been stopped when we did the * flush. */ gst_pad_start_task (tagdemux->priv->sinkpad, - (GstTaskFunction) gst_tag_demux_element_loop, tagdemux, NULL); + (GstTaskFunction) gst_tag_demux_element_loop, gst_object_ref (tagdemux), + gst_object_unref); /* streaming can continue now */ GST_PAD_STREAM_UNLOCK (tagdemux->priv->sinkpad); @@ -1603,7 +1604,8 @@ gst_tag_demux_sink_activate (GstPad * sinkpad, GstObject * parent) /* only start our task if we ourselves decide to start in pull mode */ return gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_tag_demux_element_loop, demux, NULL); + (GstTaskFunction) gst_tag_demux_element_loop, gst_object_ref (demux), + gst_object_unref); activate_push: { diff --git a/subprojects/gst-plugins-good/ext/dv/gstdvdemux.c b/subprojects/gst-plugins-good/ext/dv/gstdvdemux.c index 10c2dbaf40..5320cc011b 100644 --- a/subprojects/gst-plugins-good/ext/dv/gstdvdemux.c +++ b/subprojects/gst-plugins-good/ext/dv/gstdvdemux.c @@ -1155,7 +1155,7 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad, /* and restart the task in case it got paused explicitly or by * the FLUSH_START event we pushed out. */ gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_dvdemux_loop, - demux->sinkpad, NULL); + gst_object_ref (demux->sinkpad), gst_object_unref); /* and release the lock again so we can continue streaming */ GST_PAD_STREAM_UNLOCK (demux->sinkpad); @@ -1940,7 +1940,8 @@ gst_dvdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, if (active) { demux->seek_handler = gst_dvdemux_handle_pull_seek; res = gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_dvdemux_loop, sinkpad, NULL); + (GstTaskFunction) gst_dvdemux_loop, gst_object_ref (sinkpad), + gst_object_unref); } else { demux->seek_handler = NULL; res = gst_pad_stop_task (sinkpad); diff --git a/subprojects/gst-plugins-good/gst/avi/gstavidemux.c b/subprojects/gst-plugins-good/gst/avi/gstavidemux.c index 03adaa0df8..96788aa6c9 100644 --- a/subprojects/gst-plugins-good/gst/avi/gstavidemux.c +++ b/subprojects/gst-plugins-good/gst/avi/gstavidemux.c @@ -4697,7 +4697,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event) if (!avi->streaming) { gst_pad_start_task (avi->sinkpad, (GstTaskFunction) gst_avi_demux_loop, - avi->sinkpad, NULL); + gst_object_ref (avi->sinkpad), gst_object_unref); } /* reset the last flow and mark discont, seek is always DISCONT */ for (i = 0; i < avi->num_streams; i++) { @@ -5976,7 +5976,7 @@ gst_avi_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, if (active) { avi->streaming = FALSE; res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_avi_demux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gst-plugins-good/gst/debugutils/rndbuffersize.c b/subprojects/gst-plugins-good/gst/debugutils/rndbuffersize.c index 1fee416fbb..a85d6ce9f6 100644 --- a/subprojects/gst-plugins-good/gst/debugutils/rndbuffersize.c +++ b/subprojects/gst-plugins-good/gst/debugutils/rndbuffersize.c @@ -276,7 +276,7 @@ gst_rnd_buffer_size_activate_mode (GstPad * pad, GstObject * parent, GST_INFO_OBJECT (self, "starting pull"); res = gst_pad_start_task (pad, (GstTaskFunction) gst_rnd_buffer_size_loop, - self, NULL); + gst_object_ref (self), gst_object_unref); self->need_newsegment = TRUE; } else { GST_INFO_OBJECT (self, "stopping pull"); @@ -341,7 +341,7 @@ gst_rnd_buffer_size_src_event (GstPad * pad, GstObject * parent, self->need_newsegment = TRUE; gst_pad_start_task (self->sinkpad, (GstTaskFunction) gst_rnd_buffer_size_loop, - self, NULL); + gst_object_ref (self), gst_object_unref); GST_PAD_STREAM_UNLOCK (self->sinkpad); return TRUE; diff --git a/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c b/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c index 960ea51087..9dce51af3c 100644 --- a/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c +++ b/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c @@ -4144,7 +4144,8 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event, gst_pad_pause_task (demux->sinkpad); } else { gst_pad_start_task (demux->sinkpad, - (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad, NULL); + (GstTaskFunction) gst_flv_demux_loop, gst_object_ref (demux->sinkpad), + gst_object_unref); } GST_PAD_STREAM_UNLOCK (demux->sinkpad); @@ -4211,7 +4212,7 @@ gst_flv_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, demux->random_access = TRUE; demux->segment_seqnum = gst_util_seqnum_next (); res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { demux->random_access = FALSE; res = gst_pad_stop_task (sinkpad); diff --git a/subprojects/gst-plugins-good/gst/imagefreeze/gstimagefreeze.c b/subprojects/gst-plugins-good/gst/imagefreeze/gstimagefreeze.c index 98232dface..fc3b1779db 100644 --- a/subprojects/gst-plugins-good/gst/imagefreeze/gstimagefreeze.c +++ b/subprojects/gst-plugins-good/gst/imagefreeze/gstimagefreeze.c @@ -865,7 +865,8 @@ gst_image_freeze_src_event (GstPad * pad, GstObject * parent, GstEvent * event) if (self->buffer != NULL) gst_pad_start_task (self->srcpad, - (GstTaskFunction) gst_image_freeze_src_loop, self->srcpad, NULL); + (GstTaskFunction) gst_image_freeze_src_loop, + gst_object_ref (self->srcpad), gst_object_unref); g_mutex_unlock (&self->lock); } @@ -985,7 +986,7 @@ gst_image_freeze_sink_chain (GstPad * pad, GstObject * parent, gst_buffer_unref (buffer); gst_pad_start_task (self->srcpad, (GstTaskFunction) gst_image_freeze_src_loop, - self->srcpad, NULL); + gst_object_ref (self->srcpad), gst_object_unref); flow_ret = self->allow_replace ? GST_FLOW_OK : GST_FLOW_EOS; g_mutex_unlock (&self->lock); return flow_ret; diff --git a/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c b/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c index b3b38ae99c..d3b2dfee82 100644 --- a/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c +++ b/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c @@ -1676,7 +1676,7 @@ gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event) /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */ gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop, - qtdemux->sinkpad, NULL); + gst_object_ref (qtdemux->sinkpad), gst_object_unref); GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad); @@ -9046,7 +9046,7 @@ qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, if (active) { demux->pullbased = TRUE; res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gst-plugins-good/gst/matroska/matroska-demux.c b/subprojects/gst-plugins-good/gst/matroska/matroska-demux.c index ab11e17a02..421152754a 100644 --- a/subprojects/gst-plugins-good/gst/matroska/matroska-demux.c +++ b/subprojects/gst-plugins-good/gst/matroska/matroska-demux.c @@ -3337,7 +3337,8 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, /* restart our task since it might have been stopped when we did the * flush. */ gst_pad_start_task (demux->common.sinkpad, - (GstTaskFunction) gst_matroska_demux_loop, demux->common.sinkpad, NULL); + (GstTaskFunction) gst_matroska_demux_loop, + gst_object_ref (demux->common.sinkpad), gst_object_unref); /* streaming can continue now */ if (pad_locked) { @@ -7120,7 +7121,7 @@ gst_matroska_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, if (active) { /* if we have a scheduler we can start the task */ gst_pad_start_task (sinkpad, (GstTaskFunction) gst_matroska_demux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsrc.c b/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsrc.c index 55e662942b..f628fbd589 100644 --- a/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsrc.c +++ b/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsrc.c @@ -1110,7 +1110,8 @@ gst_splitmux_src_activate_part (GstSplitMuxSrc * splitmux, guint part, splitpad->clear_next_discont = FALSE; gst_pad_start_task (GST_PAD (splitpad), - (GstTaskFunction) gst_splitmux_pad_loop, splitpad, NULL); + (GstTaskFunction) gst_splitmux_pad_loop, gst_object_ref (splitpad), + gst_object_unref); } SPLITMUX_SRC_PADS_RUNLOCK (splitmux); @@ -1799,7 +1800,8 @@ splitmux_src_pad_event (GstPad * pad, GstObject * parent, GstEvent * event) SPLITMUX_SRC_PADS_RLOCK (splitmux); /* Restart the task on this pad */ gst_pad_start_task (GST_PAD (pad), - (GstTaskFunction) gst_splitmux_pad_loop, pad, NULL); + (GstTaskFunction) gst_splitmux_pad_loop, gst_object_ref (pad), + gst_object_unref); SPLITMUX_SRC_PADS_RUNLOCK (splitmux); break; } diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c index b353db6212..23c5724154 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c @@ -1930,7 +1930,8 @@ gst_rtp_jitter_buffer_src_activate_mode (GstPad * pad, GstObject * parent, /* start pushing out buffers */ GST_DEBUG_OBJECT (jitterbuffer, "Starting task on srcpad"); result = gst_pad_start_task (jitterbuffer->priv->srcpad, - (GstTaskFunction) gst_rtp_jitter_buffer_loop, jitterbuffer, NULL); + (GstTaskFunction) gst_rtp_jitter_buffer_loop, + gst_object_ref (jitterbuffer), gst_object_unref); } else { /* make sure all data processing stops ASAP */ gst_rtp_jitter_buffer_flush_start (jitterbuffer); diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtprtxsend.c b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtprtxsend.c index cb1afe3b08..67b9cbcdb2 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtprtxsend.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtprtxsend.c @@ -232,7 +232,8 @@ gst_rtp_rtx_send_set_task_state (GstRtpRtxSend * rtx, RtxTaskState task_state) GST_DEBUG_OBJECT (rtx, "Starting RTX task"); gst_rtp_rtx_send_set_flushing (rtx, FALSE); ret = gst_pad_start_task (rtx->srcpad, - (GstTaskFunction) gst_rtp_rtx_send_src_loop, rtx, NULL); + (GstTaskFunction) gst_rtp_rtx_send_src_loop, gst_object_ref (rtx), + gst_object_unref); } break; } diff --git a/subprojects/gst-plugins-good/gst/wavparse/gstwavparse.c b/subprojects/gst-plugins-good/gst/wavparse/gstwavparse.c index 7410b773d1..b8df1ac25e 100644 --- a/subprojects/gst-plugins-good/gst/wavparse/gstwavparse.c +++ b/subprojects/gst-plugins-good/gst/wavparse/gstwavparse.c @@ -626,7 +626,7 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event) /* and start the streaming task again */ if (!wav->streaming) { gst_pad_start_task (wav->sinkpad, (GstTaskFunction) gst_wavparse_loop, - wav->sinkpad, NULL); + gst_object_ref (wav->sinkpad), gst_object_unref); } GST_PAD_STREAM_UNLOCK (wav->sinkpad); @@ -3087,7 +3087,7 @@ gst_wavparse_sink_activate_mode (GstPad * sinkpad, GstObject * parent, if (active) { /* if we have a scheduler we can start the task */ res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_wavparse_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c index e300d9b22b..ba9effdede 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c @@ -1065,7 +1065,8 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder, self->output_flow = GST_FLOW_FLUSHING; self->draining = FALSE; if (!gst_pad_start_task (decoder->srcpad, - (GstTaskFunction) gst_v4l2_video_dec_loop, self, NULL)) + (GstTaskFunction) gst_v4l2_video_dec_loop, gst_object_ref (self), + gst_object_unref)) goto start_task_failed; } diff --git a/subprojects/gst-plugins-ugly/ext/sidplay/gstsiddec.cc b/subprojects/gst-plugins-ugly/ext/sidplay/gstsiddec.cc index 1a7c91ea9c..139674e282 100644 --- a/subprojects/gst-plugins-ugly/ext/sidplay/gstsiddec.cc +++ b/subprojects/gst-plugins-ugly/ext/sidplay/gstsiddec.cc @@ -488,7 +488,8 @@ start_play_tune (GstSidDec * siddec) siddec->group_id = G_MAXUINT; res = gst_pad_start_task (siddec->srcpad, - (GstTaskFunction) play_loop, siddec->srcpad, NULL); + (GstTaskFunction) play_loop, gst_object_ref (siddec->srcpad), + gst_object_unref); return res; /* ERRORS */ diff --git a/subprojects/gst-plugins-ugly/gst/asfdemux/gstasfdemux.c b/subprojects/gst-plugins-ugly/gst/asfdemux/gstasfdemux.c index 9450744e15..16d119c61f 100644 --- a/subprojects/gst-plugins-ugly/gst/asfdemux/gstasfdemux.c +++ b/subprojects/gst-plugins-ugly/gst/asfdemux/gstasfdemux.c @@ -383,7 +383,7 @@ gst_asf_demux_activate_mode (GstPad * sinkpad, GstObject * parent, demux->streaming = FALSE; res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_asf_demux_loop, - demux, NULL); + gst_object_ref (demux), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); } @@ -840,7 +840,7 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event) skip: /* restart our task since it might have been stopped when we did the flush */ gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_asf_demux_loop, - demux, NULL); + gst_object_ref (demux), gst_object_unref); /* streaming can continue now */ GST_PAD_STREAM_UNLOCK (demux->sinkpad); diff --git a/subprojects/gst-plugins-ugly/gst/realmedia/rademux.c b/subprojects/gst-plugins-ugly/gst/realmedia/rademux.c index 01b12f4ceb..bd60880081 100644 --- a/subprojects/gst-plugins-ugly/gst/realmedia/rademux.c +++ b/subprojects/gst-plugins-ugly/gst/realmedia/rademux.c @@ -226,7 +226,8 @@ gst_real_audio_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, demux->seekable = TRUE; res = gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_real_audio_demux_loop, demux, NULL); + (GstTaskFunction) gst_real_audio_demux_loop, gst_object_ref (demux), + gst_object_unref); } else { demux->seekable = FALSE; res = gst_pad_stop_task (sinkpad); @@ -841,7 +842,8 @@ gst_real_audio_demux_handle_seek (GstRealAudioDemux * demux, GstEvent * event) demux->segment_running = TRUE; /* restart our task since it might have been stopped when we did the flush */ gst_pad_start_task (demux->sinkpad, - (GstTaskFunction) gst_real_audio_demux_loop, demux, NULL); + (GstTaskFunction) gst_real_audio_demux_loop, gst_object_ref (demux), + gst_object_unref); /* streaming can continue now */ GST_PAD_STREAM_UNLOCK (demux->sinkpad); diff --git a/subprojects/gst-plugins-ugly/gst/realmedia/rmdemux.c b/subprojects/gst-plugins-ugly/gst/realmedia/rmdemux.c index 8501363f83..d5a4d71ee8 100644 --- a/subprojects/gst-plugins-ugly/gst/realmedia/rmdemux.c +++ b/subprojects/gst-plugins-ugly/gst/realmedia/rmdemux.c @@ -630,7 +630,7 @@ gst_rmdemux_perform_seek (GstRMDemux * rmdemux, GstEvent * event) /* restart our task since it might have been stopped when we did the * flush. */ gst_pad_start_task (rmdemux->sinkpad, (GstTaskFunction) gst_rmdemux_loop, - rmdemux->sinkpad, NULL); + gst_object_ref (rmdemux->sinkpad), gst_object_unref); } done: @@ -869,7 +869,7 @@ gst_rmdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, demux->data_offset = G_MAXUINT; res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_rmdemux_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); } else { res = gst_pad_stop_task (sinkpad); } diff --git a/subprojects/gstreamer/libs/gst/base/gstaggregator.c b/subprojects/gstreamer/libs/gst/base/gstaggregator.c index cff03e7840..a182c2fb5d 100644 --- a/subprojects/gstreamer/libs/gst/base/gstaggregator.c +++ b/subprojects/gstreamer/libs/gst/base/gstaggregator.c @@ -1683,7 +1683,8 @@ gst_aggregator_start_srcpad_task (GstAggregator * self) self->priv->running = TRUE; gst_pad_start_task (GST_PAD (self->srcpad), - (GstTaskFunction) gst_aggregator_aggregate_func, self, NULL); + (GstTaskFunction) gst_aggregator_aggregate_func, gst_object_ref (self), + gst_object_unref); } static GstFlowReturn diff --git a/subprojects/gstreamer/libs/gst/base/gstbaseparse.c b/subprojects/gstreamer/libs/gst/base/gstbaseparse.c index a278c169f1..621de253bc 100644 --- a/subprojects/gstreamer/libs/gst/base/gstbaseparse.c +++ b/subprojects/gstreamer/libs/gst/base/gstbaseparse.c @@ -3828,7 +3828,7 @@ gst_base_parse_sink_activate (GstPad * sinkpad, GstObject * parent) parse->priv->upstream_format = GST_FORMAT_BYTES; return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_base_parse_loop, - sinkpad, NULL); + gst_object_ref (sinkpad), gst_object_unref); /* fallback */ baseparse_push: { @@ -4883,7 +4883,8 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) /* Start streaming thread if paused */ gst_pad_start_task (parse->sinkpad, - (GstTaskFunction) gst_base_parse_loop, parse->sinkpad, NULL); + (GstTaskFunction) gst_base_parse_loop, gst_object_ref (parse->sinkpad), + gst_object_unref); GST_PAD_STREAM_UNLOCK (parse->sinkpad); diff --git a/subprojects/gstreamer/libs/gst/base/gstbasesink.c b/subprojects/gstreamer/libs/gst/base/gstbasesink.c index ba4b816251..0a92bdd786 100644 --- a/subprojects/gstreamer/libs/gst/base/gstbasesink.c +++ b/subprojects/gstreamer/libs/gst/base/gstbasesink.c @@ -4713,7 +4713,8 @@ gst_base_sink_default_activate_pull (GstBaseSink * basesink, gboolean active) if (active) { /* start task */ result = gst_pad_start_task (basesink->sinkpad, - (GstTaskFunction) gst_base_sink_loop, basesink->sinkpad, NULL); + (GstTaskFunction) gst_base_sink_loop, + gst_object_ref (basesink->sinkpad), gst_object_unref); } else { /* step 2, make sure streaming finishes */ result = gst_pad_stop_task (basesink->sinkpad); diff --git a/subprojects/gstreamer/libs/gst/base/gstbasesrc.c b/subprojects/gstreamer/libs/gst/base/gstbasesrc.c index c1dd9cff3b..1833e616ca 100644 --- a/subprojects/gstreamer/libs/gst/base/gstbasesrc.c +++ b/subprojects/gstreamer/libs/gst/base/gstbasesrc.c @@ -1855,7 +1855,7 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock) /* and restart the task in case it got paused explicitly or by * the FLUSH_START event we pushed out. */ tres = gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, - src->srcpad, NULL); + gst_object_ref (src->srcpad), gst_object_unref); if (res && !tres) res = FALSE; @@ -1921,7 +1921,7 @@ gst_base_src_send_event (GstElement * element, GstEvent * event) if (start) gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, - src->srcpad, NULL); + gst_object_ref (src->srcpad), gst_object_unref); GST_LIVE_UNLOCK (src); GST_PAD_STREAM_UNLOCK (src->srcpad); @@ -1970,7 +1970,7 @@ gst_base_src_send_event (GstElement * element, GstEvent * event) GST_DEBUG_OBJECT (src, "EOS marked, start task for asynchronous handling"); gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, - src->srcpad, NULL); + gst_object_ref (src->srcpad), gst_object_unref); GST_PAD_STREAM_UNLOCK (src->srcpad); } else { @@ -3947,7 +3947,7 @@ gst_base_src_set_playing (GstBaseSrc * basesrc, gboolean live_play) GST_OBJECT_UNLOCK (basesrc->srcpad); if (start) gst_pad_start_task (basesrc->srcpad, (GstTaskFunction) gst_base_src_loop, - basesrc->srcpad, NULL); + gst_object_ref (basesrc->srcpad), gst_object_unref); GST_DEBUG_OBJECT (basesrc, "signal"); GST_LIVE_SIGNAL (basesrc); } diff --git a/subprojects/gstreamer/plugins/elements/gstdownloadbuffer.c b/subprojects/gstreamer/plugins/elements/gstdownloadbuffer.c index b25aadf2f8..bb5a9eae23 100644 --- a/subprojects/gstreamer/plugins/elements/gstdownloadbuffer.c +++ b/subprojects/gstreamer/plugins/elements/gstdownloadbuffer.c @@ -1056,7 +1056,8 @@ gst_download_buffer_handle_sink_event (GstPad * pad, GstObject * parent, /* reset rate counters */ reset_rate_timer (dlbuf); gst_pad_start_task (dlbuf->srcpad, - (GstTaskFunction) gst_download_buffer_loop, dlbuf->srcpad, NULL); + (GstTaskFunction) gst_download_buffer_loop, + gst_object_ref (dlbuf->srcpad), gst_object_unref); GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); } else { GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); @@ -1421,7 +1422,7 @@ gst_download_buffer_handle_src_event (GstPad * pad, GstObject * parent, dlbuf->sinkresult = GST_FLOW_OK; if (GST_PAD_MODE (pad) == GST_PAD_MODE_PUSH) { gst_pad_start_task (pad, (GstTaskFunction) gst_download_buffer_loop, - pad, NULL); + gst_object_ref (pad), gst_object_unref); } } GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); @@ -1735,7 +1736,7 @@ gst_download_buffer_src_activate_push (GstPad * pad, GstObject * parent, dlbuf->upstream_size = -1; result = gst_pad_start_task (pad, (GstTaskFunction) gst_download_buffer_loop, - pad, NULL); + gst_object_ref (pad), gst_object_unref); GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); } else { /* unblock loop function */ diff --git a/subprojects/gstreamer/plugins/elements/gstmultiqueue.c b/subprojects/gstreamer/plugins/elements/gstmultiqueue.c index 7fb1c5f79c..a2f6272e24 100644 --- a/subprojects/gstreamer/plugins/elements/gstmultiqueue.c +++ b/subprojects/gstreamer/plugins/elements/gstmultiqueue.c @@ -1338,7 +1338,8 @@ gst_single_queue_start (GstMultiQueue * mq, GstSingleQueue * sq) if (srcpad) { res = gst_pad_start_task (srcpad, - (GstTaskFunction) gst_multi_queue_loop, srcpad, NULL); + (GstTaskFunction) gst_multi_queue_loop, gst_object_ref (srcpad), + gst_object_unref); gst_object_unref (srcpad); } diff --git a/subprojects/gstreamer/plugins/elements/gstqueue.c b/subprojects/gstreamer/plugins/elements/gstqueue.c index 4a1ac40bba..8ce17a8220 100644 --- a/subprojects/gstreamer/plugins/elements/gstqueue.c +++ b/subprojects/gstreamer/plugins/elements/gstqueue.c @@ -1045,7 +1045,7 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) queue->unexpected = FALSE; if (gst_pad_is_active (queue->srcpad)) { gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop, - queue->srcpad, NULL); + gst_object_ref (queue->srcpad), gst_object_unref); } else { GST_INFO_OBJECT (queue->srcpad, "not re-starting task on srcpad, " "pad not active any longer"); @@ -1099,7 +1099,8 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) queue->eos = FALSE; queue->unexpected = FALSE; gst_pad_start_task (queue->srcpad, - (GstTaskFunction) gst_queue_loop, queue->srcpad, NULL); + (GstTaskFunction) gst_queue_loop, + gst_object_ref (queue->srcpad), gst_object_unref); } else { queue->eos = FALSE; queue->unexpected = FALSE; @@ -1681,7 +1682,8 @@ gst_queue_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event) /* when we got not linked, assume downstream is linked again now and we * can try to start pushing again */ queue->srcresult = GST_FLOW_OK; - gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad, NULL); + gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, + gst_object_ref (pad), gst_object_unref); } GST_QUEUE_MUTEX_UNLOCK (queue); @@ -1840,8 +1842,8 @@ gst_queue_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, queue->eos = FALSE; queue->unexpected = FALSE; result = - gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad, - NULL); + gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, + gst_object_ref (pad), gst_object_unref); GST_QUEUE_MUTEX_UNLOCK (queue); } else { /* step 1, unblock loop function */ diff --git a/subprojects/gstreamer/plugins/elements/gstqueue2.c b/subprojects/gstreamer/plugins/elements/gstqueue2.c index 1fa62f9240..b22759b038 100644 --- a/subprojects/gstreamer/plugins/elements/gstqueue2.c +++ b/subprojects/gstreamer/plugins/elements/gstqueue2.c @@ -2639,7 +2639,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, /* reset rate counters */ reset_rate_timer (queue); gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue2_loop, - queue->srcpad, NULL); + gst_object_ref (queue->srcpad), gst_object_unref); GST_QUEUE2_MUTEX_UNLOCK (queue); } else { GST_QUEUE2_MUTEX_LOCK (queue); @@ -2720,7 +2720,8 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, /* reset rate counters */ reset_rate_timer (queue); gst_pad_start_task (queue->srcpad, - (GstTaskFunction) gst_queue2_loop, queue->srcpad, NULL); + (GstTaskFunction) gst_queue2_loop, + gst_object_ref (queue->srcpad), gst_object_unref); } else { queue->is_eos = FALSE; queue->unexpected = FALSE; @@ -3318,8 +3319,8 @@ gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event) queue->srcresult = GST_FLOW_OK; queue->sinkresult = GST_FLOW_OK; if (GST_PAD_MODE (pad) == GST_PAD_MODE_PUSH) { - gst_pad_start_task (pad, (GstTaskFunction) gst_queue2_loop, pad, - NULL); + gst_pad_start_task (pad, (GstTaskFunction) gst_queue2_loop, + gst_object_ref (pad), gst_object_unref); } } @@ -3703,7 +3704,8 @@ gst_queue2_src_activate_push (GstPad * pad, GstObject * parent, gboolean active) queue->is_eos = FALSE; queue->unexpected = FALSE; result = - gst_pad_start_task (pad, (GstTaskFunction) gst_queue2_loop, pad, NULL); + gst_pad_start_task (pad, (GstTaskFunction) gst_queue2_loop, + gst_object_ref (pad), gst_object_unref); GST_QUEUE2_MUTEX_UNLOCK (queue); } else { /* unblock loop function */ diff --git a/subprojects/gstreamer/plugins/elements/gsttypefindelement.c b/subprojects/gstreamer/plugins/elements/gsttypefindelement.c index ea1bf044b6..907dfec1f5 100644 --- a/subprojects/gstreamer/plugins/elements/gsttypefindelement.c +++ b/subprojects/gstreamer/plugins/elements/gsttypefindelement.c @@ -535,7 +535,8 @@ gst_type_find_element_seek (GstTypeFindElement * typefind, GstEvent * event) /* restart our task since it might have been stopped when we did the * flush. */ gst_pad_start_task (typefind->sink, - (GstTaskFunction) gst_type_find_element_loop, typefind->sink, NULL); + (GstTaskFunction) gst_type_find_element_loop, + gst_object_ref (typefind->sink), gst_object_unref); /* streaming can continue now */ GST_PAD_STREAM_UNLOCK (typefind->sink); @@ -1334,7 +1335,7 @@ gst_type_find_element_activate_sink (GstPad * pad, GstObject * parent) /* only start our task if we ourselves decide to start in pull mode */ return gst_pad_start_task (pad, (GstTaskFunction) gst_type_find_element_loop, - pad, NULL); + gst_object_ref (pad), gst_object_unref); typefind_push: { diff --git a/subprojects/gstreamer/tests/check/gst/gstelement.c b/subprojects/gstreamer/tests/check/gst/gstelement.c index 851f186a66..201a1fdbe1 100644 --- a/subprojects/gstreamer/tests/check/gst/gstelement.c +++ b/subprojects/gstreamer/tests/check/gst/gstelement.c @@ -101,7 +101,8 @@ test_add_pad_while_paused_pad_activatemode (GstPad * pad, GstObject * parent, *(gboolean *) pad->activatemodedata = active; fail_unless (mode == GST_PAD_MODE_PUSH); if (active) - gst_pad_start_task (pad, test_add_pad_while_paused_dummy_task, pad, NULL); + gst_pad_start_task (pad, test_add_pad_while_paused_dummy_task, + gst_object_ref (pad), gst_object_unref); else gst_pad_stop_task (pad); return TRUE; From c4f24c0a17c4462602fe82ea3f7bad90d1acc14d Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2026 22:09:46 +1000 Subject: [PATCH 80/82] hlsdemux2: Error out cleanly on resync failure Instead of asserting when the variant stream doesn't have a current position to resynchronise to after a discontinuity, throw an element error instead. Part-of: --- .../ext/adaptivedemux2/hls/gsthlsdemux-stream.c | 5 ++++- .../ext/adaptivedemux2/hls/gsthlsdemux.c | 11 +++++++++-- .../ext/adaptivedemux2/hls/gsthlsdemux.h | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux-stream.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux-stream.c index d4418fc6f3..5c95f65951 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux-stream.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux-stream.c @@ -1466,7 +1466,10 @@ gst_hls_demux_stream_handle_playlist_update (GstHLSDemuxStream * stream, stream->playlist_fetched = TRUE; stream->pending_discont = TRUE; - gst_hls_demux_reset_for_lost_sync (demux); + if (!gst_hls_demux_reset_for_lost_sync (demux)) { + GST_ELEMENT_ERROR (demux, STREAM, DEMUX, + ("Failed to resynchronise streams after a discontinuity"), (NULL)); + } } } diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c index 942101094e..f0eed5e858 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c @@ -1208,7 +1208,7 @@ gst_hls_demux_handle_variant_playlist_update_error (GstHLSDemux * demux, /* Reset hlsdemux in case of live synchronization loss (i.e. when a media * playlist update doesn't match at all with the previous one) */ -void +gboolean gst_hls_demux_reset_for_lost_sync (GstHLSDemux * hlsdemux) { GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux; @@ -1229,7 +1229,12 @@ gst_hls_demux_reset_for_lost_sync (GstHLSDemux * hlsdemux) GstM3U8SeekResult seek_result; /* Resynchronize the variant stream */ - g_assert (stream->current_position != GST_CLOCK_STIME_NONE); + if (stream->current_position == GST_CLOCK_TIME_NONE) { + GST_ERROR_OBJECT (stream, + "Variant doesn't have a current position to recalculate sync"); + return FALSE; + } + if (gst_hls_media_playlist_get_starting_segment (hls_stream->playlist, &seek_result)) { hls_stream->current_segment = seek_result.segment; @@ -1261,6 +1266,8 @@ gst_hls_demux_reset_for_lost_sync (GstHLSDemux * hlsdemux) hls_stream->playlist_fetched = FALSE; } } + + return TRUE; } static void diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.h b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.h index 857577f042..bad0612f73 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.h +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.h @@ -116,7 +116,7 @@ gst_hls_demux_new_track_for_rendition (GstHLSDemux * demux, GstCaps * caps, GstStreamFlags flags, GstTagList * tags); void gst_hls_demux_start_rendition_streams (GstHLSDemux * hlsdemux); -void gst_hls_demux_reset_for_lost_sync (GstHLSDemux * hlsdemux); +gboolean gst_hls_demux_reset_for_lost_sync (GstHLSDemux * hlsdemux); const GstHLSKey *gst_hls_demux_get_key (GstHLSDemux * demux, const gchar * key_url, const gchar * referer, gboolean allow_cache); From b64c8cf3e08fc853ed1b4d70c658818d163777d6 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2026 22:24:52 +1000 Subject: [PATCH 81/82] adaptivedemux2: Fix mismatched clock-time vs clock-stime check Adaptive demux stream start_position is an unsigned clock-time value, it should not be compared against GST_CLOCK_STIME_NONE Part-of: --- .../ext/adaptivedemux2/gstadaptivedemux-stream.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c index c21264b969..95245c1000 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c @@ -2089,8 +2089,6 @@ gst_adaptive_demux2_stream_next_download (GstAdaptiveDemux2Stream * stream) /* Restarting download, figure out new position * FIXME : Move this to a separate function ? */ if (G_UNLIKELY (stream->state == GST_ADAPTIVE_DEMUX2_STREAM_STATE_RESTART)) { - GstClockTimeDiff stream_time = 0; - GST_DEBUG_OBJECT (stream, "Activating stream after restart"); if (stream->parsebin_sink != NULL) { @@ -2103,12 +2101,14 @@ gst_adaptive_demux2_stream_next_download (GstAdaptiveDemux2Stream * stream) } GST_ADAPTIVE_DEMUX_SEGMENT_LOCK (demux); - stream_time = stream->start_position; GST_DEBUG_OBJECT (stream, "Restarting stream at " - "stream position %" GST_STIME_FORMAT, GST_STIME_ARGS (stream_time)); + "stream position %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream->start_position)); + + if (GST_CLOCK_TIME_IS_VALID (stream->start_position)) { + GstClockTimeDiff stream_time = stream->start_position; - if (GST_CLOCK_STIME_IS_VALID (stream_time)) { /* TODO check return */ gst_adaptive_demux2_stream_seek (stream, demux->segment.rate >= 0, 0, stream_time, &stream_time); From e66895d6f9efed4d60a3104931620802cab87079 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2026 22:58:24 +1000 Subject: [PATCH 82/82] hlsdemux2: Abort wait for variant playlist on shutdown If the element is stopped while waiting for the variant playlist, exit the loop. Part-of: --- .../ext/adaptivedemux2/hls/gsthlsdemux.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c index f0eed5e858..50f8cce4e9 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c @@ -300,14 +300,18 @@ gst_hls_demux_wait_for_variant_playlist (GstHLSDemux * hlsdemux) GstAdaptiveDemux2Stream *stream = GST_ADAPTIVE_DEMUX2_STREAM (hlsdemux->main_stream); - if (stream->state != GST_ADAPTIVE_DEMUX2_STREAM_STATE_STOPPED) { - stream->state = GST_ADAPTIVE_DEMUX2_STREAM_STATE_WAITING_PREPARE; + if (stream->state == GST_ADAPTIVE_DEMUX2_STREAM_STATE_STOPPED) { + GST_DEBUG_OBJECT (hlsdemux, + "Interrupted waiting for stream to be prepared"); + return GST_FLOW_FLUSHING; + } - if (!gst_adaptive_demux2_stream_wait_prepared (stream)) { - GST_DEBUG_OBJECT (hlsdemux, - "Interrupted waiting for stream to be prepared"); - return GST_FLOW_FLUSHING; - } + stream->state = GST_ADAPTIVE_DEMUX2_STREAM_STATE_WAITING_PREPARE; + + if (!gst_adaptive_demux2_stream_wait_prepared (stream)) { + GST_DEBUG_OBJECT (hlsdemux, + "Interrupted waiting for stream to be prepared"); + return GST_FLOW_FLUSHING; } }