mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-04 23:30:05 +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>
|
||||
|
||||
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_buffer_new ):
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -53,6 +53,7 @@ struct _GstGSMDec
|
|||
GstPad *sinkpad, *srcpad;
|
||||
|
||||
gsm state;
|
||||
gint use_wav49;
|
||||
gint64 next_of;
|
||||
GstClockTime next_ts;
|
||||
|
||||
|
|
Loading…
Reference in a new issue