static GstCaps * mulawdec_getcaps (GstPad * pad) { GstMuLawDec *mulawdec; GstPad *otherpad; GstCaps *othercaps, *result; const GstCaps *templ; const gchar *name; gint i; mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad)); /* figure out the name of the caps we are going to return */ if (pad == mulawdec->srcpad) { name = "audio/x-raw-int"; otherpad = mulawdec->sinkpad; } else { name = "audio/x-mulaw"; otherpad = mulawdec->srcpad; } /* get caps from the peer, this can return NULL when there is no peer */ othercaps = gst_pad_peer_get_caps (otherpad); /* get the template caps to make sure we return something acceptable */ templ = gst_pad_get_pad_template_caps (pad); if (othercaps) { /* there was a peer */ othercaps = gst_caps_make_writable (othercaps); /* go through the caps and remove the fields we don't want */ for (i = 0; i < gst_caps_get_size (othercaps); i++) { GstStructure *structure; structure = gst_caps_get_structure (othercaps, i); /* adjust the name */ gst_structure_set_name (structure, name); if (pad == mulawdec->sinkpad) { /* remove the fields we don't want */ gst_structure_remove_fields (structure, "width", "depth", "endianness", "signed", NULL); } else { /* add fixed fields */ gst_structure_set (structure, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, NULL); } } /* filter against the allowed caps of the pad to return our result */ result = gst_caps_intersect (othercaps, templ); gst_caps_unref (othercaps); } else { /* there was no peer, return the template caps */ result = gst_caps_copy (templ); } return result; }
static GstStateChangeReturn gst_mulawdec_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; GstMuLawDec *dec = GST_MULAWDEC (element); switch (transition) { default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret != GST_STATE_CHANGE_SUCCESS) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: dec->rate = 0; dec->channels = 0; break; default: break; } return ret; }
static gboolean mulawdec_sink_setcaps (GstPad * pad, GstCaps * caps) { GstMuLawDec *mulawdec; GstStructure *structure; int rate, channels; gboolean ret; GstCaps *outcaps; mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad)); structure = gst_caps_get_structure (caps, 0); ret = gst_structure_get_int (structure, "rate", &rate); ret = ret && gst_structure_get_int (structure, "channels", &channels); if (!ret) return FALSE; outcaps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL); ret = gst_pad_set_caps (mulawdec->srcpad, outcaps); gst_caps_unref (outcaps); if (ret) { GST_DEBUG_OBJECT (mulawdec, "rate=%d, channels=%d", rate, channels); mulawdec->rate = rate; mulawdec->channels = channels; } return ret; }
static gboolean gst_mulawdec_set_format (GstAudioDecoder * dec, GstCaps * caps) { GstMuLawDec *mulawdec = GST_MULAWDEC (dec); GstStructure *structure; int rate, channels; GstAudioInfo info; structure = gst_caps_get_structure (caps, 0); if (!structure) { GST_ERROR ("failed to get structure from caps"); goto error_failed_get_structure; } if (!gst_structure_get_int (structure, "rate", &rate)) { GST_ERROR ("failed to find field rate in input caps"); goto error_failed_find_rate; } if (!gst_structure_get_int (structure, "channels", &channels)) { GST_ERROR ("failed to find field channels in input caps"); goto error_failed_find_channel; } gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, rate, channels, NULL); GST_DEBUG_OBJECT (mulawdec, "rate=%d, channels=%d", rate, channels); return gst_audio_decoder_set_output_format (dec, &info); error_failed_find_channel: error_failed_find_rate: error_failed_get_structure: return FALSE; }
static GstFlowReturn gst_mulawdec_chain (GstPad * pad, GstBuffer * buffer) { GstMuLawDec *mulawdec; gint16 *linear_data; guint8 *mulaw_data; guint mulaw_size; GstBuffer *outbuf; GstFlowReturn ret; mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad)); if (G_UNLIKELY (mulawdec->rate == 0)) goto not_negotiated; mulaw_data = (guint8 *) GST_BUFFER_DATA (buffer); mulaw_size = GST_BUFFER_SIZE (buffer); ret = gst_pad_alloc_buffer_and_set_caps (mulawdec->srcpad, GST_BUFFER_OFFSET_NONE, mulaw_size * 2, GST_PAD_CAPS (mulawdec->srcpad), &outbuf); if (ret != GST_FLOW_OK) goto alloc_failed; linear_data = (gint16 *) GST_BUFFER_DATA (outbuf); /* copy discont flag */ if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer); if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE) GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (GST_SECOND, mulaw_size * 2, 2 * mulawdec->rate * mulawdec->channels); else GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer); gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawdec->srcpad)); mulaw_decode (mulaw_data, linear_data, mulaw_size); gst_buffer_unref (buffer); ret = gst_pad_push (mulawdec->srcpad, outbuf); return ret; /* ERRORS */ not_negotiated: { GST_WARNING_OBJECT (mulawdec, "no input format set: not-negotiated"); gst_buffer_unref (buffer); return GST_FLOW_NOT_NEGOTIATED; } alloc_failed: { GST_DEBUG_OBJECT (mulawdec, "pad alloc failed, flow: %s", gst_flow_get_name (ret)); gst_buffer_unref (buffer); return ret; } }