static GstCaps * mulawenc_getcaps (GstPad * pad) { GstMuLawEnc *mulawenc; GstPad *otherpad; GstCaps *othercaps, *result; const GstCaps *templ; const gchar *name; gint i; mulawenc = GST_MULAWENC (GST_PAD_PARENT (pad)); /* figure out the name of the caps we are going to return */ if (pad == mulawenc->srcpad) { name = "audio/x-mulaw"; otherpad = mulawenc->sinkpad; } else { name = "audio/x-raw-int"; otherpad = mulawenc->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 == mulawenc->srcpad) { /* 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 gboolean gst_mulawenc_set_format (GstAudioEncoder * audioenc, GstAudioInfo * info) { GstCaps *base_caps; GstStructure *structure; GstMuLawEnc *mulawenc = GST_MULAWENC (audioenc); gboolean ret; mulawenc->rate = info->rate; mulawenc->channels = info->channels; base_caps = gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (audioenc)); g_assert (base_caps); base_caps = gst_caps_make_writable (base_caps); g_assert (base_caps); structure = gst_caps_get_structure (base_caps, 0); g_assert (structure); gst_structure_set (structure, "rate", G_TYPE_INT, mulawenc->rate, NULL); gst_structure_set (structure, "channels", G_TYPE_INT, mulawenc->channels, NULL); gst_mulawenc_set_tags (mulawenc); ret = gst_audio_encoder_set_output_format (audioenc, base_caps); gst_caps_unref (base_caps); return ret; }
static gboolean mulawenc_setcaps (GstPad * pad, GstCaps * caps) { GstMuLawEnc *mulawenc; GstPad *otherpad; GstStructure *structure; GstCaps *base_caps; mulawenc = GST_MULAWENC (gst_pad_get_parent (pad)); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "channels", &mulawenc->channels); gst_structure_get_int (structure, "rate", &mulawenc->rate); if (pad == mulawenc->sinkpad) { otherpad = mulawenc->srcpad; } else { otherpad = mulawenc->sinkpad; } base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad)); structure = gst_caps_get_structure (base_caps, 0); gst_structure_set (structure, "rate", G_TYPE_INT, mulawenc->rate, NULL); gst_structure_set (structure, "channels", G_TYPE_INT, mulawenc->channels, NULL); gst_pad_set_caps (otherpad, base_caps); gst_object_unref (mulawenc); gst_caps_unref (base_caps); return TRUE; }
static gboolean gst_mulawenc_start (GstAudioEncoder * audioenc) { GstMuLawEnc *mulawenc = GST_MULAWENC (audioenc); mulawenc->channels = 0; mulawenc->rate = 0; return TRUE; }
static GstFlowReturn gst_mulawenc_handle_frame (GstAudioEncoder * audioenc, GstBuffer * buffer) { GstMuLawEnc *mulawenc; GstMapInfo inmap, outmap; gint16 *linear_data; gsize linear_size; guint8 *mulaw_data; guint mulaw_size; GstBuffer *outbuf; GstFlowReturn ret; if (!buffer) { ret = GST_FLOW_OK; goto done; } mulawenc = GST_MULAWENC (audioenc); if (!mulawenc->rate || !mulawenc->channels) goto not_negotiated; gst_buffer_map (buffer, &inmap, GST_MAP_READ); linear_data = (gint16 *) inmap.data; linear_size = inmap.size; mulaw_size = linear_size / 2; outbuf = gst_audio_encoder_allocate_output_buffer (audioenc, mulaw_size); g_assert (outbuf); gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE); mulaw_data = outmap.data; mulaw_encode (linear_data, mulaw_data, mulaw_size); gst_buffer_unmap (outbuf, &outmap); gst_buffer_unmap (buffer, &inmap); ret = gst_audio_encoder_finish_frame (audioenc, outbuf, -1); done: return ret; not_negotiated: { GST_DEBUG_OBJECT (mulawenc, "no format negotiated"); ret = GST_FLOW_NOT_NEGOTIATED; goto done; } }
static GstCaps * mulawenc_getcaps (GstPad * pad) { GstMuLawEnc *mulawenc; GstPad *otherpad; GstCaps *base_caps, *othercaps; mulawenc = GST_MULAWENC (GST_PAD_PARENT (pad)); base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); if (pad == mulawenc->srcpad) { otherpad = mulawenc->sinkpad; } else { otherpad = mulawenc->srcpad; } othercaps = gst_pad_peer_get_caps (otherpad); if (othercaps) { GstStructure *structure; const GValue *orate, *ochans; const GValue *rate, *chans; GValue irate = { 0 }, ichans = { 0}; if (gst_caps_is_empty (othercaps) || gst_caps_is_any (othercaps)) goto done; structure = gst_caps_get_structure (othercaps, 0); orate = gst_structure_get_value (structure, "rate"); ochans = gst_structure_get_value (structure, "channels"); if (!orate || !ochans) goto done; structure = gst_caps_get_structure (base_caps, 0); rate = gst_structure_get_value (structure, "rate"); chans = gst_structure_get_value (structure, "channels"); if (!rate || !chans) goto done; gst_value_intersect (&irate, orate, rate); gst_value_intersect (&ichans, ochans, chans); /* Set the samplerate/channels on the to-be-returned caps */ structure = gst_caps_get_structure (base_caps, 0); gst_structure_set_value (structure, "rate", &irate); gst_structure_set_value (structure, "channels", &ichans); done: gst_caps_unref (othercaps); } return base_caps; }
static GstFlowReturn gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer) { GstMuLawEnc *mulawenc; gint16 *linear_data; guint linear_size; guint8 *mulaw_data; guint mulaw_size; GstBuffer *outbuf; GstFlowReturn ret; GstClockTime timestamp, duration; mulawenc = GST_MULAWENC (gst_pad_get_parent (pad)); if (!mulawenc->rate || !mulawenc->channels) goto not_negotiated; linear_data = (gint16 *) GST_BUFFER_DATA (buffer); linear_size = GST_BUFFER_SIZE (buffer); mulaw_size = linear_size / 2; timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); ret = gst_pad_alloc_buffer_and_set_caps (mulawenc->srcpad, GST_BUFFER_OFFSET_NONE, mulaw_size, GST_PAD_CAPS (mulawenc->srcpad), &outbuf); if (ret != GST_FLOW_OK) goto alloc_failed; if (duration == -1) { duration = gst_util_uint64_scale_int (mulaw_size, GST_SECOND, mulawenc->rate * mulawenc->channels); } if (GST_BUFFER_SIZE (outbuf) < mulaw_size) { /* pad-alloc can suggest a smaller size */ gst_buffer_unref (outbuf); outbuf = gst_buffer_new_and_alloc (mulaw_size); } mulaw_data = (guint8 *) 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) = timestamp; GST_BUFFER_DURATION (outbuf) = duration; gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawenc->srcpad)); mulaw_encode (linear_data, mulaw_data, mulaw_size); gst_buffer_unref (buffer); ret = gst_pad_push (mulawenc->srcpad, outbuf); done: gst_object_unref (mulawenc); return ret; not_negotiated: { GST_DEBUG_OBJECT (mulawenc, "no format negotiated"); ret = GST_FLOW_NOT_NEGOTIATED; gst_buffer_unref (buffer); goto done; } alloc_failed: { GST_DEBUG_OBJECT (mulawenc, "pad alloc failed"); gst_buffer_unref (buffer); goto done; } }