diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/gsm/gstgsmenc.c | 165 | ||||
-rw-r--r-- | ext/gsm/gstgsmenc.h | 1 |
2 files changed, 100 insertions, 66 deletions
diff --git a/ext/gsm/gstgsmenc.c b/ext/gsm/gstgsmenc.c index 6a8f24ee..43d7f2db 100644 --- a/ext/gsm/gstgsmenc.c +++ b/ext/gsm/gstgsmenc.c @@ -56,6 +56,9 @@ static GstFlowReturn gst_gsmenc_chain (GstPad * pad, GstBuffer * buf); static GstElementClass *parent_class = NULL; static guint gst_gsmenc_signals[LAST_SIGNAL] = { 0 }; +static gboolean gst_gsmenc_sink_event (GstPad * pad, GstEvent * event); + + GType gst_gsmenc_get_type (void) { @@ -137,6 +140,7 @@ gst_gsmenc_init (GstGSMEnc * gsmenc) (&gsmenc_sink_template), "sink"); gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->sinkpad); gst_pad_set_chain_function (gsmenc->sinkpad, gst_gsmenc_chain); + gst_pad_set_event_function (gsmenc->sinkpad, gst_gsmenc_sink_event); gsmenc->srcpad = gst_pad_new_from_template (gst_static_pad_template_get @@ -146,98 +150,127 @@ gst_gsmenc_init (GstGSMEnc * gsmenc) gsmenc->state = gsm_create (); gsmenc->bufsize = 0; gsmenc->next_ts = 0; + gsmenc->firstBuf = TRUE; } -static GstFlowReturn -gst_gsmenc_chain (GstPad * pad, GstBuffer * buf) +static gboolean +gst_gsmenc_sink_event (GstPad * pad, GstEvent * event) { + GstGSMEnc *gsmenc; gsmenc = GST_GSMENC (GST_OBJECT_PARENT (pad)); - - if (GST_IS_EVENT (buf)) { - GstEvent *event = GST_EVENT (buf); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS:{ - gst_pad_push_event (gsmenc->srcpad, gst_event_new_eos ()); - gst_pad_push (gsmenc->srcpad, buf); - break; - } - case GST_EVENT_NEWSEGMENT:{ - /* drop the discontinuity */ - break; - } - default:{ - gst_pad_event_default (pad, event); - break; - } + gboolean ret = TRUE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + { + GST_STREAM_LOCK (pad); + ret = gst_pad_push_event (gsmenc->srcpad, event); + GST_STREAM_UNLOCK (pad); + break; } - return GST_FLOW_OK; - } else if (GST_IS_BUFFER (buf)) { - gsm_signal *data; - guint size; - GstCaps *tempcaps = NULL; + case GST_EVENT_NEWSEGMENT: + { + /* drop the discontinuity */ + gst_event_unref (event); + break; + } + default: + { + gst_pad_event_default (pad, event); + break; + } + } + return ret; + +} + +static GstFlowReturn +gst_gsmenc_chain (GstPad * pad, GstBuffer * buf) +{ + GstGSMEnc *gsmenc; + gsm_signal *data; + guint size; + GstFlowReturn ret = GST_FLOW_OK; - data = (gsm_signal *) GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf) / sizeof (gsm_signal); + gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); - if (gsmenc->bufsize && (gsmenc->bufsize + size >= 160)) { - GstBuffer *outbuf; + data = (gsm_signal *) GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf) / sizeof (gsm_signal); - memcpy (gsmenc->buffer + gsmenc->bufsize, data, - (160 - gsmenc->bufsize) * sizeof (gsm_signal)); + if (gsmenc->bufsize && (gsmenc->bufsize + size >= 160)) { + GstBuffer *outbuf; - outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); - GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; - GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND; - gsmenc->next_ts += 20 * GST_MSECOND; + memcpy (gsmenc->buffer + gsmenc->bufsize, data, + (160 - gsmenc->bufsize) * sizeof (gsm_signal)); - gsm_encode (gsmenc->state, gsmenc->buffer, - (gsm_byte *) GST_BUFFER_DATA (outbuf)); + outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); + GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; + GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND; + gsmenc->next_ts += 20 * GST_MSECOND; - tempcaps = gst_caps_new_simple ("audio/x-gsm", - "rate", G_TYPE_INT, 8000, "channels", G_TYPE_INT, 1, NULL); + gsm_encode (gsmenc->state, gsmenc->buffer, + (gsm_byte *) GST_BUFFER_DATA (outbuf)); - gst_buffer_set_caps (outbuf, tempcaps); - gst_pad_push (gsmenc->srcpad, outbuf); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmenc->srcpad)); - size -= (160 - gsmenc->bufsize); - data += (160 - gsmenc->bufsize); - gsmenc->bufsize = 0; + if (gsmenc->firstBuf) { + gst_pad_push_event (gsmenc->srcpad, + gst_event_new_newsegment (FALSE, 1.0, GST_FORMAT_DEFAULT, + 0, GST_CLOCK_TIME_NONE, 0)); + gsmenc->firstBuf = FALSE; } - while (size >= 160) { - GstBuffer *outbuf; + ret = gst_pad_push (gsmenc->srcpad, outbuf); + + if (ret != GST_FLOW_OK) { + gst_buffer_unref (outbuf); + goto error; + } - outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); - GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; - GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND; - gsmenc->next_ts += 20 * GST_MSECOND; + size -= (160 - gsmenc->bufsize); + data += (160 - gsmenc->bufsize); + gsmenc->bufsize = 0; - gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); + } - /* I was wondering that gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmenc->srcpad)); - * could work, but it doens't work */ + while (size >= 160) { + GstBuffer *outbuf; - tempcaps = gst_caps_new_simple ("audio/x-gsm", - "rate", G_TYPE_INT, 8000, "channels", G_TYPE_INT, 1, NULL); + outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); + GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; + GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND; + gsmenc->next_ts += 20 * GST_MSECOND; - gst_buffer_set_caps (outbuf, tempcaps); - gst_pad_push (gsmenc->srcpad, outbuf); + gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); - size -= 160; - data += 160; + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmenc->srcpad)); + if (gsmenc->firstBuf) { + gst_pad_push_event (gsmenc->srcpad, + gst_event_new_newsegment (FALSE, 1.0, GST_FORMAT_DEFAULT, + 0, GST_CLOCK_TIME_NONE, 0)); + gsmenc->firstBuf = FALSE; } + ret = gst_pad_push (gsmenc->srcpad, outbuf); - if (size) { - memcpy (gsmenc->buffer + gsmenc->bufsize, data, - size * sizeof (gsm_signal)); - gsmenc->bufsize += size; + if (ret != GST_FLOW_OK) { + gst_buffer_unref (outbuf); + goto error; } - /*gst_buffer_unref (buf); */ - return GST_FLOW_OK; + size -= 160; + data += 160; + } + + if (size) { + memcpy (gsmenc->buffer + gsmenc->bufsize, data, size * sizeof (gsm_signal)); + gsmenc->bufsize += size; } - return GST_FLOW_OK; + +error: + + gst_object_unref (gsmenc); + return ret; + } diff --git a/ext/gsm/gstgsmenc.h b/ext/gsm/gstgsmenc.h index cfc88722..a5f1f87e 100644 --- a/ext/gsm/gstgsmenc.h +++ b/ext/gsm/gstgsmenc.h @@ -55,6 +55,7 @@ struct _GstGSMEnc gsm_signal buffer[160]; gint bufsize; GstClockTime next_ts; + gboolean firstBuf; }; struct _GstGSMEncClass |