diff --git a/ChangeLog b/ChangeLog index 31471a5698..ae08c2156b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2007-04-10 Wim Taymans + + * 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 * gst/auparse/gstauparse.c: (gst_au_parse_parse_header): diff --git a/gst/rtp/gstrtpamrdepay.c b/gst/rtp/gstrtpamrdepay.c index 06ea6cd612..f5871584db 100644 --- a/gst/rtp/gstrtpamrdepay.c +++ b/gst/rtp/gstrtpamrdepay.c @@ -197,6 +197,7 @@ gst_rtp_amr_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) 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 */ @@ -233,24 +234,20 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) { 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; @@ -259,11 +256,8 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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); @@ -290,11 +284,8 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * 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; } /* @@ -317,11 +308,8 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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; @@ -335,26 +323,15 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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); @@ -386,16 +363,51 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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 */ diff --git a/gst/rtp/gstrtph264depay.c b/gst/rtp/gstrtph264depay.c index 11376797df..be27910d0f 100644 --- a/gst/rtp/gstrtph264depay.c +++ b/gst/rtp/gstrtph264depay.c @@ -154,8 +154,10 @@ gst_rtp_h264_depay_finalize (GObject * object) 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); } @@ -255,9 +257,12 @@ gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) } 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); @@ -333,6 +338,12 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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 @@ -446,13 +457,20 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) /* 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; @@ -473,6 +491,13 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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; } } diff --git a/gst/rtp/gstrtph264depay.h b/gst/rtp/gstrtph264depay.h index ede2b841d6..41c4fc076c 100644 --- a/gst/rtp/gstrtph264depay.h +++ b/gst/rtp/gstrtph264depay.h @@ -44,6 +44,7 @@ struct _GstRtpH264Depay { GstBaseRTPDepayload depayload; + GstBuffer *codec_data; GstAdapter *adapter; gboolean wait_start; }; diff --git a/gst/rtp/gstrtpmp4gdepay.c b/gst/rtp/gstrtpmp4gdepay.c index c9e2d4534f..f1d68a21ea 100644 --- a/gst/rtp/gstrtpmp4gdepay.c +++ b/gst/rtp/gstrtpmp4gdepay.c @@ -287,64 +287,92 @@ gst_rtp_mp4g_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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; - } + payload_header = 2 + AU_headers_bytes; - timestamp = gst_rtp_buffer_get_timestamp (buf); + 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; - /* 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); + GST_DEBUG_OBJECT (rtpmp4gdepay, "len, %d, size %d, index %d", + AU_headers_len, AU_size, AU_index); - /* if this was the last packet of the VOP, create and push a buffer */ - if (gst_rtp_buffer_get_marker (buf)) { - guint avail; + /* 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); - avail = gst_adapter_available (rtpmp4gdepay->adapter); + if (M) { + guint avail; - 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); + /* packet is complete, flush */ + avail = gst_adapter_available (rtpmp4gdepay->adapter); - GST_DEBUG ("gst_rtp_mp4g_depay_chain: pushing buffer of size %d", - GST_BUFFER_SIZE (outbuf)); + outbuf = gst_adapter_take_buffer (rtpmp4gdepay->adapter, avail); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad)); - return outbuf; + 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 { - return NULL; + /* 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 (M) { + guint avail; + + 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)); + + return outbuf; + } } } return NULL; diff --git a/gst/rtp/gstrtpsv3vdepay.c b/gst/rtp/gstrtpsv3vdepay.c index f2df1794ce..bc2647b58d 100644 --- a/gst/rtp/gstrtpsv3vdepay.c +++ b/gst/rtp/gstrtpsv3vdepay.c @@ -252,16 +252,11 @@ gst_rtp_sv3v_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) 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; @@ -342,5 +337,5 @@ gboolean 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); }