summaryrefslogtreecommitdiff
path: root/ext/gsm
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2006-09-19 10:10:12 +0000
committerWim Taymans <wim.taymans@gmail.com>2006-09-19 10:10:12 +0000
commitfc8b3f18bf4195b6043de436acda902bc138e0af (patch)
treea8d613a86e8e5ad0125cfcc83107717d678b6503 /ext/gsm
parent1759dfcbed01f7563ef9cd1e95d5fd5a48df282b (diff)
downloadgstreamer-plugins-bad-fc8b3f18bf4195b6043de436acda902bc138e0af.tar.gz
ext/gsm/gstgsmdec.*: Handle WAV49 variant (GSM in WAV).
Original commit message from CVS: * ext/gsm/gstgsmdec.c: (gst_gsmdec_init), (gst_gsmdec_sink_setcaps), (gst_gsmdec_sink_event), (gst_gsmdec_chain): * ext/gsm/gstgsmdec.h: Handle WAV49 variant (GSM in WAV). Some small cleanups.
Diffstat (limited to 'ext/gsm')
-rw-r--r--ext/gsm/gstgsmdec.c82
-rw-r--r--ext/gsm/gstgsmdec.h1
2 files changed, 55 insertions, 28 deletions
diff --git a/ext/gsm/gstgsmdec.c b/ext/gsm/gstgsmdec.c
index ec5205384..412aaf68a 100644
--- a/ext/gsm/gstgsmdec.c
+++ b/ext/gsm/gstgsmdec.c
@@ -88,10 +88,11 @@ gst_gsmdec_get_type (void)
}
static GstStaticPadTemplate gsmdec_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-gsm, " "rate = (int) 8000, " "channels = (int) 1")
+ GST_STATIC_CAPS ("audio/x-gsm, rate = (int) 8000, channels = (int) 1; "
+ "audio/ms-gsm, rate = (int) 8000, channels = (int) 1")
);
static GstStaticPadTemplate gsmdec_src_template =
@@ -136,8 +137,6 @@ gst_gsmdec_class_init (GstGSMDec * klass)
static void
gst_gsmdec_init (GstGSMDec * gsmdec)
{
- gint use_wav49;
-
/* create the sink and src pads */
gsmdec->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get
@@ -154,10 +153,6 @@ gst_gsmdec_init (GstGSMDec * gsmdec)
gsmdec->state = gsm_create ();
- /* turn on WAV49 handling */
- use_wav49 = 0;
- gsm_option (gsmdec->state, GSM_OPT_WAV49, &use_wav49);
-
gsmdec->adapter = gst_adapter_new ();
gsmdec->next_of = 0;
gsmdec->next_ts = 0;
@@ -181,9 +176,26 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps)
{
GstGSMDec *gsmdec;
GstCaps *srccaps;
+ GstStructure *s;
gsmdec = GST_GSMDEC (gst_pad_get_parent (pad));
+ s = gst_caps_get_structure (caps, 0);
+ if (s == NULL)
+ goto wrong_caps;
+
+ /* figure out if we deal with plain or MSGSM */
+ if (gst_structure_has_name (s, "audio/x-gsm"))
+ gsmdec->use_wav49 = 0;
+ else if (gst_structure_has_name (s, "audio/ms-gsm"))
+ gsmdec->use_wav49 = 1;
+ else
+ goto wrong_caps;
+
+ /* MSGSM needs different framing */
+ gsm_option (gsmdec->state, GSM_OPT_WAV49, &gsmdec->use_wav49);
+
+ /* we only have one possible source caps, which is the same as our template. */
srccaps = gst_static_pad_template_get_caps (&gsmdec_src_template);
gst_pad_set_caps (gsmdec->srcpad, srccaps);
@@ -191,6 +203,14 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps)
gst_object_unref (gsmdec);
return TRUE;
+
+ /* ERRORS */
+wrong_caps:
+ {
+ GST_ERROR_OBJECT (gsmdec, "invalid caps received");
+ gst_object_unref (gsmdec);
+ return FALSE;
+ }
}
static gboolean
@@ -245,6 +265,7 @@ gst_gsmdec_chain (GstPad * pad, GstBuffer * buf)
gsm_byte *data;
GstFlowReturn ret = GST_FLOW_OK;
GstClockTime timestamp;
+ gint needed;
gsmdec = GST_GSMDEC (gst_pad_get_parent (pad));
@@ -252,47 +273,52 @@ gst_gsmdec_chain (GstPad * pad, GstBuffer * buf)
if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
gst_adapter_clear (gsmdec->adapter);
+ gsmdec->next_ts = GST_CLOCK_TIME_NONE;
+ /* FIXME, do some good offset */
+ gsmdec->next_of = 0;
}
gst_adapter_push (gsmdec->adapter, buf);
- /* do we have enough bytes to read a header */
- while (gst_adapter_available (gsmdec->adapter) >= 33) {
+ needed = 33;
+ /* do we have enough bytes to read a frame */
+ while (gst_adapter_available (gsmdec->adapter) >= needed) {
GstBuffer *outbuf;
+ /* always the same amount of output samples */
outbuf = gst_buffer_new_and_alloc (160 * sizeof (gsm_signal));
- /* TODO take new segment in consideration, if not given restart
- * timestamps at 0 */
- if (timestamp == GST_CLOCK_TIME_NONE) {
- /* If we are not given any timestamp */
- GST_BUFFER_TIMESTAMP (outbuf) = gsmdec->next_ts;
- if (gsmdec->next_ts != GST_CLOCK_TIME_NONE)
- gsmdec->next_ts += 20 * GST_MSECOND;
- }
+ /* If we are not given any timestamp, interpolate from last seen
+ * timestamp (if any). */
+ if (timestamp == GST_CLOCK_TIME_NONE)
+ timestamp = gsmdec->next_ts;
- else {
- /* upstream gave a timestamp, use it. */
- GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
- gsmdec->next_ts = timestamp + 20 * GST_MSECOND;
- /* and make sure we interpollate in the next run */
- timestamp = GST_CLOCK_TIME_NONE;
- }
+ GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+
+ /* interpolate in the next run */
+ if (timestamp != GST_CLOCK_TIME_NONE)
+ gsmdec->next_ts = timestamp + (20 * GST_MSECOND);
+ timestamp = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND;
GST_BUFFER_OFFSET (outbuf) = gsmdec->next_of;
- gsmdec->next_of += 160;
+ if (gsmdec->next_of != -1)
+ gsmdec->next_of += 160;
GST_BUFFER_OFFSET_END (outbuf) = gsmdec->next_of;
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmdec->srcpad));
/* now encode frame into the output buffer */
- data = (gsm_byte *) gst_adapter_peek (gsmdec->adapter, 33);
+ data = (gsm_byte *) gst_adapter_peek (gsmdec->adapter, needed);
if (gsm_decode (gsmdec->state, data,
(gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) {
/* invalid frame */
GST_WARNING_OBJECT (gsmdec, "tried to decode an invalid frame, skipping");
}
- gst_adapter_flush (gsmdec->adapter, 33);
+ gst_adapter_flush (gsmdec->adapter, needed);
+
+ /* WAV49 requires alternating 33 and 32 bytes of input */
+ if (gsmdec->use_wav49)
+ needed = (needed == 33 ? 32 : 33);
GST_DEBUG_OBJECT (gsmdec, "Pushing buffer of size %d ts %" GST_TIME_FORMAT,
GST_BUFFER_SIZE (outbuf),
diff --git a/ext/gsm/gstgsmdec.h b/ext/gsm/gstgsmdec.h
index eb790ced6..cc633d86a 100644
--- a/ext/gsm/gstgsmdec.h
+++ b/ext/gsm/gstgsmdec.h
@@ -53,6 +53,7 @@ struct _GstGSMDec
GstPad *sinkpad, *srcpad;
gsm state;
+ gint use_wav49;
gint64 next_of;
GstClockTime next_ts;