*
* 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
#include <string.h>
#include <gst/rtp/gstrtpbuffer.h>
+#include <gst/audio/audio.h>
#include "gstrtpmp4apay.h"
+#include "gstrtputils.h"
GST_DEBUG_CATEGORY_STATIC (rtpmp4apay_debug);
#define GST_CAT_DEFAULT (rtpmp4apay_debug)
payload, GstBuffer * buffer);
#define gst_rtp_mp4a_pay_parent_class parent_class
-G_DEFINE_TYPE (GstRtpMP4APay, gst_rtp_mp4a_pay, GST_TYPE_RTP_BASE_PAYLOAD)
+G_DEFINE_TYPE (GstRtpMP4APay, gst_rtp_mp4a_pay, GST_TYPE_RTP_BASE_PAYLOAD);
- static void gst_rtp_mp4a_pay_class_init (GstRtpMP4APayClass * klass)
+static void
+gst_rtp_mp4a_pay_class_init (GstRtpMP4APayClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gstrtpbasepayload_class->set_caps = gst_rtp_mp4a_pay_setcaps;
gstrtpbasepayload_class->handle_buffer = gst_rtp_mp4a_pay_handle_buffer;
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_rtp_mp4a_pay_src_template));
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_rtp_mp4a_pay_sink_template));
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &gst_rtp_mp4a_pay_src_template);
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &gst_rtp_mp4a_pay_sink_template);
- gst_element_class_set_details_simple (gstelement_class,
+ gst_element_class_set_static_metadata (gstelement_class,
"RTP MPEG4 audio payloader", "Codec/Payloader/Network/RTP",
"Payload MPEG4 audio as RTP packets (RFC 3016)",
"Wim Taymans <wim.taymans@gmail.com>");
gst_rtp_mp4a_pay_parse_audio_config (GstRtpMP4APay * rtpmp4apay,
GstBuffer * buffer)
{
+ GstMapInfo map;
guint8 *data;
gsize size;
guint8 objectType;
guint8 samplingIdx;
guint8 channelCfg;
- data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ data = map.data;
+ size = map.size;
if (size < 2)
goto too_short;
"objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType,
samplingIdx, rtpmp4apay->rate, channelCfg);
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return TRUE;
(NULL),
("config string too short, expected 2 bytes, got %" G_GSIZE_FORMAT,
size));
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return FALSE;
}
invalid_object:
{
GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
(NULL), ("invalid object type 0"));
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return FALSE;
}
wrong_freq:
{
GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
(NULL), ("unsupported frequency index %d", samplingIdx));
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return FALSE;
}
wrong_channels:
{
GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
(NULL), ("unsupported number of channels %d, must < 8", channelCfg));
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return FALSE;
}
}
GST_LOG_OBJECT (rtpmp4apay, "got codec_data");
if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) {
GstBuffer *buffer, *cbuffer;
- guint8 *config;
- guint8 *data;
+ GstMapInfo map;
+ GstMapInfo cmap;
guint i;
- gsize size;
buffer = gst_value_get_buffer (codec_data);
GST_LOG_OBJECT (rtpmp4apay, "configuring codec_data");
if (!res)
goto config_failed;
- data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
/* make the StreamMuxConfig, we need 15 bits for the header */
- cbuffer = gst_buffer_new_and_alloc (size + 2);
- config = gst_buffer_map (cbuffer, NULL, NULL, GST_MAP_WRITE);
+ cbuffer = gst_buffer_new_and_alloc (map.size + 2);
+ gst_buffer_map (cbuffer, &cmap, GST_MAP_WRITE);
+
+ memset (cmap.data, 0, map.size + 2);
/* Create StreamMuxConfig according to ISO/IEC 14496-3:
*
* numProgram == 0 (4 bits)
* numLayer == 0 (3 bits)
*/
- config[0] = 0x40;
- config[1] = 0x00;
+ cmap.data[0] = 0x40;
+ cmap.data[1] = 0x00;
/* append the config bits, shifting them 1 bit left */
- for (i = 0; i < size; i++) {
- config[i + 1] |= ((data[i] & 0x80) >> 7);
- config[i + 2] |= ((data[i] & 0x7f) << 1);
+ for (i = 0; i < map.size; i++) {
+ cmap.data[i + 1] |= ((map.data[i] & 0x80) >> 7);
+ cmap.data[i + 2] |= ((map.data[i] & 0x7f) << 1);
}
- gst_buffer_unmap (cbuffer, config, -1);
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (cbuffer, &cmap);
+ gst_buffer_unmap (buffer, &map);
/* now we can configure the buffer */
if (rtpmp4apay->config)
}
}
+#define RTP_HEADER_LEN 12
+
/* we expect buffers as exactly one complete AU
*/
static GstFlowReturn
{
GstRtpMP4APay *rtpmp4apay;
GstFlowReturn ret;
- GstBuffer *outbuf;
- guint count, mtu;
+ GstBufferList *list;
+ guint mtu;
+ guint offset;
gsize size;
- guint8 *data, *bdata;
gboolean fragmented;
GstClockTime timestamp;
rtpmp4apay = GST_RTP_MP4A_PAY (basepayload);
- data = bdata = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
- timestamp = GST_BUFFER_TIMESTAMP (buffer);
+ offset = 0;
+ size = gst_buffer_get_size (buffer);
+
+ timestamp = GST_BUFFER_PTS (buffer);
fragmented = FALSE;
mtu = GST_RTP_BASE_PAYLOAD_MTU (rtpmp4apay);
+ list = gst_buffer_list_new_sized (size / (mtu - RTP_HEADER_LEN) + 1);
+
while (size > 0) {
guint towrite;
- guint8 *payload;
+ GstBuffer *outbuf;
guint payload_len;
guint packet_len;
+ guint header_len;
+ GstBuffer *paybuf;
GstRTPBuffer rtp = { NULL };
- /* this will be the total lenght of the packet */
- packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
-
+ header_len = 0;
if (!fragmented) {
+ guint count;
/* first packet calculate space for the packet including the header */
count = size;
while (count >= 0xff) {
- packet_len++;
+ header_len++;
count -= 0xff;
}
- packet_len++;
+ header_len++;
}
- /* fill one MTU or all available bytes */
+ packet_len = gst_rtp_buffer_calc_packet_len (header_len + size, 0, 0);
towrite = MIN (packet_len, mtu);
-
- /* this is the payload length */
payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0);
+ payload_len -= header_len;
GST_DEBUG_OBJECT (rtpmp4apay,
- "avail %" G_GSIZE_FORMAT ", towrite %d, packet_len %d, payload_len %d",
- size, towrite, packet_len, payload_len);
+ "avail %" G_GSIZE_FORMAT
+ ", header_len %d, packet_len %d, payload_len %d", size, header_len,
+ packet_len, payload_len);
/* create buffer to hold the payload. */
- outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
+ outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload,
+ header_len, 0, 0);
/* copy payload */
gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
- payload = gst_rtp_buffer_get_payload (&rtp);
if (!fragmented) {
+ guint8 *payload = gst_rtp_buffer_get_payload (&rtp);
+ guint count;
+
/* first packet write the header */
count = size;
while (count >= 0xff) {
*payload++ = 0xff;
- payload_len--;
count -= 0xff;
}
*payload++ = count;
- payload_len--;
}
- /* copy data to payload */
- memcpy (payload, data, payload_len);
- data += payload_len;
- size -= payload_len;
-
/* marker only if the packet is complete */
- gst_rtp_buffer_set_marker (&rtp, size == 0);
+ gst_rtp_buffer_set_marker (&rtp, size == payload_len);
gst_rtp_buffer_unmap (&rtp);
- /* copy incomming timestamp (if any) to outgoing buffers */
- GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+ /* create a new buf to hold the payload */
+ paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
+ offset, payload_len);
- ret = gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (rtpmp4apay), outbuf);
+ /* join memory parts */
+ gst_rtp_copy_audio_meta (rtpmp4apay, outbuf, paybuf);
+ outbuf = gst_buffer_append (outbuf, paybuf);
+ gst_buffer_list_add (list, outbuf);
+ offset += payload_len;
+ size -= payload_len;
+
+ /* copy incoming timestamp (if any) to outgoing buffers */
+ GST_BUFFER_PTS (outbuf) = timestamp;
fragmented = TRUE;
}
- gst_buffer_unmap (buffer, bdata, -1);
+ ret =
+ gst_rtp_base_payload_push_list (GST_RTP_BASE_PAYLOAD (rtpmp4apay), list);
+
gst_buffer_unref (buffer);
return ret;