mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-27 09:38:17 +00:00
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:
parent
e447f17955
commit
c248d1dba0
7 changed files with 167 additions and 39 deletions
24
ChangeLog
24
ChangeLog
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 *************************************************/
|
||||
|
|
Loading…
Reference in a new issue