mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
I don't know how I ever got to introducing this madness, but I was wrong. *REALLY* wrong. It hasn't even worked, it s...
Original commit message from CVS: I don't know how I ever got to introducing this madness, but I was wrong. *REALLY* wrong. It hasn't even worked, it still doesn't work and it will never work because the whole concept of doing a multifile output in filesink is completely braindead. Signal EOS, close file, set new filename and reset to PLAYING is so much easier. This patch removes all the multifile output cruft that I introduced and makes filesink simply work.
This commit is contained in:
parent
e5872bf925
commit
2ddc5c4974
4 changed files with 224 additions and 218 deletions
|
@ -46,8 +46,7 @@ enum {
|
|||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_LOCATION,
|
||||
ARG_MAXFILESIZE,
|
||||
ARG_LOCATION
|
||||
};
|
||||
|
||||
GST_PAD_EVENT_MASK_FUNCTION (gst_filesink_get_event_mask,
|
||||
|
@ -56,8 +55,16 @@ GST_PAD_EVENT_MASK_FUNCTION (gst_filesink_get_event_mask,
|
|||
GST_SEEK_METHOD_END |
|
||||
GST_SEEK_FLAG_FLUSH },
|
||||
{ GST_EVENT_FLUSH, 0 },
|
||||
{ GST_EVENT_DISCONTINUOUS, 0 },
|
||||
{ GST_EVENT_NEW_MEDIA, 0 }
|
||||
{ GST_EVENT_DISCONTINUOUS, 0 }
|
||||
)
|
||||
|
||||
GST_PAD_QUERY_TYPE_FUNCTION (gst_filesink_get_query_types,
|
||||
GST_QUERY_TOTAL,
|
||||
GST_QUERY_POSITION
|
||||
)
|
||||
|
||||
GST_PAD_FORMATS_FUNCTION (gst_filesink_get_formats,
|
||||
GST_FORMAT_BYTES
|
||||
)
|
||||
|
||||
|
||||
|
@ -73,6 +80,8 @@ static gboolean gst_filesink_open_file (GstFileSink *sink);
|
|||
static void gst_filesink_close_file (GstFileSink *sink);
|
||||
|
||||
static gboolean gst_filesink_handle_event (GstPad *pad, GstEvent *event);
|
||||
static gboolean gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value);
|
||||
static void gst_filesink_chain (GstPad *pad,GstBuffer *buf);
|
||||
|
||||
static GstElementStateReturn gst_filesink_change_state (GstElement *element);
|
||||
|
@ -115,9 +124,6 @@ gst_filesink_class_init (GstFileSinkClass *klass)
|
|||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
|
||||
g_param_spec_string ("location", "File Location", "Location of the file to write",
|
||||
NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAXFILESIZE,
|
||||
g_param_spec_int ("maxfilesize", "MaxFileSize", "Maximum Size Per File in MB (-1 == no limit)",
|
||||
-1, G_MAXINT, -1, G_PARAM_READWRITE));
|
||||
|
||||
gst_filesink_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
|
@ -143,30 +149,12 @@ gst_filesink_init (GstFileSink *filesink)
|
|||
gst_pad_set_event_function(pad, gst_filesink_handle_event);
|
||||
gst_pad_set_event_mask_function(pad, gst_filesink_get_event_mask);
|
||||
|
||||
gst_pad_set_query_function (pad, gst_filesink_pad_query);
|
||||
gst_pad_set_query_type_function (pad, gst_filesink_get_query_types);
|
||||
gst_pad_set_formats_function (pad, gst_filesink_get_formats);
|
||||
|
||||
filesink->filename = NULL;
|
||||
filesink->file = NULL;
|
||||
filesink->filenum = 0;
|
||||
|
||||
filesink->maxfilesize = -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
gst_filesink_getcurrentfilename (GstFileSink *filesink)
|
||||
{
|
||||
g_return_val_if_fail(filesink != NULL, NULL);
|
||||
g_return_val_if_fail(GST_IS_FILESINK(filesink), NULL);
|
||||
if (filesink->filename == NULL) return NULL;
|
||||
g_return_val_if_fail(filesink->filenum >= 0, NULL);
|
||||
|
||||
if (!strstr(filesink->filename, "%"))
|
||||
{
|
||||
if (!filesink->filenum)
|
||||
return g_strdup(filesink->filename);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_strdup_printf(filesink->filename, filesink->filenum);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -180,23 +168,18 @@ gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
switch (prop_id) {
|
||||
case ARG_LOCATION:
|
||||
/* the element must be stopped or paused in order to do this */
|
||||
g_return_if_fail ((GST_STATE (sink) < GST_STATE_PLAYING)
|
||||
|| (GST_STATE (sink) == GST_STATE_PAUSED));
|
||||
g_return_if_fail (GST_STATE (sink) < GST_STATE_PLAYING);
|
||||
if (sink->filename)
|
||||
g_free (sink->filename);
|
||||
sink->filename = g_strdup (g_value_get_string (value));
|
||||
if ( (GST_STATE (sink) == GST_STATE_PAUSED)
|
||||
&& (sink->filename != NULL))
|
||||
{
|
||||
gst_filesink_close_file (sink);
|
||||
gst_filesink_open_file (sink);
|
||||
if ((GST_STATE (sink) == GST_STATE_PAUSED) &&
|
||||
(sink->filename != NULL)) {
|
||||
gst_filesink_close_file (sink);
|
||||
gst_filesink_open_file (sink);
|
||||
}
|
||||
|
||||
break;
|
||||
case ARG_MAXFILESIZE:
|
||||
sink->maxfilesize = g_value_get_int(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -213,10 +196,7 @@ gst_filesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
|
||||
switch (prop_id) {
|
||||
case ARG_LOCATION:
|
||||
g_value_set_string (value, gst_filesink_getcurrentfilename(sink));
|
||||
break;
|
||||
case ARG_MAXFILESIZE:
|
||||
g_value_set_int (value, sink->maxfilesize);
|
||||
g_value_set_string (value, sink->filename);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -230,16 +210,17 @@ gst_filesink_open_file (GstFileSink *sink)
|
|||
g_return_val_if_fail (!GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN), FALSE);
|
||||
|
||||
/* open the file */
|
||||
if (!gst_filesink_getcurrentfilename(sink))
|
||||
if (!sink->filename)
|
||||
{
|
||||
/* Out of files */
|
||||
return FALSE;
|
||||
}
|
||||
sink->file = fopen (gst_filesink_getcurrentfilename(sink), "w");
|
||||
|
||||
sink->file = fopen (sink->filename, "w");
|
||||
if (sink->file == NULL) {
|
||||
perror ("open");
|
||||
gst_element_error (GST_ELEMENT (sink), g_strconcat("Error opening file \"",
|
||||
gst_filesink_getcurrentfilename(sink), "\": ", g_strerror(errno), NULL));
|
||||
gst_element_error (GST_ELEMENT (sink),
|
||||
"Error opening file %s: %s",
|
||||
sink->filename, g_strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -257,15 +238,52 @@ gst_filesink_close_file (GstFileSink *sink)
|
|||
|
||||
if (fclose (sink->file) != 0)
|
||||
{
|
||||
perror ("close");
|
||||
gst_element_error (GST_ELEMENT (sink), g_strconcat("Error closing file \"",
|
||||
gst_filesink_getcurrentfilename(sink), "\": ", g_strerror(errno), NULL));
|
||||
gst_element_error (GST_ELEMENT (sink),
|
||||
"Error closing file %s: %s",
|
||||
sink->filename, g_strerror(errno));
|
||||
}
|
||||
else {
|
||||
GST_FLAG_UNSET (sink, GST_FILESINK_OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value)
|
||||
{
|
||||
GstFileSink *sink = GST_FILESINK (GST_PAD_PARENT (pad));
|
||||
|
||||
switch (type) {
|
||||
case GST_QUERY_TOTAL:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT(sink), GST_FILESINK_OPEN)) {
|
||||
*value = sink->data_written; /* FIXME - doesn't the kernel provide
|
||||
such a function? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_QUERY_POSITION:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT(sink), GST_FILESINK_OPEN)) {
|
||||
*value = ftell (sink->file);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* handle events (search) */
|
||||
static gboolean
|
||||
gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
||||
|
@ -275,31 +293,32 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
|||
|
||||
filesink = GST_FILESINK (gst_pad_get_parent (pad));
|
||||
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN),
|
||||
FALSE);
|
||||
|
||||
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
|
||||
|
||||
switch (type) {
|
||||
case GST_EVENT_SEEK:
|
||||
/* we need to seek */
|
||||
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
|
||||
if (fflush(filesink->file))
|
||||
gst_element_error(GST_ELEMENT(filesink),
|
||||
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
||||
gst_filesink_getcurrentfilename(filesink), g_strerror(errno));
|
||||
g_return_val_if_fail (GST_EVENT_SEEK_FORMAT (event) == GST_FORMAT_BYTES,
|
||||
FALSE);
|
||||
|
||||
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||
g_warning("Any other then byte-offset seeking is not supported!\n");
|
||||
}
|
||||
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
|
||||
if (fflush (filesink->file))
|
||||
gst_element_error (GST_ELEMENT (filesink),
|
||||
"Error flushing file %s: %s",
|
||||
filesink->filename, g_strerror(errno));
|
||||
|
||||
switch (GST_EVENT_SEEK_METHOD(event))
|
||||
{
|
||||
case GST_SEEK_METHOD_SET:
|
||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_SET);
|
||||
break;
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_CUR);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_END);
|
||||
break;
|
||||
default:
|
||||
g_warning("unkown seek method!\n");
|
||||
|
@ -311,26 +330,21 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
|||
gint64 offset;
|
||||
|
||||
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &offset))
|
||||
fseek(filesink->file, offset, SEEK_SET);
|
||||
fseek (filesink->file, offset, SEEK_SET);
|
||||
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_NEW_MEDIA:
|
||||
/* we need to open a new file! */
|
||||
gst_filesink_close_file(filesink);
|
||||
filesink->filenum++;
|
||||
if (!gst_filesink_open_file(filesink)) {
|
||||
/* no more files, give EOS */
|
||||
gst_element_set_eos(GST_ELEMENT(filesink));
|
||||
return FALSE;
|
||||
case GST_EVENT_FLUSH:
|
||||
if (fflush (filesink->file)) {
|
||||
gst_element_error (GST_ELEMENT (filesink),
|
||||
"Error flushing file %s: %s",
|
||||
filesink->filename, g_strerror(errno));
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_FLUSH:
|
||||
if (fflush(filesink->file))
|
||||
gst_element_error(GST_ELEMENT(filesink),
|
||||
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
||||
gst_filesink_getcurrentfilename(filesink), g_strerror(errno));
|
||||
case GST_EVENT_EOS:
|
||||
gst_filesink_close_file (filesink);
|
||||
gst_element_set_eos (GST_ELEMENT (filesink));
|
||||
break;
|
||||
default:
|
||||
gst_pad_event_default (pad, event);
|
||||
|
@ -365,34 +379,23 @@ gst_filesink_chain (GstPad *pad, GstBuffer *buf)
|
|||
return;
|
||||
}
|
||||
|
||||
if (filesink->maxfilesize > 0)
|
||||
{
|
||||
if ((filesink->data_written + GST_BUFFER_SIZE(buf))/(1024*1024) > filesink->maxfilesize)
|
||||
{
|
||||
if (GST_ELEMENT_IS_EVENT_AWARE(GST_ELEMENT(filesink)))
|
||||
{
|
||||
GstEvent *event;
|
||||
event = gst_event_new(GST_EVENT_NEW_MEDIA);
|
||||
gst_pad_send_event(pad, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN))
|
||||
{
|
||||
bytes_written = fwrite (GST_BUFFER_DATA (buf), 1, GST_BUFFER_SIZE (buf), filesink->file);
|
||||
bytes_written = fwrite (GST_BUFFER_DATA (buf), 1,
|
||||
GST_BUFFER_SIZE (buf), filesink->file);
|
||||
if (bytes_written < GST_BUFFER_SIZE (buf))
|
||||
{
|
||||
printf ("filesink : Warning : %d bytes should be written, only %d bytes written\n",
|
||||
g_warning ("filesink: %d bytes should be written, only %d bytes written\n",
|
||||
GST_BUFFER_SIZE (buf), bytes_written);
|
||||
}
|
||||
filesink->data_written += bytes_written;
|
||||
}
|
||||
filesink->data_written += GST_BUFFER_SIZE(buf);
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
g_signal_emit (G_OBJECT (filesink), gst_filesink_signals[SIGNAL_HANDOFF], 0,
|
||||
filesink);
|
||||
g_signal_emit (G_OBJECT (filesink),
|
||||
gst_filesink_signals[SIGNAL_HANDOFF], 0,
|
||||
filesink);
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -400,14 +403,18 @@ gst_filesink_change_state (GstElement *element)
|
|||
{
|
||||
g_return_val_if_fail (GST_IS_FILESINK (element), GST_STATE_FAILURE);
|
||||
|
||||
if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
|
||||
if (GST_FLAG_IS_SET (element, GST_FILESINK_OPEN))
|
||||
gst_filesink_close_file (GST_FILESINK (element));
|
||||
} else {
|
||||
if (!GST_FLAG_IS_SET (element, GST_FILESINK_OPEN)) {
|
||||
if (!gst_filesink_open_file (GST_FILESINK (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
if (GST_FLAG_IS_SET (element, GST_FILESINK_OPEN))
|
||||
gst_filesink_close_file (GST_FILESINK (element));
|
||||
break;
|
||||
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (!GST_FLAG_IS_SET (element, GST_FILESINK_OPEN)) {
|
||||
if (!gst_filesink_open_file (GST_FILESINK (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
|
@ -415,4 +422,3 @@ gst_filesink_change_state (GstElement *element)
|
|||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,17 +59,14 @@ struct _GstFileSink {
|
|||
gchar *filename;
|
||||
FILE *file;
|
||||
|
||||
gint filenum;
|
||||
|
||||
guint64 data_written;
|
||||
gint maxfilesize;
|
||||
};
|
||||
|
||||
struct _GstFileSinkClass {
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*handoff) (GstElement *element,GstPad *pad);
|
||||
void (*handoff) (GstElement *element, GstPad *pad);
|
||||
};
|
||||
|
||||
GType gst_filesink_get_type(void);
|
||||
|
|
|
@ -46,8 +46,7 @@ enum {
|
|||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_LOCATION,
|
||||
ARG_MAXFILESIZE,
|
||||
ARG_LOCATION
|
||||
};
|
||||
|
||||
GST_PAD_EVENT_MASK_FUNCTION (gst_filesink_get_event_mask,
|
||||
|
@ -56,8 +55,16 @@ GST_PAD_EVENT_MASK_FUNCTION (gst_filesink_get_event_mask,
|
|||
GST_SEEK_METHOD_END |
|
||||
GST_SEEK_FLAG_FLUSH },
|
||||
{ GST_EVENT_FLUSH, 0 },
|
||||
{ GST_EVENT_DISCONTINUOUS, 0 },
|
||||
{ GST_EVENT_NEW_MEDIA, 0 }
|
||||
{ GST_EVENT_DISCONTINUOUS, 0 }
|
||||
)
|
||||
|
||||
GST_PAD_QUERY_TYPE_FUNCTION (gst_filesink_get_query_types,
|
||||
GST_QUERY_TOTAL,
|
||||
GST_QUERY_POSITION
|
||||
)
|
||||
|
||||
GST_PAD_FORMATS_FUNCTION (gst_filesink_get_formats,
|
||||
GST_FORMAT_BYTES
|
||||
)
|
||||
|
||||
|
||||
|
@ -73,6 +80,8 @@ static gboolean gst_filesink_open_file (GstFileSink *sink);
|
|||
static void gst_filesink_close_file (GstFileSink *sink);
|
||||
|
||||
static gboolean gst_filesink_handle_event (GstPad *pad, GstEvent *event);
|
||||
static gboolean gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value);
|
||||
static void gst_filesink_chain (GstPad *pad,GstBuffer *buf);
|
||||
|
||||
static GstElementStateReturn gst_filesink_change_state (GstElement *element);
|
||||
|
@ -115,9 +124,6 @@ gst_filesink_class_init (GstFileSinkClass *klass)
|
|||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
|
||||
g_param_spec_string ("location", "File Location", "Location of the file to write",
|
||||
NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAXFILESIZE,
|
||||
g_param_spec_int ("maxfilesize", "MaxFileSize", "Maximum Size Per File in MB (-1 == no limit)",
|
||||
-1, G_MAXINT, -1, G_PARAM_READWRITE));
|
||||
|
||||
gst_filesink_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
|
@ -143,30 +149,12 @@ gst_filesink_init (GstFileSink *filesink)
|
|||
gst_pad_set_event_function(pad, gst_filesink_handle_event);
|
||||
gst_pad_set_event_mask_function(pad, gst_filesink_get_event_mask);
|
||||
|
||||
gst_pad_set_query_function (pad, gst_filesink_pad_query);
|
||||
gst_pad_set_query_type_function (pad, gst_filesink_get_query_types);
|
||||
gst_pad_set_formats_function (pad, gst_filesink_get_formats);
|
||||
|
||||
filesink->filename = NULL;
|
||||
filesink->file = NULL;
|
||||
filesink->filenum = 0;
|
||||
|
||||
filesink->maxfilesize = -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
gst_filesink_getcurrentfilename (GstFileSink *filesink)
|
||||
{
|
||||
g_return_val_if_fail(filesink != NULL, NULL);
|
||||
g_return_val_if_fail(GST_IS_FILESINK(filesink), NULL);
|
||||
if (filesink->filename == NULL) return NULL;
|
||||
g_return_val_if_fail(filesink->filenum >= 0, NULL);
|
||||
|
||||
if (!strstr(filesink->filename, "%"))
|
||||
{
|
||||
if (!filesink->filenum)
|
||||
return g_strdup(filesink->filename);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_strdup_printf(filesink->filename, filesink->filenum);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -180,23 +168,18 @@ gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
switch (prop_id) {
|
||||
case ARG_LOCATION:
|
||||
/* the element must be stopped or paused in order to do this */
|
||||
g_return_if_fail ((GST_STATE (sink) < GST_STATE_PLAYING)
|
||||
|| (GST_STATE (sink) == GST_STATE_PAUSED));
|
||||
g_return_if_fail (GST_STATE (sink) < GST_STATE_PLAYING);
|
||||
if (sink->filename)
|
||||
g_free (sink->filename);
|
||||
sink->filename = g_strdup (g_value_get_string (value));
|
||||
if ( (GST_STATE (sink) == GST_STATE_PAUSED)
|
||||
&& (sink->filename != NULL))
|
||||
{
|
||||
gst_filesink_close_file (sink);
|
||||
gst_filesink_open_file (sink);
|
||||
if ((GST_STATE (sink) == GST_STATE_PAUSED) &&
|
||||
(sink->filename != NULL)) {
|
||||
gst_filesink_close_file (sink);
|
||||
gst_filesink_open_file (sink);
|
||||
}
|
||||
|
||||
break;
|
||||
case ARG_MAXFILESIZE:
|
||||
sink->maxfilesize = g_value_get_int(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -213,10 +196,7 @@ gst_filesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
|
||||
switch (prop_id) {
|
||||
case ARG_LOCATION:
|
||||
g_value_set_string (value, gst_filesink_getcurrentfilename(sink));
|
||||
break;
|
||||
case ARG_MAXFILESIZE:
|
||||
g_value_set_int (value, sink->maxfilesize);
|
||||
g_value_set_string (value, sink->filename);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -230,16 +210,17 @@ gst_filesink_open_file (GstFileSink *sink)
|
|||
g_return_val_if_fail (!GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN), FALSE);
|
||||
|
||||
/* open the file */
|
||||
if (!gst_filesink_getcurrentfilename(sink))
|
||||
if (!sink->filename)
|
||||
{
|
||||
/* Out of files */
|
||||
return FALSE;
|
||||
}
|
||||
sink->file = fopen (gst_filesink_getcurrentfilename(sink), "w");
|
||||
|
||||
sink->file = fopen (sink->filename, "w");
|
||||
if (sink->file == NULL) {
|
||||
perror ("open");
|
||||
gst_element_error (GST_ELEMENT (sink), g_strconcat("Error opening file \"",
|
||||
gst_filesink_getcurrentfilename(sink), "\": ", g_strerror(errno), NULL));
|
||||
gst_element_error (GST_ELEMENT (sink),
|
||||
"Error opening file %s: %s",
|
||||
sink->filename, g_strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -257,15 +238,52 @@ gst_filesink_close_file (GstFileSink *sink)
|
|||
|
||||
if (fclose (sink->file) != 0)
|
||||
{
|
||||
perror ("close");
|
||||
gst_element_error (GST_ELEMENT (sink), g_strconcat("Error closing file \"",
|
||||
gst_filesink_getcurrentfilename(sink), "\": ", g_strerror(errno), NULL));
|
||||
gst_element_error (GST_ELEMENT (sink),
|
||||
"Error closing file %s: %s",
|
||||
sink->filename, g_strerror(errno));
|
||||
}
|
||||
else {
|
||||
GST_FLAG_UNSET (sink, GST_FILESINK_OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value)
|
||||
{
|
||||
GstFileSink *sink = GST_FILESINK (GST_PAD_PARENT (pad));
|
||||
|
||||
switch (type) {
|
||||
case GST_QUERY_TOTAL:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT(sink), GST_FILESINK_OPEN)) {
|
||||
*value = sink->data_written; /* FIXME - doesn't the kernel provide
|
||||
such a function? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_QUERY_POSITION:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT(sink), GST_FILESINK_OPEN)) {
|
||||
*value = ftell (sink->file);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* handle events (search) */
|
||||
static gboolean
|
||||
gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
||||
|
@ -275,31 +293,32 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
|||
|
||||
filesink = GST_FILESINK (gst_pad_get_parent (pad));
|
||||
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN),
|
||||
FALSE);
|
||||
|
||||
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
|
||||
|
||||
switch (type) {
|
||||
case GST_EVENT_SEEK:
|
||||
/* we need to seek */
|
||||
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
|
||||
if (fflush(filesink->file))
|
||||
gst_element_error(GST_ELEMENT(filesink),
|
||||
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
||||
gst_filesink_getcurrentfilename(filesink), g_strerror(errno));
|
||||
g_return_val_if_fail (GST_EVENT_SEEK_FORMAT (event) == GST_FORMAT_BYTES,
|
||||
FALSE);
|
||||
|
||||
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||
g_warning("Any other then byte-offset seeking is not supported!\n");
|
||||
}
|
||||
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
|
||||
if (fflush (filesink->file))
|
||||
gst_element_error (GST_ELEMENT (filesink),
|
||||
"Error flushing file %s: %s",
|
||||
filesink->filename, g_strerror(errno));
|
||||
|
||||
switch (GST_EVENT_SEEK_METHOD(event))
|
||||
{
|
||||
case GST_SEEK_METHOD_SET:
|
||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_SET);
|
||||
break;
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_CUR);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_END);
|
||||
break;
|
||||
default:
|
||||
g_warning("unkown seek method!\n");
|
||||
|
@ -311,26 +330,21 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
|||
gint64 offset;
|
||||
|
||||
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &offset))
|
||||
fseek(filesink->file, offset, SEEK_SET);
|
||||
fseek (filesink->file, offset, SEEK_SET);
|
||||
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_NEW_MEDIA:
|
||||
/* we need to open a new file! */
|
||||
gst_filesink_close_file(filesink);
|
||||
filesink->filenum++;
|
||||
if (!gst_filesink_open_file(filesink)) {
|
||||
/* no more files, give EOS */
|
||||
gst_element_set_eos(GST_ELEMENT(filesink));
|
||||
return FALSE;
|
||||
case GST_EVENT_FLUSH:
|
||||
if (fflush (filesink->file)) {
|
||||
gst_element_error (GST_ELEMENT (filesink),
|
||||
"Error flushing file %s: %s",
|
||||
filesink->filename, g_strerror(errno));
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_FLUSH:
|
||||
if (fflush(filesink->file))
|
||||
gst_element_error(GST_ELEMENT(filesink),
|
||||
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
||||
gst_filesink_getcurrentfilename(filesink), g_strerror(errno));
|
||||
case GST_EVENT_EOS:
|
||||
gst_filesink_close_file (filesink);
|
||||
gst_element_set_eos (GST_ELEMENT (filesink));
|
||||
break;
|
||||
default:
|
||||
gst_pad_event_default (pad, event);
|
||||
|
@ -365,34 +379,23 @@ gst_filesink_chain (GstPad *pad, GstBuffer *buf)
|
|||
return;
|
||||
}
|
||||
|
||||
if (filesink->maxfilesize > 0)
|
||||
{
|
||||
if ((filesink->data_written + GST_BUFFER_SIZE(buf))/(1024*1024) > filesink->maxfilesize)
|
||||
{
|
||||
if (GST_ELEMENT_IS_EVENT_AWARE(GST_ELEMENT(filesink)))
|
||||
{
|
||||
GstEvent *event;
|
||||
event = gst_event_new(GST_EVENT_NEW_MEDIA);
|
||||
gst_pad_send_event(pad, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN))
|
||||
{
|
||||
bytes_written = fwrite (GST_BUFFER_DATA (buf), 1, GST_BUFFER_SIZE (buf), filesink->file);
|
||||
bytes_written = fwrite (GST_BUFFER_DATA (buf), 1,
|
||||
GST_BUFFER_SIZE (buf), filesink->file);
|
||||
if (bytes_written < GST_BUFFER_SIZE (buf))
|
||||
{
|
||||
printf ("filesink : Warning : %d bytes should be written, only %d bytes written\n",
|
||||
g_warning ("filesink: %d bytes should be written, only %d bytes written\n",
|
||||
GST_BUFFER_SIZE (buf), bytes_written);
|
||||
}
|
||||
filesink->data_written += bytes_written;
|
||||
}
|
||||
filesink->data_written += GST_BUFFER_SIZE(buf);
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
g_signal_emit (G_OBJECT (filesink), gst_filesink_signals[SIGNAL_HANDOFF], 0,
|
||||
filesink);
|
||||
g_signal_emit (G_OBJECT (filesink),
|
||||
gst_filesink_signals[SIGNAL_HANDOFF], 0,
|
||||
filesink);
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -400,14 +403,18 @@ gst_filesink_change_state (GstElement *element)
|
|||
{
|
||||
g_return_val_if_fail (GST_IS_FILESINK (element), GST_STATE_FAILURE);
|
||||
|
||||
if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
|
||||
if (GST_FLAG_IS_SET (element, GST_FILESINK_OPEN))
|
||||
gst_filesink_close_file (GST_FILESINK (element));
|
||||
} else {
|
||||
if (!GST_FLAG_IS_SET (element, GST_FILESINK_OPEN)) {
|
||||
if (!gst_filesink_open_file (GST_FILESINK (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
if (GST_FLAG_IS_SET (element, GST_FILESINK_OPEN))
|
||||
gst_filesink_close_file (GST_FILESINK (element));
|
||||
break;
|
||||
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (!GST_FLAG_IS_SET (element, GST_FILESINK_OPEN)) {
|
||||
if (!gst_filesink_open_file (GST_FILESINK (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
|
@ -415,4 +422,3 @@ gst_filesink_change_state (GstElement *element)
|
|||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,17 +59,14 @@ struct _GstFileSink {
|
|||
gchar *filename;
|
||||
FILE *file;
|
||||
|
||||
gint filenum;
|
||||
|
||||
guint64 data_written;
|
||||
gint maxfilesize;
|
||||
};
|
||||
|
||||
struct _GstFileSinkClass {
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*handoff) (GstElement *element,GstPad *pad);
|
||||
void (*handoff) (GstElement *element, GstPad *pad);
|
||||
};
|
||||
|
||||
GType gst_filesink_get_type(void);
|
||||
|
|
Loading…
Reference in a new issue