mpegtsmux: port to 0.11
authorMatej Knopp <matej.knopp@gmail.com>
Thu, 14 Jun 2012 21:49:55 +0000 (14:49 -0700)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Sat, 16 Jun 2012 17:22:35 +0000 (19:22 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=678130

configure.ac
gst/mpegtsmux/Makefile.am
gst/mpegtsmux/mpegtsmux.c
gst/mpegtsmux/mpegtsmux.h
gst/mpegtsmux/mpegtsmux_aac.c
gst/mpegtsmux/mpegtsmux_h264.c [deleted file]
gst/mpegtsmux/mpegtsmux_h264.h [deleted file]
gst/mpegtsmux/tsmux/crc.h
gst/mpegtsmux/tsmux/tsmux.c

index 917b1cd..5120b0f 100644 (file)
@@ -315,7 +315,7 @@ GST_PLUGINS_NONPORTED=" aiff \
  dccp faceoverlay festival \
  fieldanalysis freeverb freeze frei0r \
  hdvparse id3tag inter interlace ivfparse jpegformat jp2kdecimator \
- kate liveadder librfb mpegtsmux \
+ kate liveadder librfb \
  mpegpsmux mve mxf mythtv nsf nuvdemux \
  patchdetect pnm real \
  sdi siren speed subenc stereo tta videofilters \
index a4a9801..3f088b5 100644 (file)
@@ -4,7 +4,6 @@ SUBDIRS = tsmux
 
 libgstmpegtsmux_la_SOURCES = \
        mpegtsmux.c \
-       mpegtsmux_h264.c \
        mpegtsmux_aac.c
 
 libgstmpegtsmux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
@@ -15,5 +14,4 @@ libgstmpegtsmux_la_LIBTOOLFLAGS = --tag=disable-static
 
 noinst_HEADERS = \
        mpegtsmux.h \
-       mpegtsmux_h264.h \
        mpegtsmux_aac.h
index af2117a..0e352b8 100644 (file)
@@ -96,7 +96,6 @@
 
 #include "mpegtsmux.h"
 
-#include "mpegtsmux_h264.h"
 #include "mpegtsmux_aac.h"
 
 GST_DEBUG_CATEGORY (mpegtsmux_debug);
@@ -162,64 +161,83 @@ static gboolean new_packet_m2ts (MpegTsMux * mux, GstBuffer * buf,
     gint64 new_pcr);
 
 static void mpegtsdemux_prepare_srcpad (MpegTsMux * mux);
-static GstFlowReturn mpegtsmux_collected (GstCollectPads2 * pads,
+static GstFlowReturn mpegtsmux_collected (GstCollectPads * pads,
     MpegTsMux * mux);
-static gboolean mpegtsmux_sink_event (GstCollectPads2 * pads,
-    GstCollectData2 * data, GstEvent * event, gpointer user_data);
+static gboolean mpegtsmux_sink_event (GstCollectPads * pads,
+    GstCollectData * data, GstEvent * event, gpointer user_data);
 static GstPad *mpegtsmux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name);
+    GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
 static void mpegtsmux_release_pad (GstElement * element, GstPad * pad);
 static GstStateChangeReturn mpegtsmux_change_state (GstElement * element,
     GstStateChange transition);
 static void mpegtsdemux_set_header_on_caps (MpegTsMux * mux);
-static gboolean mpegtsmux_src_event (GstPad * pad, GstEvent * event);
+static gboolean mpegtsmux_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 
+#if 0
 static void mpegtsmux_set_index (GstElement * element, GstIndex * index);
 static GstIndex *mpegtsmux_get_index (GstElement * element);
 
 static GstFormat pts_format;
 static GstFormat spn_format;
+#endif
 
-GST_BOILERPLATE (MpegTsMux, mpegtsmux, GstElement, GST_TYPE_ELEMENT);
-
-static void
-mpegtsmux_base_init (gpointer g_class)
+typedef struct
 {
+  GstMapInfo map_info;
+  GstBuffer *buffer;
+} StreamData;
 
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_static_pad_template (element_class,
-      &mpegtsmux_sink_factory);
-  gst_element_class_add_static_pad_template (element_class,
-      &mpegtsmux_src_factory);
+G_DEFINE_TYPE (MpegTsMux, mpegtsmux, GST_TYPE_ELEMENT)
 
-  gst_element_class_set_details_simple (element_class,
-      "MPEG Transport Stream Muxer", "Codec/Muxer",
-      "Multiplexes media streams into an MPEG Transport Stream",
-      "Fluendo <contact@fluendo.com>");
+     static StreamData *stream_data_new (GstBuffer * buffer)
+{
+  StreamData *res = g_new (StreamData, 1);
+  res->buffer = buffer;
+  gst_buffer_map (buffer, &(res->map_info), GST_MAP_READ);
+  return res;
+}
 
-  pts_format =
-      gst_format_register ("PTS", "MPEG System Presentation Time Stamp");
-  spn_format = gst_format_register ("SPN", "Source Packet Number");
+static void
+stream_data_free (StreamData * data)
+{
+  if (data) {
+    gst_buffer_unmap (data->buffer, &data->map_info);
+    gst_buffer_unref (data->buffer);
+    g_free (data);
+  }
 }
 
+#define parent_class mpegtsmux_parent_class
+
 static void
 mpegtsmux_class_init (MpegTsMuxClass * klass)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&mpegtsmux_sink_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&mpegtsmux_src_factory));
+
+  gst_element_class_set_details_simple (gstelement_class,
+      "MPEG Transport Stream Muxer", "Codec/Muxer",
+      "Multiplexes media streams into an MPEG Transport Stream",
+      "Fluendo <contact@fluendo.com>");
+
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_mpegtsmux_set_property);
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_mpegtsmux_get_property);
   gobject_class->dispose = mpegtsmux_dispose;
 
-  gstelement_class->request_new_pad =
-      GST_DEBUG_FUNCPTR (mpegtsmux_request_new_pad);
-  gstelement_class->release_pad = GST_DEBUG_FUNCPTR (mpegtsmux_release_pad);
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (mpegtsmux_change_state);
+  gstelement_class->request_new_pad = mpegtsmux_request_new_pad;
+  gstelement_class->release_pad = mpegtsmux_release_pad;
+  gstelement_class->change_state = mpegtsmux_change_state;
 
+#if 0
   gstelement_class->set_index = GST_DEBUG_FUNCPTR (mpegtsmux_set_index);
   gstelement_class->get_index = GST_DEBUG_FUNCPTR (mpegtsmux_get_index);
+#endif
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PROG_MAP,
       g_param_spec_boxed ("prog-map", "Program map",
@@ -253,21 +271,26 @@ mpegtsmux_class_init (MpegTsMuxClass * klass)
 }
 
 static void
-mpegtsmux_init (MpegTsMux * mux, MpegTsMuxClass * g_class)
+mpegtsmux_init (MpegTsMux * mux)
 {
   mux->srcpad =
       gst_pad_new_from_static_template (&mpegtsmux_src_factory, "src");
   gst_pad_use_fixed_caps (mux->srcpad);
-  gst_pad_set_event_function (mux->srcpad, mpegtsmux_src_event);
+  gst_pad_set_event_function (mux->srcpad,
+      GST_DEBUG_FUNCPTR (mpegtsmux_src_event));
   gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
 
-  mux->collect = gst_collect_pads2_new ();
-  gst_collect_pads2_set_function (mux->collect,
-      (GstCollectPads2Function) GST_DEBUG_FUNCPTR (mpegtsmux_collected), mux);
-  gst_collect_pads2_set_event_function (mux->collect,
-      (GstCollectPads2EventFunction) GST_DEBUG_FUNCPTR (mpegtsmux_sink_event),
+  mux->collect = gst_collect_pads_new ();
+  gst_collect_pads_set_function (mux->collect,
+      (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (mpegtsmux_collected), mux);
+
+  gst_collect_pads_set_event_function (mux->collect,
+      (GstCollectPadsEventFunction) GST_DEBUG_FUNCPTR (mpegtsmux_sink_event),
       mux);
 
+  mux->tsmux = tsmux_new ();
+  tsmux_set_write_func (mux->tsmux, new_packet_cb, mux);
+
   mux->adapter = gst_adapter_new ();
   mux->out_adapter = gst_adapter_new ();
 
@@ -286,11 +309,15 @@ static void
 mpegtsmux_pad_reset (MpegTsPadData * pad_data)
 {
   pad_data->pid = 0;
-  pad_data->last_ts = GST_CLOCK_TIME_NONE;
-  pad_data->cur_ts = GST_CLOCK_TIME_NONE;
+  pad_data->last_pts = GST_CLOCK_TIME_NONE;
+  pad_data->last_dts = GST_CLOCK_TIME_NONE;
+  pad_data->cur_pts = GST_CLOCK_TIME_NONE;
+  pad_data->cur_dts = GST_CLOCK_TIME_NONE;
   pad_data->prog_id = -1;
   pad_data->eos = FALSE;
+#if 0
   pad_data->element_index_writer_id = -1;
+#endif
 
   if (pad_data->free_func)
     pad_data->free_func (pad_data->prepare_data);
@@ -325,14 +352,14 @@ mpegtsmux_reset (MpegTsMux * mux, gboolean alloc)
   mux->streamheader_sent = FALSE;
   mux->force_key_unit_event = NULL;
   mux->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
-
+#if 0
   mux->spn_count = 0;
 
   if (mux->element_index) {
     gst_object_unref (mux->element_index);
     mux->element_index = NULL;
   }
-
+#endif
   gst_adapter_clear (mux->adapter);
   gst_adapter_clear (mux->out_adapter);
 
@@ -357,10 +384,10 @@ mpegtsmux_reset (MpegTsMux * mux, gboolean alloc)
   gst_event_replace (&mux->force_key_unit_event, NULL);
   gst_buffer_replace (&mux->out_buffer, NULL);
 
-  GST_COLLECT_PADS2_STREAM_LOCK (mux->collect);
+  GST_COLLECT_PADS_STREAM_LOCK (mux->collect);
   for (walk = mux->collect->data; walk != NULL; walk = g_slist_next (walk))
     mpegtsmux_pad_reset ((MpegTsPadData *) walk->data);
-  GST_COLLECT_PADS2_STREAM_UNLOCK (mux->collect);
+  GST_COLLECT_PADS_STREAM_UNLOCK (mux->collect);
 
   if (alloc) {
     mux->tsmux = tsmux_new ();
@@ -472,6 +499,7 @@ gst_mpegtsmux_get_property (GObject * object, guint prop_id,
   }
 }
 
+#if 0
 static void
 mpegtsmux_set_index (GstElement * element, GstIndex * index)
 {
@@ -501,12 +529,12 @@ mpegtsmux_get_index (GstElement * element)
 
   return result;
 }
+#endif
 
 static void
 release_buffer_cb (guint8 * data, void *user_data)
 {
-  GstBuffer *buf = (GstBuffer *) user_data;
-  gst_buffer_unref (buf);
+  stream_data_free (user_data);
 }
 
 static GstFlowReturn
@@ -522,12 +550,12 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
   GstBuffer *codec_data = NULL;
 
   pad = ts_data->collect.pad;
-  caps = gst_pad_get_negotiated_caps (pad);
+  caps = gst_pad_get_current_caps (pad);
   if (caps == NULL)
     goto not_negotiated;
 
   GST_DEBUG_OBJECT (pad, "Creating stream with PID 0x%04x for caps %"
-      GST_PTR_FORMAT, caps);
+      GST_PTR_FORMAT, ts_data->pid, caps);
 
   s = gst_caps_get_structure (caps, 0);
   g_return_val_if_fail (s != NULL, FALSE);
@@ -547,16 +575,6 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
     st = TSMUX_ST_PS_AUDIO_LPCM;
   } else if (strcmp (mt, "video/x-h264") == 0) {
     st = TSMUX_ST_VIDEO_H264;
-    /* Codec data contains SPS/PPS which need to go in stream for valid ES */
-    if (codec_data) {
-      GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
-          GST_BUFFER_SIZE (codec_data));
-      ts_data->codec_data = gst_buffer_ref (codec_data);
-      ts_data->prepare_func = mpegtsmux_prepare_h264;
-      ts_data->free_func = mpegtsmux_free_h264;
-    } else {
-      ts_data->codec_data = NULL;
-    }
   } else if (strcmp (mt, "audio/mpeg") == 0) {
     gint mpegversion;
 
@@ -575,9 +593,10 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
       case 4:
       {
         st = TSMUX_ST_AUDIO_AAC;
-        if (codec_data) {
-          GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
-              GST_BUFFER_SIZE (codec_data));
+        if (codec_data) {       /* TODO - Check stream format - codec data should only come with RAW stream */
+          GST_DEBUG_OBJECT (pad,
+              "we have additional codec data (%" G_GSIZE_FORMAT " bytes)",
+              gst_buffer_get_size (codec_data));
           ts_data->codec_data = gst_buffer_ref (codec_data);
           ts_data->prepare_func = mpegtsmux_prepare_aac;
         } else {
@@ -629,7 +648,7 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
 
     ret = GST_FLOW_OK;
   }
-
+#if 0
   GST_OBJECT_LOCK (mux);
   if (mux->element_index) {
     gboolean parsed = FALSE;
@@ -652,6 +671,7 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
     }
   }
   GST_OBJECT_UNLOCK (mux);
+#endif
 
   gst_caps_unref (caps);
   return ret;
@@ -674,7 +694,7 @@ mpegtsmux_create_streams (MpegTsMux * mux)
 
   /* Create the streams */
   while (walk) {
-    GstCollectData2 *c_data = (GstCollectData2 *) walk->data;
+    GstCollectData *c_data = (GstCollectData *) walk->data;
     MpegTsPadData *ts_data = (MpegTsPadData *) walk->data;
     gchar *name = NULL;
 
@@ -743,15 +763,14 @@ mpegtsmux_choose_best_stream (MpegTsMux * mux)
   GSList *walk;
 
   for (walk = mux->collect->data; walk != NULL; walk = g_slist_next (walk)) {
-    GstCollectData2 *c_data = (GstCollectData2 *) walk->data;
+    GstCollectData *c_data = (GstCollectData *) walk->data;
     MpegTsPadData *ts_data = (MpegTsPadData *) walk->data;
 
     if (ts_data->eos == FALSE) {
       if (ts_data->queued_buf == NULL) {
         GstBuffer *buf;
 
-        ts_data->queued_buf = buf =
-            gst_collect_pads2_pop (mux->collect, c_data);
+        ts_data->queued_buf = buf = gst_collect_pads_pop (mux->collect, c_data);
 
         if (buf != NULL) {
           if (ts_data->prepare_func) {
@@ -763,30 +782,40 @@ mpegtsmux_choose_best_stream (MpegTsMux * mux)
               buf = ts_data->queued_buf;
             }
           }
-          if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
-            /* Ignore timestamps that go backward for now. FIXME: Handle all
-             * incoming PTS */
-            if (ts_data->last_ts == GST_CLOCK_TIME_NONE ||
-                ts_data->last_ts < GST_BUFFER_TIMESTAMP (buf)) {
-              ts_data->cur_ts = ts_data->last_ts =
-                  gst_segment_to_running_time (&c_data->segment,
-                  GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
+          if (GST_BUFFER_PTS (buf) != GST_CLOCK_TIME_NONE) {
+
+            ts_data->cur_pts = ts_data->last_pts =
+                gst_segment_to_running_time (&c_data->segment,
+                GST_FORMAT_TIME, GST_BUFFER_PTS (buf));
+          } else
+            ts_data->cur_pts = GST_CLOCK_TIME_NONE;
+
+          if (GST_BUFFER_DTS (buf) != GST_CLOCK_TIME_NONE) {
+            GstClockTime dts = gst_segment_to_running_time (&c_data->segment,
+                GST_FORMAT_TIME, GST_BUFFER_DTS (buf));
+            if (ts_data->last_dts == GST_CLOCK_TIME_NONE
+                || ts_data->last_dts < dts) {
+              ts_data->cur_dts = ts_data->last_dts = dts;
             } else {
-              GST_DEBUG_OBJECT (mux, "Ignoring PTS that has gone backward");
+              GST_WARNING_OBJECT (mux,
+                  "Got DTS that is going backward (%" GST_TIME_FORMAT " >= %"
+                  GST_TIME_FORMAT "). You should provide valid monotone DTS.",
+                  GST_TIME_ARGS (ts_data->last_dts), GST_TIME_ARGS (dts));
+              ts_data->cur_dts = GST_CLOCK_TIME_NONE;
             }
           } else
-            ts_data->cur_ts = GST_CLOCK_TIME_NONE;
+            ts_data->cur_dts = GST_CLOCK_TIME_NONE;
 
           GST_DEBUG_OBJECT (mux, "Pulled buffer with ts %" GST_TIME_FORMAT
-              " (uncorrected ts %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
+              " (uncorrected pts %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
               ") for PID 0x%04x",
-              GST_TIME_ARGS (ts_data->cur_ts),
-              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+              GST_TIME_ARGS (ts_data->cur_pts),
+              GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
               GST_BUFFER_TIMESTAMP (buf), ts_data->pid);
 
           /* Choose a stream we've never seen a timestamp for to ensure
            * we push enough buffers from it to reach a timestamp */
-          if (ts_data->last_ts == GST_CLOCK_TIME_NONE) {
+          if (ts_data->last_pts == GST_CLOCK_TIME_NONE) {
             best = ts_data;
           }
         } else {
@@ -798,9 +827,9 @@ mpegtsmux_choose_best_stream (MpegTsMux * mux)
       /* If we don't yet have a best pad, take this one, otherwise take
        * whichever has the oldest timestamp */
       if (best != NULL) {
-        if (ts_data->last_ts != GST_CLOCK_TIME_NONE &&
-            best->last_ts != GST_CLOCK_TIME_NONE &&
-            ts_data->last_ts < best->last_ts) {
+        if (ts_data->last_pts != GST_CLOCK_TIME_NONE &&
+            best->last_pts != GST_CLOCK_TIME_NONE &&
+            ts_data->last_pts < best->last_pts) {
           best = ts_data;
         }
       } else {
@@ -812,14 +841,15 @@ mpegtsmux_choose_best_stream (MpegTsMux * mux)
   return best;
 }
 
-#define COLLECT_DATA_PAD(collect_data) (((GstCollectData2 *)(collect_data))->pad)
+#define COLLECT_DATA_PAD(collect_data) (((GstCollectData *)(collect_data))->pad)
 
 static gboolean
-mpegtsmux_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+mpegtsmux_sink_event (GstCollectPads * pads, GstCollectData * data,
     GstEvent * event, gpointer user_data)
 {
   MpegTsMux *mux = GST_MPEG_TSMUX (user_data);
   gboolean res = FALSE;
+  gboolean forward = TRUE;
   GstPad *pad;
 
   pad = data->pad;
@@ -835,6 +865,7 @@ mpegtsmux_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
         goto out;
 
       res = TRUE;
+      forward = FALSE;
 
       gst_video_event_parse_downstream_force_key_unit (event,
           &timestamp, &stream_time, &running_time, &all_headers, &count);
@@ -861,14 +892,16 @@ mpegtsmux_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
   }
 
 out:
-  if (res)
+  if (!forward)
     gst_event_unref (event);
+  else
+    res = gst_collect_pads_event_default (pads, data, event, FALSE);
 
   return res;
 }
 
 static gboolean
-mpegtsmux_src_event (GstPad * pad, GstEvent * event)
+mpegtsmux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   MpegTsMux *mux = GST_MPEG_TSMUX (gst_pad_get_parent (pad));
   gboolean res = TRUE, forward = TRUE;
@@ -879,6 +912,7 @@ mpegtsmux_src_event (GstPad * pad, GstEvent * event)
       GstIterator *iter;
       GstIteratorResult iter_ret;
       GstPad *sinkpad;
+      GValue sinkpad_value = G_VALUE_INIT;
       GstClockTime running_time;
       gboolean all_headers, done;
       guint count;
@@ -906,7 +940,9 @@ mpegtsmux_src_event (GstPad * pad, GstEvent * event)
       done = FALSE;
       while (!done) {
         gboolean res = FALSE, tmp;
-        iter_ret = gst_iterator_next (iter, (gpointer *) & sinkpad);
+        g_value_reset (&sinkpad_value);
+        iter_ret = gst_iterator_next (iter, &sinkpad_value);
+        sinkpad = g_value_get_object (&sinkpad_value);
 
         switch (iter_ret) {
           case GST_ITERATOR_DONE:
@@ -928,6 +964,7 @@ mpegtsmux_src_event (GstPad * pad, GstEvent * event)
             break;
         }
       }
+      g_value_reset (&sinkpad_value);
       gst_iterator_free (iter);
       break;
     }
@@ -936,7 +973,7 @@ mpegtsmux_src_event (GstPad * pad, GstEvent * event)
   }
 
   if (forward)
-    res = gst_pad_event_default (pad, event);
+    res = gst_pad_event_default (pad, parent, event);
   else
     gst_event_unref (event);
 
@@ -993,7 +1030,7 @@ out:
 }
 
 static GstFlowReturn
-mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux)
+mpegtsmux_collected (GstCollectPads * pads, MpegTsMux * mux)
 {
   GstFlowReturn ret = GST_FLOW_OK;
   MpegTsPadData *best = NULL;
@@ -1016,7 +1053,9 @@ mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux)
     TsMuxProgram *prog = best->prog;
     GstBuffer *buf = best->queued_buf;
     gint64 pts = -1;
+    guint64 dts = -1;
     gboolean delta = TRUE;
+    StreamData *stream_data;
 
     if (prog == NULL)
       goto no_program;
@@ -1072,14 +1111,21 @@ mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux)
     GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best),
         "Chose stream for output (PID: 0x%04x)", best->pid);
 
-    if (GST_CLOCK_TIME_IS_VALID (best->cur_ts)) {
-      pts = GSTTIME_TO_MPEGTIME (best->cur_ts);
-      GST_DEBUG_OBJECT (mux, "Buffer has TS %" GST_TIME_FORMAT " pts %"
-          G_GINT64_FORMAT, GST_TIME_ARGS (best->cur_ts), pts);
+    if (GST_CLOCK_TIME_IS_VALID (best->cur_pts)) {
+      pts = GSTTIME_TO_MPEGTIME (best->cur_pts);
+      GST_DEBUG_OBJECT (mux, "Buffer has PTS %" GST_TIME_FORMAT " pts %"
+          G_GINT64_FORMAT, GST_TIME_ARGS (best->cur_pts), pts);
+    }
+
+    if (GST_CLOCK_TIME_IS_VALID (best->cur_dts)) {
+      dts = GSTTIME_TO_MPEGTIME (best->cur_dts);
+      GST_DEBUG_OBJECT (mux, "Buffer has DTS %" GST_TIME_FORMAT " dts %"
+          G_GINT64_FORMAT, GST_TIME_ARGS (best->cur_dts), dts);
     }
 
     if (best->stream->is_video_stream) {
       delta = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+#if 0
       GST_OBJECT_LOCK (mux);
       if (mux->element_index && !delta && best->element_index_writer_id != -1) {
         gst_index_add_association (mux->element_index,
@@ -1088,19 +1134,24 @@ mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux)
             pts_format, pts, NULL);
       }
       GST_OBJECT_UNLOCK (mux);
+#endif
     }
     GST_DEBUG_OBJECT (mux, "delta: %d", delta);
 
-    tsmux_stream_add_data (best->stream, GST_BUFFER_DATA (buf),
-        GST_BUFFER_SIZE (buf), buf, pts, -1, !delta);
+    stream_data = stream_data_new (buf);
+    tsmux_stream_add_data (best->stream, stream_data->map_info.data,
+        stream_data->map_info.size, stream_data, pts, dts, !delta);
 
     /* outgoing ts follows ts of PCR program stream */
     if (prog->pcr_stream == best->stream) {
-      mux->last_ts = best->last_ts;
+      /* prefer DTS if present for PCR as it should be monotone */
+      mux->last_ts =
+          GST_CLOCK_TIME_IS_VALID (best->last_dts) ? best->last_dts : best->
+          last_pts;
     }
 
     mux->is_delta = delta;
-    mux->last_size = GST_BUFFER_SIZE (buf);
+    mux->last_size = stream_data->map_info.size;
     while (tsmux_stream_bytes_in_buffer (best->stream) > 0) {
       if (!tsmux_write_stream_packet (mux->tsmux, best->stream)) {
         /* Failed writing data for some reason. Set appropriate error */
@@ -1139,8 +1190,8 @@ no_program:
 }
 
 static GstPad *
-mpegtsmux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name)
+mpegtsmux_request_new_pad (GstElement * element, GstPadTemplate * templ,
+    const gchar * name, const GstCaps * caps)
 {
   MpegTsMux *mux = GST_MPEG_TSMUX (element);
   gint pid = -1;
@@ -1160,8 +1211,8 @@ mpegtsmux_request_new_pad (GstElement * element,
   g_free (pad_name);
 
   pad_data = (MpegTsPadData *)
-      gst_collect_pads2_add_pad_full (mux->collect, pad, sizeof (MpegTsPadData),
-      (GstCollectData2DestroyNotify) (mpegtsmux_pad_reset), TRUE);
+      gst_collect_pads_add_pad_full (mux->collect, pad, sizeof (MpegTsPadData),
+      (GstCollectDataDestroyNotify) (mpegtsmux_pad_reset), TRUE);
   if (pad_data == NULL)
     goto pad_failure;
 
@@ -1184,7 +1235,7 @@ could_not_add:
   {
     GST_ELEMENT_ERROR (element, STREAM, FAILED,
         ("Internal data stream error."), ("Could not add pad to element"));
-    gst_collect_pads2_remove_pad (mux->collect, pad);
+    gst_collect_pads_remove_pad (mux->collect, pad);
     gst_object_unref (pad);
     return NULL;
   }
@@ -1205,7 +1256,7 @@ mpegtsmux_release_pad (GstElement * element, GstPad * pad)
   GST_DEBUG_OBJECT (mux, "Pad %" GST_PTR_FORMAT " being released", pad);
 
   if (mux->collect) {
-    gst_collect_pads2_remove_pad (mux->collect, pad);
+    gst_collect_pads_remove_pad (mux->collect, pad);
   }
 
   /* chain up */
@@ -1227,7 +1278,7 @@ new_packet_common_init (MpegTsMux * mux, GstBuffer * buf, guint8 * data,
 
       if (!buf) {
         hbuf = gst_buffer_new_and_alloc (len);
-        memcpy (GST_BUFFER_DATA (hbuf), data, len);
+        gst_buffer_fill (hbuf, 0, data, len);
       } else {
         hbuf = gst_buffer_copy (buf);
       }
@@ -1239,10 +1290,6 @@ new_packet_common_init (MpegTsMux * mux, GstBuffer * buf, guint8 * data,
   }
 
   if (buf) {
-    /* Set the caps on the buffer only after possibly setting the stream headers
-     * into the pad caps above */
-    gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));
-
     if (mux->is_delta) {
       GST_LOG_OBJECT (mux, "marking as delta unit");
       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
@@ -1287,7 +1334,7 @@ mpegtsmux_push_packets (MpegTsMux * mux, gboolean force)
     buf = gst_adapter_take_buffer (mux->out_adapter, av - (av % align));
     g_assert (buf);
     GST_BUFFER_TIMESTAMP (buf) = ts;
-    gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));
+
     ret = gst_pad_push (mux->srcpad, buf);
     av = av % align;
   }
@@ -1296,19 +1343,22 @@ mpegtsmux_push_packets (MpegTsMux * mux, gboolean force)
     guint8 *data;
     guint32 header;
     gint dummy;
+    GstMapInfo map;
 
     GST_LOG_OBJECT (mux, "handling %d leftover bytes", av);
     buf = gst_buffer_new_and_alloc (align);
+    gst_buffer_map (buf, &map, GST_MAP_READ);
+    data = map.data;
     ts = gst_adapter_prev_timestamp (mux->out_adapter, NULL);
-    gst_adapter_copy (mux->out_adapter, GST_BUFFER_DATA (buf), 0, av);
+
+    gst_adapter_copy (mux->out_adapter, data, 0, av);
     gst_adapter_clear (mux->out_adapter);
     GST_BUFFER_TIMESTAMP (buf) = ts;
-    gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));
 
-    data = GST_BUFFER_DATA (buf) + av;
+    data += av;
     header = GST_READ_UINT32_BE (data - packet_size);
 
-    dummy = (GST_BUFFER_SIZE (buf) - av) / packet_size;
+    dummy = (map.size - av) / packet_size;
     GST_LOG_OBJECT (mux, "adding %d null packets", dummy);
 
     for (; dummy > 0; dummy--) {
@@ -1332,6 +1382,8 @@ mpegtsmux_push_packets (MpegTsMux * mux, gboolean force)
       data += packet_size;
     }
 
+    gst_buffer_unmap (buf, &map);
+
     ret = gst_pad_push (mux->srcpad, buf);
   }
 
@@ -1341,7 +1393,8 @@ mpegtsmux_push_packets (MpegTsMux * mux, gboolean force)
 static GstFlowReturn
 mpegtsmux_collect_packet (MpegTsMux * mux, GstBuffer * buf)
 {
-  GST_LOG_OBJECT (mux, "collecting packet size %d", GST_BUFFER_SIZE (buf));
+  GST_LOG_OBJECT (mux, "collecting packet size %" G_GSIZE_FORMAT,
+      gst_buffer_get_size (buf));
   gst_adapter_push (mux->out_adapter, buf);
 
   return GST_FLOW_OK;
@@ -1352,6 +1405,7 @@ new_packet_m2ts (MpegTsMux * mux, GstBuffer * buf, gint64 new_pcr)
 {
   GstBuffer *out_buf;
   int chunk_bytes;
+  GstMapInfo map;
 
   GST_LOG_OBJECT (mux, "Have buffer %p with new_pcr=%" G_GINT64_FORMAT,
       buf, new_pcr);
@@ -1418,12 +1472,14 @@ new_packet_m2ts (MpegTsMux * mux, GstBuffer * buf, gint64 new_pcr)
       g_assert (out_buf);
       offset += M2TS_PACKET_LENGTH;
 
-      gst_buffer_set_caps (out_buf, GST_PAD_CAPS (mux->srcpad));
       GST_BUFFER_TIMESTAMP (out_buf) = ts;
 
+      gst_buffer_map (out_buf, &map, GST_MAP_WRITE);
+
       /* The header is the bottom 30 bits of the PCR, apparently not
        * encoded into base + ext as in the packets themselves */
-      GST_WRITE_UINT32_BE (GST_BUFFER_DATA (out_buf), cur_pcr & 0x3FFFFFFF);
+      GST_WRITE_UINT32_BE (map.data, cur_pcr & 0x3FFFFFFF);
+      gst_buffer_unmap (out_buf, &map);
 
       GST_LOG_OBJECT (mux, "Outputting a packet of length %d PCR %"
           G_GUINT64_FORMAT, M2TS_PACKET_LENGTH, cur_pcr);
@@ -1434,9 +1490,13 @@ new_packet_m2ts (MpegTsMux * mux, GstBuffer * buf, gint64 new_pcr)
   if (G_UNLIKELY (!buf))
     goto exit;
 
+  gst_buffer_map (buf, &map, GST_MAP_WRITE);
+
   /* Finally, output the passed in packet */
   /* Only write the bottom 30 bits of the PCR */
-  GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), new_pcr & 0x3FFFFFFF);
+  GST_WRITE_UINT32_BE (map.data, new_pcr & 0x3FFFFFFF);
+
+  gst_buffer_unmap (buf, &map);
 
   GST_LOG_OBJECT (mux, "Outputting a packet of length %d PCR %"
       G_GUINT64_FORMAT, M2TS_PACKET_LENGTH, new_pcr);
@@ -1458,20 +1518,30 @@ new_packet_cb (GstBuffer * buf, void *user_data, gint64 new_pcr)
 {
   MpegTsMux *mux = (MpegTsMux *) user_data;
   gint offset = 0;
+  GstMapInfo map;
 
+#if 0
   GST_LOG_OBJECT (mux, "handling packet %d", mux->spn_count);
   mux->spn_count++;
+#endif
+
+  if (mux->m2ts_mode) {
+    offset = 4;
+    gst_buffer_set_size (buf, NORMAL_TS_PACKET_LENGTH + offset);
+  }
+
+  gst_buffer_map (buf, &map, GST_MAP_READWRITE);
+
+  if (offset) {
+    /* there should be a better way to do this */
+    memmove (map.data + offset, map.data, map.size - offset);
+  }
 
-  offset = GST_BUFFER_DATA (buf) - GST_BUFFER_MALLOCDATA (buf);
-  GST_BUFFER_TIMESTAMP (buf) = mux->last_ts;
+  GST_BUFFER_PTS (buf) = mux->last_ts;
   /* do common init (flags and streamheaders) */
-  new_packet_common_init (mux, buf,
-      GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+  new_packet_common_init (mux, buf, map.data + offset, map.size);
 
   /* all is meant for downstream, including any prefix */
-  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf);
-  GST_BUFFER_SIZE (buf) += offset;
-
   if (offset)
     return new_packet_m2ts (mux, buf, new_pcr);
   else
@@ -1491,11 +1561,8 @@ alloc_packet_cb (GstBuffer ** _buf, void *user_data)
   if (mux->m2ts_mode == TRUE)
     offset = 4;
 
-  /* TODO might be even more efficient to avoid later memcpy
-   * if these are subbuffer from a larger buffer or so */
   buf = gst_buffer_new_and_alloc (NORMAL_TS_PACKET_LENGTH + offset);
-  GST_BUFFER_DATA (buf) += offset;
-  GST_BUFFER_SIZE (buf) -= offset;
+  gst_buffer_set_size (buf, NORMAL_TS_PACKET_LENGTH);
 
   *_buf = buf;
 }
@@ -1510,7 +1577,7 @@ mpegtsdemux_set_header_on_caps (MpegTsMux * mux)
   GstCaps *caps;
   GList *sh;
 
-  caps = gst_caps_copy (GST_PAD_CAPS (mux->srcpad));
+  caps = gst_caps_make_writable (gst_pad_get_current_caps (mux->srcpad));
   structure = gst_caps_get_structure (caps, 0);
 
   g_value_init (&array, GST_TYPE_ARRAY);
@@ -1518,7 +1585,6 @@ mpegtsdemux_set_header_on_caps (MpegTsMux * mux)
   sh = mux->streamheader;
   while (sh) {
     buf = sh->data;
-    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
     g_value_init (&value, GST_TYPE_BUFFER);
     gst_value_take_buffer (&value, buf);
     gst_value_array_append_value (&array, &value);
@@ -1538,15 +1604,23 @@ mpegtsdemux_set_header_on_caps (MpegTsMux * mux)
 static void
 mpegtsdemux_prepare_srcpad (MpegTsMux * mux)
 {
+  GstSegment seg;
   /* we are not going to seek */
-  GstEvent *new_seg =
-      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
+  GstEvent *new_seg;
   GstCaps *caps = gst_caps_new_simple ("video/mpegts",
       "systemstream", G_TYPE_BOOLEAN, TRUE,
       "packetsize", G_TYPE_INT,
       (mux->m2ts_mode ? M2TS_PACKET_LENGTH : NORMAL_TS_PACKET_LENGTH),
       NULL);
 
+  seg.rate = 1.0;
+  seg.format = GST_FORMAT_TIME;
+  seg.start = 0;
+  seg.stop = -1;
+  seg.position = 0;
+
+  new_seg = gst_event_new_segment (&seg);
+
   /* Set caps on src pad from our template and push new segment */
   gst_pad_set_caps (mux->srcpad, caps);
   gst_caps_unref (caps);
@@ -1566,12 +1640,12 @@ mpegtsmux_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_NULL_TO_READY:
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
-      gst_collect_pads2_start (mux->collect);
+      gst_collect_pads_start (mux->collect);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
-      gst_collect_pads2_stop (mux->collect);
+      gst_collect_pads_stop (mux->collect);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
       break;
index 23a5c61..e7b0521 100644 (file)
@@ -84,7 +84,7 @@
 #define __MPEGTSMUX_H__
 
 #include <gst/gst.h>
-#include <gst/base/gstcollectpads2.h>
+#include <gst/base/gstcollectpads.h>
 #include <gst/base/gstadapter.h>
 
 G_BEGIN_DECLS
@@ -129,7 +129,7 @@ struct MpegTsMux {
 
   GstPad *srcpad;
 
-  GstCollectPads2 *collect;
+  GstCollectPads *collect;
 
   TsMux *tsmux;
   TsMuxProgram *programs[MAX_PROG_NUMBER];
@@ -166,9 +166,11 @@ struct MpegTsMux {
   gint out_offset;
   gint last_size;
 
+#if 0
   /* SPN/PTS index handling */
   GstIndex *element_index;
   gint spn_count;
+#endif
 };
 
 struct MpegTsMuxClass {
@@ -179,7 +181,7 @@ struct MpegTsMuxClass {
 
 struct MpegTsPadData {
   /* parent */
-  GstCollectData2 collect;
+  GstCollectData collect;
 
   gint pid;
   TsMuxStream *stream;
@@ -187,12 +189,17 @@ struct MpegTsPadData {
   /* currently pulled buffer */
   GstBuffer *queued_buf;
   /* adjusted TS for the pulled buffer */
-  GstClockTime cur_ts;
+  GstClockTime cur_pts;
+  GstClockTime cur_dts;
+    
   /* most recent valid TS for this stream */
-  GstClockTime last_ts;
+  GstClockTime last_pts;
+  GstClockTime last_dts;
 
+#if 0
   /* (optional) index writing */
   gint element_index_writer_id;
+#endif
 
   /* optional codec data available in the caps */
   GstBuffer *codec_data;
index c433664..5191cca 100644 (file)
@@ -93,23 +93,26 @@ GstBuffer *
 mpegtsmux_prepare_aac (GstBuffer * buf, MpegTsPadData * data, MpegTsMux * mux)
 {
   guint8 adts_header[7] = { 0, };
-  GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 7);
+  gsize out_size = gst_buffer_get_size (buf) + 7;
+  GstBuffer *out_buf = gst_buffer_new_and_alloc (out_size);
   gsize out_offset = 0;
   guint8 rate_idx = 0, channels = 0, obj_type = 0;
+  GstMapInfo codec_data_map;
+  GstMapInfo buf_map;
 
   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);
+  gst_buffer_copy_into (out_buf, buf,
+      GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_TIMESTAMPS, 0, 0);
+
+  gst_buffer_map (data->codec_data, &codec_data_map, GST_MAP_READ);
 
   /* Generate ADTS header */
-  obj_type = (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data)) & 0xC) >> 2;
+  obj_type = (GST_READ_UINT8 (codec_data_map.data) & 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 = (GST_READ_UINT8 (codec_data_map.data) & 0x3) << 1;
+  rate_idx |= (GST_READ_UINT8 (codec_data_map.data + 1) & 0x80) >> 7;
+  channels = (GST_READ_UINT8 (codec_data_map.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 */
@@ -126,11 +129,11 @@ mpegtsmux_prepare_aac (GstBuffer * buf, MpegTsPadData * data, MpegTsMux * 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] |= (out_size & 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
@@ -138,12 +141,16 @@ mpegtsmux_prepare_aac (GstBuffer * buf, MpegTsPadData * data, MpegTsMux * mux)
   adts_header[6] = 0xFC;
 
   /* Insert ADTS header */
-  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, adts_header, 7);
+  gst_buffer_fill (out_buf, out_offset, adts_header, 7);
   out_offset += 7;
 
+  gst_buffer_map (buf, &buf_map, GST_MAP_READ);
+
   /* Now copy complete frame */
-  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, GST_BUFFER_DATA (buf),
-      GST_BUFFER_SIZE (buf));
+  gst_buffer_fill (out_buf, out_offset, buf_map.data, buf_map.size);
+
+  gst_buffer_unmap (data->codec_data, &codec_data_map);
+  gst_buffer_unmap (buf, &buf_map);
 
   return out_buf;
 }
diff --git a/gst/mpegtsmux/mpegtsmux_h264.c b/gst/mpegtsmux/mpegtsmux_h264.c
deleted file mode 100644 (file)
index bdf7f2f..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-/* 
- * Copyright 2006, 2007, 2008, 2009, 2010 Fluendo S.A.
- *  Authors: Jan Schmidt <jan@fluendo.com>
- *           Kapil Agrawal <kapil@fluendo.com>
- *           Julien Moutte <julien@fluendo.com>
- *
- * This library is licensed under 4 different licenses and you
- * can choose to use it under the terms of any one of them. The
- * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
- * license.
- *
- * MPL:
- * 
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * LGPL:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * 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.
- *
- * GPL:
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * MIT:
- *
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mpegtsmux_h264.h"
-#include <string.h>
-
-#define GST_CAT_DEFAULT mpegtsmux_debug
-
-#define SPS_PPS_PERIOD GST_SECOND
-
-typedef struct PrivDataH264 PrivDataH264;
-
-struct PrivDataH264
-{
-  GstBuffer *last_codec_data;
-  GstClockTime last_resync_ts;
-  GstBuffer *cached_es;
-  guint8 nal_length_size;
-};
-
-void
-mpegtsmux_free_h264 (gpointer prepare_data)
-{
-  PrivDataH264 *h264_data = (PrivDataH264 *) prepare_data;
-  if (h264_data->cached_es) {
-    gst_buffer_unref (h264_data->cached_es);
-    h264_data->cached_es = NULL;
-  }
-  g_free (prepare_data);
-}
-
-static inline gboolean
-mpegtsmux_process_codec_data_h264 (MpegTsPadData * data, MpegTsMux * mux)
-{
-  PrivDataH264 *h264_data;
-  gboolean ret = FALSE;
-
-  /* Initialize our private data structure for caching */
-  if (G_UNLIKELY (!data->prepare_data)) {
-    data->prepare_data = g_new0 (PrivDataH264, 1);
-    h264_data = (PrivDataH264 *) data->prepare_data;
-    h264_data->last_resync_ts = GST_CLOCK_TIME_NONE;
-  }
-
-  h264_data = (PrivDataH264 *) data->prepare_data;
-
-  /* Detect a codec data change */
-  if (h264_data->last_codec_data != data->codec_data) {
-    if (h264_data->cached_es) {
-      gst_buffer_unref (h264_data->cached_es);
-      h264_data->cached_es = NULL;
-    }
-    ret = TRUE;
-  }
-
-  /* Generate the SPS/PPS ES header that will be prepended regularly */
-  if (G_UNLIKELY (!h264_data->cached_es)) {
-    gint offset = 4, i = 0, nb_sps = 0, nb_pps = 0;
-    gsize out_offset = 0;
-    guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
-    h264_data->last_codec_data = data->codec_data;
-    h264_data->cached_es =
-        gst_buffer_new_and_alloc (GST_BUFFER_SIZE (data->codec_data) * 10);
-
-    /* Get NAL length size */
-    h264_data->nal_length_size =
-        (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x03) +
-        1;
-    GST_LOG_OBJECT (mux, "NAL length will be coded on %u bytes",
-        h264_data->nal_length_size);
-    offset++;
-
-    /* How many SPS */
-    nb_sps =
-        GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_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);
-
-      GST_LOG_OBJECT (mux, "Sequence Parameter Set is %d bytes", sps_size);
-
-      /* Jump over SPS size */
-      offset += 2;
-
-      /* Fake a start code */
-      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
-          startcode, 4);
-      out_offset += 4;
-      /* Now push the SPS */
-      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
-          GST_BUFFER_DATA (data->codec_data) + offset, sps_size);
-
-      out_offset += sps_size;
-      offset += sps_size;
-    }
-
-    /* How many PPS */
-    nb_pps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_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);
-
-      GST_LOG_OBJECT (mux, "Picture Parameter Set is %d bytes", pps_size);
-
-      /* Jump over PPS size */
-      offset += 2;
-
-      /* Fake a start code */
-      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
-          startcode, 4);
-      out_offset += 4;
-      /* Now push the PPS */
-      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
-          GST_BUFFER_DATA (data->codec_data) + offset, pps_size);
-
-      out_offset += pps_size;
-      offset += pps_size;
-    }
-    GST_BUFFER_SIZE (h264_data->cached_es) = out_offset;
-    GST_DEBUG_OBJECT (mux, "generated a %" G_GSIZE_FORMAT
-        " bytes SPS/PPS header", out_offset);
-  }
-  return ret;
-}
-
-GstBuffer *
-mpegtsmux_prepare_h264 (GstBuffer * buf, MpegTsPadData * data, MpegTsMux * mux)
-{
-  guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
-  gsize out_offset = 0, in_offset = 0;
-  GstBuffer *out_buf;
-  gboolean changed;
-  PrivDataH264 *h264_data;
-  GstClockTimeDiff diff = GST_CLOCK_TIME_NONE;
-
-  GST_DEBUG_OBJECT (mux, "Preparing H264 buffer for output");
-
-  changed = mpegtsmux_process_codec_data_h264 (data, mux);
-  h264_data = (PrivDataH264 *) data->prepare_data;
-
-  if (GST_CLOCK_TIME_IS_VALID (h264_data->last_resync_ts) &&
-      GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) {
-    diff = GST_CLOCK_DIFF (h264_data->last_resync_ts,
-        GST_BUFFER_TIMESTAMP (buf));
-  }
-
-  if (changed || (GST_CLOCK_TIME_IS_VALID (diff) && diff > SPS_PPS_PERIOD)) {
-    out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2 +
-        GST_BUFFER_SIZE (h264_data->cached_es));
-    h264_data->last_resync_ts = GST_BUFFER_TIMESTAMP (buf);
-    memcpy (GST_BUFFER_DATA (out_buf), GST_BUFFER_DATA (h264_data->cached_es),
-        GST_BUFFER_SIZE (h264_data->cached_es));
-    out_offset = GST_BUFFER_SIZE (h264_data->cached_es);
-    GST_DEBUG_OBJECT (mux, "prepending SPS/PPS information to that packet");
-  } else {
-    out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2);
-  }
-
-  /* We want the same metadata */
-  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);
-
-  while (in_offset < GST_BUFFER_SIZE (buf) &&
-      out_offset < GST_BUFFER_SIZE (out_buf) - 4) {
-    guint32 nal_size = 0;
-
-    switch (h264_data->nal_length_size) {
-      case 1:
-        nal_size = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + in_offset);
-        break;
-      case 2:
-        nal_size = GST_READ_UINT16_BE (GST_BUFFER_DATA (buf) + in_offset);
-        break;
-      case 4:
-        nal_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + in_offset);
-        break;
-      default:
-        GST_WARNING_OBJECT (mux, "unsupported NAL length size %u",
-            h264_data->nal_length_size);
-    }
-    in_offset += h264_data->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));
-    in_offset += nal_size;
-    out_offset += nal_size;
-  }
-
-  if (out_offset > GST_BUFFER_SIZE (out_buf)) {
-    GST_WARNING_OBJECT (mux, "Calculated buffer size %" G_GSIZE_FORMAT
-        " is greater than max expected size %u, "
-        "using max expected size (Input might not be in "
-        "avc format", out_offset, GST_BUFFER_SIZE (out_buf));
-    out_offset = GST_BUFFER_SIZE (out_buf);
-  }
-  GST_BUFFER_SIZE (out_buf) = out_offset;
-
-  return out_buf;
-}
diff --git a/gst/mpegtsmux/mpegtsmux_h264.h b/gst/mpegtsmux/mpegtsmux_h264.h
deleted file mode 100644 (file)
index 3a9bccb..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/* 
- * Copyright 2006, 2007, 2008, 2009, 2010 Fluendo S.A. 
- *  Authors: Jan Schmidt <jan@fluendo.com>
- *           Kapil Agrawal <kapil@fluendo.com>
- *           Julien Moutte <julien@fluendo.com>
- *
- * This library is licensed under 4 different licenses and you
- * can choose to use it under the terms of any one of them. The
- * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
- * license.
- *
- * MPL:
- * 
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * LGPL:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * 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.
- *
- * GPL:
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * MIT:
- *
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-#ifndef __MPEGTSMUX_H264_H__
-#define __MPEGTSMUX_H264_H__
-#include "mpegtsmux.h"
-
-GstBuffer * mpegtsmux_prepare_h264 (GstBuffer * buf, MpegTsPadData * data,
-    MpegTsMux * mux);
-void mpegtsmux_free_h264 (gpointer prepare_data);
-
-#endif /* __MPEGTSMUX_H264_H__ */
index 089ce2c..06f94b4 100644 (file)
@@ -45,12 +45,12 @@ static guint32 crc_tab[256] = {
 };
 
 static guint32
-calc_crc32 (guint8 *data, guint datalen)
+calc_crc32 (guint8 * data, guint datalen)
 {
   guint i;
   guint32 crc = 0xffffffff;
 
-  for (i=0; i<datalen; i++) {
+  for (i = 0; i < datalen; i++) {
     crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *data++) & 0xff];
   }
 
index 06f7992..2393ae2 100644 (file)
@@ -466,7 +466,7 @@ tsmux_get_buffer (TsMux * mux, GstBuffer ** buf)
   if (!*buf)
     return FALSE;
 
-  g_assert (GST_BUFFER_SIZE (*buf) == TSMUX_PACKET_LENGTH);
+  g_assert (gst_buffer_get_size (*buf) == TSMUX_PACKET_LENGTH);
   return TRUE;
 }
 
@@ -746,7 +746,7 @@ tsmux_write_stream_packet (TsMux * mux, TsMuxStream * stream)
   gboolean res;
   gint64 cur_pcr = -1;
   GstBuffer *buf = NULL;
-  guint8 *data;
+  GstMapInfo map;
 
   g_return_val_if_fail (mux != NULL, FALSE);
   g_return_val_if_fail (stream != NULL, FALSE);
@@ -767,7 +767,7 @@ tsmux_write_stream_packet (TsMux * mux, TsMuxStream * stream)
       cur_pcr = (cur_pts - TSMUX_PCR_OFFSET) *
           (TSMUX_SYS_CLOCK_FREQ / TSMUX_CLOCK_FREQ);
 
-    cur_pcr += CLOCK_BASE * (TSMUX_SYS_CLOCK_FREQ / TSMUX_CLOCK_FREQ);
+    cur_pcr += (gint64) CLOCK_BASE *(TSMUX_SYS_CLOCK_FREQ / TSMUX_CLOCK_FREQ);
 
     /* Need to decide whether to write a new PCR in this packet */
     if (stream->last_pcr == -1 ||
@@ -830,14 +830,17 @@ tsmux_write_stream_packet (TsMux * mux, TsMuxStream * stream)
   if (!tsmux_get_buffer (mux, &buf))
     return FALSE;
 
-  data = GST_BUFFER_DATA (buf);
+  gst_buffer_map (buf, &map, GST_MAP_READ);
 
-  if (!tsmux_write_ts_header (data, pi, &payload_len, &payload_offs))
+  if (!tsmux_write_ts_header (map.data, pi, &payload_len, &payload_offs))
     goto fail;
 
-  if (!tsmux_stream_get_data (stream, data + payload_offs, payload_len))
+
+  if (!tsmux_stream_get_data (stream, map.data + payload_offs, payload_len))
     goto fail;
 
+  gst_buffer_unmap (buf, &map);
+
   res = tsmux_packet_out (mux, buf, cur_pcr);
 
   /* Reset all dynamic flags */
@@ -848,6 +851,7 @@ tsmux_write_stream_packet (TsMux * mux, TsMuxStream * stream)
   /* ERRORS */
 fail:
   {
+    gst_buffer_unmap (buf, &map);
     if (buf)
       gst_buffer_unref (buf);
     return FALSE;
@@ -878,6 +882,7 @@ tsmux_write_section (TsMux * mux, TsMuxSection * section)
   guint payload_len, payload_offs;
   TsMuxPacketInfo *pi;
   GstBuffer *buf = NULL;
+  GstMapInfo map;
 
   pi = &section->pi;
 
@@ -887,43 +892,45 @@ tsmux_write_section (TsMux * mux, TsMuxSection * section)
   payload_remain = pi->stream_avail;
 
   while (payload_remain > 0) {
-    guint8 *data;
 
     /* obtain buffer */
+    map.data = NULL;
     if (!tsmux_get_buffer (mux, &buf))
       goto fail;
 
-    data = GST_BUFFER_DATA (buf);
+    gst_buffer_map (buf, &map, GST_MAP_WRITE);
 
     if (pi->packet_start_unit_indicator) {
       /* Need to write an extra single byte start pointer */
       pi->stream_avail++;
 
-      if (!tsmux_write_ts_header (data, pi, &payload_len, &payload_offs)) {
+      if (!tsmux_write_ts_header (map.data, pi, &payload_len, &payload_offs)) {
         pi->stream_avail--;
         goto fail;
       }
       pi->stream_avail--;
 
       /* Write the pointer byte */
-      data[payload_offs] = 0x00;
+      map.data[payload_offs] = 0x00;
 
       payload_offs++;
       payload_len--;
       pi->packet_start_unit_indicator = FALSE;
     } else {
-      if (!tsmux_write_ts_header (data, pi, &payload_len, &payload_offs))
+      if (!tsmux_write_ts_header (map.data, pi, &payload_len, &payload_offs))
         goto fail;
     }
 
     TS_DEBUG ("Outputting %d bytes to section. %d remaining after",
         payload_len, payload_remain - payload_len);
 
-    memcpy (data + payload_offs, cur_in, payload_len);
+    memcpy (map.data + payload_offs, cur_in, payload_len);
 
     cur_in += payload_len;
     payload_remain -= payload_len;
 
+    gst_buffer_unmap (buf, &map);
+
     /* we do not write PCR in section */
     if (G_UNLIKELY (!tsmux_packet_out (mux, buf, -1))) {
       /* buffer given away */
@@ -938,6 +945,8 @@ tsmux_write_section (TsMux * mux, TsMuxSection * section)
   /* ERRORS */
 fail:
   {
+    if (map.data && buf)
+      gst_buffer_unmap (buf, &map);
     if (buf)
       gst_buffer_unref (buf);
     return FALSE;