multifilesink: Add key-frame option to next-file
authorDavid Schleef <ds@schleef.org>
Wed, 24 Feb 2010 03:48:10 +0000 (19:48 -0800)
committerDavid Schleef <ds@schleef.org>
Tue, 9 Mar 2010 21:52:30 +0000 (13:52 -0800)
This allows segmenting of MPEG-TS files at key frames, which is
exactly what is needed for Apple's HTTP streaming.

gst/multifile/gstmultifilesink.c
gst/multifile/gstmultifilesink.h

index e11e7094318b567f45b6fbc7e80e60eb2048012f..be301288d8af144f0ecad5ac83a5c0b9e6be8445 100644 (file)
@@ -162,6 +162,8 @@ gst_multi_file_sink_next_get_type (void)
     {GST_MULTI_FILE_SINK_NEXT_BUFFER, "New file for each buffer", "buffer"},
     {GST_MULTI_FILE_SINK_NEXT_DISCONT, "New file after each discontinuity",
         "discont"},
+    {GST_MULTI_FILE_SINK_NEXT_KEY_FRAME, "New file at each key frame "
+          "(Useful for MPEG-TS segmenting)", "key-frame"},
     {0, NULL, NULL}
   };
 
@@ -248,6 +250,8 @@ gst_multi_file_sink_init (GstMultiFileSink * multifilesink,
   multifilesink->post_messages = DEFAULT_POST_MESSAGES;
 
   gst_base_sink_set_sync (GST_BASE_SINK (multifilesink), FALSE);
+
+  multifilesink->next_segment = GST_CLOCK_TIME_NONE;
 }
 
 static void
@@ -428,6 +432,47 @@ gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
           goto stdio_write_error;
       }
 
+      ret = fwrite (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 1,
+          multifilesink->file);
+      if (ret != 1)
+        goto stdio_write_error;
+
+      break;
+    case GST_MULTI_FILE_SINK_NEXT_KEY_FRAME:
+      if (multifilesink->next_segment == GST_CLOCK_TIME_NONE) {
+        if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
+          multifilesink->next_segment = GST_BUFFER_TIMESTAMP (buffer) +
+              10 * GST_SECOND;
+        }
+      }
+
+      if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
+          GST_BUFFER_TIMESTAMP (buffer) >= multifilesink->next_segment &&
+          !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
+        if (multifilesink->file) {
+          fclose (multifilesink->file);
+          multifilesink->file = NULL;
+
+          filename = g_strdup_printf (multifilesink->filename,
+              multifilesink->index);
+          gst_multi_file_sink_post_message (multifilesink, buffer, filename);
+          g_free (filename);
+          multifilesink->index++;
+        }
+
+        multifilesink->next_segment += 10 * GST_SECOND;
+      }
+
+      if (multifilesink->file == NULL) {
+        filename = g_strdup_printf (multifilesink->filename,
+            multifilesink->index);
+        multifilesink->file = g_fopen (filename, "wb");
+        g_free (filename);
+
+        if (multifilesink->file == NULL)
+          goto stdio_write_error;
+      }
+
       ret = fwrite (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 1,
           multifilesink->file);
       if (ret != 1)
index b95988f0af5120946d114d06379f97ede5a960e1..176891100d58832d7c8a687a245916f220087945 100644 (file)
@@ -53,7 +53,8 @@ typedef struct _GstMultiFileSinkClass GstMultiFileSinkClass;
 
 typedef enum {
   GST_MULTI_FILE_SINK_NEXT_BUFFER,
-  GST_MULTI_FILE_SINK_NEXT_DISCONT
+  GST_MULTI_FILE_SINK_NEXT_DISCONT,
+  GST_MULTI_FILE_SINK_NEXT_KEY_FRAME
 } GstMultiFileSinkNext;
 
 struct _GstMultiFileSink
@@ -65,6 +66,8 @@ struct _GstMultiFileSink
   gboolean post_messages;
   GstMultiFileSinkNext next_file;
   FILE *file;
+
+  gint64 next_segment;
 };
 
 struct _GstMultiFileSinkClass