mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-17 01:20:19 +00:00
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.
This commit is contained in:
parent
1759dfcbed
commit
fc8b3f18bf
3 changed files with 64 additions and 28 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
2006-09-19 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2006-09-18 Edgard Lima <edgard.lima@indt.org.br>
|
2006-09-18 Edgard Lima <edgard.lima@indt.org.br>
|
||||||
|
|
||||||
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_buffer_new ):
|
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_buffer_new ):
|
||||||
|
|
|
@ -91,7 +91,8 @@ static GstStaticPadTemplate gsmdec_sink_template =
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
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 =
|
static GstStaticPadTemplate gsmdec_src_template =
|
||||||
|
@ -136,8 +137,6 @@ gst_gsmdec_class_init (GstGSMDec * klass)
|
||||||
static void
|
static void
|
||||||
gst_gsmdec_init (GstGSMDec * gsmdec)
|
gst_gsmdec_init (GstGSMDec * gsmdec)
|
||||||
{
|
{
|
||||||
gint use_wav49;
|
|
||||||
|
|
||||||
/* create the sink and src pads */
|
/* create the sink and src pads */
|
||||||
gsmdec->sinkpad =
|
gsmdec->sinkpad =
|
||||||
gst_pad_new_from_template (gst_static_pad_template_get
|
gst_pad_new_from_template (gst_static_pad_template_get
|
||||||
|
@ -154,10 +153,6 @@ gst_gsmdec_init (GstGSMDec * gsmdec)
|
||||||
|
|
||||||
gsmdec->state = gsm_create ();
|
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->adapter = gst_adapter_new ();
|
||||||
gsmdec->next_of = 0;
|
gsmdec->next_of = 0;
|
||||||
gsmdec->next_ts = 0;
|
gsmdec->next_ts = 0;
|
||||||
|
@ -181,9 +176,26 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstGSMDec *gsmdec;
|
GstGSMDec *gsmdec;
|
||||||
GstCaps *srccaps;
|
GstCaps *srccaps;
|
||||||
|
GstStructure *s;
|
||||||
|
|
||||||
gsmdec = GST_GSMDEC (gst_pad_get_parent (pad));
|
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);
|
srccaps = gst_static_pad_template_get_caps (&gsmdec_src_template);
|
||||||
|
|
||||||
gst_pad_set_caps (gsmdec->srcpad, srccaps);
|
gst_pad_set_caps (gsmdec->srcpad, srccaps);
|
||||||
|
@ -191,6 +203,14 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
gst_object_unref (gsmdec);
|
gst_object_unref (gsmdec);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
wrong_caps:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (gsmdec, "invalid caps received");
|
||||||
|
gst_object_unref (gsmdec);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -245,6 +265,7 @@ gst_gsmdec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
gsm_byte *data;
|
gsm_byte *data;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
|
gint needed;
|
||||||
|
|
||||||
gsmdec = GST_GSMDEC (gst_pad_get_parent (pad));
|
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)) {
|
if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
|
||||||
gst_adapter_clear (gsmdec->adapter);
|
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);
|
gst_adapter_push (gsmdec->adapter, buf);
|
||||||
|
|
||||||
/* do we have enough bytes to read a header */
|
needed = 33;
|
||||||
while (gst_adapter_available (gsmdec->adapter) >= 33) {
|
/* do we have enough bytes to read a frame */
|
||||||
|
while (gst_adapter_available (gsmdec->adapter) >= needed) {
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
|
|
||||||
|
/* always the same amount of output samples */
|
||||||
outbuf = gst_buffer_new_and_alloc (160 * sizeof (gsm_signal));
|
outbuf = gst_buffer_new_and_alloc (160 * sizeof (gsm_signal));
|
||||||
|
|
||||||
/* TODO take new segment in consideration, if not given restart
|
/* If we are not given any timestamp, interpolate from last seen
|
||||||
* timestamps at 0 */
|
* timestamp (if any). */
|
||||||
if (timestamp == GST_CLOCK_TIME_NONE) {
|
if (timestamp == GST_CLOCK_TIME_NONE)
|
||||||
/* If we are not given any timestamp */
|
timestamp = gsmdec->next_ts;
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = gsmdec->next_ts;
|
|
||||||
if (gsmdec->next_ts != GST_CLOCK_TIME_NONE)
|
|
||||||
gsmdec->next_ts += 20 * GST_MSECOND;
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
/* upstream gave a timestamp, use it. */
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||||
gsmdec->next_ts = timestamp + 20 * GST_MSECOND;
|
|
||||||
/* and make sure we interpollate in the next run */
|
/* interpolate in the next run */
|
||||||
|
if (timestamp != GST_CLOCK_TIME_NONE)
|
||||||
|
gsmdec->next_ts = timestamp + (20 * GST_MSECOND);
|
||||||
timestamp = GST_CLOCK_TIME_NONE;
|
timestamp = GST_CLOCK_TIME_NONE;
|
||||||
}
|
|
||||||
|
|
||||||
GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND;
|
GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND;
|
||||||
GST_BUFFER_OFFSET (outbuf) = gsmdec->next_of;
|
GST_BUFFER_OFFSET (outbuf) = gsmdec->next_of;
|
||||||
|
if (gsmdec->next_of != -1)
|
||||||
gsmdec->next_of += 160;
|
gsmdec->next_of += 160;
|
||||||
GST_BUFFER_OFFSET_END (outbuf) = gsmdec->next_of;
|
GST_BUFFER_OFFSET_END (outbuf) = gsmdec->next_of;
|
||||||
|
|
||||||
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmdec->srcpad));
|
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmdec->srcpad));
|
||||||
|
|
||||||
/* now encode frame into the output buffer */
|
/* 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,
|
if (gsm_decode (gsmdec->state, data,
|
||||||
(gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) {
|
(gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) {
|
||||||
/* invalid frame */
|
/* invalid frame */
|
||||||
GST_WARNING_OBJECT (gsmdec, "tried to decode an invalid frame, skipping");
|
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_DEBUG_OBJECT (gsmdec, "Pushing buffer of size %d ts %" GST_TIME_FORMAT,
|
||||||
GST_BUFFER_SIZE (outbuf),
|
GST_BUFFER_SIZE (outbuf),
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct _GstGSMDec
|
||||||
GstPad *sinkpad, *srcpad;
|
GstPad *sinkpad, *srcpad;
|
||||||
|
|
||||||
gsm state;
|
gsm state;
|
||||||
|
gint use_wav49;
|
||||||
gint64 next_of;
|
gint64 next_of;
|
||||||
GstClockTime next_ts;
|
GstClockTime next_ts;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue