flv: port to 0.11
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 4 Jul 2011 09:09:19 +0000 (11:09 +0200)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 4 Jul 2011 09:50:02 +0000 (11:50 +0200)
* use G_DEFINE_TYPE
* adjust to new GstBuffer
* misc segment and caps changes

gst/flv/gstflvdemux.c
gst/flv/gstflvdemux.h
gst/flv/gstflvmux.c

index 5fa4068..a74f2f2 100644 (file)
@@ -77,7 +77,8 @@ static GstStaticPadTemplate video_src_template =
 GST_DEBUG_CATEGORY_STATIC (flvdemux_debug);
 #define GST_CAT_DEFAULT flvdemux_debug
 
-GST_BOILERPLATE (GstFlvDemux, gst_flv_demux, GstElement, GST_TYPE_ELEMENT);
+#define gst_flv_demux_parent_class parent_class
+G_DEFINE_TYPE (GstFlvDemux, gst_flv_demux, GST_TYPE_ELEMENT);
 
 /* 9 bytes of header + 4 bytes of first previous tag size */
 #define FLV_HEADER_SIZE 13
@@ -527,17 +528,22 @@ static GstFlowReturn
 gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
 {
   GstFlowReturn ret = GST_FLOW_OK;
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
+  GstByteReader reader;
   guint8 type = 0;
+  guint8 *data;
+  gsize size;
 
-  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) >= 7, GST_FLOW_ERROR);
+  g_return_val_if_fail (gst_buffer_get_size (buffer) >= 7, GST_FLOW_ERROR);
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  gst_byte_reader_init (&reader, data, size);
 
   gst_byte_reader_skip (&reader, 7);
 
   GST_LOG_OBJECT (demux, "parsing a script tag");
 
   if (!gst_byte_reader_get_uint8 (&reader, &type))
-    return GST_FLOW_OK;
+    goto cleanup;
 
   /* Must be string */
   if (type == 2) {
@@ -554,7 +560,7 @@ gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
 
       if (!gst_byte_reader_get_uint8 (&reader, &type)) {
         g_free (function_name);
-        return GST_FLOW_OK;
+        goto cleanup;
       }
 
       switch (type) {
@@ -565,7 +571,7 @@ gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
           /* ECMA array */
           if (!gst_byte_reader_get_uint32_be (&reader, &nb_elems)) {
             g_free (function_name);
-            return GST_FLOW_OK;
+            goto cleanup;
           }
 
           /* The number of elements is just a hint, some files have
@@ -591,7 +597,7 @@ gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
         default:
           GST_DEBUG_OBJECT (demux, "Unhandled script data type : %d", type);
           g_free (function_name);
-          return GST_FLOW_OK;
+          goto cleanup;
       }
 
       demux->push_tags = TRUE;
@@ -616,6 +622,9 @@ gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
     }
   }
 
+cleanup:
+  gst_buffer_unmap (buffer, data, -1);
+
   return ret;
 }
 
@@ -656,13 +665,17 @@ gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag,
       break;
     case 10:
     {
+      guint8 *data = NULL;
+      gsize size;
+
+      if (demux->audio_codec_data)
+        data = gst_buffer_map (demux->audio_codec_data, &size, NULL,
+            GST_MAP_READ);
       /* use codec-data to extract and verify samplerate */
-      if (demux->audio_codec_data &&
-          GST_BUFFER_SIZE (demux->audio_codec_data) >= 2) {
+      if (demux->audio_codec_data && size >= 2) {
         gint freq_index;
 
-        freq_index =
-            ((GST_READ_UINT16_BE (GST_BUFFER_DATA (demux->audio_codec_data))));
+        freq_index = GST_READ_UINT16_BE (data);
         freq_index = (freq_index & 0x0780) >> 7;
         adjusted_rate =
             gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
@@ -674,6 +687,8 @@ gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag,
           adjusted_rate = rate;
         }
       }
+      if (data)
+        gst_buffer_unmap (demux->audio_codec_data, data, -1);
       caps = gst_caps_new_simple ("audio/mpeg",
           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
           "stream-format", G_TYPE_STRING, "raw", NULL);
@@ -766,20 +781,30 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
   guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
   guint32 codec_data = 0, pts_ext = 0;
   guint8 flags = 0;
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
   GstBuffer *outbuf;
+  gsize size;
 
   GST_LOG_OBJECT (demux, "parsing an audio tag");
 
   if (demux->no_more_pads && !demux->audio_pad) {
     GST_WARNING_OBJECT (demux,
         "Signaled no-more-pads already but had no audio pad -- ignoring");
-    goto beach;
+    return GST_FLOW_OK;
   }
 
-  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) == demux->tag_size,
+  g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
       GST_FLOW_ERROR);
 
+  /* Error out on tags with too small headers */
+  if (gst_buffer_get_size (buffer) < 11) {
+    GST_ERROR_OBJECT (demux, "Too small tag size (%d)",
+        gst_buffer_get_size (buffer));
+    return GST_FLOW_ERROR;
+  }
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+
   /* Grab information about audio tag */
   pts = GST_READ_UINT24_BE (data);
   /* read the pts extension to 32 bits integer */
@@ -790,20 +815,13 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
   GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
       data[2], data[3], pts);
 
-  /* Error out on tags with too small headers */
-  if (GST_BUFFER_SIZE (buffer) < 11) {
-    GST_ERROR_OBJECT (demux, "Too small tag size (%d)",
-        GST_BUFFER_SIZE (buffer));
-    return GST_FLOW_ERROR;
-  }
-
-  /* Silently skip buffers with no data */
-  if (GST_BUFFER_SIZE (buffer) == 11)
-    return GST_FLOW_OK;
-
   /* Skip the stream id and go directly to the flags */
   flags = GST_READ_UINT8 (data + 7);
 
+  /* Silently skip buffers with no data */
+  if (size == 11)
+    goto beach;
+
   /* Channels */
   if (flags & 0x01) {
     channels = 2;
@@ -858,9 +876,17 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
       ret = GST_FLOW_ERROR;
       goto beach;
     }
+#ifndef GST_DISABLE_GST_DEBUG
+    {
+      GstCaps *caps;
 
-    GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
-        GST_PAD_CAPS (demux->audio_pad));
+      caps = gst_pad_get_current_caps (demux->audio_pad);
+      GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
+          caps);
+      if (caps)
+        gst_caps_unref (caps);
+    }
+#endif
 
     /* Set functions on the pad */
     gst_pad_set_query_type_function (demux->audio_pad,
@@ -914,9 +940,8 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
   }
 
   /* Create buffer from pad */
-  outbuf =
-      gst_buffer_create_sub (buffer, 7 + codec_data,
-      demux->tag_data_size - codec_data);
+  outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
+      7 + codec_data, demux->tag_data_size - codec_data);
 
   if (demux->audio_codec_tag == 10) {
     guint8 aac_packet_type = GST_READ_UINT8 (data + 8);
@@ -950,7 +975,6 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
   GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
-  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (demux->audio_pad));
 
   if (demux->duration == GST_CLOCK_TIME_NONE ||
       demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
@@ -968,24 +992,18 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
     demux->audio_need_discont = FALSE;
   }
 
-  gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME,
-      GST_BUFFER_TIMESTAMP (outbuf));
+  demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
 
   /* Do we need a newsegment event ? */
   if (G_UNLIKELY (demux->audio_need_segment)) {
-    if (demux->close_seg_event)
-      gst_pad_push_event (demux->audio_pad,
-          gst_event_ref (demux->close_seg_event));
-
+    /* FIXME need one segment sent for all stream to maintain a/v sync */
     if (!demux->new_seg_event) {
       GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
           GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (demux->segment.last_stop),
+          GST_TIME_ARGS (demux->segment.position),
           GST_TIME_ARGS (demux->segment.stop));
-      demux->new_seg_event =
-          gst_event_new_new_segment (FALSE, demux->segment.rate,
-          demux->segment.format, demux->segment.last_stop,
-          demux->segment.stop, demux->segment.last_stop);
+      demux->segment.start = demux->segment.time = demux->segment.position;
+      demux->new_seg_event = gst_event_new_segment (&demux->segment);
     } else {
       GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
     }
@@ -997,7 +1015,8 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
 
   GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
       " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
-      GST_BUFFER_SIZE (outbuf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+      gst_buffer_get_size (outbuf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf));
 
   if (!GST_CLOCK_TIME_IS_VALID (demux->audio_start)) {
@@ -1022,7 +1041,7 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
   ret = gst_pad_push (demux->audio_pad, outbuf);
   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
     if (demux->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
-        demux->segment.last_stop > demux->segment.stop) {
+        demux->segment.position > demux->segment.stop) {
       /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
        * we are at the end of the segment, so we just need to jump
        * back to the previous section. */
@@ -1043,6 +1062,8 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
   demux->audio_linked = TRUE;
 
 beach:
+  gst_buffer_unmap (buffer, data, -1);
+
   return ret;
 }
 
@@ -1144,21 +1165,28 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
   guint32 pts = 0, codec_data = 1, pts_ext = 0;
   gboolean keyframe = FALSE;
   guint8 flags = 0, codec_tag = 0;
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
   GstBuffer *outbuf;
+  gsize size;
 
-  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) == demux->tag_size,
+  g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
       GST_FLOW_ERROR);
 
   GST_LOG_OBJECT (demux, "parsing a video tag");
 
-
   if (demux->no_more_pads && !demux->video_pad) {
     GST_WARNING_OBJECT (demux,
         "Signaled no-more-pads already but had no audio pad -- ignoring");
-    goto beach;
+    return GST_FLOW_OK;
   }
 
+  if (gst_buffer_get_size (buffer) < 12) {
+    GST_ERROR_OBJECT (demux, "Too small tag size");
+    return GST_FLOW_ERROR;
+  }
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+
   /* Grab information about video tag */
   pts = GST_READ_UINT24_BE (data);
   /* read the pts extension to 32 bits integer */
@@ -1169,11 +1197,6 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
   GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
       data[2], data[3], pts);
 
-  if (GST_BUFFER_SIZE (buffer) < 12) {
-    GST_ERROR_OBJECT (demux, "Too small tag size");
-    return GST_FLOW_ERROR;
-  }
-
   /* Skip the stream id and go directly to the flags */
   flags = GST_READ_UINT8 (data + 7);
 
@@ -1223,8 +1246,17 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
      * metadata tag that would come later and trigger a caps change */
     demux->got_par = FALSE;
 
-    GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
-        GST_PAD_CAPS (demux->video_pad));
+#ifndef GST_DISABLE_GST_DEBUG
+    {
+      GstCaps *caps;
+
+      caps = gst_pad_get_current_caps (demux->video_pad);
+      GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
+          caps);
+      if (caps)
+        gst_caps_unref (caps);
+    }
+#endif
 
     /* Set functions on the pad */
     gst_pad_set_query_type_function (demux->video_pad,
@@ -1280,9 +1312,8 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
   }
 
   /* Create buffer from pad */
-  outbuf =
-      gst_buffer_create_sub (buffer, 7 + codec_data,
-      demux->tag_data_size - codec_data);
+  outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
+      7 + codec_data, demux->tag_data_size - codec_data);
 
   if (demux->video_codec_tag == 7) {
     guint8 avc_packet_type = GST_READ_UINT8 (data + 8);
@@ -1316,7 +1347,6 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
   GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
-  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (demux->video_pad));
 
   if (demux->duration == GST_CLOCK_TIME_NONE ||
       demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
@@ -1335,24 +1365,18 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
     demux->video_need_discont = FALSE;
   }
 
-  gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME,
-      GST_BUFFER_TIMESTAMP (outbuf));
+  demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
 
   /* Do we need a newsegment event ? */
   if (G_UNLIKELY (demux->video_need_segment)) {
-    if (demux->close_seg_event)
-      gst_pad_push_event (demux->video_pad,
-          gst_event_ref (demux->close_seg_event));
-
+    /* FIXME need one segment sent for all stream to maintain a/v sync */
     if (!demux->new_seg_event) {
       GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
           GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (demux->segment.last_stop),
+          GST_TIME_ARGS (demux->segment.position),
           GST_TIME_ARGS (demux->segment.stop));
-      demux->new_seg_event =
-          gst_event_new_new_segment (FALSE, demux->segment.rate,
-          demux->segment.format, demux->segment.last_stop,
-          demux->segment.stop, demux->segment.last_stop);
+      demux->segment.start = demux->segment.time = demux->segment.position;
+      demux->new_seg_event = gst_event_new_segment (&demux->segment);
     } else {
       GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
     }
@@ -1364,7 +1388,7 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
 
   GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
       " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
-      ", keyframe (%d)", GST_BUFFER_SIZE (outbuf),
+      ", keyframe (%d)", gst_buffer_get_size (outbuf),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
       keyframe);
@@ -1392,7 +1416,7 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
 
   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
     if (demux->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
-        demux->segment.last_stop > demux->segment.stop) {
+        demux->segment.position > demux->segment.stop) {
       /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
        * we are at the end of the segment, so we just need to jump
        * back to the previous section. */
@@ -1413,6 +1437,7 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
   demux->video_linked = TRUE;
 
 beach:
+  gst_buffer_unmap (buffer, data, -1);
   return ret;
 }
 
@@ -1424,16 +1449,20 @@ gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
   guint32 tag_data_size;
   guint8 type;
   gboolean keyframe = TRUE;
-  GstClockTime ret;
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  GstClockTime ret = GST_CLOCK_TIME_NONE;
+  guint8 *data, *bdata;
+  gsize size;
+
+  g_return_val_if_fail (gst_buffer_get_size (buffer) >= 12,
+      GST_CLOCK_TIME_NONE);
 
-  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) >= 12, GST_CLOCK_TIME_NONE);
+  data = bdata = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
 
   type = data[0];
 
   if (type != 9 && type != 8 && type != 18) {
     GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
-    return GST_CLOCK_TIME_NONE;
+    goto exit;
   }
 
   if (type == 9)
@@ -1443,10 +1472,10 @@ gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
 
   tag_data_size = GST_READ_UINT24_BE (data + 1);
 
-  if (GST_BUFFER_SIZE (buffer) >= tag_data_size + 11 + 4) {
+  if (size >= tag_data_size + 11 + 4) {
     if (GST_READ_UINT32_BE (data + tag_data_size + 11) != tag_data_size + 11) {
       GST_WARNING_OBJECT (demux, "Invalid tag size");
-      return GST_CLOCK_TIME_NONE;
+      goto exit;
     }
   }
 
@@ -1483,6 +1512,8 @@ gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
   if (demux->duration == GST_CLOCK_TIME_NONE || demux->duration < ret)
     demux->duration = ret;
 
+exit:
+  gst_buffer_unmap (buffer, bdata, -1);
   return ret;
 }
 
@@ -1491,9 +1522,11 @@ gst_flv_demux_parse_tag_type (GstFlvDemux * demux, GstBuffer * buffer)
 {
   GstFlowReturn ret = GST_FLOW_OK;
   guint8 tag_type = 0;
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
 
-  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) >= 4, GST_FLOW_ERROR);
+  g_return_val_if_fail (gst_buffer_get_size (buffer) >= 4, GST_FLOW_ERROR);
+
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
 
   tag_type = data[0];
 
@@ -1521,6 +1554,8 @@ gst_flv_demux_parse_tag_type (GstFlvDemux * demux, GstBuffer * buffer)
   GST_LOG_OBJECT (demux, "tag data size is %" G_GUINT64_FORMAT,
       demux->tag_data_size);
 
+  gst_buffer_unmap (buffer, data, -1);
+
   return ret;
 }
 
@@ -1528,9 +1563,11 @@ static GstFlowReturn
 gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
 {
   GstFlowReturn ret = GST_FLOW_OK;
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
 
-  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) >= 9, GST_FLOW_ERROR);
+  g_return_val_if_fail (gst_buffer_get_size (buffer) >= 9, GST_FLOW_ERROR);
+
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
 
   /* Check for the FLV tag */
   if (data[0] == 'F' && data[1] == 'L' && data[2] == 'V') {
@@ -1543,12 +1580,9 @@ gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
     }
   }
 
-  /* Jump over the 4 first bytes */
-  data += 4;
-
   /* Now look at audio/video flags */
   {
-    guint8 flags = data[0];
+    guint8 flags = data[4];
 
     demux->has_video = demux->has_audio = FALSE;
 
@@ -1569,6 +1603,7 @@ gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
   demux->need_header = FALSE;
 
 beach:
+  gst_buffer_unmap (buffer, data, -1);
   return ret;
 }
 
@@ -1644,11 +1679,6 @@ gst_flv_demux_cleanup (GstFlvDemux * demux)
     demux->new_seg_event = NULL;
   }
 
-  if (demux->close_seg_event) {
-    gst_event_unref (demux->close_seg_event);
-    demux->close_seg_event = NULL;
-  }
-
   gst_adapter_clear (demux->adapter);
 
   if (demux->audio_codec_data) {
@@ -1716,7 +1746,8 @@ gst_flv_demux_chain (GstPad * pad, GstBuffer * buffer)
   demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
 
   GST_LOG_OBJECT (demux, "received buffer of %d bytes at offset %"
-      G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
+      G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
+      GST_BUFFER_OFFSET (buffer));
 
   if (G_UNLIKELY (GST_BUFFER_OFFSET (buffer) == 0)) {
     GST_DEBUG_OBJECT (demux, "beginning of file, expect header");
@@ -1876,20 +1907,16 @@ parse:
 
       if (!demux->indexed) {
         if (demux->offset == demux->file_size - sizeof (guint32)) {
-          GstBuffer *buffer =
-              gst_adapter_take_buffer (demux->adapter, sizeof (guint32));
-          GstByteReader *reader = gst_byte_reader_new_from_buffer (buffer);
           guint64 seek_offset;
+          guint8 *data;
 
-          if (!gst_adapter_available (demux->adapter) >= sizeof (guint32)) {
-            /* error */
-          }
+          data = gst_adapter_take (demux->adapter, 4);
+          if (!data)
+            goto no_index;
 
-          seek_offset =
-              demux->file_size - sizeof (guint32) -
-              gst_byte_reader_peek_uint32_be_unchecked (reader);
-          gst_byte_reader_free (reader);
-          gst_buffer_unref (buffer);
+          seek_offset = demux->file_size - sizeof (guint32) -
+              GST_READ_UINT32_BE (data);
+          g_free (data);
 
           GST_INFO_OBJECT (demux,
               "Seeking to beginning of last tag at %" G_GUINT64_FORMAT,
@@ -1966,10 +1993,10 @@ gst_flv_demux_pull_range (GstFlvDemux * demux, GstPad * pad, guint64 offset,
     return ret;
   }
 
-  if (G_UNLIKELY (*buffer && GST_BUFFER_SIZE (*buffer) != size)) {
+  if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
     GST_WARNING_OBJECT (demux,
         "partial pull got %d when expecting %d from offset %" G_GUINT64_FORMAT,
-        GST_BUFFER_SIZE (*buffer), size, offset);
+        gst_buffer_get_size (*buffer), size, offset);
     gst_buffer_unref (*buffer);
     ret = GST_FLOW_UNEXPECTED;
     *buffer = NULL;
@@ -2216,6 +2243,7 @@ gst_flv_demux_get_metadata (GstFlvDemux * demux)
   GstFormat fmt = GST_FORMAT_BYTES;
   size_t tag_size, size;
   GstBuffer *buffer = NULL;
+  guint8 *data;
 
   if (G_UNLIKELY (!gst_pad_query_peer_duration (demux->sinkpad, &fmt, &offset)
           || fmt != GST_FORMAT_BYTES))
@@ -2231,7 +2259,9 @@ gst_flv_demux_get_metadata (GstFlvDemux * demux)
           4, &buffer))
     goto exit;
 
-  tag_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buffer));
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
+  tag_size = GST_READ_UINT32_BE (data);
+  gst_buffer_unmap (buffer, data, -1);
   GST_DEBUG_OBJECT (demux, "last tag size: %" G_GSIZE_FORMAT, tag_size);
   gst_buffer_unref (buffer);
   buffer = NULL;
@@ -2242,8 +2272,10 @@ gst_flv_demux_get_metadata (GstFlvDemux * demux)
     goto exit;
 
   /* a consistency check */
-  size = GST_READ_UINT24_BE (GST_BUFFER_DATA (buffer) + 1);
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
+  size = GST_READ_UINT24_BE (data + 1);
   if (size != tag_size - 11) {
+    gst_buffer_unmap (buffer, data, -1);
     GST_DEBUG_OBJECT (demux,
         "tag size %" G_GSIZE_FORMAT ", expected %" G_GSIZE_FORMAT
         ", corrupt or truncated file", size, tag_size - 11);
@@ -2254,7 +2286,8 @@ gst_flv_demux_get_metadata (GstFlvDemux * demux)
   gst_flv_demux_parse_tag_timestamp (demux, FALSE, buffer, &size);
 
   /* maybe get some more metadata */
-  if (GST_BUFFER_DATA (buffer)[0] == 18) {
+  if (data[0] == 18) {
+    gst_buffer_unmap (buffer, data, -1);
     gst_buffer_unref (buffer);
     buffer = NULL;
     GST_DEBUG_OBJECT (demux, "script tag, pulling it to parse");
@@ -2262,6 +2295,8 @@ gst_flv_demux_get_metadata (GstFlvDemux * demux)
     if (GST_FLOW_OK == gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
             tag_size, &buffer))
       gst_flv_demux_parse_tag_script (demux, buffer);
+  } else {
+    gst_buffer_unmap (buffer, data, -1);
   }
 
 exit:
@@ -2319,13 +2354,13 @@ gst_flv_demux_loop (GstPad * pad)
   if (demux->segment.rate < 0.0) {
     /* check end of section */
     if ((gint64) demux->offset >= demux->to_offset ||
-        demux->segment.last_stop >= demux->segment.stop + 2 * GST_SECOND ||
+        demux->segment.position >= demux->segment.stop + 2 * GST_SECOND ||
         (demux->audio_done && demux->video_done))
       ret = gst_flv_demux_seek_to_prev_keyframe (demux);
   } else {
     /* check EOS condition */
     if ((demux->segment.stop != -1) &&
-        (demux->segment.last_stop >= demux->segment.stop)) {
+        (demux->segment.position >= demux->segment.stop)) {
       ret = GST_FLOW_UNEXPECTED;
     }
   }
@@ -2346,6 +2381,15 @@ pause:
     gst_pad_pause_task (pad);
 
     if (ret == GST_FLOW_UNEXPECTED) {
+      /* handle end-of-stream/segment */
+      /* so align our position with the end of it, if there is one
+       * this ensures a subsequent will arrive at correct base/acc time */
+      if (demux->segment.rate > 0.0 &&
+          GST_CLOCK_TIME_IS_VALID (demux->segment.stop))
+        demux->segment.position = demux->segment.stop;
+      else if (demux->segment.rate < 0.0)
+        demux->segment.position = demux->segment.start;
+
       /* perform EOS logic */
       if (!demux->no_more_pads) {
         gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
@@ -2403,7 +2447,7 @@ gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment)
 
   g_return_val_if_fail (segment != NULL, 0);
 
-  time = segment->last_stop;
+  time = segment->position;
 
   if (demux->index) {
     /* Let's check if we have an index entry for that seek time */
@@ -2417,7 +2461,7 @@ gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment)
 
       GST_DEBUG_OBJECT (demux, "found index entry for %" GST_TIME_FORMAT
           " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
-          GST_TIME_ARGS (segment->last_stop), GST_TIME_ARGS (time), bytes);
+          GST_TIME_ARGS (segment->position), GST_TIME_ARGS (time), bytes);
 
       /* Key frame seeking */
       if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
@@ -2425,7 +2469,7 @@ gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment)
         if (time < segment->start) {
           segment->start = segment->time = time;
         }
-        segment->last_stop = time;
+        segment->position = time;
       }
     } else {
       GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
@@ -2463,13 +2507,13 @@ flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
       &demux->segment);
 
   /* Apply the seek to our segment */
-  gst_segment_set_seek (&seeksegment, rate, format, flags,
+  gst_segment_do_seek (&seeksegment, rate, format, flags,
       start_type, start, stop_type, stop, &update);
 
   GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
       &seeksegment);
 
-  if (flush || seeksegment.last_stop != demux->segment.last_stop) {
+  if (flush || seeksegment.position != demux->segment.position) {
     /* Do the actual seeking */
     guint64 offset = gst_flv_demux_find_offset (demux, &seeksegment);
 
@@ -2636,7 +2680,7 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
 
   if (flush) {
     /* Stop flushing upstream we need to pull */
-    gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
+    gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
   }
 
   /* Work on a copy until we are sure the seek succeeded. */
@@ -2646,29 +2690,29 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
       &demux->segment);
 
   /* Apply the seek to our segment */
-  gst_segment_set_seek (&seeksegment, rate, format, flags,
+  gst_segment_do_seek (&seeksegment, rate, format, flags,
       start_type, start, stop_type, stop, &update);
 
   GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
       &seeksegment);
 
-  if (flush || seeksegment.last_stop != demux->segment.last_stop) {
+  if (flush || seeksegment.position != demux->segment.position) {
     /* Do the actual seeking */
     /* index is reliable if it is complete or we do not go to far ahead */
     if (seeking && !demux->indexed &&
-        seeksegment.last_stop > demux->index_max_time + 10 * GST_SECOND) {
+        seeksegment.position > demux->index_max_time + 10 * GST_SECOND) {
       GST_DEBUG_OBJECT (demux, "delaying seek to post-scan; "
           " index only up to %" GST_TIME_FORMAT,
           GST_TIME_ARGS (demux->index_max_time));
       /* stop flushing for now */
       if (flush)
-        gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop ());
+        gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
       /* delegate scanning and index building to task thread to avoid
        * occupying main (UI) loop */
       if (demux->seek_event)
         gst_event_unref (demux->seek_event);
       demux->seek_event = gst_event_ref (event);
-      demux->seek_time = seeksegment.last_stop;
+      demux->seek_time = seeksegment.position;
       demux->state = FLV_STATE_SEEK;
       /* do not know about succes yet, but we did care and handled it */
       ret = TRUE;
@@ -2682,35 +2726,9 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
     ret = TRUE;
   }
 
-  if (G_UNLIKELY (demux->close_seg_event)) {
-    gst_event_unref (demux->close_seg_event);
-    demux->close_seg_event = NULL;
-  }
-
   if (flush) {
     /* Stop flushing, the sinks are at time 0 now */
-    gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop ());
-  } else {
-    GST_DEBUG_OBJECT (demux, "closing running segment %" GST_SEGMENT_FORMAT,
-        &demux->segment);
-
-    /* Close the current segment for a linear playback */
-    if (demux->segment.rate >= 0) {
-      /* for forward playback, we played from start to last_stop */
-      demux->close_seg_event = gst_event_new_new_segment (TRUE,
-          demux->segment.rate, demux->segment.format,
-          demux->segment.start, demux->segment.last_stop, demux->segment.time);
-    } else {
-      gint64 stop;
-
-      if ((stop = demux->segment.stop) == -1)
-        stop = demux->segment.duration;
-
-      /* for reverse playback, we played from stop to last_stop. */
-      demux->close_seg_event = gst_event_new_new_segment (TRUE,
-          demux->segment.rate, demux->segment.format,
-          demux->segment.last_stop, stop, demux->segment.last_stop);
-    }
+    gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
   }
 
   if (ret) {
@@ -2721,7 +2739,7 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
       gst_element_post_message (GST_ELEMENT (demux),
           gst_message_new_segment_start (GST_OBJECT (demux),
-              demux->segment.format, demux->segment.last_stop));
+              demux->segment.format, demux->segment.position));
     }
 
     /* Tell all the stream a new segment is needed */
@@ -2740,10 +2758,7 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
           GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
           GST_TIME_ARGS (demux->segment.start),
           GST_TIME_ARGS (demux->segment.stop));
-      demux->new_seg_event =
-          gst_event_new_new_segment (FALSE, demux->segment.rate,
-          demux->segment.format, demux->segment.start,
-          demux->segment.stop, demux->segment.start);
+      demux->new_seg_event = gst_event_new_segment (&demux->segment);
     }
   }
 
@@ -2781,9 +2796,28 @@ wrong_format:
 static gboolean
 gst_flv_demux_sink_activate (GstPad * sinkpad)
 {
-  if (gst_pad_check_pull_range (sinkpad)) {
-    return gst_pad_activate_pull (sinkpad, TRUE);
-  } else {
+  GstQuery *query;
+  gboolean pull_mode;
+
+  query = gst_query_new_scheduling ();
+
+  if (!gst_pad_peer_query (sinkpad, query)) {
+    gst_query_unref (query);
+    goto activate_push;
+  }
+
+  gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL);
+  gst_query_unref (query);
+
+  if (!pull_mode)
+    goto activate_push;
+
+  GST_DEBUG_OBJECT (sinkpad, "activating pull");
+  return gst_pad_activate_pull (sinkpad, TRUE);
+
+activate_push:
+  {
+    GST_DEBUG_OBJECT (sinkpad, "activating push");
     return gst_pad_activate_push (sinkpad, TRUE);
   }
 }
@@ -2862,22 +2896,17 @@ gst_flv_demux_sink_event (GstPad * pad, GstEvent * event)
         GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
       ret = TRUE;
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      GstFormat format;
-      gdouble rate;
-      gint64 start, stop, time;
-      gboolean update;
+      GstSegment in_segment;
 
       GST_DEBUG_OBJECT (demux, "received new segment");
 
-      gst_event_parse_new_segment (event, &update, &rate, &format, &start,
-          &stop, &time);
+      gst_event_copy_segment (event, &in_segment);
 
-      if (format == GST_FORMAT_TIME) {
+      if (in_segment.format == GST_FORMAT_TIME) {
         /* time segment, this is perfect, copy over the values. */
-        gst_segment_set_newsegment (&demux->segment, update, rate, format,
-            start, stop, time);
+        memcpy (&demux->segment, &in_segment, sizeof (in_segment));
 
         GST_DEBUG_OBJECT (demux, "NEWSEGMENT: %" GST_SEGMENT_FORMAT,
             &demux->segment);
@@ -2976,9 +3005,9 @@ gst_flv_demux_query (GstPad * pad, GstQuery * query)
       }
 
       GST_DEBUG_OBJECT (pad, "position query, replying %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (demux->segment.last_stop));
+          GST_TIME_ARGS (demux->segment.position));
 
-      gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.last_stop);
+      gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.position);
 
       break;
     }
@@ -3152,11 +3181,6 @@ gst_flv_demux_dispose (GObject * object)
     demux->new_seg_event = NULL;
   }
 
-  if (demux->close_seg_event) {
-    gst_event_unref (demux->close_seg_event);
-    demux->close_seg_event = NULL;
-  }
-
   if (demux->audio_codec_data) {
     gst_buffer_unref (demux->audio_codec_data);
     demux->audio_codec_data = NULL;
@@ -3196,23 +3220,6 @@ gst_flv_demux_dispose (GObject * object)
 }
 
 static void
-gst_flv_demux_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 (&flv_sink_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&audio_src_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&video_src_template));
-  gst_element_class_set_details_simple (element_class, "FLV Demuxer",
-      "Codec/Demuxer",
-      "Demux FLV feeds into digital streams",
-      "Julien Moutte <julien@moutte.net>");
-}
-
-static void
 gst_flv_demux_class_init (GstFlvDemuxClass * klass)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
@@ -3224,10 +3231,21 @@ gst_flv_demux_class_init (GstFlvDemuxClass * klass)
       GST_DEBUG_FUNCPTR (gst_flv_demux_change_state);
   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_flv_demux_set_index);
   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_flv_demux_get_index);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&flv_sink_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&audio_src_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&video_src_template));
+  gst_element_class_set_details_simple (gstelement_class, "FLV Demuxer",
+      "Codec/Demuxer",
+      "Demux FLV feeds into digital streams",
+      "Julien Moutte <julien@moutte.net>");
 }
 
 static void
-gst_flv_demux_init (GstFlvDemux * demux, GstFlvDemuxClass * g_class)
+gst_flv_demux_init (GstFlvDemux * demux)
 {
   demux->sinkpad =
       gst_pad_new_from_static_template (&flv_sink_template, "sink");
index 60083e8..3b50f96 100644 (file)
@@ -71,7 +71,6 @@ struct _GstFlvDemux
 
   GstSegment segment;
 
-  GstEvent *close_seg_event;
   GstEvent *new_seg_event;
 
   GstTagList *taglist;
index f1612a4..b3f4865 100644 (file)
@@ -82,19 +82,9 @@ static GstStaticPadTemplate audiosink_templ = GST_STATIC_PAD_TEMPLATE ("audio",
         "audio/x-speex, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 };")
     );
 
-#define _do_init(type)                                                          \
-  G_STMT_START{                                                                 \
-    static const GInterfaceInfo tag_setter_info = {                             \
-      NULL,                                                                     \
-      NULL,                                                                     \
-      NULL                                                                      \
-    };                                                                          \
-    g_type_add_interface_static (type, GST_TYPE_TAG_SETTER,                     \
-                                 &tag_setter_info);                             \
-  }G_STMT_END
-
-GST_BOILERPLATE_FULL (GstFlvMux, gst_flv_mux, GstElement, GST_TYPE_ELEMENT,
-    _do_init);
+#define gst_flv_mux_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFlvMux, gst_flv_mux, GST_TYPE_ELEMENT,
+    G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
 
 static void gst_flv_mux_finalize (GObject * object);
 static GstFlowReturn
@@ -102,9 +92,12 @@ gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data);
 
 static gboolean gst_flv_mux_handle_src_event (GstPad * pad, GstEvent * event);
 static GstPad *gst_flv_mux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name);
+    GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps);
 static void gst_flv_mux_release_pad (GstElement * element, GstPad * pad);
 
+static gboolean gst_flv_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps);
+static gboolean gst_flv_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps);
+
 static void gst_flv_mux_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 static void gst_flv_mux_set_property (GObject * object,
@@ -127,23 +120,27 @@ gst_flv_mux_index_entry_free (GstFlvMuxIndexEntry * entry)
   g_slice_free (GstFlvMuxIndexEntry, entry);
 }
 
-static void
-gst_flv_mux_base_init (gpointer g_class)
+static GstBuffer *
+_gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
 {
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  GstBuffer *buf;
 
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&videosink_templ));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&audiosink_templ));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_templ));
-  gst_element_class_set_details_simple (element_class, "FLV muxer",
-      "Codec/Muxer",
-      "Muxes video/audio streams into a FLV stream",
-      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+  buf = gst_buffer_new ();
+  gst_buffer_take_memory (buf, -1,
+      gst_memory_new_wrapped (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
+          mem, free_func, size, 0, size));
 
-  GST_DEBUG_CATEGORY_INIT (flvmux_debug, "flvmux", 0, "FLV muxer");
+  return buf;
+}
+
+static void
+_gst_buffer_new_and_alloc (gsize size, GstBuffer ** buffer, guint8 ** data)
+{
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (buffer != NULL);
+
+  *data = g_malloc (size);
+  *buffer = _gst_buffer_new_wrapped (*data, size, g_free);
 }
 
 static void
@@ -181,10 +178,23 @@ gst_flv_mux_class_init (GstFlvMuxClass * klass)
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_flv_mux_request_new_pad);
   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_flv_mux_release_pad);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&videosink_templ));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&audiosink_templ));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&src_templ));
+  gst_element_class_set_details_simple (gstelement_class, "FLV muxer",
+      "Codec/Muxer",
+      "Muxes video/audio streams into a FLV stream",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+  GST_DEBUG_CATEGORY_INIT (flvmux_debug, "flvmux", 0, "FLV muxer");
 }
 
 static void
-gst_flv_mux_init (GstFlvMux * mux, GstFlvMuxClass * g_class)
+gst_flv_mux_init (GstFlvMux * mux)
 {
   mux->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
   gst_pad_set_event_function (mux->srcpad, gst_flv_mux_handle_src_event);
@@ -264,6 +274,27 @@ gst_flv_mux_handle_sink_event (GstPad * pad, GstEvent * event)
   gboolean ret = TRUE;
 
   switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+      GstFlvPad *flvpad;
+
+      gst_event_parse_caps (event, &caps);
+
+      /* find stream data */
+      flvpad = (GstFlvPad *) gst_pad_get_element_private (pad);
+      g_assert (flvpad);
+
+      if (flvpad->video) {
+        ret = gst_flv_mux_video_pad_setcaps (pad, caps);
+      } else {
+        ret = gst_flv_mux_audio_pad_setcaps (pad, caps);
+      }
+      /* and eat */
+      ret = FALSE;
+      gst_event_unref (event);
+      break;
+    }
     case GST_EVENT_TAG:{
       GstTagList *list;
       GstTagSetter *setter = GST_TAG_SETTER (mux);
@@ -474,14 +505,13 @@ gst_flv_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
 
 static GstPad *
 gst_flv_mux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * pad_name)
+    GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
 {
   GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
   GstFlvMux *mux = GST_FLV_MUX (element);
   GstFlvPad *cpad;
   GstPad *pad = NULL;
   const gchar *name = NULL;
-  GstPadSetCapsFunction setcapsfunc = NULL;
   gboolean video;
 
   if (mux->state != GST_FLV_MUX_STATE_HEADER) {
@@ -497,7 +527,6 @@ gst_flv_mux_request_new_pad (GstElement * element,
     mux->have_audio = TRUE;
     name = "audio";
     video = FALSE;
-    setcapsfunc = GST_DEBUG_FUNCPTR (gst_flv_mux_audio_pad_setcaps);
   } else if (templ == gst_element_class_get_pad_template (klass, "video")) {
     if (mux->have_video) {
       GST_WARNING_OBJECT (mux, "Already have a video pad");
@@ -506,7 +535,6 @@ gst_flv_mux_request_new_pad (GstElement * element,
     mux->have_video = TRUE;
     name = "video";
     video = TRUE;
-    setcapsfunc = GST_DEBUG_FUNCPTR (gst_flv_mux_video_pad_setcaps);
   } else {
     GST_WARNING_OBJECT (mux, "Invalid template");
     return NULL;
@@ -537,7 +565,6 @@ gst_flv_mux_request_new_pad (GstElement * element,
   gst_pad_set_event_function (pad,
       GST_DEBUG_FUNCPTR (gst_flv_mux_handle_sink_event));
 
-  gst_pad_set_setcaps_function (pad, setcapsfunc);
   gst_pad_set_active (pad, TRUE);
   gst_element_add_pad (element, pad);
 
@@ -562,10 +589,9 @@ gst_flv_mux_release_pad (GstElement * element, GstPad * pad)
 static GstFlowReturn
 gst_flv_mux_push (GstFlvMux * mux, GstBuffer * buffer)
 {
-  gst_buffer_set_caps (buffer, GST_PAD_CAPS (mux->srcpad));
   /* pushing the buffer that rewrites the header will make it no longer be the
    * total output size in bytes, but it doesn't matter at that point */
-  mux->byte_count += GST_BUFFER_SIZE (buffer);
+  mux->byte_count += gst_buffer_get_size (buffer);
 
   return gst_pad_push (mux->srcpad, buffer);
 }
@@ -576,8 +602,7 @@ gst_flv_mux_create_header (GstFlvMux * mux)
   GstBuffer *header;
   guint8 *data;
 
-  header = gst_buffer_new_and_alloc (9 + 4);
-  data = GST_BUFFER_DATA (header);
+  _gst_buffer_new_and_alloc (9 + 4, &header, &data);
 
   data[0] = 'F';
   data[1] = 'L';
@@ -609,8 +634,7 @@ gst_flv_mux_preallocate_index (GstFlvMux * mux)
   GST_DEBUG_OBJECT (mux, "preallocating %d bytes for the index",
       preallocate_size);
 
-  tmp = gst_buffer_new_and_alloc (preallocate_size);
-  data = GST_BUFFER_DATA (tmp);
+  _gst_buffer_new_and_alloc (preallocate_size, &tmp, &data);
 
   /* prefill the space with a gstfiller: <spaces> script tag variable */
   GST_WRITE_UINT16_BE (data, 9);        /* 9 characters */
@@ -624,8 +648,10 @@ gst_flv_mux_preallocate_index (GstFlvMux * mux)
 static GstBuffer *
 gst_flv_mux_create_number_script_value (const gchar * name, gdouble value)
 {
-  GstBuffer *tmp = gst_buffer_new_and_alloc (2 + strlen (name) + 1 + 8);
-  guint8 *data = GST_BUFFER_DATA (tmp);
+  GstBuffer *tmp;
+  guint8 *data;
+
+  _gst_buffer_new_and_alloc (2 + strlen (name) + 1 + 8, &tmp, &data);
 
   GST_WRITE_UINT16_BE (data, strlen (name));    /* name length */
   memcpy (&data[2], name, strlen (name));
@@ -647,8 +673,9 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
 
   GST_DEBUG_OBJECT (mux, "tags = %" GST_PTR_FORMAT, tags);
 
-  script_tag = gst_buffer_new_and_alloc (11);
-  data = GST_BUFFER_DATA (script_tag);
+  /* FIXME perhaps some bytewriter'ing here ... */
+
+  _gst_buffer_new_and_alloc (11, &script_tag, &data);
 
   data[0] = 18;
 
@@ -663,8 +690,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
   /* Stream ID */
   data[8] = data[9] = data[10] = 0;
 
-  tmp = gst_buffer_new_and_alloc (13);
-  data = GST_BUFFER_DATA (tmp);
+  _gst_buffer_new_and_alloc (13, &tmp, &data);
   data[0] = 2;                  /* string */
   data[1] = 0;
   data[2] = 10;                 /* length 10 */
@@ -673,8 +699,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
   script_tag = gst_buffer_join (script_tag, tmp);
 
   n_tags = (tags) ? gst_structure_n_fields ((GstStructure *) tags) : 0;
-  tmp = gst_buffer_new_and_alloc (5);
-  data = GST_BUFFER_DATA (tmp);
+  _gst_buffer_new_and_alloc (5, &tmp, &data);
   data[0] = 8;                  /* ECMA array */
   GST_WRITE_UINT32_BE (data + 1, n_tags);
   script_tag = gst_buffer_join (script_tag, tmp);
@@ -724,8 +749,8 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
       if (!gst_tag_list_get_string (tags, tag_name, &s))
         continue;
 
-      tmp = gst_buffer_new_and_alloc (2 + strlen (t) + 1 + 2 + strlen (s));
-      data = GST_BUFFER_DATA (tmp);
+      _gst_buffer_new_and_alloc (2 + strlen (t) + 1 + 2 + strlen (s),
+          &tmp, &data);
       data[0] = 0;              /* tag name length */
       data[1] = strlen (t);
       memcpy (&data[2], t, strlen (t));
@@ -767,8 +792,9 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
     d /= (gdouble) GST_SECOND;
 
     GST_DEBUG_OBJECT (mux, "determined the duration to be %f", d);
-    data = GST_BUFFER_DATA (script_tag);
+    data = gst_buffer_map (script_tag, NULL, NULL, GST_MAP_WRITE);
     GST_WRITE_DOUBLE_BE (data + 29 + 2 + 8 + 1, d);
+    gst_buffer_unmap (script_tag, data, -1);
   }
 
   if (mux->have_video) {
@@ -784,8 +810,9 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
       }
     }
 
-    if (video_pad && GST_PAD_CAPS (video_pad)) {
-      GstStructure *s = gst_caps_get_structure (GST_PAD_CAPS (video_pad), 0);
+    if (video_pad && gst_pad_has_current_caps (video_pad)) {
+      GstCaps *caps;
+      GstStructure *s;
       gint size;
       gint num, den;
 
@@ -797,6 +824,10 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
       script_tag = gst_buffer_join (script_tag, tmp);
       tags_written++;
 
+      caps = gst_pad_get_current_caps (video_pad);
+      s = gst_caps_get_structure (caps, 0);
+      gst_caps_unref (caps);
+
       if (gst_structure_get_int (s, "width", &size)) {
         GST_DEBUG_OBJECT (mux, "putting width %d in the metadata", size);
 
@@ -871,8 +902,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
   {
     const gchar *s = "GStreamer FLV muxer";
 
-    tmp = gst_buffer_new_and_alloc (2 + 15 + 1 + 2 + strlen (s));
-    data = GST_BUFFER_DATA (tmp);
+    _gst_buffer_new_and_alloc (2 + 15 + 1 + 2 + strlen (s), &tmp, &data);
     data[0] = 0;                /* 15 bytes name */
     data[1] = 15;
     memcpy (&data[2], "metadatacreator", 15);
@@ -906,8 +936,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
         months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
         tm->tm_year + 1900);
 
-    tmp = gst_buffer_new_and_alloc (2 + 12 + 1 + 2 + strlen (s));
-    data = GST_BUFFER_DATA (tmp);
+    _gst_buffer_new_and_alloc (2 + 12 + 1 + 2 + strlen (s), &tmp, &data);
     data[0] = 0;                /* 12 bytes name */
     data[1] = 12;
     memcpy (&data[2], "creationdate", 12);
@@ -921,25 +950,24 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
     tags_written++;
   }
 
-  tmp = gst_buffer_new_and_alloc (2 + 0 + 1);
-  data = GST_BUFFER_DATA (tmp);
+  _gst_buffer_new_and_alloc (2 + 0 + 1, &tmp, &data);
   data[0] = 0;                  /* 0 byte size */
   data[1] = 0;
   data[2] = 9;                  /* end marker */
   script_tag = gst_buffer_join (script_tag, tmp);
   tags_written++;
 
-  tmp = gst_buffer_new_and_alloc (4);
-  data = GST_BUFFER_DATA (tmp);
-  GST_WRITE_UINT32_BE (data, GST_BUFFER_SIZE (script_tag));
+  _gst_buffer_new_and_alloc (4, &tmp, &data);
+  GST_WRITE_UINT32_BE (data, gst_buffer_get_size (script_tag));
   script_tag = gst_buffer_join (script_tag, tmp);
 
-  data = GST_BUFFER_DATA (script_tag);
-  data[1] = ((GST_BUFFER_SIZE (script_tag) - 11 - 4) >> 16) & 0xff;
-  data[2] = ((GST_BUFFER_SIZE (script_tag) - 11 - 4) >> 8) & 0xff;
-  data[3] = ((GST_BUFFER_SIZE (script_tag) - 11 - 4) >> 0) & 0xff;
+  data = gst_buffer_map (script_tag, NULL, NULL, GST_MAP_WRITE);
+  data[1] = ((gst_buffer_get_size (script_tag) - 11 - 4) >> 16) & 0xff;
+  data[2] = ((gst_buffer_get_size (script_tag) - 11 - 4) >> 8) & 0xff;
+  data[3] = ((gst_buffer_get_size (script_tag) - 11 - 4) >> 0) & 0xff;
 
   GST_WRITE_UINT32_BE (data + 11 + 13 + 1, tags_written);
+  gst_buffer_unmap (script_tag, data, -1);
 
   return script_tag;
 }
@@ -954,26 +982,29 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
   guint32 timestamp =
       (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) ? GST_BUFFER_TIMESTAMP (buffer) /
       GST_MSECOND : cpad->last_timestamp / GST_MSECOND;
+  guint8 *bdata;
+  gsize bsize;
+
+  bdata = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
 
   size = 11;
   if (cpad->video) {
     size += 1;
     if (cpad->video_codec == 7)
-      size += 4 + GST_BUFFER_SIZE (buffer);
+      size += 4 + bsize;
     else
-      size += GST_BUFFER_SIZE (buffer);
+      size += bsize;
   } else {
     size += 1;
     if (cpad->audio_codec == 10)
-      size += 1 + GST_BUFFER_SIZE (buffer);
+      size += 1 + bsize;
     else
-      size += GST_BUFFER_SIZE (buffer);
+      size += bsize;
   }
   size += 4;
 
-  tag = gst_buffer_new_and_alloc (size);
+  _gst_buffer_new_and_alloc (size, &tag, &data);
   GST_BUFFER_TIMESTAMP (tag) = timestamp * GST_MSECOND;
-  data = GST_BUFFER_DATA (tag);
   memset (data, 0, size);
 
   data[0] = (cpad->video) ? 9 : 8;
@@ -1005,11 +1036,9 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
       /* FIXME: what to do about composition time */
       data[13] = data[14] = data[15] = 0;
 
-      memcpy (data + 11 + 1 + 4, GST_BUFFER_DATA (buffer),
-          GST_BUFFER_SIZE (buffer));
+      memcpy (data + 11 + 1 + 4, bdata, bsize);
     } else {
-      memcpy (data + 11 + 1, GST_BUFFER_DATA (buffer),
-          GST_BUFFER_SIZE (buffer));
+      memcpy (data + 11 + 1, bdata, bsize);
     }
   } else {
     data[11] |= (cpad->audio_codec << 4) & 0xf0;
@@ -1020,17 +1049,21 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
     if (cpad->audio_codec == 10) {
       data[12] = is_codec_data ? 0 : 1;
 
-      memcpy (data + 11 + 1 + 1, GST_BUFFER_DATA (buffer),
-          GST_BUFFER_SIZE (buffer));
+      memcpy (data + 11 + 1 + 1, bdata, bsize);
     } else {
-      memcpy (data + 11 + 1, GST_BUFFER_DATA (buffer),
-          GST_BUFFER_SIZE (buffer));
+      memcpy (data + 11 + 1, bdata, bsize);
     }
   }
 
+  gst_buffer_unmap (buffer, bdata, -1);
+
   GST_WRITE_UINT32_BE (data + size - 4, size - 4);
 
-  gst_buffer_copy_metadata (tag, buffer, GST_BUFFER_COPY_TIMESTAMPS);
+  GST_BUFFER_TIMESTAMP (tag) = GST_BUFFER_TIMESTAMP (buffer);
+  GST_BUFFER_DURATION (tag) = GST_BUFFER_DURATION (buffer);
+  GST_BUFFER_OFFSET (tag) = GST_BUFFER_OFFSET (buffer);
+  GST_BUFFER_OFFSET_END (tag) = GST_BUFFER_OFFSET_END (buffer);
+
   /* mark the buffer if it's an audio buffer and there's also video being muxed
    * or it's a video interframe */
   if ((mux->have_video && !cpad->video) ||
@@ -1140,7 +1173,7 @@ gst_flv_mux_write_header (GstFlvMux * mux)
   gst_structure_set_value (structure, "streamheader", &streamheader);
   g_value_unset (&streamheader);
 
-  if (GST_PAD_CAPS (mux->srcpad) == NULL)
+  if (!gst_pad_has_current_caps (mux->srcpad))
     gst_pad_set_caps (mux->srcpad, caps);
 
   gst_caps_unref (caps);
@@ -1196,7 +1229,7 @@ gst_flv_mux_write_buffer (GstFlvMux * mux, GstFlvPad * cpad)
   GstFlowReturn ret;
 
   /* arrange downstream running time */
-  buffer = gst_buffer_make_metadata_writable (buffer);
+  buffer = gst_buffer_make_writable (buffer);
   GST_BUFFER_TIMESTAMP (buffer) =
       gst_segment_to_running_time (&cpad->collect.segment,
       GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer));
@@ -1255,13 +1288,15 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
   GList *l;
   guint32 index_len, allocate_size;
   guint32 i, index_skip;
+  GstSegment segment;
 
   if (mux->streamable)
     return GST_FLOW_OK;
 
   /* seek back to the preallocated index space */
-  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
-      13 + 29, GST_CLOCK_TIME_NONE, 13 + 29);
+  gst_segment_init (&segment, GST_FORMAT_BYTES);
+  segment.start = segment.time = 13 + 29;
+  event = gst_event_new_segment (&segment);
   if (!gst_pad_push_event (mux->srcpad, event)) {
     GST_WARNING_OBJECT (mux, "Seek to rewrite header failed");
     return GST_FLOW_OK;
@@ -1308,8 +1343,7 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
   /* see size calculation in gst_flv_mux_preallocate_index */
   allocate_size = 11 + 8 + 22 + 10 + index_len * 18;
   GST_DEBUG_OBJECT (mux, "Allocating %d bytes for index", allocate_size);
-  index = gst_buffer_new_and_alloc (allocate_size);
-  data = GST_BUFFER_DATA (index);
+  _gst_buffer_new_and_alloc (allocate_size, &index, &data);
 
   GST_WRITE_UINT16_BE (data, 9);        /* the 'keyframes' key */
   memcpy (data + 2, "keyframes", 9);
@@ -1358,8 +1392,7 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
     guint8 *data;
     guint32 remaining_filler_size;
 
-    tmp = gst_buffer_new_and_alloc (14);
-    data = GST_BUFFER_DATA (tmp);
+    _gst_buffer_new_and_alloc (14, &tmp, &data);
     GST_WRITE_UINT16_BE (data, 9);
     memcpy (data + 2, "gstfiller", 9);
     GST_WRITE_UINT8 (data + 11, 2);     /* string */
@@ -1376,7 +1409,6 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
 
   rewrite = gst_buffer_join (rewrite, index);
 
-  gst_buffer_set_caps (rewrite, GST_PAD_CAPS (mux->srcpad));
   return gst_flv_mux_push (mux, rewrite);
 }
 
@@ -1391,14 +1423,16 @@ gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data)
   gboolean eos = TRUE;
 
   if (mux->state == GST_FLV_MUX_STATE_HEADER) {
+    GstSegment segment;
+
     if (mux->collect->data == NULL) {
       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
           ("No input streams configured"));
       return GST_FLOW_ERROR;
     }
 
-    if (gst_pad_push_event (mux->srcpad,
-            gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0)))
+    gst_segment_init (&segment, GST_FORMAT_BYTES);
+    if (gst_pad_push_event (mux->srcpad, gst_event_new_segment (&segment)))
       ret = gst_flv_mux_write_header (mux);
     else
       ret = GST_FLOW_ERROR;