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.
This commit is contained in:
David Schleef 2010-02-23 19:48:10 -08:00
parent e31922913f
commit acb6ebbc9a
2 changed files with 49 additions and 1 deletions

View 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_BUFFER, "New file for each buffer", "buffer"},
{GST_MULTI_FILE_SINK_NEXT_DISCONT, "New file after each discontinuity", {GST_MULTI_FILE_SINK_NEXT_DISCONT, "New file after each discontinuity",
"discont"}, "discont"},
{GST_MULTI_FILE_SINK_NEXT_KEY_FRAME, "New file at each key frame "
"(Useful for MPEG-TS segmenting)", "key-frame"},
{0, NULL, NULL} {0, NULL, NULL}
}; };
@ -248,6 +250,8 @@ gst_multi_file_sink_init (GstMultiFileSink * multifilesink,
multifilesink->post_messages = DEFAULT_POST_MESSAGES; multifilesink->post_messages = DEFAULT_POST_MESSAGES;
gst_base_sink_set_sync (GST_BASE_SINK (multifilesink), FALSE); gst_base_sink_set_sync (GST_BASE_SINK (multifilesink), FALSE);
multifilesink->next_segment = GST_CLOCK_TIME_NONE;
} }
static void static void
@ -428,6 +432,47 @@ gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
goto stdio_write_error; 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, ret = fwrite (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 1,
multifilesink->file); multifilesink->file);
if (ret != 1) if (ret != 1)

View file

@ -53,7 +53,8 @@ typedef struct _GstMultiFileSinkClass GstMultiFileSinkClass;
typedef enum { typedef enum {
GST_MULTI_FILE_SINK_NEXT_BUFFER, 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; } GstMultiFileSinkNext;
struct _GstMultiFileSink struct _GstMultiFileSink
@ -65,6 +66,8 @@ struct _GstMultiFileSink
gboolean post_messages; gboolean post_messages;
GstMultiFileSinkNext next_file; GstMultiFileSinkNext next_file;
FILE *file; FILE *file;
gint64 next_segment;
}; };
struct _GstMultiFileSinkClass struct _GstMultiFileSinkClass