diff options
-rw-r--r-- | audio/gsta2dpsink.c | 93 | ||||
-rw-r--r-- | audio/gsta2dpsink.h | 11 | ||||
-rw-r--r-- | audio/gstrtpsbcpay.c | 6 | ||||
-rw-r--r-- | audio/gstrtpsbcpay.h | 1 |
4 files changed, 96 insertions, 15 deletions
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c index a3f3655a..a2b3286c 100644 --- a/audio/gsta2dpsink.c +++ b/audio/gsta2dpsink.c @@ -68,6 +68,17 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event); static gboolean gst_a2dp_sink_set_caps(GstPad *pad, GstCaps *caps); static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad); static gboolean gst_a2dp_sink_init_caps_filter(GstA2dpSink *self); +static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self); +static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self); + +static void gst_a2dp_sink_finalize(GObject *obj) +{ + GstA2dpSink *self = GST_A2DP_SINK(obj); + + g_mutex_free(self->cb_mutex); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} /* * Helper function to create elements, add to the bin and link it @@ -93,9 +104,9 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self, goto cleanup_and_fail; } - if (gst_element_set_state(element, GST_STATE_READY) == + if (gst_element_set_state(element, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { - GST_ERROR_OBJECT(self, "%s failed to go to ready", + GST_ERROR_OBJECT(self, "%s failed to go to playing", elementname); goto remove_element_and_fail; } @@ -224,6 +235,8 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element, switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: self->taglist = gst_tag_list_new(); + + gst_a2dp_sink_init_fakesink(self); break; case GST_STATE_CHANGE_NULL_TO_READY: @@ -263,6 +276,7 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element, gst_event_unref(self->newseg_event); self->newseg_event = NULL; } + gst_a2dp_sink_remove_fakesink(self); break; case GST_STATE_CHANGE_READY_TO_NULL: @@ -280,7 +294,6 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element, self->sink = NULL; gst_a2dp_sink_remove_dynamic_elements(self); - break; default: @@ -302,6 +315,9 @@ static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass) object_class->get_property = GST_DEBUG_FUNCPTR( gst_a2dp_sink_get_property); + object_class->finalize = GST_DEBUG_FUNCPTR( + gst_a2dp_sink_finalize); + element_class->change_state = GST_DEBUG_FUNCPTR( gst_a2dp_sink_change_state); @@ -314,7 +330,7 @@ static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass) "A2DP sink element"); } -static GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self) +GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self) { return gst_avdtp_sink_get_device_caps(self->sink); } @@ -343,12 +359,16 @@ static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad) return caps; } -static gboolean gst_a2dp_sink_init_sender_sink(GstA2dpSink *self) +static gboolean gst_a2dp_sink_init_avdtp_sink(GstA2dpSink *self) { GstElement *sink; + /* check if we don't need a new sink */ + if (self->sink_is_in_bin) + return TRUE; + if (self->sink == NULL) - sink = gst_element_factory_make("avdtpsink", "avdtosink"); + sink = gst_element_factory_make("avdtpsink", "avdtpsink"); else sink = GST_ELEMENT(self->sink); @@ -399,6 +419,10 @@ static gboolean gst_a2dp_sink_init_rtp_sbc_element(GstA2dpSink *self) { GstElement *rtppay; + /* if we already have a rtp, we don't need a new one */ + if (self->rtp != NULL) + return TRUE; + rtppay = gst_a2dp_sink_init_element(self, "rtpsbcpay", "rtp", self->capsfilter); if (rtppay == NULL) @@ -416,13 +440,16 @@ static gboolean gst_a2dp_sink_init_rtp_mpeg_element(GstA2dpSink *self) { GstElement *rtppay; - GST_LOG_OBJECT(self, "Initializing rtp mpeg element"); + /* check if we don't need a new rtp */ + if (self->rtp) + return TRUE; + GST_LOG_OBJECT(self, "Initializing rtp mpeg element"); /* if capsfilter is not created then we can't have our rtp element */ if (self->capsfilter == NULL) return FALSE; - rtppay = gst_a2dp_sink_init_element(self, "rtpmpapay", "rtp", + rtppay = gst_a2dp_sink_init_element(self, "rtpmpapay", "rtp", self->capsfilter); if (rtppay == NULL) return FALSE; @@ -445,6 +472,9 @@ static gboolean gst_a2dp_sink_init_dynamic_elements(GstA2dpSink *self, structure = gst_caps_get_structure(caps, 0); + /* before everything we need to remove fakesink */ + gst_a2dp_sink_remove_fakesink(self); + /* first, we need to create our rtp payloader */ if (gst_structure_has_name(structure, "audio/x-sbc")) { GST_LOG_OBJECT(self, "sbc media received"); @@ -459,7 +489,7 @@ static gboolean gst_a2dp_sink_init_dynamic_elements(GstA2dpSink *self, return FALSE; } - if (!gst_a2dp_sink_init_sender_sink(self)) + if (!gst_a2dp_sink_init_avdtp_sink(self)) return FALSE; /* check if we should push the taglist FIXME should we push this? @@ -518,18 +548,18 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event) { GstA2dpSink *self; GstTagList *taglist = NULL; + GstObject *parent; self = GST_A2DP_SINK(GST_PAD_PARENT(pad)); + parent = gst_element_get_parent(GST_ELEMENT(self->sink)); if (GST_EVENT_TYPE(event) == GST_EVENT_NEWSEGMENT && - gst_element_get_parent(GST_ELEMENT(self->sink)) != - GST_OBJECT_CAST(self)) { + parent != GST_OBJECT_CAST(self)) { if (self->newseg_event != NULL) gst_event_unref(self->newseg_event); self->newseg_event = gst_event_ref(event); } else if (GST_EVENT_TYPE(event) == GST_EVENT_TAG && - gst_element_get_parent(GST_ELEMENT(self->sink)) != - GST_OBJECT_CAST(self)) { + parent != GST_OBJECT_CAST(self)) { if (self->taglist == NULL) { gst_event_parse_tag(event, &self->taglist); } else { @@ -540,6 +570,9 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event) /* FIXME handle tag events */ } + if (parent != NULL) + gst_object_unref(GST_OBJECT(parent)); + return self->ghostpad_eventfunc(GST_PAD(self->ghostpad), event); } @@ -562,10 +595,40 @@ failed: return FALSE; } +static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self) +{ + if (self->fakesink != NULL) + return TRUE; + + g_mutex_lock (self->cb_mutex); + self->fakesink = gst_a2dp_sink_init_element(self, "fakesink", + "fakesink", self->capsfilter); + g_mutex_unlock (self->cb_mutex); + + if (!self->fakesink) + return FALSE; + + return TRUE; +} + +static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self) +{ + g_mutex_lock(self->cb_mutex); + if (self->fakesink != NULL) { + gst_element_set_state(self->fakesink, GST_STATE_NULL); + gst_bin_remove(GST_BIN(self), self->fakesink); + self->fakesink = NULL; + } + g_mutex_unlock(self->cb_mutex); + + return TRUE; +} + static void gst_a2dp_sink_init(GstA2dpSink *self, GstA2dpSinkClass *klass) { self->sink = NULL; + self->fakesink = NULL; self->rtp = NULL; self->device = NULL; self->capsfilter = NULL; @@ -574,12 +637,16 @@ static void gst_a2dp_sink_init(GstA2dpSink *self, self->ghostpad = NULL; self->sink_is_in_bin = FALSE; + self->cb_mutex = g_mutex_new(); + /* we initialize our capsfilter */ gst_a2dp_sink_init_caps_filter(self); g_object_set(self->capsfilter, "caps", gst_static_pad_template_get_caps(&gst_a2dp_sink_factory), NULL); + gst_a2dp_sink_init_fakesink(self); + gst_a2dp_sink_init_ghost_pad(self); } diff --git a/audio/gsta2dpsink.h b/audio/gsta2dpsink.h index 26da4c47..d79307b2 100644 --- a/audio/gsta2dpsink.h +++ b/audio/gsta2dpsink.h @@ -25,6 +25,9 @@ #include <gst/rtp/gstbasertppayload.h> #include "gstavdtpsink.h" +#ifndef __GST_A2DP_SINK_H__ +#define __GST_A2DP_SINK_H__ + G_BEGIN_DECLS #define GST_TYPE_A2DP_SINK \ @@ -47,6 +50,7 @@ struct _GstA2dpSink { GstBaseRTPPayload *rtp; GstAvdtpSink *sink; GstElement *capsfilter; + GstElement *fakesink; gchar *device; gboolean sink_is_in_bin; @@ -59,6 +63,8 @@ struct _GstA2dpSink { /* Store the tags received before the a2dpsender sink is created * when it is created we forward this to it */ GstTagList *taglist; + + GMutex *cb_mutex; }; struct _GstA2dpSinkClass { @@ -68,4 +74,9 @@ struct _GstA2dpSinkClass { GType gst_a2dp_sink_get_type(void); gboolean gst_a2dp_sink_plugin_init (GstPlugin * plugin); +GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self); + G_END_DECLS + +#endif + diff --git a/audio/gstrtpsbcpay.c b/audio/gstrtpsbcpay.c index 68aa28a9..fdb42d18 100644 --- a/audio/gstrtpsbcpay.c +++ b/audio/gstrtpsbcpay.c @@ -193,10 +193,10 @@ static GstFlowReturn gst_rtp_sbc_pay_flush_buffers(GstRtpSBCPay *sbcpay) memcpy(payload_data + RTP_SBC_PAYLOAD_HEADER_SIZE, data, max_payload); g_free(data); - /* FIXME - timestamp it! */ + GST_BUFFER_TIMESTAMP(outbuf) = sbcpay->timestamp; GST_DEBUG_OBJECT (sbcpay, "Pushing %d bytes", max_payload); - return gst_basertppayload_push (GST_BASE_RTP_PAYLOAD(sbcpay), outbuf); + return gst_basertppayload_push(GST_BASE_RTP_PAYLOAD(sbcpay), outbuf); } static GstFlowReturn gst_rtp_sbc_pay_handle_buffer(GstBaseRTPPayload *payload, @@ -208,6 +208,7 @@ static GstFlowReturn gst_rtp_sbc_pay_handle_buffer(GstBaseRTPPayload *payload, sbcpay = GST_RTP_SBC_PAY(payload); gst_adapter_push(sbcpay->adapter, gst_buffer_copy(buffer)); + sbcpay->timestamp = GST_BUFFER_TIMESTAMP(buffer); available = gst_adapter_available(sbcpay->adapter); if (available + RTP_SBC_HEADER_TOTAL >= GST_BASE_RTP_PAYLOAD_MTU(sbcpay) || @@ -325,6 +326,7 @@ static void gst_rtp_sbc_pay_init(GstRtpSBCPay *self, GstRtpSBCPayClass *klass) { self->adapter = gst_adapter_new(); self->frame_length = 0; + self->timestamp = 0; self->min_frames = DEFAULT_MIN_FRAMES; } diff --git a/audio/gstrtpsbcpay.h b/audio/gstrtpsbcpay.h index f086a1c7..474d720a 100644 --- a/audio/gstrtpsbcpay.h +++ b/audio/gstrtpsbcpay.h @@ -48,6 +48,7 @@ struct _GstRtpSBCPay { GstBaseRTPPayload base; GstAdapter *adapter; + GstClockTime timestamp; guint frame_length; |