mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-05 02:02:26 +00:00
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.
This commit is contained in:
parent
7e6d4b3eb9
commit
509035fcdb
4 changed files with 165 additions and 29 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
2006-02-09 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2006-02-09 Jan Schmidt <thaytan@mad.scientist.com>
|
2006-02-09 Jan Schmidt <thaytan@mad.scientist.com>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
|
|
@ -272,11 +272,14 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
if (!rtpamrdepay->negotiated)
|
if (!rtpamrdepay->negotiated)
|
||||||
goto not_negotiated;
|
goto not_negotiated;
|
||||||
|
|
||||||
if (!gst_rtp_buffer_validate (buf))
|
if (!gst_rtp_buffer_validate (buf)) {
|
||||||
|
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
||||||
|
(NULL), ("AMR RTP packet did not validate"));
|
||||||
goto bad_packet;
|
goto bad_packet;
|
||||||
|
}
|
||||||
|
|
||||||
/* when we get here, 1 channel, 8000 Hz, octet aligned, no CRC,
|
/* when we get here, 1 channel, 8000 Hz, octet aligned, no CRC,
|
||||||
* no robust sorting, no interleaving data is to be depayd */
|
* no robust sorting, no interleaving data is to be depayloaded */
|
||||||
{
|
{
|
||||||
gint payload_len;
|
gint payload_len;
|
||||||
guint8 *payload, *p, *dp;
|
guint8 *payload, *p, *dp;
|
||||||
|
@ -289,8 +292,11 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
payload_len = gst_rtp_buffer_get_payload_len (buf);
|
payload_len = gst_rtp_buffer_get_payload_len (buf);
|
||||||
|
|
||||||
/* need at least 2 bytes for the header */
|
/* need at least 2 bytes for the header */
|
||||||
if (payload_len < 2)
|
if (payload_len < 2) {
|
||||||
|
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
||||||
|
(NULL), ("AMR RTP payload too small (%d)", payload_len));
|
||||||
goto bad_packet;
|
goto bad_packet;
|
||||||
|
}
|
||||||
|
|
||||||
payload = gst_rtp_buffer_get_payload (buf);
|
payload = gst_rtp_buffer_get_payload (buf);
|
||||||
|
|
||||||
|
@ -308,6 +314,8 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
payload_len -= 1;
|
payload_len -= 1;
|
||||||
payload += 1;
|
payload += 1;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpamrdepay, "payload len %d", payload_len);
|
||||||
|
|
||||||
if (rtpamrdepay->interleaving) {
|
if (rtpamrdepay->interleaving) {
|
||||||
ILL = (payload[0] & 0xf0) >> 4;
|
ILL = (payload[0] & 0xf0) >> 4;
|
||||||
ILP = (payload[0] & 0x0f);
|
ILP = (payload[0] & 0x0f);
|
||||||
|
@ -315,8 +323,11 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
payload_len -= 1;
|
payload_len -= 1;
|
||||||
payload += 1;
|
payload += 1;
|
||||||
|
|
||||||
if (ILP > ILL)
|
if (ILP > ILL) {
|
||||||
|
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
||||||
|
(NULL), ("AMR RTP wrong interleaving"));
|
||||||
goto bad_packet;
|
goto bad_packet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -338,8 +349,12 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
FT = (payload[i] & 0x78) >> 3;
|
FT = (payload[i] & 0x78) >> 3;
|
||||||
|
|
||||||
fr_size = frame_size[FT];
|
fr_size = frame_size[FT];
|
||||||
if (fr_size == -1)
|
GST_DEBUG_OBJECT (rtpamrdepay, "frame size %d", fr_size);
|
||||||
|
if (fr_size == -1) {
|
||||||
|
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
||||||
|
(NULL), ("AMR RTP frame size == -1"));
|
||||||
goto bad_packet;
|
goto bad_packet;
|
||||||
|
}
|
||||||
|
|
||||||
if (fr_size > 0) {
|
if (fr_size > 0) {
|
||||||
amr_len += fr_size;
|
amr_len += fr_size;
|
||||||
|
@ -352,23 +367,33 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is impossible */
|
/* this is impossible */
|
||||||
if (num_packets == payload_len)
|
if (num_packets == payload_len) {
|
||||||
|
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
||||||
|
(NULL), ("AMR RTP num_packets == payload_len"));
|
||||||
goto bad_packet;
|
goto bad_packet;
|
||||||
|
}
|
||||||
|
|
||||||
if (rtpamrdepay->crc) {
|
if (rtpamrdepay->crc) {
|
||||||
/* data len + CRC len + header bytes should be smaller than payload_len */
|
/* data len + CRC len + header bytes should be smaller than payload_len */
|
||||||
if (num_packets + num_nonempty_packets + amr_len > payload_len)
|
if (num_packets + num_nonempty_packets + amr_len > payload_len) {
|
||||||
|
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
||||||
|
(NULL), ("AMR RTP wrong length 1"));
|
||||||
goto bad_packet;
|
goto bad_packet;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* data len + header bytes should be smaller than payload_len */
|
/* data len + header bytes should be smaller than payload_len */
|
||||||
if (num_packets + amr_len > payload_len)
|
if (num_packets + amr_len > payload_len) {
|
||||||
|
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
||||||
|
(NULL), ("AMR RTP wrong length 2"));
|
||||||
goto bad_packet;
|
goto bad_packet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp = gst_rtp_buffer_get_timestamp (buf);
|
timestamp = gst_rtp_buffer_get_timestamp (buf);
|
||||||
|
|
||||||
outbuf = gst_buffer_new_and_alloc (payload_len);
|
outbuf = gst_buffer_new_and_alloc (payload_len);
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / rtpamrdepay->rate;
|
GST_BUFFER_TIMESTAMP (outbuf) =
|
||||||
|
gst_util_uint64_scale_int (timestamp, GST_SECOND, rtpamrdepay->rate);
|
||||||
|
|
||||||
/* point to destination */
|
/* point to destination */
|
||||||
p = GST_BUFFER_DATA (outbuf);
|
p = GST_BUFFER_DATA (outbuf);
|
||||||
|
@ -384,8 +409,8 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
|
|
||||||
fr_size = frame_size[(payload[i] & 0x78) >> 3];
|
fr_size = frame_size[(payload[i] & 0x78) >> 3];
|
||||||
if (fr_size > 0) {
|
if (fr_size > 0) {
|
||||||
/* copy FT */
|
/* copy FT, clear F bit */
|
||||||
*p++ = payload[i];
|
*p++ = payload[i] & 0x7f;
|
||||||
/* copy data packet, FIXME, calc CRC here. */
|
/* copy data packet, FIXME, calc CRC here. */
|
||||||
memcpy (p, dp, fr_size);
|
memcpy (p, dp, fr_size);
|
||||||
|
|
||||||
|
@ -404,18 +429,18 @@ gst_rtp_amr_depay_chain (GstPad * pad, GstBuffer * buf)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
not_negotiated:
|
not_negotiated:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (rtpamrdepay, STREAM, NOT_IMPLEMENTED,
|
GST_ELEMENT_ERROR (rtpamrdepay, STREAM, NOT_IMPLEMENTED,
|
||||||
("not negotiated"), (NULL));
|
(NULL), ("not negotiated"));
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
bad_packet:
|
bad_packet:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
|
|
||||||
("amr packet did not validate"), (NULL));
|
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
|
/* no fatal error */
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
#include "gstrtpamrpay.h"
|
#include "gstrtpamrpay.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY (rtpamrpay_debug);
|
||||||
|
#define GST_CAT_DEFAULT (rtpamrpay_debug)
|
||||||
|
|
||||||
/* references:
|
/* references:
|
||||||
*
|
*
|
||||||
* RFC 3267 - Real-Time Transport Protocol (RTP) Payload Format and File
|
* 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->set_caps = gst_rtp_amr_pay_setcaps;
|
||||||
gstbasertppayload_class->handle_buffer = gst_rtp_amr_pay_handle_buffer;
|
gstbasertppayload_class->handle_buffer = gst_rtp_amr_pay_handle_buffer;
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (rtpamrpay_debug, "rtpamrpay", 0,
|
||||||
|
"AMR RTP Depayloader");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -156,6 +163,12 @@ gst_rtp_amr_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
return TRUE;
|
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
|
static GstFlowReturn
|
||||||
gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
GstBuffer * buffer)
|
GstBuffer * buffer)
|
||||||
|
@ -164,30 +177,63 @@ gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
guint size, payload_len;
|
guint size, payload_len;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
guint8 *payload, *data;
|
guint8 *payload, *data, *payload_amr;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
|
guint packet_len, mtu;
|
||||||
|
gint i, num_packets, num_nonempty_packets;
|
||||||
|
gint amr_len;
|
||||||
|
|
||||||
rtpamrpay = GST_RTP_AMR_PAY (basepayload);
|
rtpamrpay = GST_RTP_AMR_PAY (basepayload);
|
||||||
|
mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpamrpay);
|
||||||
|
|
||||||
size = GST_BUFFER_SIZE (buffer);
|
size = GST_BUFFER_SIZE (buffer);
|
||||||
|
data = GST_BUFFER_DATA (buffer);
|
||||||
timestamp = GST_BUFFER_TIMESTAMP (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,
|
* octet aligned, no interleaving, single channel, no CRC,
|
||||||
* no robust-sorting. */
|
* 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
|
/* we need one extra byte for the CMR, the ToC is in the input
|
||||||
* data */
|
* data */
|
||||||
payload_len = size + 1;
|
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);
|
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 */
|
/* copy timestamp */
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||||
|
|
||||||
/* get payload */
|
/* get payload, this is now writable */
|
||||||
payload = gst_rtp_buffer_get_payload (outbuf);
|
payload = gst_rtp_buffer_get_payload (outbuf);
|
||||||
|
|
||||||
/* 0 1 2 3 4 5 6 7
|
/* 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 */
|
payload[0] = 0xF0; /* CMR, no specific mode requested */
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (buffer);
|
/* 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 */
|
/* copy data in payload, first we copy all the FTs then all
|
||||||
memcpy (&payload[1], data, size);
|
* 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
|
/* 0 1 2 3 4 5 6 7
|
||||||
* +-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+
|
||||||
* |F| FT |Q|P|P|
|
* |F| FT |Q|P|P| more FT...
|
||||||
* +-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+
|
||||||
*/
|
*/
|
||||||
/* clear F flag */
|
FT = (*data & 0x78) >> 3;
|
||||||
payload[1] = payload[1] & 0x7f;
|
|
||||||
|
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);
|
gst_buffer_unref (buffer);
|
||||||
|
|
||||||
ret = gst_basertppayload_push (basepayload, outbuf);
|
ret = gst_basertppayload_push (basepayload, outbuf);
|
||||||
|
|
||||||
return ret;
|
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
|
gboolean
|
||||||
|
|
|
@ -275,6 +275,7 @@ gst_rtp_mp4v_pay_depay_data (GstRtpMP4VPay * enc, guint8 * data, guint size,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
code = GST_READ_UINT32_BE (data);
|
code = GST_READ_UINT32_BE (data);
|
||||||
|
GST_DEBUG_OBJECT (enc, "start code 0x%08x", code);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case VOS_STARTCODE:
|
case VOS_STARTCODE:
|
||||||
|
@ -287,6 +288,8 @@ gst_rtp_mp4v_pay_depay_data (GstRtpMP4VPay * enc, guint8 * data, guint size,
|
||||||
/* profile_and_level_indication */
|
/* profile_and_level_indication */
|
||||||
profile = data[4];
|
profile = data[4];
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (enc, "VOS profile 0x%08x", profile);
|
||||||
|
|
||||||
if (profile != enc->profile) {
|
if (profile != enc->profile) {
|
||||||
newprofile = TRUE;
|
newprofile = TRUE;
|
||||||
enc->profile = profile;
|
enc->profile = profile;
|
||||||
|
@ -322,10 +325,12 @@ gst_rtp_mp4v_pay_depay_data (GstRtpMP4VPay * enc, guint8 * data, guint size,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VOP_STARTCODE:
|
case VOP_STARTCODE:
|
||||||
|
GST_DEBUG_OBJECT (enc, "VOP");
|
||||||
/* VOP startcode, we don't have to flush the packet */
|
/* VOP startcode, we don't have to flush the packet */
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
GST_DEBUG_OBJECT (enc, "other startcode");
|
||||||
/* all other startcodes need a flush */
|
/* all other startcodes need a flush */
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue