X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Frtp%2Fgstrtpvorbisdepay.c;h=556bd76c0080821325033c7ccb8cd1fc8ae81153;hb=775ccdf9775bd7051929b257444b3be915e88ec6;hp=08ef282da7235bd5226c36df2bc7281d730c0ccb;hpb=632588b3d969cdbef343262579ea94c249c8d0cc;p=platform%2Fupstream%2Fgst-plugins-good.git diff --git a/gst/rtp/gstrtpvorbisdepay.c b/gst/rtp/gstrtpvorbisdepay.c index 08ef282..556bd76 100644 --- a/gst/rtp/gstrtpvorbisdepay.c +++ b/gst/rtp/gstrtpvorbisdepay.c @@ -13,8 +13,8 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H @@ -23,9 +23,11 @@ #include #include +#include #include #include "gstrtpvorbisdepay.h" +#include "gstrtputils.h" GST_DEBUG_CATEGORY_STATIC (rtpvorbisdepay_debug); #define GST_CAT_DEFAULT (rtpvorbisdepay_debug) @@ -40,7 +42,6 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"VORBIS\"" /* All required parameters * @@ -59,12 +60,12 @@ GST_STATIC_PAD_TEMPLATE ("src", #define gst_rtp_vorbis_depay_parent_class parent_class G_DEFINE_TYPE (GstRtpVorbisDepay, gst_rtp_vorbis_depay, - GST_TYPE_BASE_RTP_DEPAYLOAD); + GST_TYPE_RTP_BASE_DEPAYLOAD); -static gboolean gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, +static gboolean gst_rtp_vorbis_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps); -static GstBuffer *gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, - GstBuffer * buf); +static GstBuffer *gst_rtp_vorbis_depay_process (GstRTPBaseDepayload * depayload, + GstRTPBuffer * rtp); static void gst_rtp_vorbis_depay_finalize (GObject * object); @@ -76,25 +77,25 @@ gst_rtp_vorbis_depay_class_init (GstRtpVorbisDepayClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; - GstBaseRTPDepayloadClass *gstbasertpdepayload_class; + GstRTPBaseDepayloadClass *gstrtpbasedepayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; + gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass; gobject_class->finalize = gst_rtp_vorbis_depay_finalize; gstelement_class->change_state = gst_rtp_vorbis_depay_change_state; - gstbasertpdepayload_class->process = gst_rtp_vorbis_depay_process; - gstbasertpdepayload_class->set_caps = gst_rtp_vorbis_depay_setcaps; + gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_vorbis_depay_process; + gstrtpbasedepayload_class->set_caps = gst_rtp_vorbis_depay_setcaps; - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_rtp_vorbis_depay_sink_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_rtp_vorbis_depay_src_template)); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_vorbis_depay_sink_template); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_vorbis_depay_src_template); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "RTP Vorbis depayloader", "Codec/Depayloader/Network/RTP", "Extracts Vorbis Audio from RTP packets (RFC 5215)", "Wim Taymans "); @@ -112,26 +113,14 @@ gst_rtp_vorbis_depay_init (GstRtpVorbisDepay * rtpvorbisdepay) static void free_config (GstRtpVorbisConfig * conf) { - GList *headers; - - for (headers = conf->headers; headers; headers = g_list_next (headers)) { - GstBuffer *header = GST_BUFFER_CAST (headers->data); - - gst_buffer_unref (header); - } - g_list_free (conf->headers); + g_list_free_full (conf->headers, (GDestroyNotify) gst_buffer_unref); g_free (conf); } static void free_indents (GstRtpVorbisDepay * rtpvorbisdepay) { - GList *walk; - - for (walk = rtpvorbisdepay->configs; walk; walk = g_list_next (walk)) { - free_config ((GstRtpVorbisConfig *) walk->data); - } - g_list_free (rtpvorbisdepay->configs); + g_list_free_full (rtpvorbisdepay->configs, (GDestroyNotify) free_config); rtpvorbisdepay->configs = NULL; } @@ -145,6 +134,22 @@ gst_rtp_vorbis_depay_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static gboolean +gst_rtp_vorbis_depay_has_ident (GstRtpVorbisDepay * rtpvorbisdepay, + guint32 ident) +{ + GList *walk; + + for (walk = rtpvorbisdepay->configs; walk; walk = g_list_next (walk)) { + GstRtpVorbisConfig *conf = (GstRtpVorbisConfig *) walk->data; + + if (conf->ident == ident) + return TRUE; + } + + return FALSE; +} + /* takes ownership of confbuf */ static gboolean gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, @@ -152,12 +157,15 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, { GstBuffer *buf; guint32 num_headers; - guint8 *data, *bdata; + GstMapInfo map; + guint8 *data; gsize size; guint offset; gint i, j; - bdata = data = gst_buffer_map (confbuf, &size, NULL, GST_MAP_READ); + gst_buffer_map (confbuf, &map, GST_MAP_READ); + data = map.data; + size = map.size; GST_DEBUG_OBJECT (rtpvorbisdepay, "config size %" G_GSIZE_FORMAT, size); @@ -227,7 +235,8 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, offset += 6; GST_DEBUG_OBJECT (rtpvorbisdepay, - "header %d, ident 0x%08x, length %u, left %u", i, ident, length, size); + "header %d, ident 0x%08x, length %u, left %" G_GSIZE_FORMAT, i, ident, + length, size); /* FIXME check if we already got this ident */ @@ -235,6 +244,13 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, if (size < length && size + 1 != length) goto too_small; + if (gst_rtp_vorbis_depay_has_ident (rtpvorbisdepay, ident)) { + size -= length; + data += length; + offset += length; + continue; + } + /* read header sizes we read 2 sizes, the third size (for which we allocate * space) must be derived from the total packed header length. */ h_sizes = g_newa (guint, n_headers + 1); @@ -285,7 +301,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, GST_DEBUG_OBJECT (rtpvorbisdepay, "reading header %d, size %u", j, h_size); - buf = gst_buffer_copy_region (confbuf, GST_BUFFER_COPY_MEMORY, offset, + buf = gst_buffer_copy_region (confbuf, GST_BUFFER_COPY_ALL, offset, h_size); conf->headers = g_list_append (conf->headers, buf); offset += h_size; @@ -294,7 +310,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, rtpvorbisdepay->configs = g_list_append (rtpvorbisdepay->configs, conf); } - gst_buffer_unmap (confbuf, bdata, -1); + gst_buffer_unmap (confbuf, &map); gst_buffer_unref (confbuf); return TRUE; @@ -303,7 +319,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, too_small: { GST_DEBUG_OBJECT (rtpvorbisdepay, "configuration too small"); - gst_buffer_unmap (confbuf, bdata, -1); + gst_buffer_unmap (confbuf, &map); gst_buffer_unref (confbuf); return FALSE; } @@ -315,29 +331,29 @@ gst_rtp_vorbis_depay_parse_inband_configuration (GstRtpVorbisDepay * guint length) { GstBuffer *confbuf; - guint8 *conf; + GstMapInfo map; if (G_UNLIKELY (size < 4)) return FALSE; /* transform inline to out-of-band and parse that one */ confbuf = gst_buffer_new_and_alloc (size + 9); - conf = gst_buffer_map (confbuf, NULL, NULL, -1); + gst_buffer_map (confbuf, &map, GST_MAP_WRITE); /* 1 header */ - GST_WRITE_UINT32_BE (conf, 1); + GST_WRITE_UINT32_BE (map.data, 1); /* write Ident */ - GST_WRITE_UINT24_BE (conf + 4, ident); + GST_WRITE_UINT24_BE (map.data + 4, ident); /* write sort-of-length */ - GST_WRITE_UINT16_BE (conf + 7, length); + GST_WRITE_UINT16_BE (map.data + 7, length); /* copy remainder */ - memcpy (conf + 9, configuration, size); - gst_buffer_unmap (confbuf, conf, -1); + memcpy (map.data + 9, configuration, size); + gst_buffer_unmap (confbuf, &map); return gst_rtp_vorbis_depay_parse_configuration (rtpvorbisdepay, confbuf); } static gboolean -gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) +gst_rtp_vorbis_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstStructure *structure; GstRtpVorbisDepay *rtpvorbisdepay; @@ -365,8 +381,8 @@ gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) data = g_base64_decode (configuration, &size); confbuf = gst_buffer_new (); - gst_buffer_take_memory (confbuf, -1, - gst_memory_new_wrapped (0, data, g_free, size, 0, size)); + gst_buffer_append_memory (confbuf, + gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); if (!gst_rtp_vorbis_depay_parse_configuration (rtpvorbisdepay, confbuf)) goto invalid_configuration; } else { @@ -377,7 +393,7 @@ gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) depayload->clock_rate = clock_rate; /* set caps on pad and on header */ - srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL); + srccaps = gst_caps_new_empty_simple ("audio/x-vorbis"); res = gst_pad_set_caps (depayload->srcpad, srccaps); gst_caps_unref (srccaps); @@ -417,7 +433,7 @@ gst_rtp_vorbis_depay_switch_codebook (GstRtpVorbisDepay * rtpvorbisdepay, GstBuffer *header = GST_BUFFER_CAST (headers->data); gst_buffer_ref (header); - gst_base_rtp_depayload_push (GST_BASE_RTP_DEPAYLOAD (rtpvorbisdepay), + gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpvorbisdepay), header); } /* remember the current config */ @@ -433,23 +449,23 @@ gst_rtp_vorbis_depay_switch_codebook (GstRtpVorbisDepay * rtpvorbisdepay, } static GstBuffer * -gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) +gst_rtp_vorbis_depay_process (GstRTPBaseDepayload * depayload, + GstRTPBuffer * rtp) { GstRtpVorbisDepay *rtpvorbisdepay; GstBuffer *outbuf; GstFlowReturn ret; gint payload_len; - guint8 *payload, *to_free = NULL; - guint32 timestamp; + GstBuffer *payload_buffer = NULL; + guint8 *payload; + GstMapInfo map; guint32 header, ident; guint8 F, VDT, packets; - GstRTPBuffer rtp; + guint length; rtpvorbisdepay = GST_RTP_VORBIS_DEPAY (depayload); - gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); - - payload_len = gst_rtp_buffer_get_payload_len (&rtp); + payload_len = gst_rtp_buffer_get_payload_len (rtp); GST_DEBUG_OBJECT (depayload, "got RTP packet of size %d", payload_len); @@ -457,8 +473,7 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) if (G_UNLIKELY (payload_len < 4)) goto packet_short; - payload = gst_rtp_buffer_get_payload (&rtp); - + payload = gst_rtp_buffer_get_payload (rtp); header = GST_READ_UINT32_BE (payload); /* * 0 1 2 3 @@ -500,17 +515,12 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } } - /* skip header */ - payload += 4; - payload_len -= 4; - GST_DEBUG_OBJECT (depayload, "ident: %u, F: %d, VDT: %d, packets: %d", ident, F, VDT, packets); /* fragmented packets, assemble */ if (F != 0) { GstBuffer *vdata; - guint headerskip; if (F == 1) { /* if we start a packet, clear adapter and start assembling. */ @@ -522,10 +532,8 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) if (!rtpvorbisdepay->assembling) goto no_output; - /* first assembled packet, reuse 2 bytes to store the length */ - headerskip = (F == 1 ? 4 : 6); /* skip header and length. */ - vdata = gst_rtp_buffer_get_payload_subbuffer (&rtp, headerskip, -1); + vdata = gst_rtp_buffer_get_payload_subbuffer (rtp, 6, -1); GST_DEBUG_OBJECT (depayload, "assemble vorbis packet"); gst_adapter_push (rtpvorbisdepay->adapter, vdata); @@ -535,16 +543,19 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) goto no_output; /* construct assembled buffer */ - payload_len = gst_adapter_available (rtpvorbisdepay->adapter); - payload = gst_adapter_take (rtpvorbisdepay->adapter, payload_len); - /* fix the length */ - payload[0] = ((payload_len - 2) >> 8) & 0xff; - payload[1] = (payload_len - 2) & 0xff; - to_free = payload; + length = gst_adapter_available (rtpvorbisdepay->adapter); + payload_buffer = gst_adapter_take_buffer (rtpvorbisdepay->adapter, length); + } else { + payload_buffer = gst_rtp_buffer_get_payload_subbuffer (rtp, 4, -1); + length = 0; } GST_DEBUG_OBJECT (depayload, "assemble done"); + gst_buffer_map (payload_buffer, &map, GST_MAP_READ); + payload = map.data; + payload_len = map.size; + /* we not assembling anymore now */ rtpvorbisdepay->assembling = FALSE; gst_adapter_clear (rtpvorbisdepay->adapter); @@ -564,14 +575,16 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) * .. vorbis data | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* */ - timestamp = gst_rtp_buffer_get_timestamp (&rtp); - while (payload_len > 2) { - guint16 length; - - length = GST_READ_UINT16_BE (payload); - payload += 2; - payload_len -= 2; + /* If length is not 0, we have a reassembled packet for which we + * calculated the length already and don't have to skip over the + * length field anymore + */ + if (length == 0) { + length = GST_READ_UINT16_BE (payload); + payload += 2; + payload_len -= 2; + } GST_DEBUG_OBJECT (depayload, "read length %u, avail: %d", length, payload_len); @@ -590,75 +603,59 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } /* create buffer for packet */ - if (G_UNLIKELY (to_free)) { - outbuf = gst_buffer_new (); - gst_buffer_take_memory (outbuf, -1, - gst_memory_new_wrapped (0, to_free, g_free, - (payload - to_free) + length, payload - to_free, length)); - to_free = NULL; - } else { - guint8 *data; - - outbuf = gst_buffer_new_and_alloc (length); - data = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE); - memcpy (data, payload, length); - gst_buffer_unmap (outbuf, data, -1); - } + outbuf = + gst_buffer_copy_region (payload_buffer, GST_BUFFER_COPY_ALL, + payload - map.data, length); payload += length; payload_len -= length; + /* make sure to read next length */ + length = 0; - if (timestamp != -1) - /* push with timestamp of the last packet, which is the same timestamp that - * should apply to the first assembled packet. */ - ret = gst_base_rtp_depayload_push_ts (depayload, timestamp, outbuf); - else - ret = gst_base_rtp_depayload_push (depayload, outbuf); - + ret = gst_rtp_base_depayload_push (depayload, outbuf); if (ret != GST_FLOW_OK) break; - - /* make sure we don't set a timestamp on next buffers */ - timestamp = -1; } - g_free (to_free); - - gst_rtp_buffer_unmap (&rtp); + gst_buffer_unmap (payload_buffer, &map); + gst_buffer_unref (payload_buffer); return NULL; no_output: { - gst_rtp_buffer_unmap (&rtp); + if (payload_buffer) { + gst_buffer_unmap (payload_buffer, &map); + gst_buffer_unref (payload_buffer); + } return NULL; } - /* ERORRS */ + /* ERRORS */ switch_failed: { GST_ELEMENT_WARNING (rtpvorbisdepay, STREAM, DECODE, (NULL), ("Could not switch codebooks")); - gst_rtp_buffer_unmap (&rtp); return NULL; } packet_short: { GST_ELEMENT_WARNING (rtpvorbisdepay, STREAM, DECODE, (NULL), ("Packet was too short (%d < 4)", payload_len)); - gst_rtp_buffer_unmap (&rtp); return NULL; } ignore_reserved: { GST_WARNING_OBJECT (rtpvorbisdepay, "reserved VDT ignored"); - gst_rtp_buffer_unmap (&rtp); return NULL; } length_short: { GST_ELEMENT_WARNING (rtpvorbisdepay, STREAM, DECODE, (NULL), ("Packet contains invalid data")); - gst_rtp_buffer_unmap (&rtp); + if (payload_buffer) { + gst_buffer_unmap (payload_buffer, &map); + gst_buffer_unref (payload_buffer); + } return NULL; } invalid_configuration: @@ -666,7 +663,10 @@ invalid_configuration: /* fatal, as we otherwise risk carrying on without output */ GST_ELEMENT_ERROR (rtpvorbisdepay, STREAM, DECODE, (NULL), ("Packet contains invalid configuration")); - gst_rtp_buffer_unmap (&rtp); + if (payload_buffer) { + gst_buffer_unmap (payload_buffer, &map); + gst_buffer_unref (payload_buffer); + } return NULL; } }