void gst_decklink_sink_finalize (GObject * object) { GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (object); g_cond_clear (&decklinksink->cond); g_mutex_clear (&decklinksink->mutex); g_cond_clear (&decklinksink->audio_cond); g_mutex_clear (&decklinksink->audio_mutex); delete decklinksink->callback; #ifdef _MSC_VER /* signal the COM thread that it should uninitialize COM */ if (decklinksink->comInitialized) { g_mutex_lock (&decklinksink->com_deinit_lock); g_cond_signal (&decklinksink->com_uninitialize); g_cond_wait (&decklinksink->com_uninitialized, &decklinksink->com_deinit_lock); g_mutex_unlock (&decklinksink->com_deinit_lock); } g_mutex_clear (&decklinksink->com_init_lock); g_mutex_clear (&decklinksink->com_deinit_lock); g_cond_clear (&decklinksink->com_initialized); g_cond_clear (&decklinksink->com_uninitialize); g_cond_clear (&decklinksink->com_uninitialized); #endif /* _MSC_VER */ G_OBJECT_CLASS (parent_class)->finalize (object); }
static gboolean gst_decklink_sink_videosink_query (GstPad * pad, GstObject * parent, GstQuery * query) { gboolean res; GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (parent); GST_DEBUG_OBJECT (decklinksink, "query"); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS:{ GstCaps *mode_caps, *filter, *caps; /* FIXME: do we change mode if incoming caps change? If yes, we * should probably return the template caps instead */ mode_caps = gst_decklink_mode_get_caps (decklinksink->mode); gst_query_parse_caps (query, &filter); caps = gst_caps_intersect (mode_caps, filter); gst_caps_unref (mode_caps); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); break; } default: res = gst_pad_query_default (pad, parent, query); break; } return res; }
static gboolean gst_decklink_sink_audiosink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res; GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (parent); GST_DEBUG_OBJECT (pad, "event: %" GST_PTR_FORMAT, event); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: /* FIXME: EOS aggregation with video pad looks wrong */ decklinksink->audio_eos = TRUE; decklinksink->audio_seqnum = gst_event_get_seqnum (event); res = gst_pad_event_default (pad, parent, event); break; default: res = gst_pad_event_default (pad, parent, event); break; } return res; }
static GstFlowReturn gst_decklink_sink_audiosink_chainlist (GstPad * pad, GstBufferList * bufferlist) { GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "chainlist"); gst_object_unref (decklinksink); return GST_FLOW_OK; }
static gboolean gst_decklink_sink_audiosink_acceptcaps (GstPad * pad, GstCaps * caps) { GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "acceptcaps"); gst_object_unref (decklinksink); return TRUE; }
static GstPadLinkReturn gst_decklink_sink_audiosink_link (GstPad * pad, GstPad * peer) { GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "link"); gst_object_unref (decklinksink); return GST_PAD_LINK_OK; }
static gboolean gst_decklink_sink_audiosink_activatepull (GstPad * pad, gboolean active) { GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "activatepull"); gst_object_unref (decklinksink); return TRUE; }
static gboolean gst_decklink_sink_videosink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res; GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (parent); GST_DEBUG_OBJECT (pad, "event: %" GST_PTR_FORMAT, event); switch (GST_EVENT_TYPE (event)) { /* FIXME: this makes no sense, template caps don't contain v210 */ #if 0 case GST_EVENT_CAPS:{ GstCaps *caps; gst_event_parse_caps (event, &caps); ret = gst_video_format_parse_caps (caps, &format, &width, &height); if (ret) { if (format == GST_VIDEO_FORMAT_v210) { decklinksink->pixel_format = bmdFormat10BitYUV; } else { decklinksink->pixel_format = bmdFormat8BitYUV; } } break; } #endif case GST_EVENT_EOS: /* FIXME: EOS aggregation with audio pad looks wrong */ decklinksink->video_eos = TRUE; decklinksink->video_seqnum = gst_event_get_seqnum (event); { GstMessage *message; message = gst_message_new_eos (GST_OBJECT_CAST (decklinksink)); gst_message_set_seqnum (message, decklinksink->video_seqnum); gst_element_post_message (GST_ELEMENT_CAST (decklinksink), message); } res = gst_pad_event_default (pad, parent, event); break; default: res = gst_pad_event_default (pad, parent, event); break; } return res; }
static GstCaps * gst_decklink_sink_audiosink_getcaps (GstPad * pad) { GstDecklinkSink *decklinksink; GstCaps *caps; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "getcaps"); caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); gst_object_unref (decklinksink); return caps; }
static GstIterator * gst_decklink_sink_videosink_iterintlink (GstPad * pad) { GstDecklinkSink *decklinksink; GstIterator *iter; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "iterintlink"); iter = gst_pad_iterate_internal_links_default (pad); gst_object_unref (decklinksink); return iter; }
static GstCaps * gst_decklink_sink_videosink_getcaps (GstPad * pad) { GstDecklinkSink *decklinksink; GstCaps *caps; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "getcaps"); caps = gst_decklink_mode_get_caps (decklinksink->mode); gst_object_unref (decklinksink); return caps; }
static GstFlowReturn gst_decklink_sink_videosink_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf) { GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "bufferalloc"); *buf = gst_buffer_new_and_alloc (size); gst_buffer_set_caps (*buf, caps); gst_object_unref (decklinksink); return GST_FLOW_OK; }
void gst_decklink_sink_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { GstDecklinkSink *decklinksink; g_return_if_fail (GST_IS_DECKLINK_SINK (object)); decklinksink = GST_DECKLINK_SINK (object); switch (property_id) { case PROP_MODE: g_value_set_enum (value, decklinksink->mode); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } }
static gboolean gst_decklink_sink_audiosink_event (GstPad * pad, GstEvent * event) { gboolean res; GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "event"); switch (GST_EVENT_TYPE (event)) { default: res = gst_pad_event_default (pad, event); break; } gst_object_unref (decklinksink); return res; }
static gboolean gst_decklink_sink_videosink_query (GstPad * pad, GstQuery * query) { gboolean res; GstDecklinkSink *decklinksink; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "query"); switch (GST_QUERY_TYPE (query)) { default: res = gst_pad_query_default (pad, query); break; } gst_object_unref (decklinksink); return res; }
static GstStateChangeReturn gst_decklink_sink_change_state (GstElement * element, GstStateChange transition) { GstDecklinkSink *decklinksink; GstStateChangeReturn ret; g_return_val_if_fail (GST_IS_DECKLINK_SINK (element), GST_STATE_CHANGE_FAILURE); decklinksink = GST_DECKLINK_SINK (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_decklink_sink_start (decklinksink)) { ret = GST_STATE_CHANGE_FAILURE; goto out; } break; case GST_STATE_CHANGE_READY_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: gst_decklink_sink_force_stop (decklinksink); break; case GST_STATE_CHANGE_PAUSED_TO_READY: break; case GST_STATE_CHANGE_READY_TO_NULL: gst_decklink_sink_stop (decklinksink); break; default: break; } out: return ret; }
static gboolean gst_decklink_sink_audiosink_activate (GstPad * pad) { GstDecklinkSink *decklinksink; gboolean ret; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "activate"); if (gst_pad_check_pull_range (pad)) { GST_DEBUG_OBJECT (pad, "activating pull"); ret = gst_pad_activate_pull (pad, TRUE); } else { GST_DEBUG_OBJECT (pad, "activating push"); ret = gst_pad_activate_push (pad, TRUE); } gst_object_unref (decklinksink); return ret; }
void gst_decklink_sink_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { GstDecklinkSink *decklinksink; g_return_if_fail (GST_IS_DECKLINK_SINK (object)); decklinksink = GST_DECKLINK_SINK (object); switch (property_id) { case PROP_MODE: decklinksink->mode = (GstDecklinkModeEnum) g_value_get_enum (value); break; case PROP_DEVICE_NUMBER: decklinksink->device_number = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } }
static GstFlowReturn gst_decklink_sink_audiosink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstDecklinkSink *decklinksink; GstFlowReturn ret; decklinksink = GST_DECKLINK_SINK (parent); if (decklinksink->stop) return GST_FLOW_FLUSHING; g_mutex_lock (&decklinksink->audio_mutex); while (!decklinksink->stop && gst_adapter_available (decklinksink->audio_adapter) > 1600 * 4 * 2) { g_cond_wait (&decklinksink->audio_cond, &decklinksink->audio_mutex); } gst_adapter_push (decklinksink->audio_adapter, buffer); g_mutex_unlock (&decklinksink->audio_mutex); ret = GST_FLOW_OK; return ret; }
static GstFlowReturn gst_decklink_sink_audiosink_chain (GstPad * pad, GstBuffer * buffer) { GstDecklinkSink *decklinksink; GstFlowReturn ret; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "chain"); // concatenate both buffers g_mutex_lock (decklinksink->audio_mutex); decklinksink->audio_buffer = gst_buffer_join (decklinksink->audio_buffer, buffer); g_mutex_unlock (decklinksink->audio_mutex); // GST_DEBUG("Audio Buffer Size: %d", GST_BUFFER_SIZE (decklinksink->audio_buffer)); gst_object_unref (decklinksink); ret = GST_FLOW_OK; return ret; }
static GstFlowReturn gst_decklink_sink_videosink_chain (GstPad * pad, GstBuffer * buffer) { GstDecklinkSink *decklinksink; IDeckLinkMutableVideoFrame *frame; void *data; GstFlowReturn ret; const GstDecklinkMode *mode; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (decklinksink, "chain"); #if 0 if (!decklinksink->video_enabled) { HRESULT ret; ret = decklinksink->output->EnableVideoOutput (decklinksink->display_mode, bmdVideoOutputFlagDefault); if (ret != S_OK) { GST_ERROR ("failed to enable video output"); //return FALSE; } decklinksink->video_enabled = TRUE; } #endif mode = gst_decklink_get_mode (decklinksink->mode); decklinksink->output->CreateVideoFrame (mode->width, mode->height, mode->width * 2, bmdFormat8BitYUV, bmdFrameFlagDefault, &frame); frame->GetBytes (&data); memcpy (data, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); gst_buffer_unref (buffer); g_mutex_lock (decklinksink->mutex); while (decklinksink->queued_frames > 2 && !decklinksink->stop) { g_cond_wait (decklinksink->cond, decklinksink->mutex); } if (!decklinksink->stop) { decklinksink->queued_frames++; } g_mutex_unlock (decklinksink->mutex); if (!decklinksink->stop) { decklinksink->output->ScheduleVideoFrame (frame, decklinksink->num_frames * mode->fps_d, mode->fps_d, mode->fps_n); decklinksink->num_frames++; if (!decklinksink->sched_started) { decklinksink->output->StartScheduledPlayback (0, mode->fps_d, 1.0); decklinksink->sched_started = TRUE; } ret = GST_FLOW_OK; } else { ret = GST_FLOW_WRONG_STATE; } frame->Release (); gst_object_unref (decklinksink); return ret; }
static GstFlowReturn gst_decklink_sink_videosink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstDecklinkSink *decklinksink; IDeckLinkMutableVideoFrame *frame; void *data; GstFlowReturn ret; const GstDecklinkMode *mode; decklinksink = GST_DECKLINK_SINK (parent); #if 0 if (!decklinksink->video_enabled) { HRESULT ret; ret = decklinksink->output->EnableVideoOutput (decklinksink->display_mode, bmdVideoOutputFlagDefault); if (ret != S_OK) { GST_WARNING ("failed to enable video output"); //return FALSE; } decklinksink->video_enabled = TRUE; } #endif mode = gst_decklink_get_mode (decklinksink->mode); decklinksink->output->CreateVideoFrame (mode->width, mode->height, mode->width * 2, decklinksink->pixel_format, bmdFrameFlagDefault, &frame); frame->GetBytes (&data); gst_buffer_extract (buffer, 0, data, gst_buffer_get_size (buffer)); gst_buffer_unref (buffer); g_mutex_lock (&decklinksink->mutex); while (decklinksink->queued_frames > 2 && !decklinksink->stop) { g_cond_wait (&decklinksink->cond, &decklinksink->mutex); } if (!decklinksink->stop) { decklinksink->queued_frames++; } g_mutex_unlock (&decklinksink->mutex); if (!decklinksink->stop) { decklinksink->output->ScheduleVideoFrame (frame, decklinksink->num_frames * mode->fps_d, mode->fps_d, mode->fps_n); decklinksink->num_frames++; if (!decklinksink->sched_started) { decklinksink->output->StartScheduledPlayback (0, mode->fps_d, 1.0); decklinksink->sched_started = TRUE; } ret = GST_FLOW_OK; } else { ret = GST_FLOW_FLUSHING; } frame->Release (); return ret; }