matroskamux: set delta unit on all buffers except cluster start ones
authorZaheer Abbas Merali <zaheerabbas@merali.org>
Fri, 21 May 2010 13:35:34 +0000 (14:35 +0100)
committerZaheer Abbas Merali <zaheerabbas@merali.org>
Tue, 1 Jun 2010 15:43:04 +0000 (16:43 +0100)
gst/matroska/ebml-write.c
gst/matroska/ebml-write.h
gst/matroska/matroska-mux.c

index 6bcc3e4..0691d5d 100644 (file)
@@ -212,7 +212,7 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
  * Flush the cache.
  */
 void
-gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
+gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe)
 {
   GstBuffer *buffer;
 
@@ -226,7 +226,7 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
   if (ebml->last_write_result == GST_FLOW_OK) {
     if (ebml->need_newsegment) {
       GstEvent *ev;
-
+      GST_WARNING ("new segment being sent");
       ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
       if (gst_pad_push_event (ebml->srcpad, ev))
         ebml->need_newsegment = FALSE;
@@ -234,6 +234,9 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
     if (ebml->writing_streamheader) {
       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
     }
+    if (!is_keyframe) {
+      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
+    }
     ebml->last_write_result = gst_pad_push (ebml->srcpad, buffer);
   } else {
     gst_buffer_unref (buffer);
@@ -403,6 +406,7 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
     if (ebml->writing_streamheader) {
       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
     }
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
     ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
   } else {
     gst_buffer_unref (buf);
@@ -446,13 +450,14 @@ gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
       return;
     } else {
       GST_LOG ("Seek outside cache range. Clearing...");
-      gst_ebml_write_flush_cache (ebml);
+      gst_ebml_write_flush_cache (ebml, FALSE);
     }
   }
 
   event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, pos, -1, 0);
   if (gst_pad_push_event (ebml->srcpad, event)) {
-    GST_DEBUG ("Seek'd to offset %" G_GUINT64_FORMAT, pos);
+    GST_DEBUG ("Seek'd to offset %" G_GUINT64_FORMAT " from %" G_GUINT64_FORMAT,
+        pos, ebml->pos);
   } else {
     GST_WARNING ("Seek to offset %" G_GUINT64_FORMAT " failed", pos);
   }
@@ -773,6 +778,7 @@ gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
   guint64 oldpos = ebml->pos;
   GstBuffer *buf = gst_buffer_new_and_alloc (8);
 
+  GST_DEBUG ("replace_uint");
   gst_ebml_write_seek (ebml, pos);
   GST_BUFFER_SIZE (buf) = 0;
   gst_ebml_write_set_uint (buf, num, 8);
@@ -810,5 +816,5 @@ gst_ebml_write_header (GstEbmlWrite * ebml, const gchar * doctype,
   gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
   gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
   gst_ebml_write_master_finish (ebml, pos);
-  gst_ebml_write_flush_cache (ebml);
+  gst_ebml_write_flush_cache (ebml, FALSE);
 }
index 38f0766..2240f4f 100644 (file)
@@ -84,7 +84,8 @@ GstBuffer*    gst_ebml_stop_streamheader   (GstEbmlWrite *ebml);
  */
 void    gst_ebml_write_set_cache     (GstEbmlWrite *ebml,
                                       guint         size);
-void    gst_ebml_write_flush_cache   (GstEbmlWrite *ebml);
+void    gst_ebml_write_flush_cache   (GstEbmlWrite *ebml,
+                                      gboolean is_keyframe);
 
 /*
  * Seeking.
index f0244c4..feaff36 100644 (file)
@@ -2005,7 +2005,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
   GstClockTime duration = 0;
   guint32 segment_uid[4];
   GTimeVal time = { 0, 0 };
-  GstBuffer *streamheader_buffer;
 
   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
     ebml->caps = gst_caps_from_string ("video/webm");
@@ -2016,7 +2015,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
   doctype = mux->doctype;
   GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
       doctype, mux->doctype_version);
-  gst_ebml_start_streamheader (ebml);
   gst_ebml_write_header (ebml, doctype, mux->doctype_version);
 
   /* the rest of the header is cached */
@@ -2108,30 +2106,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
   gst_ebml_write_master_finish (ebml, master);
 
   /* lastly, flush the cache */
-  gst_ebml_write_flush_cache (ebml);
-  streamheader_buffer = gst_ebml_stop_streamheader (ebml);
-  /* lets set the pad caps, which is how the buffer caps is set currently :( */
-  {
-    GstCaps *caps;
-    GstStructure *s;
-    GValue streamheader = { 0 };
-    GValue bufval = { 0 };
-    if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
-      caps = gst_caps_from_string ("video/webm");
-    } else {
-      caps = gst_caps_from_string ("video/x-matroska");
-    }
-    s = gst_caps_get_structure (caps, 0);
-    g_value_init (&streamheader, GST_TYPE_ARRAY);
-    g_value_init (&bufval, GST_TYPE_BUFFER);
-    gst_value_set_buffer (&bufval, streamheader_buffer);
-    gst_value_array_append_value (&streamheader, &bufval);
-    g_value_unset (&bufval);
-    gst_structure_set_value (s, "streamheader", &streamheader);
-    g_value_unset (&streamheader);
-    gst_caps_unref (ebml->caps);
-    ebml->caps = caps;
-  }
+  gst_ebml_write_flush_cache (ebml, FALSE);
 }
 
 static void
@@ -2240,7 +2215,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
     }
 
     gst_ebml_write_master_finish (ebml, master);
-    gst_ebml_write_flush_cache (ebml);
+    gst_ebml_write_flush_cache (ebml, FALSE);
   }
 
   /* tags */
@@ -2271,6 +2246,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
    * - all entries are local to the segment (so pos - segment_master).
    * - so each entry is at 12 + 20 + num * 28. */
   if (!mux->is_live) {
+    GST_DEBUG_OBJECT (mux, "not live");
     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
         mux->info_pos - mux->segment_master);
     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
@@ -2348,6 +2324,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
       gst_ebml_write_seek (ebml, my_pos);
     }
   }
+  GST_DEBUG_OBJECT (mux, "finishing segment");
   /* finish segment - this also writes element length */
   gst_ebml_write_master_finish (ebml, mux->segment_pos);
 }
@@ -2496,6 +2473,34 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
   return ret;
 }
 
+static void
+gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
+{
+  GstCaps *caps;
+  GstStructure *s;
+  GValue streamheader = { 0 };
+  GValue bufval = { 0 };
+  GstBuffer *streamheader_buffer;
+  GstEbmlWrite *ebml = mux->ebml_write;
+
+  streamheader_buffer = gst_ebml_stop_streamheader (ebml);
+  if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
+    caps = gst_caps_from_string ("video/webm");
+  } else {
+    caps = gst_caps_from_string ("video/x-matroska");
+  }
+  s = gst_caps_get_structure (caps, 0);
+  g_value_init (&streamheader, GST_TYPE_ARRAY);
+  g_value_init (&bufval, GST_TYPE_BUFFER);
+  gst_value_set_buffer (&bufval, streamheader_buffer);
+  gst_value_array_append_value (&streamheader, &bufval);
+  g_value_unset (&bufval);
+  gst_structure_set_value (s, "streamheader", &streamheader);
+  g_value_unset (&streamheader);
+  gst_caps_unref (ebml->caps);
+  ebml->caps = caps;
+}
+
 /**
  * gst_matroska_mux_write_data:
  * @mux: #GstMatroskaMux
@@ -2563,8 +2568,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
     /* start a new cluster every two seconds or at keyframe */
     if (mux->cluster_time + GST_SECOND * 2 < GST_BUFFER_TIMESTAMP (buf)
         || is_video_keyframe) {
-
-      gst_ebml_write_master_finish (ebml, mux->cluster);
+      if (!mux->is_live)
+        gst_ebml_write_master_finish (ebml, mux->cluster);
       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
       mux->cluster_pos = ebml->pos;
       gst_ebml_write_set_cache (ebml, 0x20);
@@ -2572,7 +2577,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
           GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
-      gst_ebml_write_flush_cache (ebml);
+      gst_ebml_write_flush_cache (ebml, TRUE);
       mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
           mux->prev_cluster_size);
@@ -2585,7 +2590,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
         GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
-    gst_ebml_write_flush_cache (ebml);
+    gst_ebml_write_flush_cache (ebml, TRUE);
     mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
   }
 
@@ -2662,12 +2667,12 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
         GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
     gst_ebml_write_buffer (ebml, hdr);
-    gst_ebml_write_flush_cache (ebml);
+    gst_ebml_write_flush_cache (ebml, FALSE);
     gst_ebml_write_buffer (ebml, buf);
 
     return gst_ebml_last_write_result (ebml);
   } else {
-    gst_ebml_write_set_cache (ebml, 0x40);
+    gst_ebml_write_set_cache (ebml, GST_BUFFER_SIZE (buf) * 2);
     /* write and call order slightly unnatural,
      * but avoids seek and minizes pushing */
     blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
@@ -2682,7 +2687,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
         GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
     gst_ebml_write_buffer (ebml, hdr);
     gst_ebml_write_master_finish_full (ebml, blockgroup, GST_BUFFER_SIZE (buf));
-    gst_ebml_write_flush_cache (ebml);
+    gst_ebml_write_flush_cache (ebml, FALSE);
     gst_ebml_write_buffer (ebml, buf);
     return gst_ebml_last_write_result (ebml);
   }
@@ -2702,6 +2707,7 @@ static GstFlowReturn
 gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
 {
   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
+  GstEbmlWrite *ebml = mux->ebml_write;
   GstMatroskaPad *best;
   gboolean popped;
   GstFlowReturn ret;
@@ -2716,7 +2722,9 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
       return GST_FLOW_ERROR;
     }
     mux->state = GST_MATROSKA_MUX_STATE_HEADER;
+    gst_ebml_start_streamheader (ebml);
     gst_matroska_mux_start (mux);
+    gst_matroska_mux_stop_streamheader (mux);
     mux->state = GST_MATROSKA_MUX_STATE_DATA;
   }