+2007-04-10 Wim Taymans <wim@fluendo.com>
+
+ * gst/rtp/gstrtpamrdepay.c: (gst_rtp_amr_depay_setcaps),
+ (gst_rtp_amr_depay_process):
+ Fix depayloader clock_rate and some cleanups.
+
+ * gst/rtp/gstrtph264depay.c: (gst_rtp_h264_depay_finalize),
+ (gst_rtp_h264_depay_setcaps), (gst_rtp_h264_depay_process):
+ * gst/rtp/gstrtph264depay.h:
+ Don't push codec_data in the adapter because it might get flushed when
+ we get a discont.
+
+ * gst/rtp/gstrtpmp4gdepay.c: (gst_rtp_mp4g_depay_process):
+ Handle multiple AU per packet.
+
+ * gst/rtp/gstrtpsv3vdepay.c: (gst_rtp_sv3v_depay_process),
+ (gst_rtp_sv3v_depay_plugin_init):
+ Disable rank, this one does not work.
+ Remove timestamping, base class does that.
+
2007-04-10 Stefan Kost <ensonic@users.sf.net>
* gst/auparse/gstauparse.c: (gst_au_parse_parse_header):
if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
clock_rate = 8000;
+ depayload->clock_rate = clock_rate;
/* we require 1 channel, 8000 Hz, octet aligned, no CRC,
* no robust sorting, no interleaving for now */
{
GstRtpAMRDepay *rtpamrdepay;
GstBuffer *outbuf = NULL;
+ gint payload_len;
rtpamrdepay = GST_RTP_AMR_DEPAY (depayload);
if (!rtpamrdepay->negotiated)
goto not_negotiated;
- if (!gst_rtp_buffer_validate (buf)) {
- GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
- (NULL), ("AMR RTP packet did not validate"));
- goto bad_packet;
- }
+ if (!gst_rtp_buffer_validate (buf))
+ goto invalid_packet;
/* when we get here, 1 channel, 8000 Hz, octet aligned, no CRC,
* no robust sorting, no interleaving data is to be depayloaded */
{
- gint payload_len;
guint8 *payload, *p, *dp;
- guint32 timestamp;
guint8 CMR;
gint i, num_packets, num_nonempty_packets;
gint amr_len;
payload_len = gst_rtp_buffer_get_payload_len (buf);
/* need at least 2 bytes for the header */
- if (payload_len < 2) {
- GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
- (NULL), ("AMR RTP payload too small (%d)", payload_len));
- goto bad_packet;
- }
+ if (payload_len < 2)
+ goto too_small;
payload = gst_rtp_buffer_get_payload (buf);
payload_len -= 1;
payload += 1;
- if (ILP > ILL) {
- GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
- (NULL), ("AMR RTP wrong interleaving"));
- goto bad_packet;
- }
+ if (ILP > ILL)
+ goto wrong_interleaving;
}
/*
fr_size = frame_size[FT];
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;
- }
+ if (fr_size == -1)
+ goto wrong_framesize;
if (fr_size > 0) {
amr_len += fr_size;
if (rtpamrdepay->crc) {
/* data len + CRC len + header bytes should be smaller than 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;
- }
+ if (num_packets + num_nonempty_packets + amr_len > payload_len)
+ goto wrong_length_1;
} else {
/* data len + header bytes should be smaller than payload_len */
- if (num_packets + amr_len > payload_len) {
- GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
- (NULL), ("AMR RTP wrong length 2"));
- goto bad_packet;
- }
+ if (num_packets + amr_len > payload_len)
+ goto wrong_length_2;
}
- timestamp = gst_rtp_buffer_get_timestamp (buf);
-
outbuf = gst_buffer_new_and_alloc (payload_len);
- GST_BUFFER_TIMESTAMP (outbuf) =
- gst_util_uint64_scale_int (timestamp, GST_SECOND,
- depayload->clock_rate);
/* point to destination */
p = GST_BUFFER_DATA (outbuf);
GST_DEBUG ("gst_rtp_amr_depay_chain: pushing buffer of size %d",
GST_BUFFER_SIZE (outbuf));
}
-
return outbuf;
/* ERRORS */
+invalid_packet:
+ {
+ GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
+ (NULL), ("AMR RTP packet did not validate"));
+ goto bad_packet;
+ }
not_negotiated:
{
GST_ELEMENT_ERROR (rtpamrdepay, STREAM, NOT_IMPLEMENTED,
(NULL), ("not negotiated"));
return NULL;
}
+too_small:
+ {
+ GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
+ (NULL), ("AMR RTP payload too small (%d)", payload_len));
+ goto bad_packet;
+ }
+wrong_interleaving:
+ {
+ GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
+ (NULL), ("AMR RTP wrong interleaving"));
+ goto bad_packet;
+ }
+wrong_framesize:
+ {
+ GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
+ (NULL), ("AMR RTP frame size == -1"));
+ goto bad_packet;
+ }
+wrong_length_1:
+ {
+ GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
+ (NULL), ("AMR RTP wrong length 1"));
+ goto bad_packet;
+ }
+wrong_length_2:
+ {
+ GST_ELEMENT_WARNING (rtpamrdepay, STREAM, DECODE,
+ (NULL), ("AMR RTP wrong length 2"));
+ goto bad_packet;
+ }
bad_packet:
{
/* no fatal error */
rtph264depay = GST_RTP_H264_DEPAY (object);
+ if (rtph264depay->codec_data)
+ gst_buffer_unref (rtph264depay->codec_data);
+
g_object_unref (rtph264depay->adapter);
- rtph264depay->adapter = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
}
GST_BUFFER_SIZE (codec_data) = total;
- /* don't set codec_data, we send unpacketized data so let the decoder
- * packetize for us */
- gst_adapter_push (rtph264depay->adapter, codec_data);
+ /* keep the codec_data, we need to send it as the first buffer. We cannot
+ * push it in the adapter because the adapter might be flushed on discont.
+ */
+ if (rtph264depay->codec_data)
+ gst_buffer_unref (rtph264depay->codec_data);
+ rtph264depay->codec_data = codec_data;
}
gst_pad_set_caps (depayload->srcpad, srccaps);
rtph264depay->wait_start = FALSE;
+ /* prepend codec_data */
+ if (rtph264depay->codec_data) {
+ gst_adapter_push (rtph264depay->adapter, rtph264depay->codec_data);
+ rtph264depay->codec_data = NULL;
+ }
+
/* STAP-A Single-time aggregation packet 5.7.1 */
while (payload_len > 2) {
/* 1
/* if NAL unit ends, flush the adapter */
if (E) {
+ GST_DEBUG_OBJECT (rtph264depay, "output %d bytes", outsize);
+
outsize = gst_adapter_available (rtph264depay->adapter);
outbuf = gst_adapter_take_buffer (rtph264depay->adapter, outsize);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
- GST_DEBUG_OBJECT (rtph264depay, "output %d bytes", outsize);
-
+ /* push codec_data first */
+ if (rtph264depay->codec_data) {
+ gst_buffer_set_caps (rtph264depay->codec_data,
+ GST_PAD_CAPS (depayload->srcpad));
+ gst_base_rtp_depayload_push (depayload, rtph264depay->codec_data);
+ rtph264depay->codec_data = NULL;
+ }
return outbuf;
}
break;
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
+ /* push codec_data first */
+ if (rtph264depay->codec_data) {
+ gst_buffer_set_caps (rtph264depay->codec_data,
+ GST_PAD_CAPS (depayload->srcpad));
+ gst_base_rtp_depayload_push (depayload, rtph264depay->codec_data);
+ rtph264depay->codec_data = NULL;
+ }
return outbuf;
}
}
{
GstBaseRTPDepayload depayload;
+ GstBuffer *codec_data;
GstAdapter *adapter;
gboolean wait_start;
};
guint32 timestamp;
guint AU_headers_len;
guint AU_size, AU_index;
+ gboolean M;
payload_len = gst_rtp_buffer_get_payload_len (buf);
payload = gst_rtp_buffer_get_payload (buf);
payload_header = 0;
+ timestamp = gst_rtp_buffer_get_timestamp (buf);
+ M = gst_rtp_buffer_get_marker (buf);
+
if (rtpmp4gdepay->sizelength > 0) {
+ gint num_AU_headers, AU_headers_bytes, i;
+
/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+
* |AU-headers-length|AU-header|AU-header| |AU-header|padding|
* | | (1) | (2) | | (n) * | bits |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+
*
- * The lenght is 2 bytes and contains the length of the following
+ * The length is 2 bytes and contains the length of the following
* AU-headers in bits.
*/
AU_headers_len = (payload[0] << 8) | payload[1];
+ AU_headers_bytes = (AU_headers_len + 7) / 8;
+ num_AU_headers = AU_headers_len / 16;
+
+ GST_DEBUG_OBJECT (rtpmp4gdepay, "AU headers len %d, bytes %d, num %d",
+ AU_headers_len, AU_headers_bytes, num_AU_headers);
/* skip header */
payload += 2;
- payload_header += 2;
- payload_len -= 2;
-
- /* FIXME, use bits */
- AU_size = ((payload[0] << 8) | payload[1]) >> 3;
- AU_index = payload[1] & 0x7;
-
- GST_DEBUG_OBJECT (rtpmp4gdepay, "len, %d, size %d, index %d",
- AU_headers_len, AU_size, AU_index);
-
/* skip special headers */
- payload += (AU_headers_len + 7) / 8;
- payload_header += (AU_headers_len + 7) / 8;
- payload_len = AU_size;
- }
-
- timestamp = gst_rtp_buffer_get_timestamp (buf);
-
- /* strip header from payload and push in the adapter */
- outbuf =
- gst_rtp_buffer_get_payload_subbuffer (buf, payload_header, payload_len);
- gst_adapter_push (rtpmp4gdepay->adapter, outbuf);
+ payload_header = 2 + AU_headers_bytes;
+
+ for (i = 0; i < num_AU_headers; i++) {
+ /* FIXME, use bits */
+ AU_size = ((payload[0] << 8) | payload[1]) >> 3;
+ AU_index = payload[1] & 0x7;
+ payload += 2;
+
+ GST_DEBUG_OBJECT (rtpmp4gdepay, "len, %d, size %d, index %d",
+ AU_headers_len, AU_size, AU_index);
+
+ /* collect stuff in the adapter, strip header from payload and push in
+ * the adapter */
+ outbuf =
+ gst_rtp_buffer_get_payload_subbuffer (buf, payload_header, AU_size);
+ gst_adapter_push (rtpmp4gdepay->adapter, outbuf);
+
+ if (M) {
+ guint avail;
+
+ /* packet is complete, flush */
+ avail = gst_adapter_available (rtpmp4gdepay->adapter);
+
+ outbuf = gst_adapter_take_buffer (rtpmp4gdepay->adapter, avail);
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
+
+ GST_DEBUG ("gst_rtp_mp4g_depay_chain: pushing buffer of size %d",
+ GST_BUFFER_SIZE (outbuf));
+
+ /* only apply the timestamp for the first buffer */
+ if (i == 0)
+ gst_base_rtp_depayload_push_ts (depayload, timestamp, outbuf);
+ else
+ gst_base_rtp_depayload_push (depayload, outbuf);
+ }
+ payload_header += AU_size;
+ }
+ } else {
+ /* push complete buffer in adapter */
+ outbuf = gst_rtp_buffer_get_payload_subbuffer (buf, 0, payload_len);
+ gst_adapter_push (rtpmp4gdepay->adapter, outbuf);
- /* if this was the last packet of the VOP, create and push a buffer */
- if (gst_rtp_buffer_get_marker (buf)) {
- guint avail;
+ /* if this was the last packet of the VOP, create and push a buffer */
+ if (M) {
+ guint avail;
- avail = gst_adapter_available (rtpmp4gdepay->adapter);
+ avail = gst_adapter_available (rtpmp4gdepay->adapter);
- outbuf = gst_adapter_take_buffer (rtpmp4gdepay->adapter, avail);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
- GST_BUFFER_TIMESTAMP (outbuf) = gst_util_uint64_scale_int
- (timestamp, GST_SECOND, depayload->clock_rate);
+ outbuf = gst_adapter_take_buffer (rtpmp4gdepay->adapter, avail);
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
- GST_DEBUG ("gst_rtp_mp4g_depay_chain: pushing buffer of size %d",
- GST_BUFFER_SIZE (outbuf));
+ GST_DEBUG ("gst_rtp_mp4g_depay_chain: pushing buffer of size %d",
+ GST_BUFFER_SIZE (outbuf));
- return outbuf;
- } else {
- return NULL;
+ return outbuf;
+ }
}
}
return NULL;
if (M) {
/* frame is completed: push contents of adapter */
guint avail;
- guint32 timestamp;
avail = gst_adapter_available (rtpsv3vdepay->adapter);
outbuf = gst_adapter_take_buffer (rtpsv3vdepay->adapter, avail);
/* timestamp for complete buffer is that of last buffer as well */
- timestamp = gst_rtp_buffer_get_timestamp (buf);
- GST_BUFFER_TIMESTAMP (outbuf) =
- gst_util_uint64_scale_int (timestamp, GST_SECOND,
- depayload->clock_rate);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
return outbuf;
gst_rtp_sv3v_depay_plugin_init (GstPlugin * plugin)
{
return gst_element_register (plugin, "rtpsv3vdepay",
- GST_RANK_MARGINAL, GST_TYPE_RTP_SV3V_DEPAY);
+ GST_RANK_NONE, GST_TYPE_RTP_SV3V_DEPAY);
}