summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2010-02-23 19:48:10 -0800
committerDavid Schleef <ds@schleef.org>2010-03-09 13:52:30 -0800
commitacb6ebbc9a057c18d568f20d9ce1e75bb8841f05 (patch)
tree61477b1858dd07a3ed7501491a9bfd0ca4488456
parente31922913fc60e6b6a2527ec08799a6877ac3900 (diff)
multifilesink: Add key-frame option to next-file
This allows segmenting of MPEG-TS files at key frames, which is exactly what is needed for Apple's HTTP streaming.
-rw-r--r--gst/multifile/gstmultifilesink.c45
-rw-r--r--gst/multifile/gstmultifilesink.h5
2 files changed, 49 insertions, 1 deletions
diff --git a/gst/multifile/gstmultifilesink.c b/gst/multifile/gstmultifilesink.c
index e11e70943..be301288d 100644
--- a/gst/multifile/gstmultifilesink.c
+++ b/gst/multifile/gstmultifilesink.c
@@ -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
@@ -434,6 +438,47 @@ gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
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)
+ goto stdio_write_error;
+
+ break;
default:
g_assert_not_reached ();
}
diff --git a/gst/multifile/gstmultifilesink.h b/gst/multifile/gstmultifilesink.h
index b95988f0a..176891100 100644
--- a/gst/multifile/gstmultifilesink.h
+++ b/gst/multifile/gstmultifilesink.h
@@ -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