diff options
Diffstat (limited to 'gst/rtp/gstrtpg711pay.c')
-rw-r--r-- | gst/rtp/gstrtpg711pay.c | 117 |
1 files changed, 91 insertions, 26 deletions
diff --git a/gst/rtp/gstrtpg711pay.c b/gst/rtp/gstrtpg711pay.c index e0c70678..e83c888b 100644 --- a/gst/rtp/gstrtpg711pay.c +++ b/gst/rtp/gstrtpg711pay.c @@ -45,12 +45,12 @@ static GstStaticPadTemplate gst_rtpg711enc_src_template = GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 0, " + "payload = (int) " GST_RTP_PAYLOAD_PCMU_STRING ", " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMU\"; " "application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 8, " + "payload = (int) " GST_RTP_PAYLOAD_PCMA_STRING ", " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMA\"") ); @@ -58,6 +58,7 @@ static gboolean gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps); static GstFlowReturn gst_rtpg711enc_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer); +static void gst_rtpg711enc_finalize (GObject * object); GST_BOILERPLATE (GstRtpG711Enc, gst_rtpg711enc, GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD); @@ -86,6 +87,7 @@ gst_rtpg711enc_class_init (GstRtpG711EncClass * klass) gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); + gobject_class->finalize = gst_rtpg711enc_finalize; gstbasertppayload_class->set_caps = gst_rtpg711enc_setcaps; gstbasertppayload_class->handle_buffer = gst_rtpg711enc_handle_buffer; @@ -94,9 +96,23 @@ gst_rtpg711enc_class_init (GstRtpG711EncClass * klass) static void gst_rtpg711enc_init (GstRtpG711Enc * rtpg711enc, GstRtpG711EncClass * klass) { + rtpg711enc->adapter = gst_adapter_new (); GST_BASE_RTP_PAYLOAD (rtpg711enc)->clock_rate = 8000; } +static void +gst_rtpg711enc_finalize (GObject * object) +{ + GstRtpG711Enc *rtpg711enc; + + rtpg711enc = GST_RTP_G711_ENC (object); + + g_object_unref (rtpg711enc->adapter); + rtpg711enc->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static gboolean gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) { @@ -109,9 +125,11 @@ gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) stname = gst_structure_get_name (structure); if (0 == strcmp ("audio/x-mulaw", stname)) { - gst_basertppayload_set_options (payload, "audio", TRUE, "PCMU", 8000); + payload->pt = GST_RTP_PAYLOAD_PCMU; + gst_basertppayload_set_options (payload, "audio", FALSE, "PCMU", 8000); } else if (0 == strcmp ("audio/x-alaw", stname)) { - gst_basertppayload_set_options (payload, "audio", TRUE, "PCMA", 8000); + payload->pt = GST_RTP_PAYLOAD_PCMA; + gst_basertppayload_set_options (payload, "audio", FALSE, "PCMA", 8000); } else { return FALSE; } @@ -122,41 +140,88 @@ gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) } static GstFlowReturn +gst_rtpg711enc_flush (GstRtpG711Enc * rtpg711enc) +{ + guint avail; + GstBuffer *outbuf; + GstFlowReturn ret; + + /* the data available in the adapter is either smaller + * than the MTU or bigger. In the case it is smaller, the complete + * adapter contents can be put in one packet. */ + avail = gst_adapter_available (rtpg711enc->adapter); + + ret = GST_FLOW_OK; + + while (avail > 0) { + guint towrite; + guint8 *payload; + guint8 *data; + guint payload_len; + guint packet_len; + + /* this will be the total lenght of the packet */ + packet_len = gst_rtpbuffer_calc_packet_len (avail, 0, 0); + /* fill one MTU or all available bytes */ + towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpg711enc)); + /* this is the payload length */ + payload_len = gst_rtpbuffer_calc_payload_len (towrite, 0, 0); + /* create buffer to hold the payload */ + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + + /* copy payload */ + gst_rtpbuffer_set_payload_type (outbuf, + GST_BASE_RTP_PAYLOAD_PT (rtpg711enc)); + payload = gst_rtpbuffer_get_payload (outbuf); + data = (guint8 *) gst_adapter_peek (rtpg711enc->adapter, payload_len); + memcpy (payload, data, payload_len); + gst_adapter_flush (rtpg711enc->adapter, payload_len); + + avail -= payload_len; + + GST_BUFFER_TIMESTAMP (outbuf) = rtpg711enc->first_ts; + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpg711enc), outbuf); + } + + return ret; +} + +static GstFlowReturn gst_rtpg711enc_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRtpG711Enc *rtpg711enc; - guint size, payload_len; - GstBuffer *outbuf; - guint8 *payload, *data; - GstClockTime timestamp; + guint size, packet_len, avail; GstFlowReturn ret; + GstClockTime duration; rtpg711enc = GST_RTP_G711_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); - timestamp = GST_BUFFER_TIMESTAMP (buffer); + duration = GST_BUFFER_TIMESTAMP (buffer); - /* FIXME, only one G711 frame per RTP packet for now */ - payload_len = size; - - outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); - /* FIXME, assert for now */ - g_assert (payload_len <= GST_BASE_RTP_PAYLOAD_MTU (rtpg711enc)); - - /* copy timestamp */ - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - /* get payload */ - payload = gst_rtpbuffer_get_payload (outbuf); - - data = GST_BUFFER_DATA (buffer); + avail = gst_adapter_available (rtpg711enc->adapter); + if (avail == 0) { + rtpg711enc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + rtpg711enc->duration = 0; + } - /* copy data in payload */ - memcpy (&payload[0], data, size); + /* get packet length of data and see if we exceeded MTU. */ + packet_len = gst_rtpbuffer_calc_packet_len (avail + size, 0, 0); - gst_buffer_unref (buffer); + /* if this buffer is going to overflow the packet, flush what we + * have. */ + if (gst_basertppayload_is_filled (basepayload, + packet_len, rtpg711enc->duration + duration)) { + ret = gst_rtpg711enc_flush (rtpg711enc); + rtpg711enc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + rtpg711enc->duration = 0; + } else { + ret = GST_FLOW_OK; + } - ret = gst_basertppayload_push (basepayload, outbuf); + gst_adapter_push (rtpg711enc->adapter, buffer); + rtpg711enc->duration += duration; return ret; } |