mpegpsmux: port to 0.11
authorTim-Philipp Müller <tim@centricular.net>
Mon, 31 Dec 2012 19:42:03 +0000 (19:42 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Mon, 31 Dec 2012 19:42:03 +0000 (19:42 +0000)
Naive port. Barely tested.

configure.ac
gst/mpegpsmux/mpegpsmux.c
gst/mpegpsmux/mpegpsmux_aac.c
gst/mpegpsmux/mpegpsmux_h264.c
gst/mpegpsmux/psmux.c
gst/mpegpsmux/psmuxstream.c
gst/mpegpsmux/psmuxstream.h

index 34a9d92..3b3a3a4 100644 (file)
@@ -315,7 +315,7 @@ GST_PLUGINS_NONPORTED=" aiff \
  freeverb \
  hdvparse ivfparse jp2kdecimator \
  kate librfb \
- mpegpsmux mve mythtv nsf nuvdemux \
+ mve mythtv nsf nuvdemux \
  patchdetect real \
  sdi stereo tta videofilters \
  videomeasure videosignal vmnc \
index 17f6f36..996550b 100644 (file)
@@ -93,37 +93,20 @@ static void gst_mpegpsmux_set_property (GObject * object, guint prop_id,
 static void gst_mpegpsmux_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static void mpegpsmux_dispose (GObject * object);
+static void mpegpsmux_finalize (GObject * object);
 static gboolean new_packet_cb (guint8 * data, guint len, void *user_data);
-static void release_buffer_cb (guint8 * data, void *user_data);
 
 static gboolean mpegpsdemux_prepare_srcpad (MpegPsMux * mux);
 static GstFlowReturn mpegpsmux_collected (GstCollectPads * pads,
     MpegPsMux * mux);
 static GstPad *mpegpsmux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name);
+    GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
 static void mpegpsmux_release_pad (GstElement * element, GstPad * pad);
 static GstStateChangeReturn mpegpsmux_change_state (GstElement * element,
     GstStateChange transition);
 
-GST_BOILERPLATE (MpegPsMux, mpegpsmux, GstElement, GST_TYPE_ELEMENT);
-
-static void
-mpegpsmux_base_init (gpointer g_class)
-{
-
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&mpegpsmux_sink_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&mpegpsmux_src_factory));
-
-  gst_element_class_set_static_metadata (element_class,
-      "MPEG Program Stream Muxer", "Codec/Muxer",
-      "Multiplexes media streams into an MPEG Program Stream",
-      "Lin YANG <oxcsnicho@gmail.com>");
-}
+#define parent_class mpegpsmux_parent_class
+G_DEFINE_TYPE (MpegPsMux, mpegpsmux, GST_TYPE_ELEMENT);
 
 static void
 mpegpsmux_class_init (MpegPsMuxClass * klass)
@@ -131,9 +114,9 @@ mpegpsmux_class_init (MpegPsMuxClass * klass)
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_mpegpsmux_set_property);
-  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_mpegpsmux_get_property);
-  gobject_class->dispose = mpegpsmux_dispose;
+  gobject_class->set_property = gst_mpegpsmux_set_property;
+  gobject_class->get_property = gst_mpegpsmux_get_property;
+  gobject_class->finalize = mpegpsmux_finalize;
 
   gstelement_class->request_new_pad = mpegpsmux_request_new_pad;
   gstelement_class->release_pad = mpegpsmux_release_pad;
@@ -143,10 +126,20 @@ mpegpsmux_class_init (MpegPsMuxClass * klass)
       g_param_spec_boolean ("aggregate-gops", "Aggregate GOPs",
           "Whether to aggregate GOPs and push them out as buffer lists",
           DEFAULT_AGGREGATE_GOPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&mpegpsmux_sink_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&mpegpsmux_src_factory));
+
+  gst_element_class_set_static_metadata (gstelement_class,
+      "MPEG Program Stream Muxer", "Codec/Muxer",
+      "Multiplexes media streams into an MPEG Program Stream",
+      "Lin YANG <oxcsnicho@gmail.com>");
 }
 
 static void
-mpegpsmux_init (MpegPsMux * mux, MpegPsMuxClass * g_class)
+mpegpsmux_init (MpegPsMux * mux)
 {
   mux->srcpad = gst_pad_new_from_static_template (&mpegpsmux_src_factory,
       "src");
@@ -166,7 +159,7 @@ mpegpsmux_init (MpegPsMux * mux, MpegPsMuxClass * g_class)
 }
 
 static void
-mpegpsmux_dispose (GObject * object)
+mpegpsmux_finalize (GObject * object)
 {
   MpegPsMux *mux = GST_MPEG_PSMUX (object);
 
@@ -184,7 +177,7 @@ mpegpsmux_dispose (GObject * object)
     mux->gop_list = NULL;
   }
 
-  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+  G_OBJECT_CLASS (mpegpsmux_parent_class)->finalize (object);
 }
 
 static void
@@ -219,25 +212,17 @@ gst_mpegpsmux_get_property (GObject * object, guint prop_id,
   }
 }
 
-static void
-release_buffer_cb (guint8 * data, void *user_data)
-{
-  /* release a given buffer. callback func */
-
-  GstBuffer *buf = (GstBuffer *) user_data;
-  gst_buffer_unref (buf);
-}
-
 static GstFlowReturn
 mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad)
 {
   /* Create a steam. Fill in codec specific information */
 
   GstFlowReturn ret = GST_FLOW_ERROR;
-  GstCaps *caps = gst_pad_get_negotiated_caps (pad);
+  GstCaps *caps;
   GstStructure *s;
   gboolean is_video = FALSE;
 
+  caps = gst_pad_get_current_caps (pad);
   if (caps == NULL) {
     GST_DEBUG_OBJECT (pad, "Sink pad caps were not set before pushing");
     return GST_FLOW_NOT_NEGOTIATED;
@@ -266,8 +251,8 @@ mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad)
     value = gst_structure_get_value (s, "codec_data");
     if (value) {
       ps_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value));
-      GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
-          GST_BUFFER_SIZE (ps_data->codec_data));
+      GST_DEBUG_OBJECT (pad, "%" G_GSIZE_FORMAT " bytes of codec data",
+          gst_buffer_get_size (ps_data->codec_data));
       ps_data->prepare_func = mpegpsmux_prepare_h264;
     } else {
       ps_data->codec_data = NULL;
@@ -302,8 +287,8 @@ mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad)
         value = gst_structure_get_value (s, "codec_data");
         if (value) {
           ps_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value));
-          GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
-              GST_BUFFER_SIZE (ps_data->codec_data));
+          GST_DEBUG_OBJECT (pad, "%" G_GSIZE_FORMAT " bytes of codec data",
+              gst_buffer_get_size (ps_data->codec_data));
           ps_data->prepare_func = mpegpsmux_prepare_aac;
         } else {
           ps_data->codec_data = NULL;
@@ -347,8 +332,6 @@ mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad)
     gst_structure_get_int (s, "channels", &ps_data->stream->audio_channels);
     gst_structure_get_int (s, "bitrate", &ps_data->stream->audio_bitrate);
 
-    psmux_stream_set_buffer_release_func (ps_data->stream, release_buffer_cb);
-
     ret = GST_FLOW_OK;
 
     if (is_video && mux->video_stream_id == 0) {
@@ -483,7 +466,7 @@ mpegpsmux_push_gop_list (MpegPsMux * mux)
   g_assert (mux->gop_list != NULL);
 
   GST_DEBUG_OBJECT (mux, "Sending pending GOP of %u buffers",
-      gst_buffer_list_n_groups (mux->gop_list));
+      gst_buffer_list_length (mux->gop_list));
   flow = gst_pad_push_list (mux->srcpad, mux->gop_list);
   mux->gop_list = NULL;
   return flow;
@@ -549,9 +532,9 @@ mpegpsmux_collected (GstCollectPads * pads, MpegPsMux * mux)
         goto done;
     }
 
+    /* FIXME: porting: add DTS */
     /* give the buffer to libpsmux for processing */
-    psmux_stream_add_data (best->stream, GST_BUFFER_DATA (buf),
-        GST_BUFFER_SIZE (buf), buf, pts, -1, keyunit);
+    psmux_stream_add_data (best->stream, buf, pts, -1, keyunit);
 
     best->queued_buf = NULL;
 
@@ -588,9 +571,8 @@ write_fail:
 
 static GstPad *
 mpegpsmux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name)
+    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
 {
-
   MpegPsMux *mux = GST_MPEG_PSMUX (element);
   GstPad *pad = NULL;
   MpegPsPadData *pad_data = NULL;
@@ -652,26 +634,6 @@ mpegpsmux_release_pad (GstElement * element, GstPad * pad)
   gst_collect_pads_remove_pad (mux->collect, pad);
 }
 
-static void
-add_buffer_to_goplist (MpegPsMux * mux, GstBuffer * buf)
-{
-  GstBufferListIterator *it;
-
-  if (mux->gop_list == NULL)
-    mux->gop_list = gst_buffer_list_new ();
-
-  it = gst_buffer_list_iterate (mux->gop_list);
-
-  /* move iterator to end */
-  while (gst_buffer_list_iterator_next_group (it)) {
-    /* .. */
-  }
-
-  gst_buffer_list_iterator_add_group (it);
-  gst_buffer_list_iterator_add (it, buf);
-  gst_buffer_list_iterator_free (it);
-}
-
 static gboolean
 new_packet_cb (guint8 * data, guint len, void *user_data)
 {
@@ -683,18 +645,17 @@ new_packet_cb (guint8 * data, guint len, void *user_data)
   GstFlowReturn ret;
 
   GST_LOG_OBJECT (mux, "Outputting a packet of length %d", len);
-  buf = gst_buffer_new_and_alloc (len);
-  if (G_UNLIKELY (buf == NULL)) {
-    mux->last_flow_ret = GST_FLOW_ERROR;
-    return FALSE;
-  }
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));
 
-  memcpy (GST_BUFFER_DATA (buf), data, len);
+  data = g_memdup (data, len);
+  buf = gst_buffer_new_wrapped (data, len);
+
   GST_BUFFER_TIMESTAMP (buf) = mux->last_ts;
 
   if (mux->aggregate_gops) {
-    add_buffer_to_goplist (mux, buf);
+    if (mux->gop_list == NULL)
+      mux->gop_list = gst_buffer_list_new ();
+
+    gst_buffer_list_add (mux->gop_list, buf);
     return TRUE;
   }
 
@@ -708,22 +669,17 @@ new_packet_cb (guint8 * data, guint len, void *user_data)
   return TRUE;
 }
 
+/* prepare the source pad for output */
 static gboolean
 mpegpsdemux_prepare_srcpad (MpegPsMux * mux)
 {
+  GstSegment segment;
   GValue val = { 0, };
   GList *headers, *l;
+  GstCaps *caps;
 
-  /* prepare the source pad for output */
-
-  GstEvent *new_seg =
-      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
-  GstCaps *caps = gst_caps_new_simple ("video/mpeg",
-      "mpegversion", G_TYPE_INT, 2,
-      "systemstream", G_TYPE_BOOLEAN, TRUE,
-      NULL);
-
-/*      gst_static_pad_template_get_caps (&mpegpsmux_src_factory); */
+  caps = gst_caps_new_simple ("video/mpeg",
+      "mpegversion", G_TYPE_INT, 2, "systemstream", G_TYPE_BOOLEAN, TRUE, NULL);
 
   headers = psmux_get_stream_headers (mux->psmux);
   g_value_init (&val, GST_TYPE_ARRAY);
@@ -740,13 +696,12 @@ mpegpsdemux_prepare_srcpad (MpegPsMux * mux)
   g_value_unset (&val);
   g_list_free (headers);
 
-  /* Set caps on src pad from our template and push new segment */
-  gst_pad_set_caps (mux->srcpad, caps);
+  /* Set caps on src pad and push new segment */
+  gst_pad_push_event (mux->srcpad, gst_event_new_caps (caps));
+  gst_caps_unref (caps);
 
-  if (!gst_pad_push_event (mux->srcpad, new_seg)) {
-    GST_WARNING_OBJECT (mux, "New segment event was not handled");
-    return FALSE;
-  }
+  gst_segment_init (&segment, GST_FORMAT_BYTES);
+  gst_pad_push_event (mux->srcpad, gst_event_new_segment (&segment));
 
   return TRUE;
 }
index 177d3e5..3f7b0cb 100644 (file)
@@ -95,24 +95,28 @@ GST_DEBUG_CATEGORY_EXTERN (mpegpsmux_debug);
 GstBuffer *
 mpegpsmux_prepare_aac (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux)
 {
-  guint8 adts_header[7] = { 0, };
-  GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 7);
-  gsize out_offset = 0;
+  GstBuffer *out_buf;
+  GstMemory *mem;
+  gsize out_size;
+  guint8 *adts_header, codec_data[2];
   guint8 rate_idx = 0, channels = 0, obj_type = 0;
 
   GST_DEBUG_OBJECT (mux, "Preparing AAC buffer for output");
 
-  /* We want the same metadata */
-  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);
+  adts_header = g_malloc0 (7);
+
+  /* We want the same data and metadata, and then prepend some bytes */
+  out_buf = gst_buffer_copy (buf);
+  out_size = gst_buffer_get_size (buf) + 7;
+
+  gst_buffer_extract (data->codec_data, 0, codec_data, 2);
 
   /* Generate ADTS header */
-  obj_type = (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data)) & 0xC) >> 2;
+  obj_type = (codec_data[0] & 0xC) >> 2;
   obj_type++;
-  rate_idx = (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data)) & 0x3) << 1;
-  rate_idx |=
-      (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + 1) & 0x80) >> 7;
-  channels =
-      (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + 1) & 0x78) >> 3;
+  rate_idx = (codec_data[0] & 0x3) << 1;
+  rate_idx |= (codec_data[1] & 0x80) >> 7;
+  channels = (codec_data[1] & 0x78) >> 3;
   GST_DEBUG_OBJECT (mux, "Rate index %u, channels %u, object type %u", rate_idx,
       channels, obj_type);
   /* Sync point over a full byte */
@@ -129,24 +133,20 @@ mpegpsmux_prepare_aac (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux)
   /* channels continued over next 2 bits + 4 bits at zero */
   adts_header[3] = (channels & 0x3) << 6;
   /* frame size over last 2 bits */
-  adts_header[3] |= (GST_BUFFER_SIZE (out_buf) & 0x1800) >> 11;
+  adts_header[3] |= (gst_buffer_get_size (out_buf) & 0x1800) >> 11;
   /* frame size continued over full byte */
-  adts_header[4] = (GST_BUFFER_SIZE (out_buf) & 0x1FF8) >> 3;
+  adts_header[4] = (out_size & 0x1FF8) >> 3;
   /* frame size continued first 3 bits */
-  adts_header[5] = (GST_BUFFER_SIZE (out_buf) & 0x7) << 5;
+  adts_header[5] = (out_size & 0x7) << 5;
   /* buffer fullness (0x7FF for VBR) over 5 last bits */
   adts_header[5] |= 0x1F;
   /* buffer fullness (0x7FF for VBR) continued over 6 first bits + 2 zeros for
    * number of raw data blocks */
   adts_header[6] = 0xFC;
 
-  /* Insert ADTS header */
-  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, adts_header, 7);
-  out_offset += 7;
-
-  /* Now copy complete frame */
-  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, GST_BUFFER_DATA (buf),
-      GST_BUFFER_SIZE (buf));
+  /* Prepend ADTS header */
+  mem = gst_memory_new_wrapped (0, adts_header, 7, 0, 7, adts_header, g_free);
+  gst_buffer_prepend_memory (out_buf, mem);
 
   return out_buf;
 }
index d3d5f84..35189bb 100644 (file)
@@ -87,6 +87,7 @@
 #endif
 
 #include "mpegpsmux_h264.h"
+#include <gst/base/gstbytewriter.h>
 #include <string.h>
 
 GST_DEBUG_CATEGORY_EXTERN (mpegpsmux_debug);
@@ -95,32 +96,37 @@ GST_DEBUG_CATEGORY_EXTERN (mpegpsmux_debug);
 GstBuffer *
 mpegpsmux_prepare_h264 (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux)
 {
+  GstByteWriter bw;
+  GstMapInfo codec_data, map;
   guint8 nal_length_size = 0;
-  guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
-  GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2);
-  gint offset = 4, i = 0, nb_sps = 0, nb_pps = 0;
-  gsize out_offset = 0, in_offset = 0;
+  GstBuffer *out_buf;
+  guint8 nb_sps = 0, nb_pps = 0;
+  gint offset = 4, i = 0;
+  gsize in_offset;
 
   GST_DEBUG_OBJECT (mux, "Preparing H264 buffer for output");
 
-  /* We want the same metadata */
-  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);
+  /* FIXME: are we prepending SPS/PPS in front of every single buffer?
+   * (should only be in front of keyframes really, if at all) */
+  /* FIXME: create a byte-stream version of SPS/PPS once in set_caps */
+  if (!gst_buffer_map (data->codec_data, &codec_data, GST_MAP_READ))
+    return NULL;
+
+  gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buf) * 2, FALSE);
 
   /* Get NAL length size */
-  nal_length_size =
-      (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x03) + 1;
+  nal_length_size = (codec_data.data[offset] & 0x03) + 1;
   GST_LOG_OBJECT (mux, "NAL length will be coded on %u bytes", nal_length_size);
   offset++;
 
   /* Generate SPS */
-  nb_sps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x1f;
+  nb_sps = codec_data.data[offset] & 0x1f;
   GST_DEBUG_OBJECT (mux, "we have %d Sequence Parameter Set", nb_sps);
   offset++;
 
   /* For each SPS */
   for (i = 0; i < nb_sps; i++) {
-    guint16 sps_size =
-        GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset);
+    guint16 sps_size = GST_READ_UINT16_BE (codec_data.data + offset);
 
     GST_LOG_OBJECT (mux, "Sequence Parameter Set is %d bytes", sps_size);
 
@@ -128,24 +134,21 @@ mpegpsmux_prepare_h264 (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux)
     offset += 2;
 
     /* Fake a start code */
-    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
-    out_offset += 4;
+    gst_byte_writer_put_uint32_be (&bw, 0x00000001);
+
     /* Now push the SPS */
-    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
-        GST_BUFFER_DATA (data->codec_data) + offset, sps_size);
+    gst_byte_writer_put_data (&bw, codec_data.data + offset, sps_size);
 
-    out_offset += sps_size;
     offset += sps_size;
   }
 
-  nb_pps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset);
+  nb_pps = codec_data.data[offset];
   GST_LOG_OBJECT (mux, "we have %d Picture Parameter Set", nb_sps);
   offset++;
 
   /* For each PPS */
   for (i = 0; i < nb_pps; i++) {
-    gint pps_size =
-        GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset);
+    gint pps_size = GST_READ_UINT16_BE (codec_data.data + offset);
 
     GST_LOG_OBJECT (mux, "Picture Parameter Set is %d bytes", pps_size);
 
@@ -153,47 +156,52 @@ mpegpsmux_prepare_h264 (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux)
     offset += 2;
 
     /* Fake a start code */
-    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
-    out_offset += 4;
+    gst_byte_writer_put_uint32_be (&bw, 0x00000001);
+
     /* Now push the PPS */
-    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
-        GST_BUFFER_DATA (data->codec_data) + offset, pps_size);
+    gst_byte_writer_put_data (&bw, codec_data.data + offset, pps_size);
 
-    out_offset += pps_size;
     offset += pps_size;
   }
 
-  while (in_offset < GST_BUFFER_SIZE (buf) &&
-      out_offset < GST_BUFFER_SIZE (out_buf) - 4) {
+  gst_buffer_unmap (data->codec_data, &codec_data);
+
+  if (!gst_buffer_map (buf, &map, GST_MAP_READ))
+    return NULL;
+
+  /* now process NALs and change them to byte-stream format */
+  in_offset = 0;
+  while (in_offset < map.size) {
     guint32 nal_size = 0;
 
     switch (nal_length_size) {
       case 1:
-        nal_size = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + in_offset);
+        nal_size = GST_READ_UINT8 (map.data + in_offset);
         break;
       case 2:
-        nal_size = GST_READ_UINT16_BE (GST_BUFFER_DATA (buf) + in_offset);
+        nal_size = GST_READ_UINT16_BE (map.data + in_offset);
         break;
       case 4:
-        nal_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + in_offset);
+        nal_size = GST_READ_UINT32_BE (map.data + in_offset);
         break;
       default:
         GST_WARNING_OBJECT (mux, "unsupported NAL length size %u",
             nal_length_size);
+        break;
     }
     in_offset += nal_length_size;
 
     /* Generate an Elementary stream buffer by inserting a startcode */
-    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
-    out_offset += 4;
-    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
-        GST_BUFFER_DATA (buf) + in_offset,
-        MIN (nal_size, GST_BUFFER_SIZE (out_buf) - out_offset));
+    gst_byte_writer_put_uint32_be (&bw, 0x00000001);
+    gst_byte_writer_put_data (&bw, map.data + in_offset,
+        MIN (nal_size, map.size - in_offset));
     in_offset += nal_size;
-    out_offset += nal_size;
   }
 
-  GST_BUFFER_SIZE (out_buf) = out_offset;
+  out_buf = gst_byte_writer_reset_and_get_buffer (&bw);
+
+  /* We want the same metadata */
+  gst_buffer_copy_into (out_buf, buf, GST_BUFFER_COPY_METADATA, 0, 0);
 
   return out_buf;
 }
index 7e757a4..fbe3fe5 100644 (file)
@@ -341,20 +341,19 @@ psmux_write_pack_header (PsMux * mux)
 static void
 psmux_ensure_system_header (PsMux * mux)
 {
-  GstBuffer *buf;
   bits_buffer_t bw;
   guint len = 12 + (mux->nb_streams +
       (mux->nb_private_streams > 1 ? mux->nb_private_streams - 1 : 0)) * 3;
   GList *cur;
   gboolean private_hit = FALSE;
+  guint8 *data;
 
   if (mux->sys_header != NULL)
     return;
 
-  buf = gst_buffer_new_and_alloc (len);
+  data = g_malloc (len);
 
-  /* system_header_start_code */
-  bits_initwrite (&bw, len, GST_BUFFER_DATA (buf));
+  bits_initwrite (&bw, len, data);
 
   /* system_header start code */
   bits_write (&bw, 24, PSMUX_START_CODE_PREFIX);
@@ -374,8 +373,7 @@ psmux_ensure_system_header (PsMux * mux)
   bits_write (&bw, 1, 0);       /* packet_rate_restriction_flag */
   bits_write (&bw, 7, 0x7f);    /* reserved_bits */
 
-  for (cur = g_list_first (mux->streams), private_hit = FALSE; cur != NULL;
-      cur = g_list_next (cur)) {
+  for (cur = mux->streams, private_hit = FALSE; cur != NULL; cur = cur->next) {
     PsMuxStream *stream = (PsMuxStream *) cur->data;
 
     if (private_hit && stream->stream_id == PSMUX_EXTENDED_STREAM)
@@ -390,19 +388,22 @@ psmux_ensure_system_header (PsMux * mux)
       private_hit = TRUE;
   }
 
-  GST_MEMDUMP ("System Header", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+  GST_MEMDUMP ("System Header", data, len);
 
-  mux->sys_header = buf;
+  mux->sys_header = gst_buffer_new_wrapped (data, len);
 }
 
 static gboolean
 psmux_write_system_header (PsMux * mux)
 {
+  GstMapInfo map;
+
   psmux_ensure_system_header (mux);
 
-  memcpy (mux->packet_buf, GST_BUFFER_DATA (mux->sys_header),
-      GST_BUFFER_SIZE (mux->sys_header));
-  mux->packet_bytes_written = GST_BUFFER_SIZE (mux->sys_header);
+  gst_buffer_map (mux->sys_header, &map, GST_MAP_READ);
+  memcpy (mux->packet_buf, map.data, map.size);
+  mux->packet_bytes_written = map.size;
+  gst_buffer_unmap (mux->sys_header, &map);
 
   return psmux_packet_out (mux);
 }
@@ -410,19 +411,19 @@ psmux_write_system_header (PsMux * mux)
 static void
 psmux_ensure_program_stream_map (PsMux * mux)
 {
-  GstBuffer *buf;
   gint psm_size = 16, es_map_size = 0;
   bits_buffer_t bw;
   GList *cur;
   guint16 len;
   guint8 *pos;
+  guint8 *data;
 
   if (mux->psm != NULL)
     return;
 
   /* pre-write the descriptor loop */
   pos = mux->es_info_buf;
-  for (cur = g_list_first (mux->streams); cur != NULL; cur = g_list_next (cur)) {
+  for (cur = mux->streams; cur != NULL; cur = cur->next) {
     PsMuxStream *stream = (PsMuxStream *) cur->data;
     len = 0;
 
@@ -442,9 +443,9 @@ psmux_ensure_program_stream_map (PsMux * mux)
 
   psm_size += es_map_size;
 
-  buf = gst_buffer_new_and_alloc (psm_size);
+  data = g_malloc (psm_size);
 
-  bits_initwrite (&bw, psm_size, GST_BUFFER_DATA (buf));
+  bits_initwrite (&bw, psm_size, data);
 
   /* psm start code */
   bits_write (&bw, 24, PSMUX_START_CODE_PREFIX);
@@ -471,20 +472,22 @@ psmux_ensure_program_stream_map (PsMux * mux)
     psmux_put32 (&pos, crc);
   }
 
-  GST_MEMDUMP ("Program Stream Map", GST_BUFFER_DATA (buf),
-      GST_BUFFER_SIZE (buf));
+  GST_MEMDUMP ("Program Stream Map", data, psm_size);
 
-  mux->psm = buf;
+  mux->psm = gst_buffer_new_wrapped (data, psm_size);
 }
 
 static gboolean
 psmux_write_program_stream_map (PsMux * mux)
 {
+  GstMapInfo map;
+
   psmux_ensure_program_stream_map (mux);
 
-  memcpy (mux->packet_buf, GST_BUFFER_DATA (mux->psm),
-      GST_BUFFER_SIZE (mux->psm));
-  mux->packet_bytes_written = GST_BUFFER_SIZE (mux->psm);
+  gst_buffer_map (mux->psm, &map, GST_MAP_READ);
+  memcpy (mux->packet_buf, map.data, map.size);
+  mux->packet_bytes_written = map.size;
+  gst_buffer_unmap (mux->psm, &map);
 
   return psmux_packet_out (mux);
 }
index 68c39e3..ce66b2f 100644 (file)
@@ -174,8 +174,6 @@ psmux_stream_new (PsMux * mux, PsMuxStreamType stream_type)
 
   stream->cur_pes_payload_size = 0;
 
-  stream->buffer_release = NULL;
-
   stream->pts = -1;
   stream->dts = -1;
   stream->last_pts = -1;
@@ -215,31 +213,13 @@ psmux_stream_free (PsMuxStream * stream)
   g_slice_free (PsMuxStream, stream);
 }
 
-/**
- * psmux_stream_set_buffer_release_func:
- * @stream: a #PsMuxStream
- * @func: the new #PsMuxStreamBufferReleaseFunc
- *
- * Set the function that will be called when a a piece of data fed to @stream
- * with psmux_stream_add_data() can be freed. @func will be called with user
- * data as provided with the call to psmux_stream_add_data().
- */
-void
-psmux_stream_set_buffer_release_func (PsMuxStream * stream,
-    PsMuxStreamBufferReleaseFunc func)
-{
-  g_return_if_fail (stream != NULL);
-
-  stream->buffer_release = func;
-}
-
 /* Advance the current packet stream position by len bytes.
  * Mustn't consume more than available in the current packet */
 static void
 psmux_stream_consume (PsMuxStream * stream, guint len)
 {
   g_assert (stream->cur_buffer != NULL);
-  g_assert (len <= stream->cur_buffer->size - stream->cur_buffer_consumed);
+  g_assert (len <= stream->cur_buffer->map.size - stream->cur_buffer_consumed);
 
   stream->cur_buffer_consumed += len;
   stream->bytes_avail -= len;
@@ -250,15 +230,12 @@ psmux_stream_consume (PsMuxStream * stream, guint len)
   if (stream->cur_buffer->pts != -1)
     stream->last_pts = stream->cur_buffer->pts;
 
-  if (stream->cur_buffer_consumed == stream->cur_buffer->size) {
+  if (stream->cur_buffer_consumed == stream->cur_buffer->map.size) {
     /* Current packet is completed, move along */
     stream->buffers = g_list_delete_link (stream->buffers, stream->buffers);
 
-    if (stream->buffer_release) {
-      stream->buffer_release (stream->cur_buffer->data,
-          stream->cur_buffer->user_data);
-    }
-
+    gst_buffer_unmap (stream->cur_buffer->buf, &stream->cur_buffer->map);
+    gst_buffer_unref (stream->cur_buffer->buf);
     g_slice_free (PsMuxStreamBuffer, stream->cur_buffer);
     stream->cur_buffer = NULL;
   }
@@ -346,8 +323,8 @@ psmux_stream_get_data (PsMuxStream * stream, guint8 * buf, guint len)
     }
 
     /* Take as much as we can from the current buffer */
-    avail = stream->cur_buffer->size - stream->cur_buffer_consumed;
-    cur = stream->cur_buffer->data + stream->cur_buffer_consumed;
+    avail = stream->cur_buffer->map.size - stream->cur_buffer_consumed;
+    cur = stream->cur_buffer->map.data + stream->cur_buffer_consumed;
     if (avail < w) {
       memcpy (buf, cur, avail);
       psmux_stream_consume (stream, avail);
@@ -417,7 +394,7 @@ psmux_stream_find_pts_dts_within (PsMuxStream * stream, guint bound,
     /* FIXME: This isn't quite correct - if the 'bound' is within this
      * buffer, we don't know if the timestamp is before or after the split
      * so we shouldn't return it */
-    if (bound <= curbuf->size) {
+    if (bound <= curbuf->map.size) {
       *pts = curbuf->pts;
       *dts = curbuf->dts;
       return;
@@ -430,7 +407,7 @@ psmux_stream_find_pts_dts_within (PsMuxStream * stream, guint bound,
       return;
     }
 
-    bound -= curbuf->size;
+    bound -= curbuf->map.size;
   }
 }
 
@@ -498,9 +475,7 @@ psmux_stream_write_pes_header (PsMuxStream * stream, guint8 * data)
 /**
  * psmux_stream_add_data:
  * @stream: a #PsMuxStream
- * @data: data to add
- * @len: length of @data
- * @user_data: user data to pass to release func
+ * @buffer: (transfer full): buffer with data to add
  * @pts: PTS of access unit in @data
  * @dts: DTS of access unit in @data
  *
@@ -508,21 +483,25 @@ psmux_stream_write_pes_header (PsMuxStream * stream, guint8 * data)
  * timestamp (against a 90Hz clock) of the first access unit in @data. A
  * timestamp of -1 for @pts or @dts means unknown.
  *
- * @user_data will be passed to the release function as set with
- * psmux_stream_set_buffer_release_func() when @data can be freed.
+ * This function takes ownership of @buffer.
  */
 void
-psmux_stream_add_data (PsMuxStream * stream, guint8 * data, guint len,
-    void *user_data, gint64 pts, gint64 dts, gboolean keyunit)
+psmux_stream_add_data (PsMuxStream * stream, GstBuffer * buffer,
+    gint64 pts, gint64 dts, gboolean keyunit)
 {
   PsMuxStreamBuffer *packet;
 
   g_return_if_fail (stream != NULL);
 
   packet = g_slice_new (PsMuxStreamBuffer);
-  packet->data = data;
-  packet->size = len;
-  packet->user_data = user_data;
+  packet->buf = buffer;
+
+  if (!gst_buffer_map (packet->buf, &packet->map, GST_MAP_READ)) {
+    GST_ERROR ("Failed to map buffer for reading");
+    gst_buffer_unref (packet->buf);
+    g_slice_free (PsMuxStreamBuffer, packet);
+    return;
+  }
 
   packet->keyunit = keyunit;
   packet->pts = pts;
@@ -531,7 +510,8 @@ psmux_stream_add_data (PsMuxStream * stream, guint8 * data, guint len,
   if (stream->bytes_avail == 0)
     stream->last_pts = pts;
 
-  stream->bytes_avail += len;
+  stream->bytes_avail += packet->map.size;
+  /* FIXME: perhaps use GstQueueArray instead? */
   stream->buffers = g_list_append (stream->buffers, packet);
 
 }
index 87c2aca..0b3c139 100644 (file)
@@ -45,7 +45,7 @@
 #ifndef __PSMUXSTREAM_H__
 #define __PSMUXSTREAM_H__
 
-#include <glib.h>
+#include <gst/gst.h>
 
 #include "psmuxcommon.h"
 
@@ -83,16 +83,14 @@ enum PsMuxStreamType { /* Table 2-29 in spec */
 
 struct PsMuxStreamBuffer
 {
-  guint8 *data;
-  guint32 size;
-
   gboolean keyunit;
 
   /* PTS & DTS associated with the contents of this buffer */
   GstClockTime pts;
   GstClockTime dts;
 
-  void *user_data;
+  GstBuffer *buf;
+  GstMapInfo map;
 };
 
 /* PsMuxStream receives elementary streams for parsing.
@@ -116,9 +114,6 @@ struct PsMuxStream{
   guint16 cur_pes_payload_size;
   guint16 pes_bytes_written; /* delete*/
 
-  /* Release function */
-  PsMuxStreamBufferReleaseFunc buffer_release;
-
   /* PTS/DTS to write if the flags in the packet info are set */
   gint64 pts; /* TODO: cur_buffer->pts?*/
   gint64 dts; /* TODO: cur_buffer->dts?*/
@@ -141,14 +136,11 @@ struct PsMuxStream{
 PsMuxStream*    psmux_stream_new                (PsMux * mux, PsMuxStreamType stream_type);
 void           psmux_stream_free               (PsMuxStream *stream);
 
-/* The callback when a buffer is released. Used to unref the buffer in GStreamer */
-void           psmux_stream_set_buffer_release_func    (PsMuxStream *stream,
-                                                                PsMuxStreamBufferReleaseFunc func);
-
 /* Add a new buffer to the pool of available bytes. If pts or dts are not -1, they
  * indicate the PTS or DTS of the first access unit within this packet */
-void           psmux_stream_add_data           (PsMuxStream *stream, guint8 *data, guint len,
-                                                void *user_data, gint64 pts, gint64 dts,
+void           psmux_stream_add_data           (PsMuxStream *stream,
+                                                GstBuffer * buffer,
+                                                gint64 pts, gint64 dts,
                                                 gboolean keyunit);
 
 /* total bytes in buffer */