summaryrefslogtreecommitdiffstats
path: root/gst/rtp/gstrtpamrpay.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2006-02-09 14:14:07 +0000
committerWim Taymans <wim.taymans@gmail.com>2006-02-09 14:14:07 +0000
commit509035fcdb2bc6237bf906aa5fb030dbf33852ba (patch)
treedc888b640f9716816074ff91bb729c825467de89 /gst/rtp/gstrtpamrpay.c
parent7e6d4b3eb90e25ffc4db979cefd17a0634416d44 (diff)
gst/rtp/gstrtpamrdepay.c: Added more meaningfull warnings when something goes wrong.
Original commit message from CVS: * gst/rtp/gstrtpamrdepay.c: (gst_rtp_amr_depay_chain): Added more meaningfull warnings when something goes wrong. Clear F bit on outgoing AMR packets. * gst/rtp/gstrtpamrpay.c: (gst_rtp_amr_pay_class_init), (gst_rtp_amr_pay_handle_buffer): Added debugging category Support payloading of multiple AMR frames. * gst/rtp/gstrtpmp4vpay.c: (gst_rtp_mp4v_pay_depay_data): Added some debugging.
Diffstat (limited to 'gst/rtp/gstrtpamrpay.c')
-rw-r--r--gst/rtp/gstrtpamrpay.c126
1 files changed, 109 insertions, 17 deletions
diff --git a/gst/rtp/gstrtpamrpay.c b/gst/rtp/gstrtpamrpay.c
index 8dfed712..7dacce5a 100644
--- a/gst/rtp/gstrtpamrpay.c
+++ b/gst/rtp/gstrtpamrpay.c
@@ -22,6 +22,9 @@
#include "gstrtpamrpay.h"
+GST_DEBUG_CATEGORY (rtpamrpay_debug);
+#define GST_CAT_DEFAULT (rtpamrpay_debug)
+
/* references:
*
* RFC 3267 - Real-Time Transport Protocol (RTP) Payload Format and File
@@ -128,6 +131,10 @@ gst_rtp_amr_pay_class_init (GstRtpAMRPayClass * klass)
gstbasertppayload_class->set_caps = gst_rtp_amr_pay_setcaps;
gstbasertppayload_class->handle_buffer = gst_rtp_amr_pay_handle_buffer;
+
+ GST_DEBUG_CATEGORY_INIT (rtpamrpay_debug, "rtpamrpay", 0,
+ "AMR RTP Depayloader");
+
}
static void
@@ -156,6 +163,12 @@ gst_rtp_amr_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
return TRUE;
}
+/* -1 is invalid */
+static gint frame_size[16] = {
+ 12, 13, 15, 17, 19, 20, 26, 31,
+ 5, -1, -1, -1, -1, -1, -1, 0
+};
+
static GstFlowReturn
gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
GstBuffer * buffer)
@@ -164,30 +177,63 @@ gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
GstFlowReturn ret;
guint size, payload_len;
GstBuffer *outbuf;
- guint8 *payload, *data;
+ guint8 *payload, *data, *payload_amr;
GstClockTime timestamp;
+ guint packet_len, mtu;
+ gint i, num_packets, num_nonempty_packets;
+ gint amr_len;
rtpamrpay = GST_RTP_AMR_PAY (basepayload);
+ mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpamrpay);
size = GST_BUFFER_SIZE (buffer);
+ data = GST_BUFFER_DATA (buffer);
timestamp = GST_BUFFER_TIMESTAMP (buffer);
- /* FIXME, only one AMR frame per RTP packet for now,
+ /* FIXME, only
* octet aligned, no interleaving, single channel, no CRC,
* no robust-sorting. */
+ GST_DEBUG_OBJECT (basepayload, "got %d bytes", size);
+
+ /* first count number of packets and total amr frame size */
+ amr_len = num_packets = num_nonempty_packets = 0;
+ for (i = 0; i < size; i++) {
+ guint8 FT;
+ gint fr_size;
+
+ FT = (data[i] & 0x78) >> 3;
+
+ fr_size = frame_size[FT];
+ GST_DEBUG_OBJECT (basepayload, "frame size %d", fr_size);
+ /* FIXME, we don't handle this yet.. */
+ if (fr_size <= 0)
+ goto wrong_size;
+
+ amr_len += fr_size;
+ num_nonempty_packets++;
+ num_packets++;
+ i += fr_size;
+ }
+ if (amr_len > size)
+ goto incomplete_frame;
+
/* we need one extra byte for the CMR, the ToC is in the input
* data */
payload_len = size + 1;
+ /* get packet len to check against MTU */
+ packet_len = gst_rtp_buffer_calc_packet_len (payload_len, 0, 0);
+ if (packet_len > mtu)
+ goto too_big;
+
+ /* now alloc output buffer */
outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
- /* FIXME, assert for now */
- g_assert (GST_BUFFER_SIZE (outbuf) < GST_BASE_RTP_PAYLOAD_MTU (rtpamrpay));
/* copy timestamp */
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
- /* get payload */
+ /* get payload, this is now writable */
payload = gst_rtp_buffer_get_payload (outbuf);
/* 0 1 2 3 4 5 6 7
@@ -197,24 +243,70 @@ gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
*/
payload[0] = 0xF0; /* CMR, no specific mode requested */
- data = GST_BUFFER_DATA (buffer);
-
- /* copy data in payload */
- memcpy (&payload[1], data, size);
-
- /* 0 1 2 3 4 5 6 7
- * +-+-+-+-+-+-+-+-+
- * |F| FT |Q|P|P|
- * +-+-+-+-+-+-+-+-+
- */
- /* clear F flag */
- payload[1] = payload[1] & 0x7f;
+ /* this is where we copy the AMR data, after num_packets FTs and the
+ * CMR. */
+ payload_amr = payload + num_packets + 1;
+
+ /* copy data in payload, first we copy all the FTs then all
+ * the AMR data. The last FT has to have the F flag cleared. */
+ for (i = 1; i <= num_packets; i++) {
+ guint8 FT;
+ gint fr_size;
+
+ /* 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+
+ * |F| FT |Q|P|P| more FT...
+ * +-+-+-+-+-+-+-+-+
+ */
+ FT = (*data & 0x78) >> 3;
+
+ fr_size = frame_size[FT];
+
+ if (i == num_packets)
+ /* last packet, clear F flag */
+ payload[i] = *data & 0x7f;
+ else
+ /* set F flag */
+ payload[i] = *data | 0x80;
+
+ memcpy (payload_amr, &data[1], fr_size);
+
+ /* all sizes are > 0 since we checked for that above */
+ data += fr_size + 1;
+ payload_amr += fr_size;
+ }
gst_buffer_unref (buffer);
ret = gst_basertppayload_push (basepayload, outbuf);
return ret;
+
+ /* ERRORS */
+wrong_size:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, FORMAT,
+ (NULL), ("received AMR frame with size <= 0"));
+ gst_buffer_unref (buffer);
+
+ return GST_FLOW_ERROR;
+ }
+incomplete_frame:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, FORMAT,
+ (NULL), ("received incomplete AMR frames"));
+ gst_buffer_unref (buffer);
+
+ return GST_FLOW_ERROR;
+ }
+too_big:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, FORMAT,
+ (NULL), ("received too many AMR frames for MTU"));
+ gst_buffer_unref (buffer);
+
+ return GST_FLOW_ERROR;
+ }
}
gboolean