libs/gst/base/: Add ::unlock_stop to basesrc and basesink. This allows an opportunity for sub-classes to correctly cl...

Original commit message from CVS:
* libs/gst/base/gstbasesink.c: (gst_base_sink_set_flushing),
(gst_base_sink_change_state):
* libs/gst/base/gstbasesink.h:
* libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek),
(gst_base_src_default_event), (gst_base_src_unlock_stop),
(gst_base_src_deactivate):
* libs/gst/base/gstbasesrc.h:
Add ::unlock_stop to basesrc and basesink. This allows an opportunity
for sub-classes to correctly clear any state they set trying to
unlock, such as clearing out unlock commands from a command fd.
* plugins/elements/gstfdsink.c: (gst_fd_sink_class_init),
(gst_fd_sink_render), (gst_fd_sink_unlock),
(gst_fd_sink_unlock_stop):
* plugins/elements/gstfdsrc.c: (gst_fd_src_class_init),
(gst_fd_src_init), (gst_fd_src_unlock), (gst_fd_src_unlock_stop),
(gst_fd_src_create), (gst_fd_src_get_size), (gst_fd_src_do_seek):
Implement unlock_stop in fdsrc and fdsink.
Implement seeking in fdsrc when a seekable fd is passed, as in
gst-launch-0.10 fdsrc ! ... ! xvimagesink < /path/to/file
This commit is contained in:
Jan Schmidt 2007-03-19 15:01:40 +00:00
parent e447f17955
commit c248d1dba0
7 changed files with 167 additions and 39 deletions

View file

@ -1,3 +1,27 @@
2007-03-19 Jan Schmidt <thaytan@mad.scientist.com>
* libs/gst/base/gstbasesink.c: (gst_base_sink_set_flushing),
(gst_base_sink_change_state):
* libs/gst/base/gstbasesink.h:
* libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek),
(gst_base_src_default_event), (gst_base_src_unlock_stop),
(gst_base_src_deactivate):
* libs/gst/base/gstbasesrc.h:
Add ::unlock_stop to basesrc and basesink. This allows an opportunity
for sub-classes to correctly clear any state they set trying to
unlock, such as clearing out unlock commands from a command fd.
* plugins/elements/gstfdsink.c: (gst_fd_sink_class_init),
(gst_fd_sink_render), (gst_fd_sink_unlock),
(gst_fd_sink_unlock_stop):
* plugins/elements/gstfdsrc.c: (gst_fd_src_class_init),
(gst_fd_src_init), (gst_fd_src_unlock), (gst_fd_src_unlock_stop),
(gst_fd_src_create), (gst_fd_src_get_size), (gst_fd_src_do_seek):
Implement unlock_stop in fdsrc and fdsink.
Implement seeking in fdsrc when a seekable fd is passed, as in
gst-launch-0.10 fdsrc ! ... ! xvimagesink < /path/to/file
2007-03-19 Wim Taymans <wim@fluendo.com>
Patch by: Evan Nemerson <evan at coeus dash group dot com>

View file

@ -2245,12 +2245,11 @@ static gboolean
gst_base_sink_set_flushing (GstBaseSink * basesink, GstPad * pad,
gboolean flushing)
{
GstBaseSinkClass *bclass;
bclass = GST_BASE_SINK_GET_CLASS (basesink);
if (flushing) {
GstBaseSinkClass *bclass;
bclass = GST_BASE_SINK_GET_CLASS (basesink);
/* unlock any subclasses, we need to do this before grabbing the
* PREROLL_LOCK since we hold this lock before going into ::render. */
if (bclass->unlock)
@ -2260,7 +2259,11 @@ gst_base_sink_set_flushing (GstBaseSink * basesink, GstPad * pad,
GST_PAD_PREROLL_LOCK (pad);
basesink->flushing = flushing;
if (flushing) {
/* step 1, unblock clock sync (if any) or any other blocking thing */
/* step 1, now that we have the PREROLL lock, clear our unlock request */
if (bclass->unlock_stop)
bclass->unlock_stop (basesink);
/* step 2, unblock clock sync (if any) or any other blocking thing */
basesink->need_preroll = TRUE;
if (basesink->clock_id) {
gst_clock_id_unschedule (basesink->clock_id);
@ -2868,6 +2871,10 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
bclass->unlock (basesink);
GST_PAD_PREROLL_LOCK (basesink->sinkpad);
/* now that we have the PREROLL lock, clear our unlock request */
if (bclass->unlock_stop)
bclass->unlock_stop (basesink);
basesink->need_preroll = TRUE;
if (basesink->clock_id) {
gst_clock_id_unschedule (basesink->clock_id);

View file

@ -114,6 +114,8 @@ struct _GstBaseSink {
* @stop: Stop processing. Subclasses should use this to close resources.
* @unlock: Unlock any pending access to the resource. Subclasses should
* unblock any blocked function ASAP
* @unlock_stop: Clear the previous unlock request. Subclasses should clear
* any state they set during unlock(), such as clearing command queues.
* @event: Override this to handle events arriving on the sink pad
* @preroll: Called to present the preroll buffer if desired
* @render: Called when a buffer should be presented or output, at the
@ -174,8 +176,13 @@ struct _GstBaseSinkClass {
/* fixate sink caps during pull-mode negotiation */
void (*fixate) (GstBaseSink *sink, GstCaps *caps);
/* Clear a previously indicated unlock request not that unlocking is
* complete. Sub-classes should clear any command queue or indicator they
* set during unlock */
gboolean (*unlock_stop) (GstBaseSink *sink);
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE-3];
gpointer _gst_reserved[GST_PADDING_LARGE-4];
};
GType gst_base_sink_get_type(void);

View file

@ -290,6 +290,7 @@ static gboolean gst_base_src_default_do_seek (GstBaseSrc * src,
static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query);
static gboolean gst_base_src_unlock (GstBaseSrc * basesrc);
static gboolean gst_base_src_unlock_stop (GstBaseSrc * basesrc);
static gboolean gst_base_src_start (GstBaseSrc * basesrc);
static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
@ -910,6 +911,9 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
* because our peer is flushing. */
GST_PAD_STREAM_LOCK (src->srcpad);
if (unlock)
gst_base_src_unlock_stop (src);
/* make copy into temp structure, we can only update the main one
* when the subclass actually could do the seek. */
memcpy (&seeksegment, &src->segment, sizeof (GstSegment));
@ -1110,6 +1114,8 @@ gst_base_src_default_event (GstBaseSrc * src, GstEvent * event)
result = gst_base_src_unlock (src);
break;
case GST_EVENT_FLUSH_STOP:
result = gst_base_src_unlock_stop (src);
break;
default:
result = TRUE;
break;
@ -1687,6 +1693,28 @@ gst_base_src_unlock (GstBaseSrc * basesrc)
return result;
}
/* this will always be called between start() and stop(). So you can rely on
* resources allocated by start() and freed from stop(). This needs to be added
* to the docs at some point. */
static gboolean
gst_base_src_unlock_stop (GstBaseSrc * basesrc)
{
GstBaseSrcClass *bclass;
gboolean result = TRUE;
GST_DEBUG_OBJECT (basesrc, "unlock stop");
/* Finish a previous unblock request, allowing subclasses to flush command
* queues or whatever they need to do */
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
if (bclass->unlock_stop)
result = bclass->unlock_stop (basesrc);
GST_DEBUG_OBJECT (basesrc, "unlock stop done");
return result;
}
/* default negotiation code.
*
* Take intersection between src and sink pads, take first
@ -1906,6 +1934,9 @@ gst_base_src_deactivate (GstBaseSrc * basesrc, GstPad * pad)
/* step 2, make sure streaming finishes */
result &= gst_pad_stop_task (pad);
/* step 3, clear the unblock condition */
result &= gst_base_src_unlock_stop (basesrc);
return result;
}

View file

@ -132,6 +132,8 @@ struct _GstBaseSrc {
* @is_seekable: Check if the source can seek
* @unlock: Unlock any pending access to the resource. Subclasses should
* unblock any blocked function ASAP
* @unlock_stop: Clear the previous unlock request. Subclasses should clear
* any state they set during unlock(), such as clearing command queues.
* @event: Override this to implement custom event handling.
* @create: Ask the subclass to create a buffer with offset and size.
* @do_seek: Perform seeking on the resource to the indicated segment.
@ -208,8 +210,11 @@ struct _GstBaseSrcClass {
/* called if, in negotation, caps need fixating */
void (*fixate) (GstBaseSrc *src, GstCaps *caps);
/* Clear any pending unlock request, as we succeeded in unlocking */
gboolean (*unlock_stop) (GstBaseSrc *src);
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE - 4];
gpointer _gst_reserved[GST_PADDING_LARGE - 5];
};
GType gst_base_src_get_type (void);

View file

@ -141,6 +141,7 @@ static GstFlowReturn gst_fd_sink_render (GstBaseSink * sink,
static gboolean gst_fd_sink_start (GstBaseSink * basesink);
static gboolean gst_fd_sink_stop (GstBaseSink * basesink);
static gboolean gst_fd_sink_unlock (GstBaseSink * basesink);
static gboolean gst_fd_sink_unlock_stop (GstBaseSink * basesink);
static void
gst_fd_sink_base_init (gpointer g_class)
@ -170,6 +171,7 @@ gst_fd_sink_class_init (GstFdSinkClass * klass)
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_fd_sink_start);
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_fd_sink_stop);
gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock);
gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop);
gstbasesink_class->event = NULL;
g_object_class_install_property (gobject_class, ARG_FD,
@ -272,21 +274,8 @@ again:
if (retval == -1)
goto select_error;
if (FD_ISSET (READ_SOCKET (fdsink), &readfds)) {
/* read all stop commands */
while (TRUE) {
gchar command;
int res;
READ_COMMAND (fdsink, command, res);
if (res < 0) {
GST_LOG_OBJECT (fdsink, "no more commands");
/* no more commands */
break;
}
}
if (FD_ISSET (READ_SOCKET (fdsink), &readfds))
goto stopped;
}
#endif
GST_DEBUG_OBJECT (fdsink, "writing %d bytes to file descriptor %d", size,
@ -437,11 +426,35 @@ gst_fd_sink_unlock (GstBaseSink * basesink)
{
GstFdSink *fdsink = GST_FD_SINK (basesink);
GST_LOG_OBJECT (fdsink, "Sending unlock command to queue");
SEND_COMMAND (fdsink, CONTROL_STOP);
return TRUE;
}
static gboolean
gst_fd_sink_unlock_stop (GstBaseSink * basesink)
{
GstFdSink *fdsink = GST_FD_SINK (basesink);
/* read all stop commands */
GST_LOG_OBJECT (fdsink, "Clearing unlock command queue");
while (TRUE) {
gchar command;
int res;
READ_COMMAND (fdsink, command, res);
if (res < 0) {
GST_LOG_OBJECT (fdsink, "no more commands");
/* no more commands */
break;
}
}
return TRUE;
}
static gboolean
gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd)
{

View file

@ -119,8 +119,10 @@ static void gst_fd_src_dispose (GObject * obj);
static gboolean gst_fd_src_start (GstBaseSrc * bsrc);
static gboolean gst_fd_src_stop (GstBaseSrc * bsrc);
static gboolean gst_fd_src_unlock (GstBaseSrc * bsrc);
static gboolean gst_fd_src_unlock_stop (GstBaseSrc * bsrc);
static gboolean gst_fd_src_is_seekable (GstBaseSrc * bsrc);
static gboolean gst_fd_src_get_size (GstBaseSrc * src, guint64 * size);
static gboolean gst_fd_src_do_seek (GstBaseSrc * src, GstSegment * segment);
static GstFlowReturn gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf);
@ -160,8 +162,10 @@ gst_fd_src_class_init (GstFdSrcClass * klass)
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fd_src_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fd_src_stop);
gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_src_unlock);
gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_src_unlock_stop);
gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fd_src_is_seekable);
gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_fd_src_get_size);
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_fd_src_do_seek);
gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_fd_src_create);
}
@ -169,10 +173,10 @@ gst_fd_src_class_init (GstFdSrcClass * klass)
static void
gst_fd_src_init (GstFdSrc * fdsrc, GstFdSrcClass * klass)
{
fdsrc->fd = 0;
fdsrc->fd = -1;
fdsrc->new_fd = 0;
fdsrc->seekable_fd = FALSE;
fdsrc->uri = g_strdup_printf ("fd://%d", fdsrc->fd);
fdsrc->uri = g_strdup_printf ("fd://0");
fdsrc->curoffset = 0;
}
@ -268,11 +272,37 @@ gst_fd_src_unlock (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FD_SRC (bsrc);
GST_LOG_OBJECT (src, "sending unlock command");
SEND_COMMAND (src, CONTROL_STOP);
return TRUE;
}
static gboolean
gst_fd_src_unlock_stop (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FD_SRC (bsrc);
GST_LOG_OBJECT (src, "clearing unlock command queue");
/* read all stop commands */
while (TRUE) {
gchar command;
int res;
GST_LOG_OBJECT (src, "reading command");
READ_COMMAND (src, command, res);
if (res < 0) {
GST_LOG_OBJECT (src, "no more commands");
/* no more commands */
break;
}
}
return TRUE;
}
static void
gst_fd_src_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec)
@ -343,23 +373,8 @@ gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
if (retval == -1)
goto select_error;
if (FD_ISSET (READ_SOCKET (src), &readfds)) {
/* read all stop commands */
while (TRUE) {
gchar command;
int res;
GST_LOG_OBJECT (src, "reading command");
READ_COMMAND (src, command, res);
if (res < 0) {
GST_LOG_OBJECT (src, "no more commands");
/* no more commands */
break;
}
}
if (FD_ISSET (READ_SOCKET (src), &readfds))
goto stopped;
}
#endif
blocksize = GST_BASE_SRC (src)->blocksize;
@ -453,7 +468,33 @@ could_not_stat:
{
return FALSE;
}
}
gboolean
gst_fd_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
{
gint res;
gint64 offset;
GstFdSrc *src = GST_FD_SRC (bsrc);
offset = segment->start;
/* No need to seek to the current position */
if (offset == src->curoffset)
return TRUE;
res = lseek (src->fd, offset, SEEK_SET);
if (G_UNLIKELY (res < 0 || res != offset))
goto seek_failed;
segment->last_stop = segment->start;
segment->time = segment->start;
return TRUE;
seek_failed:
GST_DEBUG_OBJECT (src, "lseek returned %" G_GINT64_FORMAT, offset);
return FALSE;
}
/*** GSTURIHANDLER INTERFACE *************************************************/