mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-07 06:52:41 +00:00
Some docs updates
Original commit message from CVS: * CHANGES-0.9: * docs/design/part-TODO.txt: * docs/design/part-events.txt: Some docs updates * gst/base/gstbasesink.c: (gst_base_sink_handle_object), (gst_base_sink_event), (gst_base_sink_do_sync), (gst_base_sink_activate_push), (gst_base_sink_activate_pull): * gst/base/gstbasesrc.c: (gst_base_src_send_discont), (gst_base_src_do_seek), (gst_base_src_event_handler), (gst_base_src_loop): * gst/base/gstbasetransform.c: (gst_base_transform_transform_caps), (gst_base_transform_configure_caps), (gst_base_transform_setcaps), (gst_base_transform_get_size), (gst_base_transform_buffer_alloc), (gst_base_transform_event), (gst_base_transform_handle_buffer), (gst_base_transform_set_passthrough), (gst_base_transform_is_passthrough): * gst/elements/gstfakesink.c: (gst_fake_sink_event): * gst/elements/gstfilesink.c: (gst_file_sink_event): Event updates. * gst/gstbuffer.h: Use faster casts. * gst/gstelement.c: (gst_element_seek): * gst/gstelement.h: Update gst_element_seek. * gst/gstevent.c: (gst_event_finalize), (_gst_event_copy), (gst_event_new), (gst_event_new_custom), (gst_event_get_structure), (gst_event_new_flush_start), (gst_event_new_flush_stop), (gst_event_new_eos), (gst_event_new_newsegment), (gst_event_parse_newsegment), (gst_event_new_tag), (gst_event_parse_tag), (gst_event_new_filler), (gst_event_new_qos), (gst_event_parse_qos), (gst_event_new_seek), (gst_event_parse_seek), (gst_event_new_navigation): * gst/gstevent.h: Make GstEvent use GstStructure. Add parsing code, make sure the API is sufficiently generic. Mark possible directions of events and serialization. * gst/gstmessage.c: (gst_message_init), (gst_message_finalize), (_gst_message_copy), (gst_message_new_segment_start), (gst_message_new_segment_done), (gst_message_new_custom), (gst_message_parse_segment_start), (gst_message_parse_segment_done): Small cleanups. * gst/gstpad.c: (gst_pad_get_caps_unlocked), (gst_pad_accept_caps), (gst_pad_set_caps), (gst_pad_send_event): Update for new events. Catch events sent in wrong directions. * gst/gstqueue.c: (gst_queue_link_src), (gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop), (gst_queue_handle_src_query): Event updates. * gst/gsttag.c: * gst/gsttag.h: Remove event code from this file. * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_event), (gst_dp_event_from_packet): Event updates.
This commit is contained in:
parent
4795d25721
commit
66d7070ef1
28 changed files with 944 additions and 926 deletions
|
@ -17,7 +17,7 @@ Changes in the 0.9 version
|
|||
remains in this state.
|
||||
|
||||
- GMainLoop integration. Information on the state of the pipeline
|
||||
is now received in the mainloop.
|
||||
is now received in the mainloop via the GstBus.
|
||||
|
||||
- Events move separate from the datastream, this allows for both
|
||||
in and out of sync delivery of events.
|
||||
|
|
68
ChangeLog
68
ChangeLog
|
@ -1,3 +1,71 @@
|
|||
2005-07-27 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* CHANGES-0.9:
|
||||
* docs/design/part-TODO.txt:
|
||||
* docs/design/part-events.txt:
|
||||
Some docs updates
|
||||
|
||||
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
|
||||
(gst_base_sink_event), (gst_base_sink_do_sync),
|
||||
(gst_base_sink_activate_push), (gst_base_sink_activate_pull):
|
||||
* gst/base/gstbasesrc.c: (gst_base_src_send_discont),
|
||||
(gst_base_src_do_seek), (gst_base_src_event_handler),
|
||||
(gst_base_src_loop):
|
||||
* gst/base/gstbasetransform.c: (gst_base_transform_transform_caps),
|
||||
(gst_base_transform_configure_caps), (gst_base_transform_setcaps),
|
||||
(gst_base_transform_get_size), (gst_base_transform_buffer_alloc),
|
||||
(gst_base_transform_event), (gst_base_transform_handle_buffer),
|
||||
(gst_base_transform_set_passthrough),
|
||||
(gst_base_transform_is_passthrough):
|
||||
* gst/elements/gstfakesink.c: (gst_fake_sink_event):
|
||||
* gst/elements/gstfilesink.c: (gst_file_sink_event):
|
||||
Event updates.
|
||||
|
||||
* gst/gstbuffer.h:
|
||||
Use faster casts.
|
||||
|
||||
* gst/gstelement.c: (gst_element_seek):
|
||||
* gst/gstelement.h:
|
||||
Update gst_element_seek.
|
||||
|
||||
* gst/gstevent.c: (gst_event_finalize), (_gst_event_copy),
|
||||
(gst_event_new), (gst_event_new_custom), (gst_event_get_structure),
|
||||
(gst_event_new_flush_start), (gst_event_new_flush_stop),
|
||||
(gst_event_new_eos), (gst_event_new_newsegment),
|
||||
(gst_event_parse_newsegment), (gst_event_new_tag),
|
||||
(gst_event_parse_tag), (gst_event_new_filler), (gst_event_new_qos),
|
||||
(gst_event_parse_qos), (gst_event_new_seek),
|
||||
(gst_event_parse_seek), (gst_event_new_navigation):
|
||||
* gst/gstevent.h:
|
||||
Make GstEvent use GstStructure. Add parsing code, make sure the
|
||||
API is sufficiently generic.
|
||||
Mark possible directions of events and serialization.
|
||||
|
||||
* gst/gstmessage.c: (gst_message_init), (gst_message_finalize),
|
||||
(_gst_message_copy), (gst_message_new_segment_start),
|
||||
(gst_message_new_segment_done), (gst_message_new_custom),
|
||||
(gst_message_parse_segment_start),
|
||||
(gst_message_parse_segment_done):
|
||||
Small cleanups.
|
||||
|
||||
* gst/gstpad.c: (gst_pad_get_caps_unlocked), (gst_pad_accept_caps),
|
||||
(gst_pad_set_caps), (gst_pad_send_event):
|
||||
Update for new events.
|
||||
Catch events sent in wrong directions.
|
||||
|
||||
* gst/gstqueue.c: (gst_queue_link_src),
|
||||
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
|
||||
(gst_queue_handle_src_query):
|
||||
Event updates.
|
||||
|
||||
* gst/gsttag.c:
|
||||
* gst/gsttag.h:
|
||||
Remove event code from this file.
|
||||
|
||||
* libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_event),
|
||||
(gst_dp_event_from_packet):
|
||||
Event updates.
|
||||
|
||||
2005-07-27 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
||||
* gst/base/gstbasetransform.c: (gst_base_transform_getcaps),
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
done by making the event contain a GstStructure with input/output values, similar
|
||||
to GstMessage.
|
||||
|
||||
- implement iterators for traversing elements upstream or dowstream.
|
||||
- implement iterators for traversing elements upstream or dowstream. Use more simple
|
||||
algorithm using indegree topological sort.
|
||||
|
||||
- unlinking pads in the PAUSED state needs to make sure the stream thread is not
|
||||
executing code. Can this be done with a flush to unlock all downstream chain
|
||||
|
|
|
@ -10,15 +10,47 @@ others don't.
|
|||
|
||||
Different types of events exist to implement various functionalities.
|
||||
|
||||
GST_EVENT_FLUSH_START: data is to be discarded
|
||||
GST_EVENT_FLUSH_STOP: data is allowed again
|
||||
GST_EVENT_EOS: no more data is to be expected on a pad.
|
||||
GST_EVENT_FLUSH: data is to be discarded or allowed again
|
||||
GST_EVENT_DISCONTINUOUS: A new group of buffers with common start time
|
||||
GST_EVENT_NEWSEGMENT: A new group of buffers with common start time
|
||||
GST_EVENT_TAG: Stream metadata.
|
||||
GST_EVENT_FILLER: Filler for sparse data streams
|
||||
GST_EVENT_QOS: A notification of the quality of service of the stream
|
||||
GST_EVENT_SEEK: A seek should be performed to a new position in the stream
|
||||
GST_EVENT_SIZE: Notification of suggested buffer size.
|
||||
GST_EVENT_RATE: Notification to change the processing speed of a stream
|
||||
GST_EVENT_NAVIGATION: A navigation event.
|
||||
GST_EVENT_TAG: Stream metadata.
|
||||
|
||||
|
||||
FLUSH_START/STOP
|
||||
----------------
|
||||
|
||||
A flush event is sent both downstream and upstream to clear any pending data
|
||||
from the pipeline. This might be needed to make the graph more responsive
|
||||
when the normal dataflow gets interrupted by for example a seek event.
|
||||
|
||||
Flushing happens in two stages.
|
||||
|
||||
1) a source filter sends the FLUSH_START event to the downstream peer element. The
|
||||
downstream element starts rejecting buffers from the upstream elements. It
|
||||
sends the flush event further downstream and discards any buffers it is
|
||||
holding as well as return from the chain function as soon as possible.
|
||||
This makes sure that all upstream elements get unblocked.
|
||||
This event is not synchronized with the STREAM_LOCK and can be done in the
|
||||
application thread.
|
||||
|
||||
2) a source filter sends the FLUSH_STOP event to indicate
|
||||
that the downstream element can accept buffers again. The downstream
|
||||
element sends the flush event to its peer elements. After this step dataflow
|
||||
continues. The FLUSH_STOP call is synchronized with the STREAM_LOCK so any
|
||||
data used by the chain function can safely freed here if needed. Any
|
||||
pending EOS events should be discarded too.
|
||||
|
||||
After the flush completes the second stage, data is flowing again in the pipeline
|
||||
and all buffers are more recent than those before the flush.
|
||||
|
||||
For elements that use the pullregion function, they send both flush events to
|
||||
the upstream pads in the same way top make sure that the pullregion function
|
||||
unlocks and any pending buffers are cleared in the upstream elements.
|
||||
|
||||
|
||||
EOS
|
||||
|
@ -57,67 +89,39 @@ the EOS event is received in the PAUSED state, it is queued until the element
|
|||
goes to PLAYING.
|
||||
|
||||
|
||||
FLUSH
|
||||
-----
|
||||
|
||||
A flush event is sent both downstream and upstream to clear any pending data
|
||||
from the pipeline. This might be needed to make the graph more responsive
|
||||
when the normal dataflow gets interrupted by for example a seek event.
|
||||
|
||||
Flushing happens in two stages.
|
||||
|
||||
1) a source filter sends the flush event to the downstream peer element. The
|
||||
downstream element starts rejecting buffers from the upstream elements. It
|
||||
sends the flush event further downstream and discards any buffers it is
|
||||
holding as well as return from the chain function as soon as possible.
|
||||
This makes sure that all upstream elements get unblocked.
|
||||
This event is not synchronized with the STREAM_LOCK and can be done in the
|
||||
application thread.
|
||||
|
||||
2) a source filter sends the flush event with the done flag set to indicate
|
||||
that the downstream element can accept buffers again. The downstream
|
||||
element sends the flush event to its peer elements. After this step dataflow
|
||||
continues. The endflush call is synchronized with the STREAM_LOCK so any
|
||||
data used by the chain function can safely freed here if needed. Any
|
||||
pending EOS events should be discarded too.
|
||||
|
||||
After the flush completes the second stage, data is flowing again in the pipeline
|
||||
and all buffers are more recent than those before the flush.
|
||||
|
||||
For elements that use the pullregion function, they send both flush events to
|
||||
the upstream pads in the same way top make sure that the pullregion function
|
||||
unlocks and any pending buffers are cleared in the upstream elements.
|
||||
|
||||
|
||||
DISCONTINUOUS
|
||||
NEWSEGMENT
|
||||
-------------
|
||||
|
||||
A discont event is sent downstream by an element to indicate that the following
|
||||
group of buffers start and end at the specified time. The discont event
|
||||
A newsegment event is sent downstream by an element to indicate that the following
|
||||
group of buffers start and end at the specified positions. The newsegment event
|
||||
also contains the playback speed of the stream.
|
||||
|
||||
Since the stream time is always set to 0 at start and after a seek, a 0
|
||||
point for all next buffer's timestamps has to be propagated through the
|
||||
pipeline using the DISCONT event.
|
||||
pipeline using the NEWSEGMENT event.
|
||||
|
||||
Before sending buffers, an element must send a DISCONT event. An element is
|
||||
free to refuse buffers if they were not preceeded by a DISCONT event.
|
||||
Before sending buffers, an element must send a NEWSEGMENT event. An element is
|
||||
free to refuse buffers if they were not preceeded by a NEWSEGMENT event.
|
||||
|
||||
Elements that sync to the clock should store the DISCONT start and end values
|
||||
Elements that sync to the clock should store the NEWSEGMENT start and end values
|
||||
and substract the start value from the buffer timestamp before comparing
|
||||
it against the stream time (see part-clocks.txt).
|
||||
|
||||
An element is allowed to send out buffers with the DISCONT start time already
|
||||
An element is allowed to send out buffers with the NEWSEGMENT start time already
|
||||
substracted from the timestamp. If it does so, it needs to send a corrected
|
||||
DISCONT downstream, ie, one with start time 0.
|
||||
NEWSEGMENT downstream, ie, one with start time 0.
|
||||
|
||||
A DISCONT event should be generated as soon as possible in the pipeline and
|
||||
A NEWSEGMENT event should be generated as soon as possible in the pipeline and
|
||||
is usually generated by a demuxer or source. The event is generated before
|
||||
pushing the first buffer and after a seek, right before pushing the new buffer.
|
||||
|
||||
The DISCONT event can be send from both the application and the streaming
|
||||
The NEWSEGMENT event can be send from both the application and the streaming
|
||||
thread and should be serialized with the buffers.
|
||||
|
||||
Buffers should be clipped within the range indicated by the newsegment event
|
||||
start and stop values. Sinks are allowed to drop buffers with timestamps out
|
||||
of the indicated newsegment range.
|
||||
|
||||
|
||||
SEEK
|
||||
----
|
||||
|
@ -149,7 +153,7 @@ the STREAM_LOCK so that the streaming thread and the seek gets serialized.
|
|||
The general flow of executing the seek with FLUSH is as follows:
|
||||
|
||||
1) unblock the streaming threads, they could be blocked in a chain
|
||||
function. This is done by sending a flush on all srcpads.
|
||||
function. This is done by sending a FLUSH_START on all srcpads.
|
||||
The flush will make sure that all downstream elements unlock and
|
||||
that control will return to this element chain/loop function.
|
||||
We cannot lock the STREAM_LOCK before doing this since it might
|
||||
|
@ -162,9 +166,9 @@ The general flow of executing the seek with FLUSH is as follows:
|
|||
will wait for the seek to complete. Most likely, the stream thread
|
||||
will pause because the peer elements are flushing.
|
||||
|
||||
4) send a flush event with the done flag set to allow streaming again.
|
||||
4) send a FLUSH_STOP event to all peer elements to allow streaming again.
|
||||
|
||||
5) send a DISCONT event to signal the new buffer timestamp base time.
|
||||
5) send a NEWSEGMENT event to signal the new buffer timestamp base time.
|
||||
|
||||
6) start stopped tasks and unlock the STREAM_LOCK, dataflow will continue
|
||||
now from the new position.
|
||||
|
@ -173,29 +177,6 @@ More information about the different seek types can be found in
|
|||
part-seeking.txt.
|
||||
|
||||
|
||||
SIZE
|
||||
----
|
||||
|
||||
Some demuxers know an optimal size for any downstream buffers. They can
|
||||
use this event to signal this fact. Similary an element can signal an
|
||||
upstream element for a prefered buffer size.
|
||||
|
||||
|
||||
RATE
|
||||
----
|
||||
|
||||
When the application wants to change the playback rate of the stream, it
|
||||
issues a rate event on the sinks. A rate of 1.0 is the normal playback rate,
|
||||
2.0 plays at twice the speed and negative values play backwards.
|
||||
|
||||
The rate event travels upstream. After the rate event reaches an element
|
||||
that can handle the rate event, it issues a flush and generates a new
|
||||
DISCONT event with the updated rate.
|
||||
|
||||
Note that the clock speed does not change. More specific information about
|
||||
changing the playback rate are to be thought out and written down.
|
||||
|
||||
|
||||
NAVIGATION
|
||||
----------
|
||||
|
||||
|
|
|
@ -468,11 +468,17 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
|
|||
basesink->preroll_queued++;
|
||||
basesink->eos = TRUE;
|
||||
break;
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
/* the discont event is needed to bring the buffer timestamps to the
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate;
|
||||
|
||||
/* the newsegment event is needed to bring the buffer timestamps to the
|
||||
* stream time */
|
||||
if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
|
||||
&basesink->discont_start, &basesink->discont_stop)) {
|
||||
gst_event_parse_newsegment (event, &rate, &format,
|
||||
&basesink->discont_start, &basesink->discont_stop, NULL);
|
||||
|
||||
if (format != GST_FORMAT_TIME) {
|
||||
/* this means this sink will not be able to sync to the clock */
|
||||
basesink->discont_start = 0;
|
||||
basesink->discont_stop = 0;
|
||||
|
@ -483,6 +489,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
|
|||
GST_TIME_ARGS (basesink->discont_start),
|
||||
GST_TIME_ARGS (basesink->discont_stop));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -664,7 +671,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
|
|||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
|
||||
|
@ -674,39 +681,44 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
|
|||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_FLUSH_START:
|
||||
/* make sure we are not blocked on the clock also clear any pending
|
||||
* eos state. */
|
||||
if (bclass->event)
|
||||
bclass->event (basesink, event);
|
||||
|
||||
if (!GST_EVENT_FLUSH_DONE (event)) {
|
||||
GST_PREROLL_LOCK (pad);
|
||||
/* we need preroll after the flush */
|
||||
basesink->need_preroll = TRUE;
|
||||
/* unlock from a possible state change/preroll */
|
||||
gst_base_sink_preroll_queue_flush (basesink, pad);
|
||||
GST_PREROLL_LOCK (pad);
|
||||
/* we need preroll after the flush */
|
||||
basesink->need_preroll = TRUE;
|
||||
/* unlock from a possible state change/preroll */
|
||||
gst_base_sink_preroll_queue_flush (basesink, pad);
|
||||
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* and we need to commit our state again on the next
|
||||
* prerolled buffer */
|
||||
GST_STATE_LOCK (basesink);
|
||||
GST_STREAM_LOCK (pad);
|
||||
gst_element_lost_state (GST_ELEMENT (basesink));
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_STATE_UNLOCK (basesink);
|
||||
} else {
|
||||
/* now we are completely unblocked and the _chain method
|
||||
* will return */
|
||||
GST_STREAM_LOCK (pad);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* and we need to commit our state again on the next
|
||||
* prerolled buffer */
|
||||
GST_STATE_LOCK (basesink);
|
||||
GST_STREAM_LOCK (pad);
|
||||
gst_element_lost_state (GST_ELEMENT (basesink));
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_STATE_UNLOCK (basesink);
|
||||
GST_DEBUG ("event unref %p %p", basesink, event);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
if (bclass->event)
|
||||
bclass->event (basesink, event);
|
||||
|
||||
/* now we are completely unblocked and the _chain method
|
||||
* will return */
|
||||
GST_STREAM_LOCK (pad);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
|
||||
GST_DEBUG ("event unref %p %p", basesink, event);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
|
|
|
@ -362,9 +362,9 @@ gst_base_src_send_discont (GstBaseSrc * src)
|
|||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new_discontinuous (1.0,
|
||||
event = gst_event_new_newsegment (1.0,
|
||||
GST_FORMAT_BYTES,
|
||||
(gint64) src->segment_start, (gint64) src->segment_end, NULL);
|
||||
(gint64) src->segment_start, (gint64) src->segment_end, (gint64) 0);
|
||||
|
||||
return gst_pad_push_event (src->srcpad, event);
|
||||
}
|
||||
|
@ -372,10 +372,14 @@ gst_base_src_send_discont (GstBaseSrc * src)
|
|||
static gboolean
|
||||
gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
|
||||
{
|
||||
gdouble rate;
|
||||
GstFormat format;
|
||||
gint64 offset;
|
||||
GstSeekFlags flags;
|
||||
GstSeekType cur_type, stop_type;
|
||||
gint64 cur, stop;
|
||||
|
||||
format = GST_EVENT_SEEK_FORMAT (event);
|
||||
gst_event_parse_seek (event, &rate, &format, &flags,
|
||||
&cur_type, &cur, &stop_type, &stop);
|
||||
|
||||
/* get seek format */
|
||||
if (format == GST_FORMAT_DEFAULT)
|
||||
|
@ -385,11 +389,10 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
|
|||
return FALSE;
|
||||
|
||||
/* get seek positions */
|
||||
offset = GST_EVENT_SEEK_OFFSET (event);
|
||||
src->segment_loop = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP;
|
||||
src->segment_loop = flags & GST_SEEK_FLAG_SEGMENT;
|
||||
|
||||
/* send flush start */
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush (FALSE));
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
|
||||
|
||||
/* unblock streaming thread */
|
||||
gst_base_src_unlock (src);
|
||||
|
@ -397,35 +400,35 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
|
|||
/* grab streaming lock */
|
||||
GST_STREAM_LOCK (src->srcpad);
|
||||
|
||||
/* send flush end */
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush (TRUE));
|
||||
/* send flush stop */
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
|
||||
|
||||
/* perform the seek */
|
||||
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||
case GST_SEEK_METHOD_SET:
|
||||
if (offset < 0)
|
||||
switch (cur_type) {
|
||||
case GST_SEEK_TYPE_SET:
|
||||
if (cur < 0)
|
||||
goto error;
|
||||
src->offset = MIN (offset, src->size);
|
||||
src->offset = MIN (cur, src->size);
|
||||
src->segment_start = src->offset;
|
||||
src->segment_end = MIN (GST_EVENT_SEEK_ENDOFFSET (event), src->size);
|
||||
src->segment_end = MIN (stop, src->size);
|
||||
GST_DEBUG_OBJECT (src, "seek set pending to %" G_GINT64_FORMAT,
|
||||
src->offset);
|
||||
break;
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
offset += src->offset;
|
||||
src->offset = CLAMP (offset, 0, src->size);
|
||||
case GST_SEEK_TYPE_CUR:
|
||||
cur += src->offset;
|
||||
src->offset = CLAMP (cur, 0, src->size);
|
||||
src->segment_start = src->offset;
|
||||
src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
|
||||
src->segment_end = stop;
|
||||
GST_DEBUG_OBJECT (src, "seek cur pending to %" G_GINT64_FORMAT,
|
||||
src->offset);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
if (offset > 0)
|
||||
case GST_SEEK_TYPE_END:
|
||||
if (cur > 0)
|
||||
goto error;
|
||||
offset = src->size + offset;
|
||||
src->offset = MAX (0, offset);
|
||||
cur = src->size + cur;
|
||||
src->offset = MAX (0, cur);
|
||||
src->segment_start = src->offset;
|
||||
src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
|
||||
src->segment_end = stop;
|
||||
GST_DEBUG_OBJECT (src, "seek end pending to %" G_GINT64_FORMAT,
|
||||
src->offset);
|
||||
break;
|
||||
|
@ -471,25 +474,11 @@ gst_base_src_event_handler (GstPad * pad, GstEvent * event)
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
return gst_base_src_do_seek (src, event);
|
||||
case GST_EVENT_SIZE:
|
||||
{
|
||||
GstFormat format;
|
||||
|
||||
format = GST_EVENT_SIZE_FORMAT (event);
|
||||
if (format == GST_FORMAT_DEFAULT)
|
||||
format = GST_FORMAT_BYTES;
|
||||
/* we can only accept bytes */
|
||||
if (format != GST_FORMAT_BYTES)
|
||||
return FALSE;
|
||||
|
||||
src->blocksize = GST_EVENT_SIZE_VALUE (event);
|
||||
g_object_notify (G_OBJECT (src), "blocksize");
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_FLUSH_START:
|
||||
/* cancel any blocking getrange */
|
||||
if (!GST_EVENT_FLUSH_DONE (event))
|
||||
gst_base_src_unlock (src);
|
||||
gst_base_src_unlock (src);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -695,7 +684,7 @@ eos:
|
|||
{
|
||||
GST_DEBUG_OBJECT (src, "going to EOS");
|
||||
gst_pad_pause_task (pad);
|
||||
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||
return;
|
||||
}
|
||||
pause:
|
||||
|
@ -707,7 +696,7 @@ pause:
|
|||
GST_ELEMENT_ERROR (src, STREAM, STOPPED,
|
||||
("streaming stopped, reason %s", gst_flow_get_name (ret)),
|
||||
("streaming stopped, reason %s", gst_flow_get_name (ret)));
|
||||
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -717,7 +706,7 @@ error:
|
|||
("internal: element returned NULL buffer"),
|
||||
("internal: element returned NULL buffer"));
|
||||
gst_pad_pause_task (pad);
|
||||
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -497,11 +497,11 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
|
|||
unlock = FALSE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH:
|
||||
if (GST_EVENT_FLUSH_DONE (event)) {
|
||||
GST_STREAM_LOCK (pad);
|
||||
unlock = TRUE;
|
||||
}
|
||||
case GST_EVENT_FLUSH_START:
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
GST_STREAM_LOCK (pad);
|
||||
unlock = TRUE;
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
GST_STREAM_LOCK (pad);
|
||||
|
|
|
@ -273,13 +273,20 @@ static gboolean
|
|||
gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event)
|
||||
{
|
||||
GstFakeSink *sink = GST_FAKE_SINK (bsink);
|
||||
const GstStructure *s;
|
||||
|
||||
if (!sink->silent) {
|
||||
gchar *sstr;
|
||||
|
||||
g_free (sink->last_message);
|
||||
|
||||
s = gst_event_get_structure (event);
|
||||
sstr = gst_structure_to_string (s);
|
||||
|
||||
sink->last_message =
|
||||
g_strdup_printf ("event ******* E (type: %d) %p",
|
||||
GST_EVENT_TYPE (event), event);
|
||||
g_strdup_printf ("event ******* E (type: %d, %s) %p",
|
||||
GST_EVENT_TYPE (event), sstr, event);
|
||||
g_free (sstr);
|
||||
|
||||
g_object_notify (G_OBJECT (sink), "last_message");
|
||||
}
|
||||
|
|
|
@ -291,48 +291,23 @@ gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
|
|||
|
||||
filesink = GST_FILE_SINK (sink);
|
||||
|
||||
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
|
||||
type = GST_EVENT_TYPE (event);
|
||||
|
||||
switch (type) {
|
||||
case GST_EVENT_SEEK:
|
||||
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
|
||||
if (fflush (filesink->file)) {
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||
case GST_SEEK_METHOD_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);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_END);
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown seek method!");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
gint64 soffset, eoffset;
|
||||
GstFormat format;
|
||||
|
||||
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &soffset,
|
||||
&eoffset))
|
||||
gst_event_parse_newsegment (event, NULL, &format, &soffset, &eoffset,
|
||||
NULL);
|
||||
|
||||
if (format == GST_FORMAT_BYTES) {
|
||||
fseek (filesink->file, soffset, SEEK_SET);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_EOS:
|
||||
if (fflush (filesink->file)) {
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
|
|
|
@ -48,14 +48,14 @@ typedef struct _GstBufferClass GstBufferClass;
|
|||
#define GST_BUFFER_FLAG_SET(buf,flag) GST_MINI_OBJECT_FLAG_SET (buf, flag)
|
||||
#define GST_BUFFER_FLAG_UNSET(buf,flag) GST_MINI_OBJECT_FLAG_UNSET (buf, flag)
|
||||
|
||||
#define GST_BUFFER_DATA(buf) (GST_BUFFER(buf)->data)
|
||||
#define GST_BUFFER_SIZE(buf) (GST_BUFFER(buf)->size)
|
||||
#define GST_BUFFER_TIMESTAMP(buf) (GST_BUFFER(buf)->timestamp)
|
||||
#define GST_BUFFER_DURATION(buf) (GST_BUFFER(buf)->duration)
|
||||
#define GST_BUFFER_CAPS(buf) (GST_BUFFER(buf)->caps)
|
||||
#define GST_BUFFER_OFFSET(buf) (GST_BUFFER(buf)->offset)
|
||||
#define GST_BUFFER_OFFSET_END(buf) (GST_BUFFER(buf)->offset_end)
|
||||
#define GST_BUFFER_MALLOCDATA(buf) (GST_BUFFER(buf)->malloc_data)
|
||||
#define GST_BUFFER_DATA(buf) (GST_BUFFER_CAST(buf)->data)
|
||||
#define GST_BUFFER_SIZE(buf) (GST_BUFFER_CAST(buf)->size)
|
||||
#define GST_BUFFER_TIMESTAMP(buf) (GST_BUFFER_CAST(buf)->timestamp)
|
||||
#define GST_BUFFER_DURATION(buf) (GST_BUFFER_CAST(buf)->duration)
|
||||
#define GST_BUFFER_CAPS(buf) (GST_BUFFER_CAST(buf)->caps)
|
||||
#define GST_BUFFER_OFFSET(buf) (GST_BUFFER_CAST(buf)->offset)
|
||||
#define GST_BUFFER_OFFSET_END(buf) (GST_BUFFER_CAST(buf)->offset_end)
|
||||
#define GST_BUFFER_MALLOCDATA(buf) (GST_BUFFER_CAST(buf)->malloc_data)
|
||||
|
||||
#define GST_BUFFER_OFFSET_NONE ((guint64)-1)
|
||||
|
||||
|
@ -138,12 +138,12 @@ G_STMT_START { \
|
|||
} G_STMT_END
|
||||
|
||||
/* refcounting */
|
||||
#define gst_buffer_ref(buf) GST_BUFFER (gst_mini_object_ref (GST_MINI_OBJECT (buf)))
|
||||
#define gst_buffer_ref(buf) GST_BUFFER_CAST (gst_mini_object_ref (GST_MINI_OBJECT (buf)))
|
||||
#define gst_buffer_unref(buf) gst_mini_object_unref (GST_MINI_OBJECT (buf))
|
||||
/* copy buffer */
|
||||
#define gst_buffer_copy(buf) GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT (buf)))
|
||||
#define gst_buffer_copy(buf) GST_BUFFER_CAST (gst_mini_object_copy (GST_MINI_OBJECT (buf)))
|
||||
#define gst_buffer_is_writable(buf) gst_mini_object_is_writable (GST_MINI_OBJECT (buf))
|
||||
#define gst_buffer_make_writable(buf) GST_BUFFER (gst_mini_object_make_writable (GST_MINI_OBJECT (buf)))
|
||||
#define gst_buffer_make_writable(buf) GST_BUFFER_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT (buf)))
|
||||
|
||||
#define gst_buffer_replace(obuf,nbuf) gst_mini_object_replace ((GstMiniObject **)(obuf), GST_MINI_OBJECT (nbuf))
|
||||
|
||||
|
|
|
@ -1160,15 +1160,17 @@ gst_element_send_event (GstElement * element, GstEvent * event)
|
|||
* MT safe.
|
||||
*/
|
||||
gboolean
|
||||
gst_element_seek (GstElement * element, GstSeekType seek_method,
|
||||
GstFormat seek_format, GstSeekType seek_flags, guint64 offset)
|
||||
gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
|
||||
GstSeekFlags flags, GstSeekType cur_type, gint64 cur,
|
||||
GstSeekType stop_type, gint64 stop)
|
||||
{
|
||||
GstEvent *event;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
||||
|
||||
event = gst_event_new_seek (seek_method | seek_format | seek_flags, offset);
|
||||
event =
|
||||
gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop);
|
||||
result = gst_element_send_event (element, event);
|
||||
|
||||
return result;
|
||||
|
|
|
@ -302,11 +302,10 @@ GstIterator * gst_element_iterate_sink_pads (GstElement * element);
|
|||
|
||||
/* event/query/format stuff */
|
||||
gboolean gst_element_send_event (GstElement *element, GstEvent *event);
|
||||
gboolean gst_element_seek (GstElement *element,
|
||||
GstSeekType seek_method,
|
||||
GstFormat seek_format,
|
||||
GstSeekType seek_flags,
|
||||
guint64 offset);
|
||||
gboolean gst_element_seek (GstElement *element, gdouble rate,
|
||||
GstFormat format, GstSeekFlags flags,
|
||||
GstSeekType cur_type, gint64 cur,
|
||||
GstSeekType stop_type, gint64 stop);
|
||||
G_CONST_RETURN GstQueryType*
|
||||
gst_element_get_query_types (GstElement *element);
|
||||
gboolean gst_element_query (GstElement *element, GstQuery *query);
|
||||
|
|
616
gst/gstevent.c
616
gst/gstevent.c
|
@ -25,12 +25,10 @@
|
|||
#include "gst_private.h"
|
||||
|
||||
#include "gstinfo.h"
|
||||
#include "gstmemchunk.h"
|
||||
#include "gstevent.h"
|
||||
#include "gsttag.h"
|
||||
#include "gstenumtypes.h"
|
||||
#include "gstutils.h"
|
||||
|
||||
|
||||
static void gst_event_init (GTypeInstance * instance, gpointer g_class);
|
||||
static void gst_event_class_init (gpointer g_class, gpointer class_data);
|
||||
static void gst_event_finalize (GstEvent * event);
|
||||
|
@ -101,298 +99,400 @@ gst_event_finalize (GstEvent * event)
|
|||
gst_object_unref (GST_EVENT_SRC (event));
|
||||
GST_EVENT_SRC (event) = NULL;
|
||||
}
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_TAG:
|
||||
if (GST_IS_TAG_LIST (event->event_data.structure.structure)) {
|
||||
gst_tag_list_free (event->event_data.structure.structure);
|
||||
} else {
|
||||
g_warning ("tag event %p didn't contain a valid tag list!", event);
|
||||
GST_ERROR ("tag event %p didn't contain a valid tag list!", event);
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_NAVIGATION:
|
||||
gst_structure_free (event->event_data.structure.structure);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (event->structure) {
|
||||
gst_structure_set_parent_refcount (event->structure, NULL);
|
||||
gst_structure_free (event->structure);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GstEvent *
|
||||
_gst_event_copy (GstEvent * event)
|
||||
{
|
||||
GstEvent *copy;
|
||||
|
||||
copy = gst_event_new (event->type);
|
||||
copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
|
||||
|
||||
copy->timestamp = event->timestamp;
|
||||
if (event->src) {
|
||||
copy->src = gst_object_ref (event->src);
|
||||
GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
|
||||
GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
|
||||
|
||||
if (GST_EVENT_SRC (event)) {
|
||||
GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
|
||||
}
|
||||
|
||||
memcpy (©->event_data, &event->event_data, sizeof (event->event_data));
|
||||
|
||||
/* FIXME copy/ref additional fields */
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_TAG:
|
||||
copy->event_data.structure.structure =
|
||||
gst_tag_list_copy ((GstTagList *) event->event_data.structure.
|
||||
structure);
|
||||
break;
|
||||
case GST_EVENT_NAVIGATION:
|
||||
copy->event_data.structure.structure =
|
||||
gst_structure_copy (event->event_data.structure.structure);
|
||||
default:
|
||||
break;
|
||||
if (event->structure) {
|
||||
copy->structure = gst_structure_copy (event->structure);
|
||||
gst_structure_set_parent_refcount (copy->structure,
|
||||
&event->mini_object.refcount);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_masks_contains:
|
||||
* @masks: The eventmask array to search
|
||||
* @mask: the event mask to find
|
||||
*
|
||||
* See if the given eventmask is inside the eventmask array.
|
||||
*
|
||||
* Returns: TRUE if the eventmask is found inside the array
|
||||
*/
|
||||
gboolean
|
||||
gst_event_masks_contains (const GstEventMask * masks, GstEventMask * mask)
|
||||
{
|
||||
g_return_val_if_fail (mask != NULL, FALSE);
|
||||
|
||||
if (!masks)
|
||||
return FALSE;
|
||||
|
||||
while (masks->type) {
|
||||
if (masks->type == mask->type &&
|
||||
(masks->flags & mask->flags) == mask->flags)
|
||||
return TRUE;
|
||||
|
||||
masks++;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new:
|
||||
* @type: The type of the new event
|
||||
*
|
||||
* Allocate a new event of the given type.
|
||||
*
|
||||
* Returns: A new event.
|
||||
*/
|
||||
GstEvent *
|
||||
static GstEvent *
|
||||
gst_event_new (GstEventType type)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
|
||||
|
||||
GST_CAT_INFO (GST_CAT_EVENT, "creating new event type %d: %p", type, event);
|
||||
GST_CAT_INFO (GST_CAT_EVENT, "creating new event %p %d", event, type);
|
||||
|
||||
GST_EVENT_TYPE (event) = type;
|
||||
event->type = type;
|
||||
event->src = NULL;
|
||||
event->structure = NULL;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_custom:
|
||||
* @type: The type of the new event
|
||||
* @structure: The structure for the event. The event will take ownership of
|
||||
* the structure.
|
||||
*
|
||||
* Create a new custom-typed event. This can be used for anything not
|
||||
* handled by other event-specific functions to pass an event to another
|
||||
* element.
|
||||
*
|
||||
* Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
|
||||
* assigning a free number and filling in the correct direction and
|
||||
* serialization flags.
|
||||
*
|
||||
* New custom events can also be created by subclassing the event type if
|
||||
* needed.
|
||||
*
|
||||
* Returns: The new custom event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_custom (GstEventType type, GstStructure * structure)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new (type);
|
||||
if (structure) {
|
||||
gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
|
||||
event->structure = structure;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_get_structure:
|
||||
* @event: The #GstEvent.
|
||||
*
|
||||
* Access the structure of the event.
|
||||
*
|
||||
* Returns: The structure of the event. The structure is still
|
||||
* owned by the event, which means that you should not free it and
|
||||
* that the pointer becomes invalid when you free the event.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
const GstStructure *
|
||||
gst_event_get_structure (GstEvent * event)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_EVENT (event), NULL);
|
||||
|
||||
return event->structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_flush_start:
|
||||
*
|
||||
* Allocate a new flush start event. The flush start event can be send
|
||||
* upstream and downstream and travels out-of-bounds with the dataflow.
|
||||
* It marks pads as being in a WRONG_STATE to process more data.
|
||||
*
|
||||
* Elements unlock and blocking functions and exit their streaming functions
|
||||
* as fast as possible.
|
||||
*
|
||||
* This event is typically generated after a seek to minimize the latency
|
||||
* after the seek.
|
||||
*
|
||||
* Returns: A new flush start event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_flush_start (void)
|
||||
{
|
||||
return gst_event_new (GST_EVENT_FLUSH_START);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_flush_stop:
|
||||
*
|
||||
* Allocate a new flush stop event. The flush start event can be send
|
||||
* upstream and downstream and travels out-of-bounds with the dataflow.
|
||||
* It is typically send after sending a FLUSH_START event to make the
|
||||
* pads accept data again.
|
||||
*
|
||||
* Elements can process this event synchronized with the dataflow since
|
||||
* the preceeding FLUSH_START event stopped the dataflow.
|
||||
*
|
||||
* This event is typically generated to complete a seek and to resume
|
||||
* dataflow.
|
||||
*
|
||||
* Returns: A new flush stop event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_flush_stop (void)
|
||||
{
|
||||
return gst_event_new (GST_EVENT_FLUSH_STOP);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_eos:
|
||||
*
|
||||
* Create a new EOS event. The eos event can only travel downstream
|
||||
* synchronized with the buffer flow. Elements that receive the EOS
|
||||
* event on a pad can return UNEXPECTED as a GstFlowReturn when data
|
||||
* after the EOS event arrives.
|
||||
*
|
||||
* The EOS event will travel up to the sink elements in the pipeline
|
||||
* which will then post the GST_MESSAGE_EOS on the bus.
|
||||
*
|
||||
* When all sinks have posted an EOS message, the EOS message is
|
||||
* forwarded to the application.
|
||||
*
|
||||
* Returns: The new EOS event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_eos (void)
|
||||
{
|
||||
return gst_event_new (GST_EVENT_EOS);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_newsegment:
|
||||
* @rate: a new rate for playback
|
||||
* @format: The format of the segment values
|
||||
* @start_val: the start value of the segment
|
||||
* @stop_val: the stop value of the segment
|
||||
* @base: base value for buffer timestamps.
|
||||
*
|
||||
* Allocate a new newsegment event with the given format/values tripplets.
|
||||
*
|
||||
* The newsegment event marks the range of buffers to be processed. All
|
||||
* data not within the segment range is not to be processed.
|
||||
*
|
||||
* The base time of the segment is used to convert the buffer timestamps
|
||||
* into the stream time again.
|
||||
*
|
||||
* After a newsegment event, the buffer stream time is calculated with:
|
||||
*
|
||||
* TIMESTAMP(buf) - start_time + base
|
||||
*
|
||||
* Returns: A new newsegment event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_newsegment (gdouble rate, GstFormat format,
|
||||
gint64 start_val, gint64 stop_val, gint64 base)
|
||||
{
|
||||
return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
|
||||
gst_structure_new ("GstEventNewsegment", "rate", G_TYPE_DOUBLE, rate,
|
||||
"format", GST_TYPE_FORMAT, format,
|
||||
"start_val", G_TYPE_INT64, start_val,
|
||||
"stop_val", G_TYPE_INT64, stop_val,
|
||||
"base", G_TYPE_INT64, base, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_parse_newsegment:
|
||||
* @event: The event to query
|
||||
* @rate: A pointer to the rate of the segment
|
||||
* @format: A pointer to the format of the newsegment values
|
||||
* @start_value: A pointer to store the start value in
|
||||
* @stop_value: A pointer to store the stop value in
|
||||
* @base: A pointer to store the base time in
|
||||
*
|
||||
* Get the start, stop and format in the newsegment event.
|
||||
*/
|
||||
void
|
||||
gst_event_parse_newsegment (GstEvent * event, gdouble * rate,
|
||||
GstFormat * format, gint64 * start_value, gint64 * stop_value,
|
||||
gint64 * base)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
if (rate)
|
||||
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
|
||||
if (format)
|
||||
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
|
||||
if (start_value)
|
||||
*start_value =
|
||||
g_value_get_int64 (gst_structure_get_value (structure, "start_val"));
|
||||
if (stop_value)
|
||||
*stop_value =
|
||||
g_value_get_int64 (gst_structure_get_value (structure, "stop_val"));
|
||||
if (base)
|
||||
*base = g_value_get_int64 (gst_structure_get_value (structure, "base"));
|
||||
}
|
||||
|
||||
/* tag event */
|
||||
GstEvent *
|
||||
gst_event_new_tag (GstTagList * taglist)
|
||||
{
|
||||
g_return_val_if_fail (taglist != NULL, NULL);
|
||||
|
||||
return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
|
||||
}
|
||||
|
||||
void
|
||||
gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
|
||||
{
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
|
||||
|
||||
if (taglist)
|
||||
*taglist = (GstTagList *) event->structure;
|
||||
}
|
||||
|
||||
/* filler event */
|
||||
GstEvent *
|
||||
gst_event_new_filler (void)
|
||||
{
|
||||
return gst_event_new (GST_EVENT_FILLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_qos:
|
||||
* @proportion: the proportion of the qos message
|
||||
* @diff: The time difference of the last Clock sync
|
||||
* @timestamp: The timestamp of the buffer
|
||||
*
|
||||
* Allocate a new qos event with the given values.
|
||||
* The QOS event is generated in an element that wants an upstream
|
||||
* element to either reduce or increase its rate because of
|
||||
* high/low CPU load.
|
||||
*
|
||||
* proportion is the requested adjustment in datarate, 1.0 is the normal
|
||||
* datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
|
||||
* values request a slow down, so -0.75 means a decrease by 75%.
|
||||
*
|
||||
* diff is the difference against the clock in stream time of the last
|
||||
* buffer that caused the element to generate the QOS event.
|
||||
*
|
||||
* timestamp is the timestamp of the last buffer that cause the element
|
||||
* to generate the QOS event.
|
||||
*
|
||||
* Returns: A new QOS event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
|
||||
GstClockTime timestamp)
|
||||
{
|
||||
return gst_event_new_custom (GST_EVENT_QOS,
|
||||
gst_structure_new ("GstEventQOS",
|
||||
"proportion", G_TYPE_DOUBLE, proportion,
|
||||
"diff", G_TYPE_INT64, diff,
|
||||
"timestamp", G_TYPE_UINT64, timestamp, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_parse_qos:
|
||||
* @event: The event to query
|
||||
* @proportion: A pointer to store the proportion in
|
||||
* @diff: A pointer to store the diff in
|
||||
* @timestamp: A pointer to store the timestamp in
|
||||
*
|
||||
* Get the proportion, diff and timestamp in the qos event.
|
||||
*/
|
||||
void
|
||||
gst_event_parse_qos (GstEvent * event, gdouble * proportion,
|
||||
GstClockTimeDiff * diff, GstClockTime * timestamp)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
if (proportion)
|
||||
*proportion =
|
||||
g_value_get_double (gst_structure_get_value (structure, "proportion"));
|
||||
if (diff)
|
||||
*diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
|
||||
if (timestamp)
|
||||
*timestamp =
|
||||
g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_seek:
|
||||
* @type: The type of the seek event
|
||||
* @offset: The offset of the seek
|
||||
* @rate: The new playback rate
|
||||
* @format: The format of the seek values
|
||||
* @flags: The optional seek flags.
|
||||
* @cur_type: The type and flags for the new current position
|
||||
* @cur: The value of the new current position
|
||||
* @stop_type: The type and flags for the new stop position
|
||||
* @stop: The value of the new stop position
|
||||
*
|
||||
* Allocate a new seek event with the given parameters.
|
||||
*
|
||||
* The seek event configures playback of the pipeline from
|
||||
* @cur to @stop at the speed given in @rate.
|
||||
* The @cur and @stop values are expressed in format @format.
|
||||
*
|
||||
* A @rate of 1.0 means normal playback rate, 2.0 means double speed.
|
||||
* Negatives values means backwards playback. A value of 0.0 for the
|
||||
* rate is not allowed.
|
||||
*
|
||||
* @cur_type and @stop_type specify how to adjust the current and stop
|
||||
* time, relative or absolute. A type of #GST_EVENT_TYPE_NONE means that
|
||||
* the position should not be updated.
|
||||
*
|
||||
* Returns: A new seek event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_seek (GstSeekType type, gint64 offset)
|
||||
gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
|
||||
GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new (GST_EVENT_SEEK);
|
||||
|
||||
GST_EVENT_SEEK_TYPE (event) = type;
|
||||
GST_EVENT_SEEK_OFFSET (event) = offset;
|
||||
GST_EVENT_SEEK_ENDOFFSET (event) = -1;
|
||||
|
||||
return event;
|
||||
return gst_event_new_custom (GST_EVENT_SEEK,
|
||||
gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
|
||||
"format", GST_TYPE_FORMAT, format,
|
||||
"flags", GST_TYPE_SEEK_FLAGS, flags,
|
||||
"cur_type", GST_TYPE_SEEK_TYPE, cur_type,
|
||||
"cur", G_TYPE_INT64, cur,
|
||||
"stop_type", GST_TYPE_SEEK_TYPE, stop_type,
|
||||
"stop", G_TYPE_INT64, stop, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_discontinuous_valist:
|
||||
* @new_media: A flag indicating a new media type starts
|
||||
* @format1: The format of the discont value
|
||||
* @var_args: more discont values and formats
|
||||
*
|
||||
* Allocate a new discontinuous event with the given format/value pairs. Note
|
||||
* that the values are of type gint64 - you may not use simple integers such
|
||||
* as "0" when calling this function, always cast them like "(gint64) 0".
|
||||
* Terminate the list with #GST_FORMAT_UNDEFINED.
|
||||
*
|
||||
* Returns: A new discontinuous event.
|
||||
*/
|
||||
void
|
||||
gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
|
||||
GstSeekFlags * flags,
|
||||
GstSeekType * cur_type, gint64 * cur,
|
||||
GstSeekType * stop_type, gint64 * stop)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
if (rate)
|
||||
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
|
||||
if (format)
|
||||
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
|
||||
if (flags)
|
||||
*flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
|
||||
if (cur_type)
|
||||
*cur_type =
|
||||
g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
|
||||
if (cur)
|
||||
*cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
|
||||
if (stop_type)
|
||||
*stop_type =
|
||||
g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
|
||||
if (stop)
|
||||
*stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
|
||||
}
|
||||
|
||||
/* navigation event */
|
||||
GstEvent *
|
||||
gst_event_new_discontinuous_valist (gdouble rate, GstFormat format1,
|
||||
va_list var_args)
|
||||
gst_event_new_navigation (GstStructure * structure)
|
||||
{
|
||||
GstEvent *event;
|
||||
gint count = 0;
|
||||
g_return_val_if_fail (structure != NULL, NULL);
|
||||
|
||||
event = gst_event_new (GST_EVENT_DISCONTINUOUS);
|
||||
GST_EVENT_DISCONT_RATE (event) = rate;
|
||||
|
||||
while (format1 != GST_FORMAT_UNDEFINED && count < 8) {
|
||||
|
||||
GST_EVENT_DISCONT_OFFSET (event, count).format =
|
||||
format1 & GST_SEEK_FORMAT_MASK;
|
||||
GST_EVENT_DISCONT_OFFSET (event, count).start_value =
|
||||
va_arg (var_args, gint64);
|
||||
GST_EVENT_DISCONT_OFFSET (event, count).end_value =
|
||||
va_arg (var_args, gint64);
|
||||
|
||||
format1 = va_arg (var_args, GstFormat);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
GST_EVENT_DISCONT_OFFSET_LEN (event) = count;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_discontinuous:
|
||||
* @new_media: A flag indicating a new media type starts
|
||||
* @format1: The format of the discont value
|
||||
* @...: more discont values and formats
|
||||
*
|
||||
* Allocate a new discontinuous event with the given format/value pairs. Note
|
||||
* that the values are of type gint64 - you may not use simple integers such
|
||||
* as "0" when calling this function, always cast them like "(gint64) 0".
|
||||
* Terminate the list with #GST_FORMAT_UNDEFINED.
|
||||
*
|
||||
* Returns: A new discontinuous event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_discontinuous (gdouble rate, GstFormat format1, ...)
|
||||
{
|
||||
va_list var_args;
|
||||
GstEvent *event;
|
||||
|
||||
va_start (var_args, format1);
|
||||
|
||||
event = gst_event_new_discontinuous_valist (rate, format1, var_args);
|
||||
|
||||
va_end (var_args);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_discont_get_value:
|
||||
* @event: The event to query
|
||||
* @format: The format of the discontinuous value
|
||||
* @start_value: A pointer to store the end value in
|
||||
* @end_value: A pointer to store the end value in
|
||||
*
|
||||
* Get the start and end value for the given format in the discontinous event.
|
||||
*
|
||||
* Returns: TRUE if the discontinuous event carries the specified
|
||||
* format/value pair.
|
||||
*/
|
||||
gboolean
|
||||
gst_event_discont_get_value (GstEvent * event, GstFormat format,
|
||||
gint64 * start_value, gint64 * end_value)
|
||||
{
|
||||
gint i, n;
|
||||
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
n = GST_EVENT_DISCONT_OFFSET_LEN (event);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (GST_EVENT_DISCONT_OFFSET (event, i).format == format) {
|
||||
if (start_value)
|
||||
*start_value = GST_EVENT_DISCONT_OFFSET (event, i).start_value;
|
||||
if (end_value)
|
||||
*end_value = GST_EVENT_DISCONT_OFFSET (event, i).end_value;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_event_new_size:
|
||||
* @format: The format of the size value
|
||||
* @value: The value of the size event
|
||||
*
|
||||
* Create a new size event with the given values.
|
||||
*
|
||||
* Returns: The new size event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_size (GstFormat format, gint64 value)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new (GST_EVENT_SIZE);
|
||||
|
||||
GST_EVENT_SIZE_FORMAT (event) = format;
|
||||
GST_EVENT_SIZE_VALUE (event) = value;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_event_new_segment_seek:
|
||||
* @type: The type of the seek event
|
||||
* @start: The start offset of the seek
|
||||
* @stop: The stop offset of the seek
|
||||
*
|
||||
* Allocate a new segment seek event with the given parameters.
|
||||
*
|
||||
* Returns: A new segment seek event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_segment_seek (GstSeekType type, gint64 start, gint64 stop)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
g_return_val_if_fail (start < stop || stop == -1, NULL);
|
||||
|
||||
event = gst_event_new (GST_EVENT_SEEK);
|
||||
|
||||
GST_EVENT_SEEK_TYPE (event) = type;
|
||||
GST_EVENT_SEEK_OFFSET (event) = start;
|
||||
GST_EVENT_SEEK_ENDOFFSET (event) = stop;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_flush:
|
||||
* @done: Indicates the end of the flush
|
||||
*
|
||||
* Allocate a new flush event.
|
||||
*
|
||||
* Returns: A new flush event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_flush (gboolean done)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new (GST_EVENT_FLUSH);
|
||||
GST_EVENT_FLUSH_DONE (event) = done;
|
||||
|
||||
return event;
|
||||
return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
|
||||
}
|
||||
|
|
263
gst/gstevent.h
263
gst/gstevent.h
|
@ -1,6 +1,7 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000 Wim Taymans <wim.taymans@chello.be>
|
||||
* 2005 Wim Taymans <wim@fluendo.com>
|
||||
*
|
||||
* gstevent.h: Header for GstEvent subsystem
|
||||
*
|
||||
|
@ -27,122 +28,110 @@
|
|||
#include <gst/gstminiobject.h>
|
||||
#include <gst/gstformat.h>
|
||||
#include <gst/gstobject.h>
|
||||
#include <gst/gstclock.h>
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/gsttag.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* bitmaks defining the direction */
|
||||
#define GST_EVDIR_US (1 << 0)
|
||||
#define GST_EVDIR_DS (1 << 1)
|
||||
#define GST_EVDIR_BOTH GST_EVDIR_US | GST_EVDIR_DS
|
||||
/* mask defining event is serialized with data */
|
||||
#define GST_EVSER (1 << 2)
|
||||
#define GST_EVSHIFT 4
|
||||
|
||||
/* when making custom event types, use this macro with the num and
|
||||
* the given flags */
|
||||
#define GST_EVENT_MAKE_TYPE(num,flags) (((num) << GST_EVSHIFT) | (flags))
|
||||
|
||||
/**
|
||||
* GstEventType:
|
||||
* @GST_EVENT_UNKNOWN:
|
||||
* @GST_EVENT_EOS:
|
||||
* @GST_EVENT_FLUSH:
|
||||
* @GST_EVENT_DISCONTINUOUS:
|
||||
* @GST_EVENT_QOS:
|
||||
* @GST_EVENT_SEEK:
|
||||
* @GST_EVENT_SIZE:
|
||||
* @GST_EVENT_RATE:
|
||||
* @GST_EVENT_NAVIGATION:
|
||||
* @GST_EVENT_TAG:
|
||||
* @GST_EVENT_UNKNOWN: unknown event.
|
||||
* @GST_EVENT_FLUSH_START: start a flush operation
|
||||
* @GST_EVENT_FLUSH_STOP: stop a flush operation
|
||||
* @GST_EVENT_EOS: no more data is to be expected.
|
||||
* @GST_EVENT_NEWSEGMENT: a new segment started
|
||||
* @GST_EVENT_TAG: a new tag
|
||||
* @GST_EVENT_FILLER: filler for sparse data streams.
|
||||
* @GST_EVENT_QOS: a quality message
|
||||
* @GST_EVENT_SEEK: a request for a new playback position and rate.
|
||||
* @GST_EVENT_NAVIGATION: a navigation event
|
||||
*/
|
||||
typedef enum {
|
||||
GST_EVENT_UNKNOWN = 0,
|
||||
GST_EVENT_EOS = 1,
|
||||
GST_EVENT_FLUSH = 2,
|
||||
GST_EVENT_DISCONTINUOUS = 3,
|
||||
GST_EVENT_QOS = 4,
|
||||
GST_EVENT_SEEK = 5,
|
||||
GST_EVENT_SIZE = 8,
|
||||
GST_EVENT_RATE = 9,
|
||||
GST_EVENT_NAVIGATION = 10,
|
||||
GST_EVENT_TAG = 11
|
||||
GST_EVENT_UNKNOWN = GST_EVENT_MAKE_TYPE (0, 0),
|
||||
/* bidirectional events */
|
||||
GST_EVENT_FLUSH_START = GST_EVENT_MAKE_TYPE (1, GST_EVDIR_BOTH),
|
||||
GST_EVENT_FLUSH_STOP = GST_EVENT_MAKE_TYPE (2, GST_EVDIR_BOTH),
|
||||
/* downstream serialized events */
|
||||
GST_EVENT_EOS = GST_EVENT_MAKE_TYPE (3, GST_EVDIR_DS | GST_EVSER),
|
||||
GST_EVENT_NEWSEGMENT = GST_EVENT_MAKE_TYPE (4, GST_EVDIR_DS | GST_EVSER),
|
||||
GST_EVENT_TAG = GST_EVENT_MAKE_TYPE (5, GST_EVDIR_DS | GST_EVSER),
|
||||
GST_EVENT_FILLER = GST_EVENT_MAKE_TYPE (6, GST_EVDIR_DS | GST_EVSER),
|
||||
/* upstream events */
|
||||
GST_EVENT_QOS = GST_EVENT_MAKE_TYPE (7, GST_EVDIR_US),
|
||||
GST_EVENT_SEEK = GST_EVENT_MAKE_TYPE (8, GST_EVDIR_US),
|
||||
GST_EVENT_NAVIGATION = GST_EVENT_MAKE_TYPE (9, GST_EVDIR_US),
|
||||
|
||||
/* custom events start here */
|
||||
GST_EVENT_CUSTOM_START = 32
|
||||
} GstEventType;
|
||||
#define GST_EVENT_ANY GST_EVENT_NAVIGATION
|
||||
|
||||
#define GST_EVENT_TRACE_NAME "GstEvent"
|
||||
|
||||
typedef struct _GstEvent GstEvent;
|
||||
typedef struct _GstEventClass GstEventClass;
|
||||
|
||||
#define GST_TYPE_EVENT (gst_event_get_type())
|
||||
#define GST_IS_EVENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVENT))
|
||||
#define GST_IS_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_EVENT))
|
||||
#define GST_EVENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_EVENT, GstEventClass))
|
||||
#define GST_EVENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVENT, GstEvent))
|
||||
#define GST_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_EVENT, GstEventClass))
|
||||
#define GST_TYPE_EVENT (gst_event_get_type())
|
||||
#define GST_IS_EVENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVENT))
|
||||
#define GST_IS_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_EVENT))
|
||||
#define GST_EVENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_EVENT, GstEventClass))
|
||||
#define GST_EVENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVENT, GstEvent))
|
||||
#define GST_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_EVENT, GstEventClass))
|
||||
|
||||
#define GST_EVENT_TYPE(event) (GST_EVENT(event)->type)
|
||||
#define GST_EVENT_TIMESTAMP(event) (GST_EVENT(event)->timestamp)
|
||||
#define GST_EVENT_SRC(event) (GST_EVENT(event)->src)
|
||||
|
||||
#define GST_EVENT_IS_INTERRUPT(event) (GST_EVENT_TYPE (event) == GST_EVENT_INTERRUPT)
|
||||
|
||||
#define GST_SEEK_FORMAT_SHIFT 0
|
||||
#define GST_SEEK_METHOD_SHIFT 16
|
||||
#define GST_SEEK_FLAGS_SHIFT 20
|
||||
#define GST_SEEK_FORMAT_MASK 0x0000ffff
|
||||
#define GST_SEEK_METHOD_MASK 0x000f0000
|
||||
#define GST_SEEK_FLAGS_MASK 0xfff00000
|
||||
#define GST_EVENT_IS_UPSTREAM(ev) !!(GST_EVENT_TYPE (ev) & GST_EVDIR_US)
|
||||
#define GST_EVENT_IS_DOWNSTREAM(ev) !!(GST_EVENT_TYPE (ev) & GST_EVDIR_DS)
|
||||
#define GST_EVENT_IS_SERIALIZED(ev) !!(GST_EVENT_TYPE (ev) & GST_EVSER)
|
||||
|
||||
/**
|
||||
* GstSeekType:
|
||||
* @GST_SEEK_TYPE_NONE: no change in position is required
|
||||
* @GST_SEEK_TYPE_CUR: change relative to current position
|
||||
* @GST_SEEK_TYPE_SET: absolute position is requested
|
||||
* @GST_SEEK_TYPE_END: relative position to duration is requested
|
||||
*/
|
||||
typedef enum {
|
||||
GST_EVENT_FLAG_NONE = 0,
|
||||
|
||||
/* indicates negative rates are supported */
|
||||
GST_RATE_FLAG_NEGATIVE = (1 << 1)
|
||||
} GstEventFlag;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstEventType type;
|
||||
GstEventFlag flags;
|
||||
} GstEventMask;
|
||||
|
||||
/* seek events, extends GstEventFlag */
|
||||
typedef enum {
|
||||
/* | with some format */
|
||||
/* | with one of these */
|
||||
GST_SEEK_METHOD_CUR = (1 << (GST_SEEK_METHOD_SHIFT + 0)),
|
||||
GST_SEEK_METHOD_SET = (1 << (GST_SEEK_METHOD_SHIFT + 1)),
|
||||
GST_SEEK_METHOD_END = (1 << (GST_SEEK_METHOD_SHIFT + 2)),
|
||||
|
||||
/* | with optional seek flags */
|
||||
/* seek flags */
|
||||
GST_SEEK_FLAG_FLUSH = (1 << (GST_SEEK_FLAGS_SHIFT + 0)),
|
||||
GST_SEEK_FLAG_ACCURATE = (1 << (GST_SEEK_FLAGS_SHIFT + 1)),
|
||||
GST_SEEK_FLAG_KEY_UNIT = (1 << (GST_SEEK_FLAGS_SHIFT + 2)),
|
||||
GST_SEEK_FLAG_SEGMENT_LOOP = (1 << (GST_SEEK_FLAGS_SHIFT + 3))
|
||||
|
||||
/* one of these */
|
||||
GST_SEEK_TYPE_NONE = 0,
|
||||
GST_SEEK_TYPE_CUR = 1,
|
||||
GST_SEEK_TYPE_SET = 2,
|
||||
GST_SEEK_TYPE_END = 3
|
||||
} GstSeekType;
|
||||
|
||||
/**
|
||||
* GstSeekFlags:
|
||||
* @GST_SEEK_FLAG_NONE: no flag
|
||||
* @GST_SEEK_FLAG_FLUSH: flush pipeline
|
||||
* @GST_SEEK_FLAG_ACCURATE: accurate position is requested, this might
|
||||
* be slower for some formats.
|
||||
* @GST_SEEK_FLAG_KEY_UNIT: seek to the nearest keyframe. This might be
|
||||
* faster but less accurate.
|
||||
* @GST_SEEK_FLAG_SEGMENT: perform a segment seek. After the playback
|
||||
* of the segment completes, no EOS will be emmited but a
|
||||
* SEGMENT_DONE message will be posted on the bus.
|
||||
*/
|
||||
typedef enum {
|
||||
GST_SEEK_CERTAIN,
|
||||
GST_SEEK_FUZZY
|
||||
} GstSeekAccuracy;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstFormat format;
|
||||
gint64 start_value;
|
||||
gint64 end_value;
|
||||
} GstFormatValue;
|
||||
|
||||
#define GST_EVENT_SEEK_TYPE(event) (GST_EVENT(event)->event_data.seek.type)
|
||||
#define GST_EVENT_SEEK_FORMAT(event) (GST_EVENT_SEEK_TYPE(event) & GST_SEEK_FORMAT_MASK)
|
||||
#define GST_EVENT_SEEK_METHOD(event) (GST_EVENT_SEEK_TYPE(event) & GST_SEEK_METHOD_MASK)
|
||||
#define GST_EVENT_SEEK_FLAGS(event) (GST_EVENT_SEEK_TYPE(event) & GST_SEEK_FLAGS_MASK)
|
||||
#define GST_EVENT_SEEK_OFFSET(event) (GST_EVENT(event)->event_data.seek.offset)
|
||||
#define GST_EVENT_SEEK_ENDOFFSET(event) (GST_EVENT(event)->event_data.seek.endoffset)
|
||||
#define GST_EVENT_SEEK_ACCURACY(event) (GST_EVENT(event)->event_data.seek.accuracy)
|
||||
|
||||
#define GST_EVENT_DISCONT_RATE(event) (GST_EVENT(event)->event_data.discont.rate)
|
||||
#define GST_EVENT_DISCONT_OFFSET(event,i) (GST_EVENT(event)->event_data.discont.offsets[i])
|
||||
#define GST_EVENT_DISCONT_OFFSET_LEN(event) (GST_EVENT(event)->event_data.discont.noffsets)
|
||||
|
||||
#define GST_EVENT_FLUSH_DONE(event) (GST_EVENT(event)->event_data.flush.done)
|
||||
|
||||
#define GST_EVENT_SIZE_FORMAT(event) (GST_EVENT(event)->event_data.size.format)
|
||||
#define GST_EVENT_SIZE_VALUE(event) (GST_EVENT(event)->event_data.size.value)
|
||||
|
||||
#define GST_EVENT_RATE_VALUE(event) (GST_EVENT(event)->event_data.rate.value)
|
||||
GST_SEEK_FLAG_NONE = 0,
|
||||
GST_SEEK_FLAG_FLUSH = (1 << 0),
|
||||
GST_SEEK_FLAG_ACCURATE = (1 << 1),
|
||||
GST_SEEK_FLAG_KEY_UNIT = (1 << 2),
|
||||
GST_SEEK_FLAG_SEGMENT = (1 << 3)
|
||||
} GstSeekFlags;
|
||||
|
||||
struct _GstEvent {
|
||||
GstMiniObject mini_object;
|
||||
|
@ -152,32 +141,7 @@ struct _GstEvent {
|
|||
guint64 timestamp;
|
||||
GstObject *src;
|
||||
|
||||
union {
|
||||
struct {
|
||||
GstSeekType type;
|
||||
gint64 offset;
|
||||
gint64 endoffset;
|
||||
GstSeekAccuracy accuracy;
|
||||
} seek;
|
||||
struct {
|
||||
GstFormatValue offsets[8];
|
||||
gint noffsets;
|
||||
gdouble rate;
|
||||
} discont;
|
||||
struct {
|
||||
gboolean done;
|
||||
} flush;
|
||||
struct {
|
||||
GstFormat format;
|
||||
gint64 value;
|
||||
} size;
|
||||
struct {
|
||||
gdouble value;
|
||||
} rate;
|
||||
struct {
|
||||
GstStructure *structure;
|
||||
} structure;
|
||||
} event_data;
|
||||
GstStructure *structure;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
|
@ -193,39 +157,54 @@ struct _GstEventClass {
|
|||
void _gst_event_initialize (void);
|
||||
|
||||
GType gst_event_get_type (void);
|
||||
GstEvent* gst_event_new (GstEventType type);
|
||||
|
||||
/* refcounting */
|
||||
#define gst_event_ref(ev) GST_EVENT (gst_mini_object_ref (GST_MINI_OBJECT (ev)))
|
||||
#define gst_event_unref(ev) gst_mini_object_unref (GST_MINI_OBJECT (ev))
|
||||
/* copy buffer */
|
||||
/* copy event */
|
||||
#define gst_event_copy(ev) GST_EVENT (gst_mini_object_copy (GST_MINI_OBJECT (ev)))
|
||||
|
||||
gboolean gst_event_masks_contains (const GstEventMask *masks, GstEventMask *mask);
|
||||
/* custom event */
|
||||
GstEvent* gst_event_new_custom (GstEventType type, GstStructure *structure);
|
||||
|
||||
/* seek event */
|
||||
GstEvent* gst_event_new_seek (GstSeekType type, gint64 offset);
|
||||
|
||||
GstEvent* gst_event_new_segment_seek (GstSeekType type, gint64 start, gint64 stop);
|
||||
|
||||
|
||||
/* size events */
|
||||
GstEvent* gst_event_new_size (GstFormat format, gint64 value);
|
||||
|
||||
/* discontinous event */
|
||||
GstEvent* gst_event_new_discontinuous (gdouble rate,
|
||||
GstFormat format1, ...);
|
||||
GstEvent* gst_event_new_discontinuous_valist (gdouble rate,
|
||||
GstFormat format1,
|
||||
va_list var_args);
|
||||
gboolean gst_event_discont_get_value (GstEvent *event, GstFormat format,
|
||||
gint64 *start_value, gint64 *end_value);
|
||||
|
||||
#define gst_event_new_filler() gst_event_new(GST_EVENT_FILLER)
|
||||
#define gst_event_new_eos() gst_event_new(GST_EVENT_EOS)
|
||||
const GstStructure *
|
||||
gst_event_get_structure (GstEvent *event);
|
||||
|
||||
/* flush events */
|
||||
GstEvent* gst_event_new_flush (gboolean done);
|
||||
GstEvent * gst_event_new_flush_start (void);
|
||||
GstEvent * gst_event_new_flush_stop (void);
|
||||
|
||||
/* EOS event */
|
||||
GstEvent * gst_event_new_eos (void);
|
||||
|
||||
/* newsegment events */
|
||||
GstEvent* gst_event_new_newsegment (gdouble rate,
|
||||
GstFormat format, gint64 start_value, gint64 stop_value,
|
||||
gint64 base);
|
||||
void gst_event_parse_newsegment (GstEvent *event, gdouble *rate, GstFormat *format,
|
||||
gint64 *start_value, gint64 *end_value, gint64 *base);
|
||||
/* tag event */
|
||||
GstEvent* gst_event_new_tag (GstTagList *taglist);
|
||||
void gst_event_parse_tag (GstEvent *event, GstTagList **taglist);
|
||||
|
||||
/* filler event */
|
||||
GstEvent * gst_event_new_filler (void);
|
||||
|
||||
|
||||
/* QOS events */
|
||||
GstEvent* gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
|
||||
GstClockTime timestamp);
|
||||
void gst_event_parse_qos (GstEvent *event, gdouble *proportion, GstClockTimeDiff *diff,
|
||||
GstClockTime *timestamp);
|
||||
/* seek event */
|
||||
GstEvent* gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
|
||||
GstSeekType cur_type, gint64 cur,
|
||||
GstSeekType stop_type, gint64 stop);
|
||||
void gst_event_parse_seek (GstEvent *event, gdouble *rate, GstFormat *format,
|
||||
GstSeekFlags *flags,
|
||||
GstSeekType *cur_type, gint64 *cur,
|
||||
GstSeekType *stop_type, gint64 *stop);
|
||||
/* navigation event */
|
||||
GstEvent* gst_event_new_navigation (GstStructure *structure);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ gst_message_init (GTypeInstance * instance, gpointer g_class)
|
|||
{
|
||||
GstMessage *message = GST_MESSAGE (instance);
|
||||
|
||||
message->timestamp = GST_CLOCK_TIME_NONE;
|
||||
GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -106,6 +106,7 @@ gst_message_finalize (GstMessage * message)
|
|||
|
||||
if (GST_MESSAGE_SRC (message)) {
|
||||
gst_object_unref (GST_MESSAGE_SRC (message));
|
||||
GST_MESSAGE_SRC (message) = NULL;
|
||||
}
|
||||
|
||||
if (message->lock) {
|
||||
|
@ -132,10 +133,10 @@ _gst_message_copy (GstMessage * message)
|
|||
/* FIXME, need to copy relevant data from the miniobject. */
|
||||
//memcpy (copy, message, sizeof (GstMessage));
|
||||
|
||||
copy->lock = message->lock;
|
||||
copy->cond = message->cond;
|
||||
copy->type = message->type;
|
||||
copy->timestamp = message->timestamp;
|
||||
GST_MESSAGE_GET_LOCK (copy) = GST_MESSAGE_GET_LOCK (message);
|
||||
GST_MESSAGE_COND (copy) = GST_MESSAGE_COND (message);
|
||||
GST_MESSAGE_TYPE (copy) = GST_MESSAGE_TYPE (message);
|
||||
GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message);
|
||||
|
||||
if (GST_MESSAGE_SRC (message)) {
|
||||
GST_MESSAGE_SRC (copy) = gst_object_ref (GST_MESSAGE_SRC (message));
|
||||
|
@ -150,16 +151,6 @@ _gst_message_copy (GstMessage * message)
|
|||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_new:
|
||||
* @type: The type of the new message
|
||||
*
|
||||
* Allocate a new message of the given type.
|
||||
*
|
||||
* Returns: A new message.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
static GstMessage *
|
||||
gst_message_new (GstMessageType type, GstObject * src)
|
||||
{
|
||||
|
@ -386,7 +377,7 @@ gst_message_new_segment_done (GstObject * src, GstClockTime timestamp)
|
|||
*
|
||||
* Create a new custom-typed message. This can be used for anything not
|
||||
* handled by other message-specific functions to pass a message to the
|
||||
* app.
|
||||
* app. The structure field can be NULL.
|
||||
*
|
||||
* Returns: The new message.
|
||||
*
|
||||
|
@ -398,12 +389,12 @@ gst_message_new_custom (GstMessageType type, GstObject * src,
|
|||
{
|
||||
GstMessage *message;
|
||||
|
||||
g_return_val_if_fail (GST_IS_STRUCTURE (structure), NULL);
|
||||
|
||||
message = gst_message_new (type, src);
|
||||
gst_structure_set_parent_refcount (structure, &message->mini_object.refcount);
|
||||
message->structure = structure;
|
||||
|
||||
if (structure) {
|
||||
gst_structure_set_parent_refcount (structure,
|
||||
&message->mini_object.refcount);
|
||||
message->structure = structure;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
|
|
37
gst/gstpad.c
37
gst/gstpad.c
|
@ -3255,24 +3255,29 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
|
|||
|
||||
GST_LOCK (pad);
|
||||
|
||||
if (GST_PAD_IS_SINK (pad) && !GST_EVENT_IS_DOWNSTREAM (event))
|
||||
goto wrong_direction;
|
||||
if (GST_PAD_IS_SRC (pad) && !GST_EVENT_IS_UPSTREAM (event))
|
||||
goto wrong_direction;
|
||||
|
||||
if (GST_EVENT_SRC (event) == NULL)
|
||||
GST_EVENT_SRC (event) = gst_object_ref (pad);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH:
|
||||
GST_CAT_DEBUG (GST_CAT_EVENT, "have event type %d (FLUSH) on pad %s:%s",
|
||||
case GST_EVENT_FLUSH_START:
|
||||
GST_CAT_DEBUG (GST_CAT_EVENT,
|
||||
"have event type %d (FLUSH_START) on pad %s:%s",
|
||||
GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
if (GST_EVENT_FLUSH_DONE (event)) {
|
||||
GST_PAD_UNSET_FLUSHING (pad);
|
||||
GST_CAT_DEBUG (GST_CAT_EVENT, "cleared flush flag");
|
||||
} else {
|
||||
/* can't even accept a flush begin event when flushing */
|
||||
if (GST_PAD_IS_FLUSHING (pad))
|
||||
goto flushing;
|
||||
GST_PAD_SET_FLUSHING (pad);
|
||||
GST_CAT_DEBUG (GST_CAT_EVENT, "set flush flag");
|
||||
}
|
||||
/* can't even accept a flush begin event when flushing */
|
||||
if (GST_PAD_IS_FLUSHING (pad))
|
||||
goto flushing;
|
||||
GST_PAD_SET_FLUSHING (pad);
|
||||
GST_CAT_DEBUG (GST_CAT_EVENT, "set flush flag");
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
GST_PAD_UNSET_FLUSHING (pad);
|
||||
GST_CAT_DEBUG (GST_CAT_EVENT, "cleared flush flag");
|
||||
break;
|
||||
default:
|
||||
GST_CAT_DEBUG (GST_CAT_EVENT, "have event type %d on pad %s:%s",
|
||||
|
@ -3303,6 +3308,14 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
|
|||
return result;
|
||||
|
||||
/* ERROR handling */
|
||||
wrong_direction:
|
||||
{
|
||||
g_warning ("pad %s:%s sending event in wrong direction",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
GST_UNLOCK (pad);
|
||||
gst_event_unref (event);
|
||||
return FALSE;
|
||||
}
|
||||
no_function:
|
||||
{
|
||||
g_warning ("pad %s:%s has no event handler, file a bug.",
|
||||
|
|
|
@ -491,32 +491,38 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH:
|
||||
STATUS (queue, "received flush event");
|
||||
case GST_EVENT_FLUSH_START:
|
||||
STATUS (queue, "received flush start event");
|
||||
/* forward event, re first as we're going to use it still */
|
||||
gst_event_ref (event);
|
||||
gst_pad_push_event (queue->srcpad, event);
|
||||
if (GST_EVENT_FLUSH_DONE (event)) {
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
gst_queue_locked_flush (queue);
|
||||
queue->srcresult = GST_FLOW_OK;
|
||||
gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop,
|
||||
queue->srcpad);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
|
||||
STATUS (queue, "after flush");
|
||||
} else {
|
||||
/* now unblock the chain function */
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
queue->srcresult = GST_FLOW_WRONG_STATE;
|
||||
/* unblock the loop function */
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
/* now unblock the chain function */
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
queue->srcresult = GST_FLOW_WRONG_STATE;
|
||||
/* unblock the loop function */
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
|
||||
/* make sure it pauses */
|
||||
gst_pad_pause_task (queue->srcpad);
|
||||
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped");
|
||||
}
|
||||
/* make sure it pauses */
|
||||
gst_pad_pause_task (queue->srcpad);
|
||||
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped");
|
||||
gst_event_unref (event);
|
||||
goto done;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
STATUS (queue, "received flush stop event");
|
||||
/* forward event, re first as we're going to use it still */
|
||||
gst_event_ref (event);
|
||||
gst_pad_push_event (queue->srcpad, event);
|
||||
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
gst_queue_locked_flush (queue);
|
||||
queue->srcresult = GST_FLOW_OK;
|
||||
gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop,
|
||||
queue->srcpad);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
|
||||
STATUS (queue, "after flush");
|
||||
gst_event_unref (event);
|
||||
goto done;
|
||||
case GST_EVENT_EOS:
|
||||
|
@ -775,7 +781,7 @@ restart:
|
|||
GST_ELEMENT_ERROR (queue, STREAM, STOPPED,
|
||||
("streaming stopped, reason %s", flowname),
|
||||
("streaming stopped, reason %s", flowname));
|
||||
gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (queue->srcpad, gst_event_new_eos ());
|
||||
}
|
||||
GST_DEBUG ("pausing queue, reason %s", flowname);
|
||||
gst_pad_pause_task (queue->srcpad);
|
||||
|
|
42
gst/gsttag.c
42
gst/gsttag.c
|
@ -804,48 +804,6 @@ gst_tag_list_foreach (GstTagList * list, GstTagForeachFunc func,
|
|||
&data);
|
||||
}
|
||||
|
||||
/***** tag events *****/
|
||||
|
||||
/**
|
||||
* gst_event_new_tag:
|
||||
* @list: the tag list to put into the event or NULL for an empty list
|
||||
*
|
||||
* Creates a new tag event with the given list and takes ownership of it.
|
||||
*
|
||||
* Returns: a new tag event
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_tag (GstTagList * list)
|
||||
{
|
||||
GstEvent *ret;
|
||||
|
||||
g_return_val_if_fail (list == NULL || GST_IS_TAG_LIST (list), NULL);
|
||||
|
||||
ret = gst_event_new (GST_EVENT_TAG);
|
||||
if (!list)
|
||||
list = gst_tag_list_new ();
|
||||
ret->event_data.structure.structure = (GstStructure *) list;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_tag_get_list:
|
||||
* @tag_event: a tagging #GstEvent
|
||||
*
|
||||
* Gets the taglist from a given tagging event.
|
||||
*
|
||||
* Returns: The #GstTagList of the event
|
||||
*/
|
||||
GstTagList *
|
||||
gst_event_tag_get_list (GstEvent * tag_event)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_EVENT (tag_event), NULL);
|
||||
g_return_val_if_fail (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG, NULL);
|
||||
|
||||
return GST_TAG_LIST (tag_event->event_data.structure.structure);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tag_list_get_value_index:
|
||||
* @list: a #GStTagList
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define __GST_TAG_H__
|
||||
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/gstevent.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -220,11 +219,6 @@ gboolean gst_tag_list_get_pointer_index (const GstTagList * list,
|
|||
guint index,
|
||||
gpointer * value);
|
||||
|
||||
/* tag events */
|
||||
GstEvent * gst_event_new_tag (GstTagList * list);
|
||||
GstTagList * gst_event_tag_get_list (GstEvent * tag_event);
|
||||
|
||||
|
||||
/* GStreamer core tags (need to be discussed) */
|
||||
/**
|
||||
* GST_TAG_TITLE:
|
||||
|
|
|
@ -804,48 +804,6 @@ gst_tag_list_foreach (GstTagList * list, GstTagForeachFunc func,
|
|||
&data);
|
||||
}
|
||||
|
||||
/***** tag events *****/
|
||||
|
||||
/**
|
||||
* gst_event_new_tag:
|
||||
* @list: the tag list to put into the event or NULL for an empty list
|
||||
*
|
||||
* Creates a new tag event with the given list and takes ownership of it.
|
||||
*
|
||||
* Returns: a new tag event
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_tag (GstTagList * list)
|
||||
{
|
||||
GstEvent *ret;
|
||||
|
||||
g_return_val_if_fail (list == NULL || GST_IS_TAG_LIST (list), NULL);
|
||||
|
||||
ret = gst_event_new (GST_EVENT_TAG);
|
||||
if (!list)
|
||||
list = gst_tag_list_new ();
|
||||
ret->event_data.structure.structure = (GstStructure *) list;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_tag_get_list:
|
||||
* @tag_event: a tagging #GstEvent
|
||||
*
|
||||
* Gets the taglist from a given tagging event.
|
||||
*
|
||||
* Returns: The #GstTagList of the event
|
||||
*/
|
||||
GstTagList *
|
||||
gst_event_tag_get_list (GstEvent * tag_event)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_EVENT (tag_event), NULL);
|
||||
g_return_val_if_fail (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG, NULL);
|
||||
|
||||
return GST_TAG_LIST (tag_event->event_data.structure.structure);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tag_list_get_value_index:
|
||||
* @list: a #GStTagList
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define __GST_TAG_H__
|
||||
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/gstevent.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -220,11 +219,6 @@ gboolean gst_tag_list_get_pointer_index (const GstTagList * list,
|
|||
guint index,
|
||||
gpointer * value);
|
||||
|
||||
/* tag events */
|
||||
GstEvent * gst_event_new_tag (GstTagList * list);
|
||||
GstTagList * gst_event_tag_get_list (GstEvent * tag_event);
|
||||
|
||||
|
||||
/* GStreamer core tags (need to be discussed) */
|
||||
/**
|
||||
* GST_TAG_TITLE:
|
||||
|
|
|
@ -468,11 +468,17 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
|
|||
basesink->preroll_queued++;
|
||||
basesink->eos = TRUE;
|
||||
break;
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
/* the discont event is needed to bring the buffer timestamps to the
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate;
|
||||
|
||||
/* the newsegment event is needed to bring the buffer timestamps to the
|
||||
* stream time */
|
||||
if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
|
||||
&basesink->discont_start, &basesink->discont_stop)) {
|
||||
gst_event_parse_newsegment (event, &rate, &format,
|
||||
&basesink->discont_start, &basesink->discont_stop, NULL);
|
||||
|
||||
if (format != GST_FORMAT_TIME) {
|
||||
/* this means this sink will not be able to sync to the clock */
|
||||
basesink->discont_start = 0;
|
||||
basesink->discont_stop = 0;
|
||||
|
@ -483,6 +489,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
|
|||
GST_TIME_ARGS (basesink->discont_start),
|
||||
GST_TIME_ARGS (basesink->discont_stop));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -664,7 +671,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
|
|||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
|
||||
|
@ -674,39 +681,44 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
|
|||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_FLUSH_START:
|
||||
/* make sure we are not blocked on the clock also clear any pending
|
||||
* eos state. */
|
||||
if (bclass->event)
|
||||
bclass->event (basesink, event);
|
||||
|
||||
if (!GST_EVENT_FLUSH_DONE (event)) {
|
||||
GST_PREROLL_LOCK (pad);
|
||||
/* we need preroll after the flush */
|
||||
basesink->need_preroll = TRUE;
|
||||
/* unlock from a possible state change/preroll */
|
||||
gst_base_sink_preroll_queue_flush (basesink, pad);
|
||||
GST_PREROLL_LOCK (pad);
|
||||
/* we need preroll after the flush */
|
||||
basesink->need_preroll = TRUE;
|
||||
/* unlock from a possible state change/preroll */
|
||||
gst_base_sink_preroll_queue_flush (basesink, pad);
|
||||
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* and we need to commit our state again on the next
|
||||
* prerolled buffer */
|
||||
GST_STATE_LOCK (basesink);
|
||||
GST_STREAM_LOCK (pad);
|
||||
gst_element_lost_state (GST_ELEMENT (basesink));
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_STATE_UNLOCK (basesink);
|
||||
} else {
|
||||
/* now we are completely unblocked and the _chain method
|
||||
* will return */
|
||||
GST_STREAM_LOCK (pad);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* and we need to commit our state again on the next
|
||||
* prerolled buffer */
|
||||
GST_STATE_LOCK (basesink);
|
||||
GST_STREAM_LOCK (pad);
|
||||
gst_element_lost_state (GST_ELEMENT (basesink));
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_STATE_UNLOCK (basesink);
|
||||
GST_DEBUG ("event unref %p %p", basesink, event);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
if (bclass->event)
|
||||
bclass->event (basesink, event);
|
||||
|
||||
/* now we are completely unblocked and the _chain method
|
||||
* will return */
|
||||
GST_STREAM_LOCK (pad);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
|
||||
GST_DEBUG ("event unref %p %p", basesink, event);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
|
|
|
@ -362,9 +362,9 @@ gst_base_src_send_discont (GstBaseSrc * src)
|
|||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new_discontinuous (1.0,
|
||||
event = gst_event_new_newsegment (1.0,
|
||||
GST_FORMAT_BYTES,
|
||||
(gint64) src->segment_start, (gint64) src->segment_end, NULL);
|
||||
(gint64) src->segment_start, (gint64) src->segment_end, (gint64) 0);
|
||||
|
||||
return gst_pad_push_event (src->srcpad, event);
|
||||
}
|
||||
|
@ -372,10 +372,14 @@ gst_base_src_send_discont (GstBaseSrc * src)
|
|||
static gboolean
|
||||
gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
|
||||
{
|
||||
gdouble rate;
|
||||
GstFormat format;
|
||||
gint64 offset;
|
||||
GstSeekFlags flags;
|
||||
GstSeekType cur_type, stop_type;
|
||||
gint64 cur, stop;
|
||||
|
||||
format = GST_EVENT_SEEK_FORMAT (event);
|
||||
gst_event_parse_seek (event, &rate, &format, &flags,
|
||||
&cur_type, &cur, &stop_type, &stop);
|
||||
|
||||
/* get seek format */
|
||||
if (format == GST_FORMAT_DEFAULT)
|
||||
|
@ -385,11 +389,10 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
|
|||
return FALSE;
|
||||
|
||||
/* get seek positions */
|
||||
offset = GST_EVENT_SEEK_OFFSET (event);
|
||||
src->segment_loop = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP;
|
||||
src->segment_loop = flags & GST_SEEK_FLAG_SEGMENT;
|
||||
|
||||
/* send flush start */
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush (FALSE));
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
|
||||
|
||||
/* unblock streaming thread */
|
||||
gst_base_src_unlock (src);
|
||||
|
@ -397,35 +400,35 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
|
|||
/* grab streaming lock */
|
||||
GST_STREAM_LOCK (src->srcpad);
|
||||
|
||||
/* send flush end */
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush (TRUE));
|
||||
/* send flush stop */
|
||||
gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
|
||||
|
||||
/* perform the seek */
|
||||
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||
case GST_SEEK_METHOD_SET:
|
||||
if (offset < 0)
|
||||
switch (cur_type) {
|
||||
case GST_SEEK_TYPE_SET:
|
||||
if (cur < 0)
|
||||
goto error;
|
||||
src->offset = MIN (offset, src->size);
|
||||
src->offset = MIN (cur, src->size);
|
||||
src->segment_start = src->offset;
|
||||
src->segment_end = MIN (GST_EVENT_SEEK_ENDOFFSET (event), src->size);
|
||||
src->segment_end = MIN (stop, src->size);
|
||||
GST_DEBUG_OBJECT (src, "seek set pending to %" G_GINT64_FORMAT,
|
||||
src->offset);
|
||||
break;
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
offset += src->offset;
|
||||
src->offset = CLAMP (offset, 0, src->size);
|
||||
case GST_SEEK_TYPE_CUR:
|
||||
cur += src->offset;
|
||||
src->offset = CLAMP (cur, 0, src->size);
|
||||
src->segment_start = src->offset;
|
||||
src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
|
||||
src->segment_end = stop;
|
||||
GST_DEBUG_OBJECT (src, "seek cur pending to %" G_GINT64_FORMAT,
|
||||
src->offset);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
if (offset > 0)
|
||||
case GST_SEEK_TYPE_END:
|
||||
if (cur > 0)
|
||||
goto error;
|
||||
offset = src->size + offset;
|
||||
src->offset = MAX (0, offset);
|
||||
cur = src->size + cur;
|
||||
src->offset = MAX (0, cur);
|
||||
src->segment_start = src->offset;
|
||||
src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
|
||||
src->segment_end = stop;
|
||||
GST_DEBUG_OBJECT (src, "seek end pending to %" G_GINT64_FORMAT,
|
||||
src->offset);
|
||||
break;
|
||||
|
@ -471,25 +474,11 @@ gst_base_src_event_handler (GstPad * pad, GstEvent * event)
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
return gst_base_src_do_seek (src, event);
|
||||
case GST_EVENT_SIZE:
|
||||
{
|
||||
GstFormat format;
|
||||
|
||||
format = GST_EVENT_SIZE_FORMAT (event);
|
||||
if (format == GST_FORMAT_DEFAULT)
|
||||
format = GST_FORMAT_BYTES;
|
||||
/* we can only accept bytes */
|
||||
if (format != GST_FORMAT_BYTES)
|
||||
return FALSE;
|
||||
|
||||
src->blocksize = GST_EVENT_SIZE_VALUE (event);
|
||||
g_object_notify (G_OBJECT (src), "blocksize");
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_FLUSH_START:
|
||||
/* cancel any blocking getrange */
|
||||
if (!GST_EVENT_FLUSH_DONE (event))
|
||||
gst_base_src_unlock (src);
|
||||
gst_base_src_unlock (src);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -695,7 +684,7 @@ eos:
|
|||
{
|
||||
GST_DEBUG_OBJECT (src, "going to EOS");
|
||||
gst_pad_pause_task (pad);
|
||||
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||
return;
|
||||
}
|
||||
pause:
|
||||
|
@ -707,7 +696,7 @@ pause:
|
|||
GST_ELEMENT_ERROR (src, STREAM, STOPPED,
|
||||
("streaming stopped, reason %s", gst_flow_get_name (ret)),
|
||||
("streaming stopped, reason %s", gst_flow_get_name (ret)));
|
||||
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -717,7 +706,7 @@ error:
|
|||
("internal: element returned NULL buffer"),
|
||||
("internal: element returned NULL buffer"));
|
||||
gst_pad_pause_task (pad);
|
||||
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -497,11 +497,11 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
|
|||
unlock = FALSE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH:
|
||||
if (GST_EVENT_FLUSH_DONE (event)) {
|
||||
GST_STREAM_LOCK (pad);
|
||||
unlock = TRUE;
|
||||
}
|
||||
case GST_EVENT_FLUSH_START:
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
GST_STREAM_LOCK (pad);
|
||||
unlock = TRUE;
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
GST_STREAM_LOCK (pad);
|
||||
|
|
|
@ -321,8 +321,9 @@ gst_dp_packet_from_event (const GstEvent * event, GstDPHeaderFlag flags,
|
|||
g_free (h);
|
||||
return FALSE;
|
||||
case GST_EVENT_EOS:
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
case GST_EVENT_FLUSH_START:
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
GST_WRITE_UINT64_BE (h + 8, GST_EVENT_TIMESTAMP (event));
|
||||
pl_length = 0;
|
||||
*payload = NULL;
|
||||
|
@ -330,17 +331,17 @@ gst_dp_packet_from_event (const GstEvent * event, GstDPHeaderFlag flags,
|
|||
case GST_EVENT_SEEK:
|
||||
pl_length = 4 + 8 + 8 + 4;
|
||||
*payload = g_malloc0 (pl_length);
|
||||
GST_WRITE_UINT32_BE (*payload, (guint32) GST_EVENT_SEEK_TYPE (event));
|
||||
GST_WRITE_UINT64_BE (*payload + 4,
|
||||
(guint64) GST_EVENT_SEEK_OFFSET (event));
|
||||
GST_WRITE_UINT64_BE (*payload + 12,
|
||||
(guint64) GST_EVENT_SEEK_ENDOFFSET (event));
|
||||
GST_WRITE_UINT32_BE (*payload + 20,
|
||||
(guint32) GST_EVENT_SEEK_ACCURACY (event));
|
||||
/*
|
||||
GST_WRITE_UINT32_BE (*payload, (guint32) GST_EVENT_SEEK_TYPE (event));
|
||||
GST_WRITE_UINT64_BE (*payload + 4,
|
||||
(guint64) GST_EVENT_SEEK_OFFSET (event));
|
||||
GST_WRITE_UINT64_BE (*payload + 12,
|
||||
(guint64) GST_EVENT_SEEK_ENDOFFSET (event));
|
||||
GST_WRITE_UINT32_BE (*payload + 20,
|
||||
(guint32) GST_EVENT_SEEK_ACCURACY (event));
|
||||
*/
|
||||
break;
|
||||
case GST_EVENT_QOS:
|
||||
case GST_EVENT_SIZE:
|
||||
case GST_EVENT_RATE:
|
||||
case GST_EVENT_NAVIGATION:
|
||||
case GST_EVENT_TAG:
|
||||
g_warning ("Unhandled event type %d, ignoring", GST_EVENT_TYPE (event));
|
||||
|
@ -472,29 +473,30 @@ gst_dp_event_from_packet (guint header_length, const guint8 * header,
|
|||
g_warning ("Unknown event, ignoring");
|
||||
return FALSE;
|
||||
case GST_EVENT_EOS:
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
event = gst_event_new (type);
|
||||
case GST_EVENT_FLUSH_START:
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
event = gst_event_new_custom (type, NULL);
|
||||
GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header);
|
||||
break;
|
||||
case GST_EVENT_SEEK:
|
||||
{
|
||||
GstSeekType type;
|
||||
gint64 offset, endoffset;
|
||||
GstSeekAccuracy accuracy;
|
||||
/*
|
||||
GstSeekType type;
|
||||
gint64 offset, endoffset;
|
||||
GstSeekAccuracy accuracy;
|
||||
|
||||
type = (GstSeekType) GST_READ_UINT32_BE (payload);
|
||||
offset = (gint64) GST_READ_UINT64_BE (payload + 4);
|
||||
endoffset = (gint64) GST_READ_UINT64_BE (payload + 12);
|
||||
accuracy = (GstSeekAccuracy) GST_READ_UINT32_BE (payload + 20);
|
||||
event = gst_event_new_segment_seek (type, offset, endoffset);
|
||||
GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header);
|
||||
GST_EVENT_SEEK_ACCURACY (event) = accuracy;
|
||||
type = (GstSeekType) GST_READ_UINT32_BE (payload);
|
||||
offset = (gint64) GST_READ_UINT64_BE (payload + 4);
|
||||
endoffset = (gint64) GST_READ_UINT64_BE (payload + 12);
|
||||
accuracy = (GstSeekAccuracy) GST_READ_UINT32_BE (payload + 20);
|
||||
event = gst_event_new_segment_seek (type, offset, endoffset);
|
||||
GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header);
|
||||
GST_EVENT_SEEK_ACCURACY (event) = accuracy;
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_QOS:
|
||||
case GST_EVENT_SIZE:
|
||||
case GST_EVENT_RATE:
|
||||
case GST_EVENT_NAVIGATION:
|
||||
case GST_EVENT_TAG:
|
||||
g_warning ("Unhandled event type %d, ignoring", GST_EVENT_TYPE (event));
|
||||
|
|
|
@ -273,13 +273,20 @@ static gboolean
|
|||
gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event)
|
||||
{
|
||||
GstFakeSink *sink = GST_FAKE_SINK (bsink);
|
||||
const GstStructure *s;
|
||||
|
||||
if (!sink->silent) {
|
||||
gchar *sstr;
|
||||
|
||||
g_free (sink->last_message);
|
||||
|
||||
s = gst_event_get_structure (event);
|
||||
sstr = gst_structure_to_string (s);
|
||||
|
||||
sink->last_message =
|
||||
g_strdup_printf ("event ******* E (type: %d) %p",
|
||||
GST_EVENT_TYPE (event), event);
|
||||
g_strdup_printf ("event ******* E (type: %d, %s) %p",
|
||||
GST_EVENT_TYPE (event), sstr, event);
|
||||
g_free (sstr);
|
||||
|
||||
g_object_notify (G_OBJECT (sink), "last_message");
|
||||
}
|
||||
|
|
|
@ -291,48 +291,23 @@ gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
|
|||
|
||||
filesink = GST_FILE_SINK (sink);
|
||||
|
||||
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
|
||||
type = GST_EVENT_TYPE (event);
|
||||
|
||||
switch (type) {
|
||||
case GST_EVENT_SEEK:
|
||||
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
|
||||
if (fflush (filesink->file)) {
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||
case GST_SEEK_METHOD_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);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_END);
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown seek method!");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
gint64 soffset, eoffset;
|
||||
GstFormat format;
|
||||
|
||||
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &soffset,
|
||||
&eoffset))
|
||||
gst_event_parse_newsegment (event, NULL, &format, &soffset, &eoffset,
|
||||
NULL);
|
||||
|
||||
if (format == GST_FORMAT_BYTES) {
|
||||
fseek (filesink->file, soffset, SEEK_SET);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_EOS:
|
||||
if (fflush (filesink->file)) {
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
|
|
|
@ -491,32 +491,38 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH:
|
||||
STATUS (queue, "received flush event");
|
||||
case GST_EVENT_FLUSH_START:
|
||||
STATUS (queue, "received flush start event");
|
||||
/* forward event, re first as we're going to use it still */
|
||||
gst_event_ref (event);
|
||||
gst_pad_push_event (queue->srcpad, event);
|
||||
if (GST_EVENT_FLUSH_DONE (event)) {
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
gst_queue_locked_flush (queue);
|
||||
queue->srcresult = GST_FLOW_OK;
|
||||
gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop,
|
||||
queue->srcpad);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
|
||||
STATUS (queue, "after flush");
|
||||
} else {
|
||||
/* now unblock the chain function */
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
queue->srcresult = GST_FLOW_WRONG_STATE;
|
||||
/* unblock the loop function */
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
/* now unblock the chain function */
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
queue->srcresult = GST_FLOW_WRONG_STATE;
|
||||
/* unblock the loop function */
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
|
||||
/* make sure it pauses */
|
||||
gst_pad_pause_task (queue->srcpad);
|
||||
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped");
|
||||
}
|
||||
/* make sure it pauses */
|
||||
gst_pad_pause_task (queue->srcpad);
|
||||
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped");
|
||||
gst_event_unref (event);
|
||||
goto done;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
STATUS (queue, "received flush stop event");
|
||||
/* forward event, re first as we're going to use it still */
|
||||
gst_event_ref (event);
|
||||
gst_pad_push_event (queue->srcpad, event);
|
||||
|
||||
GST_QUEUE_MUTEX_LOCK (queue);
|
||||
gst_queue_locked_flush (queue);
|
||||
queue->srcresult = GST_FLOW_OK;
|
||||
gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop,
|
||||
queue->srcpad);
|
||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||
|
||||
STATUS (queue, "after flush");
|
||||
gst_event_unref (event);
|
||||
goto done;
|
||||
case GST_EVENT_EOS:
|
||||
|
@ -775,7 +781,7 @@ restart:
|
|||
GST_ELEMENT_ERROR (queue, STREAM, STOPPED,
|
||||
("streaming stopped, reason %s", flowname),
|
||||
("streaming stopped, reason %s", flowname));
|
||||
gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS));
|
||||
gst_pad_push_event (queue->srcpad, gst_event_new_eos ());
|
||||
}
|
||||
GST_DEBUG ("pausing queue, reason %s", flowname);
|
||||
gst_pad_pause_task (queue->srcpad);
|
||||
|
|
Loading…
Reference in a new issue