mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
- The clock_wait now returns the difference between requested time and unlock time.
Original commit message from CVS: - The clock_wait now returns the difference between requested time and unlock time. - Misc defines like GST_SECOND in gstclock.h - remove pre/post in gstelement.c until fixed. - added release_locks to gstelement so that the element can unlock itself - added some more predefined events. - added folowing functions to gstpad: - convert function: get the relation between formats on this pad - query function: get stats about the pad (position/total/latency) - internal connect function: find out how this pad connects to other pad internally to the element. - generic pad_dispatcher. - removed the last bits of pullregion - use release_locks on the queue. - added some events to queue - make gstthread use the new release_locks function - make the scheduler use the new clock_wait functions - added events to fakesink - added query functions to filesrc - swap type and offset in the bytestream seek API to match fseek - added some event handling in bytestream.
This commit is contained in:
parent
692b076459
commit
6f96a24d2e
31 changed files with 1092 additions and 392 deletions
|
@ -149,6 +149,8 @@ gst_fakesink_init (GstFakeSink *fakesink)
|
||||||
fakesink->last_message = NULL;
|
fakesink->last_message = NULL;
|
||||||
|
|
||||||
GST_ELEMENT (fakesink)->setclockfunc = gst_fakesink_set_clock;
|
GST_ELEMENT (fakesink)->setclockfunc = gst_fakesink_set_clock;
|
||||||
|
|
||||||
|
GST_FLAG_SET (fakesink, GST_ELEMENT_EVENT_AWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -251,8 +253,26 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
|
||||||
|
|
||||||
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
|
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
if (fakesink->sync) {
|
if (GST_IS_EVENT (buf)) {
|
||||||
gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf));
|
GstEvent *event = GST_EVENT (buf);
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
|
if (fakesink->sync && fakesink->clock) {
|
||||||
|
gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
|
||||||
|
gst_clock_handle_discont (fakesink->clock, value);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
gst_pad_event_default (pad, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_event_free (event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fakesink->sync && fakesink->clock) {
|
||||||
|
gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fakesink->silent) {
|
if (!fakesink->silent) {
|
||||||
|
|
|
@ -322,7 +322,7 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
||||||
|
|
||||||
if (!GST_EVENT_SEEK_FLUSH (event)) {
|
if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
|
||||||
gst_event_free (event);
|
gst_event_free (event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,24 +271,29 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
/* we need to seek */
|
/* we need to seek */
|
||||||
if (GST_EVENT_SEEK_FLUSH(event))
|
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
|
||||||
if (fflush(filesink->file))
|
if (fflush(filesink->file))
|
||||||
gst_element_error(GST_ELEMENT(filesink),
|
gst_element_error(GST_ELEMENT(filesink),
|
||||||
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
||||||
gst_filesink_getcurrentfilename(filesink), sys_errlist[errno]);
|
gst_filesink_getcurrentfilename(filesink), sys_errlist[errno]);
|
||||||
switch (GST_EVENT_SEEK_TYPE(event))
|
|
||||||
|
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||||
|
g_warning("Any other then byte-offset seeking is not supported!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GST_EVENT_SEEK_METHOD(event))
|
||||||
{
|
{
|
||||||
case GST_SEEK_BYTEOFFSET_SET:
|
case GST_SEEK_METHOD_SET:
|
||||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
|
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_CUR:
|
case GST_SEEK_METHOD_CUR:
|
||||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
|
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_END:
|
case GST_SEEK_METHOD_END:
|
||||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
|
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_warning("Any other then byte-offset seeking is not supported!\n");
|
g_warning("unkown seek method!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -110,6 +110,8 @@ static void gst_filesrc_get_property (GObject *object, guint prop_id,
|
||||||
|
|
||||||
static GstBuffer * gst_filesrc_get (GstPad *pad);
|
static GstBuffer * gst_filesrc_get (GstPad *pad);
|
||||||
static gboolean gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event);
|
static gboolean gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event);
|
||||||
|
static gboolean gst_filesrc_srcpad_query (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstSeekType *format, gint64 *value);
|
||||||
|
|
||||||
static GstElementStateReturn gst_filesrc_change_state (GstElement *element);
|
static GstElementStateReturn gst_filesrc_change_state (GstElement *element);
|
||||||
|
|
||||||
|
@ -186,6 +188,7 @@ gst_filesrc_init (GstFileSrc *src)
|
||||||
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
|
gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
|
||||||
gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
|
gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
|
||||||
|
gst_pad_set_query_function (src->srcpad, gst_filesrc_srcpad_query);
|
||||||
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
||||||
|
|
||||||
src->pagesize = getpagesize();
|
src->pagesize = getpagesize();
|
||||||
|
@ -445,12 +448,19 @@ gst_filesrc_get (GstPad *pad)
|
||||||
|
|
||||||
/* check for seek */
|
/* check for seek */
|
||||||
if (src->seek_happened) {
|
if (src->seek_happened) {
|
||||||
|
GstEvent *event;
|
||||||
|
|
||||||
src->seek_happened = FALSE;
|
src->seek_happened = FALSE;
|
||||||
return GST_BUFFER (gst_event_new (GST_EVENT_DISCONTINUOUS));
|
GST_DEBUG (GST_CAT_EVENT, "filesrc sending discont\n");
|
||||||
|
event = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset, NULL);
|
||||||
|
GST_EVENT_DISCONT_FLUSH (event) = src->need_flush;
|
||||||
|
src->need_flush = FALSE;
|
||||||
|
return GST_BUFFER (event);
|
||||||
}
|
}
|
||||||
/* check for flush */
|
/* check for flush */
|
||||||
if (src->need_flush) {
|
if (src->need_flush) {
|
||||||
src->need_flush = FALSE;
|
src->need_flush = FALSE;
|
||||||
|
GST_DEBUG (GST_CAT_EVENT, "filesrc sending flush\n");
|
||||||
return GST_BUFFER (gst_event_new_flush ());
|
return GST_BUFFER (gst_event_new_flush ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,6 +655,7 @@ gst_filesrc_change_state (GstElement *element)
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
src->curoffset = 0;
|
src->curoffset = 0;
|
||||||
|
src->seek_happened = TRUE;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -655,6 +666,32 @@ gst_filesrc_change_state (GstElement *element)
|
||||||
return GST_STATE_SUCCESS;
|
return GST_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_filesrc_srcpad_query (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstFormat *format, gint64 *value)
|
||||||
|
{
|
||||||
|
GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case GST_PAD_QUERY_TOTAL:
|
||||||
|
if (*format != GST_FORMAT_BYTES) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*value = src->filelen;
|
||||||
|
break;
|
||||||
|
case GST_PAD_QUERY_POSITION:
|
||||||
|
if (*format != GST_FORMAT_BYTES) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*value = src->curoffset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
|
@ -662,14 +699,17 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
switch (GST_EVENT_SEEK_TYPE (event)) {
|
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||||
case GST_SEEK_BYTEOFFSET_SET:
|
return FALSE;
|
||||||
|
}
|
||||||
|
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||||
|
case GST_SEEK_METHOD_SET:
|
||||||
src->curoffset = (guint64) GST_EVENT_SEEK_OFFSET (event);
|
src->curoffset = (guint64) GST_EVENT_SEEK_OFFSET (event);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_CUR:
|
case GST_SEEK_METHOD_CUR:
|
||||||
src->curoffset += GST_EVENT_SEEK_OFFSET (event);
|
src->curoffset += GST_EVENT_SEEK_OFFSET (event);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_END:
|
case GST_SEEK_METHOD_END:
|
||||||
src->curoffset = src->filelen - ABS (GST_EVENT_SEEK_OFFSET (event));
|
src->curoffset = src->filelen - ABS (GST_EVENT_SEEK_OFFSET (event));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -678,9 +718,7 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
||||||
}
|
}
|
||||||
g_object_notify (G_OBJECT (src), "offset");
|
g_object_notify (G_OBJECT (src), "offset");
|
||||||
src->seek_happened = TRUE;
|
src->seek_happened = TRUE;
|
||||||
src->need_flush = GST_EVENT_SEEK_FLUSH(event);
|
src->need_flush = GST_EVENT_SEEK_FLAGS(event) & GST_SEEK_FLAG_FLUSH;
|
||||||
gst_event_free (event);
|
|
||||||
/* push a discontinuous event? */
|
|
||||||
break;
|
break;
|
||||||
case GST_EVENT_FLUSH:
|
case GST_EVENT_FLUSH:
|
||||||
src->need_flush = TRUE;
|
src->need_flush = TRUE;
|
||||||
|
|
|
@ -258,10 +258,12 @@ gst_clock_set_active (GstClock *clock, gboolean active)
|
||||||
|
|
||||||
GST_LOCK (clock);
|
GST_LOCK (clock);
|
||||||
if (active) {
|
if (active) {
|
||||||
clock->start_time = time - clock->last_time;;
|
clock->start_time = time - clock->last_time;
|
||||||
|
clock->accept_discont = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
clock->last_time = time - clock->start_time;
|
clock->last_time = time - clock->start_time;
|
||||||
|
clock->accept_discont = FALSE;
|
||||||
}
|
}
|
||||||
GST_UNLOCK (clock);
|
GST_UNLOCK (clock);
|
||||||
|
|
||||||
|
@ -286,6 +288,39 @@ gst_clock_is_active (GstClock *clock)
|
||||||
return clock->active;
|
return clock->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_clock_handle_discont (GstClock *clock, guint64 time)
|
||||||
|
{
|
||||||
|
GstClockTime itime = 0LL;
|
||||||
|
|
||||||
|
GST_DEBUG (GST_CAT_CLOCK, "clock discont %llu %llu %d\n", time, clock->start_time, clock->accept_discont);
|
||||||
|
|
||||||
|
GST_LOCK (clock);
|
||||||
|
if (clock->accept_discont) {
|
||||||
|
if (CLASS (clock)->get_internal_time) {
|
||||||
|
itime = CLASS (clock)->get_internal_time (clock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GST_UNLOCK (clock);
|
||||||
|
GST_DEBUG (GST_CAT_CLOCK, "clock discont refused %llu %llu\n", time, clock->start_time);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock->start_time = itime - time;
|
||||||
|
clock->last_time = time;
|
||||||
|
clock->accept_discont = FALSE;
|
||||||
|
GST_UNLOCK (clock);
|
||||||
|
|
||||||
|
GST_DEBUG (GST_CAT_CLOCK, "new time %llu\n", gst_clock_get_time (clock));
|
||||||
|
|
||||||
|
g_mutex_lock (clock->active_mutex);
|
||||||
|
g_cond_broadcast (clock->active_cond);
|
||||||
|
g_mutex_unlock (clock->active_mutex);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_clock_get_time
|
* gst_clock_get_time
|
||||||
* @clock: a #GstClock to query
|
* @clock: a #GstClock to query
|
||||||
|
@ -311,7 +346,7 @@ gst_clock_get_time (GstClock *clock)
|
||||||
ret = CLASS (clock)->get_internal_time (clock) - clock->start_time;
|
ret = CLASS (clock)->get_internal_time (clock) - clock->start_time;
|
||||||
}
|
}
|
||||||
/* make sure the time is increasing, else return last_time */
|
/* make sure the time is increasing, else return last_time */
|
||||||
if (ret < clock->last_time) {
|
if ((gint64) ret < (gint64) clock->last_time) {
|
||||||
ret = clock->last_time;
|
ret = clock->last_time;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -355,7 +390,7 @@ gst_clock_wait_async_func (GstClock *clock, GstClockTime time,
|
||||||
* Returns: the #GstClockReturn result of the operation.
|
* Returns: the #GstClockReturn result of the operation.
|
||||||
*/
|
*/
|
||||||
GstClockReturn
|
GstClockReturn
|
||||||
gst_clock_wait (GstClock *clock, GstClockTime time)
|
gst_clock_wait (GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
|
||||||
{
|
{
|
||||||
GstClockID id;
|
GstClockID id;
|
||||||
GstClockReturn res;
|
GstClockReturn res;
|
||||||
|
@ -363,7 +398,7 @@ gst_clock_wait (GstClock *clock, GstClockTime time)
|
||||||
g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_STOPPED);
|
g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_STOPPED);
|
||||||
|
|
||||||
id = gst_clock_wait_async_func (clock, time, NULL, NULL);
|
id = gst_clock_wait_async_func (clock, time, NULL, NULL);
|
||||||
res = gst_clock_wait_id (clock, id);
|
res = gst_clock_wait_id (clock, id, jitter);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -460,12 +495,13 @@ gst_clock_unlock_func (GstClock *clock, GstClockTime time, GstClockID id, gpoint
|
||||||
* Returns: result of the operation.
|
* Returns: result of the operation.
|
||||||
*/
|
*/
|
||||||
GstClockReturn
|
GstClockReturn
|
||||||
gst_clock_wait_id (GstClock *clock, GstClockID id)
|
gst_clock_wait_id (GstClock *clock, GstClockID id, GstClockTimeDiff *jitter)
|
||||||
{
|
{
|
||||||
GstClockReturn res = GST_CLOCK_TIMEOUT;
|
GstClockReturn res = GST_CLOCK_TIMEOUT;
|
||||||
GstClockEntry *entry = (GstClockEntry *) id;
|
GstClockEntry *entry = (GstClockEntry *) id;
|
||||||
GstClockTime current_real, current, target;
|
GstClockTime current_real, current, target;
|
||||||
GTimeVal timeval;
|
GTimeVal timeval;
|
||||||
|
GstClockTimeDiff this_jitter;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_ERROR);
|
g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_ERROR);
|
||||||
g_return_val_if_fail (entry, GST_CLOCK_ERROR);
|
g_return_val_if_fail (entry, GST_CLOCK_ERROR);
|
||||||
|
@ -479,16 +515,24 @@ gst_clock_wait_id (GstClock *clock, GstClockID id)
|
||||||
entry->func = gst_clock_unlock_func;
|
entry->func = gst_clock_unlock_func;
|
||||||
target = GST_CLOCK_ENTRY_TIME (entry) - current + current_real;
|
target = GST_CLOCK_ENTRY_TIME (entry) - current + current_real;
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_CLOCK, "%llu %llu %llu\n", target, current, current_real);
|
GST_DEBUG (GST_CAT_CLOCK, "real_target %llu, current_real %llu, target %llu, now %llu\n",
|
||||||
|
target, current_real, GST_CLOCK_ENTRY_TIME (entry), current);
|
||||||
|
|
||||||
if (target > current_real) {
|
if (target > current_real) {
|
||||||
timeval.tv_usec = target % 1000000;
|
GST_TIME_TO_TIMEVAL (target, timeval);
|
||||||
timeval.tv_sec = target / 1000000;
|
|
||||||
|
|
||||||
GST_CLOCK_ENTRY_TIMED_WAIT (entry, &timeval);
|
GST_CLOCK_ENTRY_TIMED_WAIT (entry, &timeval);
|
||||||
|
current = gst_clock_get_time (clock);
|
||||||
|
this_jitter = current - GST_CLOCK_ENTRY_TIME (entry);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = GST_CLOCK_EARLY;
|
||||||
|
this_jitter = target - current_real;
|
||||||
}
|
}
|
||||||
GST_CLOCK_ENTRY_UNLOCK (entry);
|
GST_CLOCK_ENTRY_UNLOCK (entry);
|
||||||
|
|
||||||
|
if (jitter)
|
||||||
|
*jitter = this_jitter;
|
||||||
|
|
||||||
gst_clock_free_entry (clock, entry);
|
gst_clock_free_entry (clock, entry);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -45,8 +45,18 @@ typedef guint64 GstClockTime;
|
||||||
typedef gint64 GstClockTimeDiff;
|
typedef gint64 GstClockTimeDiff;
|
||||||
typedef gpointer GstClockID;
|
typedef gpointer GstClockID;
|
||||||
|
|
||||||
|
#define GST_SECOND ((guint64)G_USEC_PER_SEC)
|
||||||
|
#define GST_MSECOND ((guint64)GST_SECOND/1000LL)
|
||||||
|
#define GST_USECOND ((guint64)GST_SECOND/1000000LL)
|
||||||
|
#define GST_NSECOND ((guint64)GST_SECOND/1000000000LL)
|
||||||
|
|
||||||
#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e))
|
#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e))
|
||||||
#define GST_TIMEVAL_TO_TIME(tv) ((tv).tv_sec * (guint64) G_USEC_PER_SEC + (tv).tv_usec)
|
#define GST_TIMEVAL_TO_TIME(tv) ((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND)
|
||||||
|
#define GST_TIME_TO_TIMEVAL(t,tv) \
|
||||||
|
G_STMT_START { \
|
||||||
|
(tv).tv_sec = (t) / GST_SECOND; \
|
||||||
|
(tv).tv_usec = ((t) / GST_USECOND) % GST_SECOND; \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
typedef struct _GstClock GstClock;
|
typedef struct _GstClock GstClock;
|
||||||
typedef struct _GstClockClass GstClockClass;
|
typedef struct _GstClockClass GstClockClass;
|
||||||
|
@ -66,6 +76,7 @@ struct _GstClock {
|
||||||
|
|
||||||
GstClockTime start_time;
|
GstClockTime start_time;
|
||||||
GstClockTime last_time;
|
GstClockTime last_time;
|
||||||
|
gboolean accept_discont;
|
||||||
gdouble speed;
|
gdouble speed;
|
||||||
gboolean active;
|
gboolean active;
|
||||||
GList *entries;
|
GList *entries;
|
||||||
|
@ -95,18 +106,19 @@ gdouble gst_clock_get_speed (GstClock *clock);
|
||||||
void gst_clock_set_active (GstClock *clock, gboolean active);
|
void gst_clock_set_active (GstClock *clock, gboolean active);
|
||||||
gboolean gst_clock_is_active (GstClock *clock);
|
gboolean gst_clock_is_active (GstClock *clock);
|
||||||
void gst_clock_reset (GstClock *clock);
|
void gst_clock_reset (GstClock *clock);
|
||||||
|
gboolean gst_clock_handle_discont (GstClock *clock, guint64 time);
|
||||||
gboolean gst_clock_async_supported (GstClock *clock);
|
gboolean gst_clock_async_supported (GstClock *clock);
|
||||||
|
|
||||||
GstClockTime gst_clock_get_time (GstClock *clock);
|
GstClockTime gst_clock_get_time (GstClock *clock);
|
||||||
|
|
||||||
GstClockReturn gst_clock_wait (GstClock *clock, GstClockTime time);
|
GstClockReturn gst_clock_wait (GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
|
||||||
GstClockID gst_clock_wait_async (GstClock *clock, GstClockTime time,
|
GstClockID gst_clock_wait_async (GstClock *clock, GstClockTime time,
|
||||||
GstClockCallback func, gpointer user_data);
|
GstClockCallback func, gpointer user_data);
|
||||||
void gst_clock_cancel_wait_async (GstClock *clock, GstClockID id);
|
void gst_clock_cancel_wait_async (GstClock *clock, GstClockID id);
|
||||||
GstClockID gst_clock_notify_async (GstClock *clock, GstClockTime interval,
|
GstClockID gst_clock_notify_async (GstClock *clock, GstClockTime interval,
|
||||||
GstClockCallback func, gpointer user_data);
|
GstClockCallback func, gpointer user_data);
|
||||||
void gst_clock_remove_notify_async (GstClock *clock, GstClockID id);
|
void gst_clock_remove_notify_async (GstClock *clock, GstClockID id);
|
||||||
GstClockReturn gst_clock_wait_id (GstClock *clock, GstClockID id);
|
GstClockReturn gst_clock_wait_id (GstClock *clock, GstClockID id, GstClockTimeDiff *jitter);
|
||||||
|
|
||||||
GstClockID gst_clock_get_next_id (GstClock *clock);
|
GstClockID gst_clock_get_next_id (GstClock *clock);
|
||||||
void gst_clock_unlock_id (GstClock *clock, GstClockID id);
|
void gst_clock_unlock_id (GstClock *clock, GstClockID id);
|
||||||
|
|
|
@ -183,6 +183,7 @@ gst_element_init (GstElement *element)
|
||||||
element->pads = NULL;
|
element->pads = NULL;
|
||||||
element->loopfunc = NULL;
|
element->loopfunc = NULL;
|
||||||
element->sched = NULL;
|
element->sched = NULL;
|
||||||
|
element->clock = NULL;
|
||||||
element->sched_private = NULL;
|
element->sched_private = NULL;
|
||||||
element->state_mutex = g_mutex_new ();
|
element->state_mutex = g_mutex_new ();
|
||||||
element->state_cond = g_cond_new ();
|
element->state_cond = g_cond_new ();
|
||||||
|
@ -223,9 +224,8 @@ gst_element_dispatch_properties_changed (GObject *object,
|
||||||
G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
|
G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
|
||||||
|
|
||||||
/* now let the parent dispatch those, too */
|
/* now let the parent dispatch those, too */
|
||||||
gst_object = GST_OBJECT (object);
|
gst_object = GST_OBJECT_PARENT (object);
|
||||||
while (gst_object)
|
while (gst_object) {
|
||||||
{
|
|
||||||
/* need own category? */
|
/* need own category? */
|
||||||
for (i = 0; i < n_pspecs; i++) {
|
for (i = 0; i < n_pspecs; i++) {
|
||||||
GST_DEBUG (GST_CAT_EVENT, "deep notification from %s to %s (%s)", GST_OBJECT_NAME (object),
|
GST_DEBUG (GST_CAT_EVENT, "deep notification from %s to %s (%s)", GST_OBJECT_NAME (object),
|
||||||
|
@ -266,7 +266,7 @@ static void
|
||||||
gst_element_threadsafe_properties_pre_run (GstElement *element)
|
gst_element_threadsafe_properties_pre_run (GstElement *element)
|
||||||
{
|
{
|
||||||
GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
|
GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
|
||||||
g_mutex_lock (element->property_mutex);
|
//g_mutex_lock (element->property_mutex);
|
||||||
gst_element_set_pending_properties (element);
|
gst_element_set_pending_properties (element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ static void
|
||||||
gst_element_threadsafe_properties_post_run (GstElement *element)
|
gst_element_threadsafe_properties_post_run (GstElement *element)
|
||||||
{
|
{
|
||||||
GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
|
GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
|
||||||
g_mutex_unlock (element->property_mutex);
|
//g_mutex_unlock (element->property_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -678,6 +678,8 @@ gst_element_set_clock (GstElement *element, GstClock *clock)
|
||||||
|
|
||||||
if (element->setclockfunc)
|
if (element->setclockfunc)
|
||||||
element->setclockfunc (element, clock);
|
element->setclockfunc (element, clock);
|
||||||
|
|
||||||
|
element->clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -711,16 +713,41 @@ gst_element_get_clock (GstElement *element)
|
||||||
* Returns: the #GstClockReturn result of the wait operation
|
* Returns: the #GstClockReturn result of the wait operation
|
||||||
*/
|
*/
|
||||||
GstClockReturn
|
GstClockReturn
|
||||||
gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time)
|
gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
|
||||||
{
|
{
|
||||||
|
GstClockReturn res;
|
||||||
|
|
||||||
g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
|
g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
|
||||||
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
|
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
|
||||||
|
|
||||||
if (GST_ELEMENT_SCHED (element)) {
|
if (GST_ELEMENT_SCHED (element)) {
|
||||||
return gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time);
|
res = gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time, jitter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return GST_CLOCK_TIMEOUT;
|
res = GST_CLOCK_TIMEOUT;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_element_release_locks:
|
||||||
|
* @element: an element
|
||||||
|
*
|
||||||
|
* Instruct the element to release all the locks it is holding, ex
|
||||||
|
* blocking reads, waiting for the clock, ...
|
||||||
|
*
|
||||||
|
* Returns: TRUE if the locks could be released.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_element_release_locks (GstElement *element)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
||||||
|
|
||||||
|
if (CLASS (element)->release_locks)
|
||||||
|
return CLASS (element)->release_locks (element);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -130,6 +130,7 @@ struct _GstElement {
|
||||||
gpointer sched_private;
|
gpointer sched_private;
|
||||||
GstElementSetClockFunction setclockfunc;
|
GstElementSetClockFunction setclockfunc;
|
||||||
GstElementGetClockFunction getclockfunc;
|
GstElementGetClockFunction getclockfunc;
|
||||||
|
GstClock *clock;
|
||||||
|
|
||||||
/* element pads */
|
/* element pads */
|
||||||
guint16 numpads;
|
guint16 numpads;
|
||||||
|
@ -169,6 +170,7 @@ struct _GstElementClass {
|
||||||
void (*get_property) (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
void (*get_property) (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||||
|
|
||||||
/* vtable*/
|
/* vtable*/
|
||||||
|
gboolean (*release_locks) (GstElement *element);
|
||||||
/* change the element state */
|
/* change the element state */
|
||||||
GstElementStateReturn (*change_state) (GstElement *element);
|
GstElementStateReturn (*change_state) (GstElement *element);
|
||||||
/* request a new pad */
|
/* request a new pad */
|
||||||
|
@ -211,7 +213,10 @@ GstObject* gst_element_get_parent (GstElement *element);
|
||||||
|
|
||||||
GstClock* gst_element_get_clock (GstElement *element);
|
GstClock* gst_element_get_clock (GstElement *element);
|
||||||
void gst_element_set_clock (GstElement *element, GstClock *clock);
|
void gst_element_set_clock (GstElement *element, GstClock *clock);
|
||||||
GstClockReturn gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time);
|
GstClockReturn gst_element_clock_wait (GstElement *element, GstClock *clock,
|
||||||
|
GstClockTime time, GstClockTimeDiff *jitter);
|
||||||
|
|
||||||
|
gboolean gst_element_release_locks (GstElement *element);
|
||||||
|
|
||||||
void gst_element_yield (GstElement *element);
|
void gst_element_yield (GstElement *element);
|
||||||
gboolean gst_element_interrupt (GstElement *element);
|
gboolean gst_element_interrupt (GstElement *element);
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "gst/gstevent.h"
|
#include "gst/gstevent.h"
|
||||||
#include <string.h> /* memcpy */
|
#include <string.h> /* memcpy */
|
||||||
|
|
||||||
|
/* #define MEMPROF */
|
||||||
|
|
||||||
GType _gst_event_type;
|
GType _gst_event_type;
|
||||||
|
|
||||||
static GMemChunk *_gst_event_chunk;
|
static GMemChunk *_gst_event_chunk;
|
||||||
|
@ -71,9 +73,13 @@ gst_event_new (GstEventType type)
|
||||||
{
|
{
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
|
||||||
|
#ifndef MEMPROF
|
||||||
g_mutex_lock (_gst_event_chunk_lock);
|
g_mutex_lock (_gst_event_chunk_lock);
|
||||||
event = g_mem_chunk_alloc (_gst_event_chunk);
|
event = g_mem_chunk_alloc (_gst_event_chunk);
|
||||||
g_mutex_unlock (_gst_event_chunk_lock);
|
g_mutex_unlock (_gst_event_chunk_lock);
|
||||||
|
#else
|
||||||
|
event = g_new0(GstEvent, 1);
|
||||||
|
#endif
|
||||||
GST_INFO (GST_CAT_EVENT, "creating new event %p", event);
|
GST_INFO (GST_CAT_EVENT, "creating new event %p", event);
|
||||||
|
|
||||||
GST_DATA_TYPE (event) = _gst_event_type;
|
GST_DATA_TYPE (event) = _gst_event_type;
|
||||||
|
@ -97,9 +103,13 @@ gst_event_copy (GstEvent *event)
|
||||||
{
|
{
|
||||||
GstEvent *copy;
|
GstEvent *copy;
|
||||||
|
|
||||||
|
#ifndef MEMPROF
|
||||||
g_mutex_lock (_gst_event_chunk_lock);
|
g_mutex_lock (_gst_event_chunk_lock);
|
||||||
copy = g_mem_chunk_alloc (_gst_event_chunk);
|
copy = g_mem_chunk_alloc (_gst_event_chunk);
|
||||||
g_mutex_unlock (_gst_event_chunk_lock);
|
g_mutex_unlock (_gst_event_chunk_lock);
|
||||||
|
#else
|
||||||
|
copy = g_new0(GstEvent, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
memcpy (copy, event, sizeof (GstEvent));
|
memcpy (copy, event, sizeof (GstEvent));
|
||||||
|
|
||||||
|
@ -127,7 +137,11 @@ gst_event_free (GstEvent* event)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifndef MEMPROF
|
||||||
g_mem_chunk_free (_gst_event_chunk, event);
|
g_mem_chunk_free (_gst_event_chunk, event);
|
||||||
|
#else
|
||||||
|
g_free (event);
|
||||||
|
#endif
|
||||||
g_mutex_unlock (_gst_event_chunk_lock);
|
g_mutex_unlock (_gst_event_chunk_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,16 +156,65 @@ gst_event_free (GstEvent* event)
|
||||||
* Returns: A new seek event.
|
* Returns: A new seek event.
|
||||||
*/
|
*/
|
||||||
GstEvent*
|
GstEvent*
|
||||||
gst_event_new_seek (GstSeekType type, gint64 offset, gboolean flush)
|
gst_event_new_seek (GstSeekType type, gint64 offset)
|
||||||
{
|
{
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
|
||||||
event = gst_event_new (GST_EVENT_SEEK);
|
event = gst_event_new (GST_EVENT_SEEK);
|
||||||
GST_EVENT_SEEK_TYPE (event) = type;
|
GST_EVENT_SEEK_TYPE (event) = type;
|
||||||
GST_EVENT_SEEK_OFFSET (event) = offset;
|
GST_EVENT_SEEK_OFFSET (event) = offset;
|
||||||
GST_EVENT_SEEK_FLUSH (event) = flush;
|
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstEvent*
|
||||||
|
gst_event_new_discontinuous (gboolean new_media, GstSeekType format1, ...)
|
||||||
|
{
|
||||||
|
va_list var_args;
|
||||||
|
GstEvent *event;
|
||||||
|
gint count = 0;
|
||||||
|
|
||||||
|
event = gst_event_new (GST_EVENT_DISCONTINUOUS);
|
||||||
|
GST_EVENT_DISCONT_NEW_MEDIA (event) = new_media;
|
||||||
|
|
||||||
|
va_start (var_args, format1);
|
||||||
|
|
||||||
|
while (format1) {
|
||||||
|
|
||||||
|
GST_EVENT_DISCONT_OFFSET (event, count).format = format1 & GST_SEEK_FORMAT_MASK;
|
||||||
|
GST_EVENT_DISCONT_OFFSET (event, count).value = va_arg (var_args, gint64);
|
||||||
|
|
||||||
|
format1 = va_arg (var_args, GstSeekType);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
va_end (var_args);
|
||||||
|
|
||||||
|
GST_EVENT_DISCONT_OFFSET_LEN (event) = count;
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_event_discont_get_value (GstEvent *event, GstSeekType type, gint64 *value)
|
||||||
|
{
|
||||||
|
gint i, n;
|
||||||
|
|
||||||
|
g_return_val_if_fail (event, FALSE);
|
||||||
|
g_return_val_if_fail (value, FALSE);
|
||||||
|
|
||||||
|
n = GST_EVENT_DISCONT_OFFSET_LEN (event);
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (GST_EVENT_DISCONT_OFFSET(event,i).format == type) {
|
||||||
|
*value = GST_EVENT_DISCONT_OFFSET(event,i).value;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,23 +25,22 @@
|
||||||
#define __GST_EVENT_H__
|
#define __GST_EVENT_H__
|
||||||
|
|
||||||
#include <gst/gsttypes.h>
|
#include <gst/gsttypes.h>
|
||||||
#include <gst/gstelement.h>
|
|
||||||
#include <gst/gstobject.h>
|
|
||||||
#include <gst/gstdata.h>
|
#include <gst/gstdata.h>
|
||||||
#include <gst/gstcaps.h>
|
#include <gst/gstcaps.h>
|
||||||
|
#include <gst/gstformat.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
G_BEGIN_DECLS
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_EVENT_UNKNOWN,
|
GST_EVENT_UNKNOWN,
|
||||||
GST_EVENT_EOS,
|
GST_EVENT_EOS,
|
||||||
GST_EVENT_FLUSH,
|
GST_EVENT_FLUSH,
|
||||||
GST_EVENT_EMPTY,
|
GST_EVENT_EMPTY,
|
||||||
GST_EVENT_SEEK,
|
|
||||||
GST_EVENT_DISCONTINUOUS,
|
GST_EVENT_DISCONTINUOUS,
|
||||||
GST_EVENT_NEW_MEDIA,
|
GST_EVENT_NEW_MEDIA,
|
||||||
|
GST_EVENT_QOS,
|
||||||
|
GST_EVENT_SEEK,
|
||||||
|
GST_EVENT_FILLER,
|
||||||
} GstEventType;
|
} GstEventType;
|
||||||
|
|
||||||
extern GType _gst_event_type;
|
extern GType _gst_event_type;
|
||||||
|
@ -54,20 +53,45 @@ extern GType _gst_event_type;
|
||||||
#define GST_EVENT_TIMESTAMP(event) (GST_EVENT(event)->timestamp)
|
#define GST_EVENT_TIMESTAMP(event) (GST_EVENT(event)->timestamp)
|
||||||
#define GST_EVENT_SRC(event) (GST_EVENT(event)->src)
|
#define GST_EVENT_SRC(event) (GST_EVENT(event)->src)
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
/* seek events */
|
/* seek events */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_SEEK_ANY,
|
GST_SEEK_METHOD_CUR = (1 << GST_SEEK_METHOD_SHIFT),
|
||||||
GST_SEEK_TIMEOFFSET_CUR,
|
GST_SEEK_METHOD_SET = (2 << GST_SEEK_METHOD_SHIFT),
|
||||||
GST_SEEK_TIMEOFFSET_SET,
|
GST_SEEK_METHOD_END = (3 << GST_SEEK_METHOD_SHIFT),
|
||||||
GST_SEEK_TIMEOFFSET_END,
|
|
||||||
GST_SEEK_BYTEOFFSET_SET,
|
GST_SEEK_FLAG_FLUSH = (1 << (GST_SEEK_FLAGS_SHIFT + 0)),
|
||||||
GST_SEEK_BYTEOFFSET_CUR,
|
GST_SEEK_FLAG_ACCURATE = (1 << (GST_SEEK_FLAGS_SHIFT + 1)),
|
||||||
GST_SEEK_BYTEOFFSET_END,
|
|
||||||
} GstSeekType;
|
} GstSeekType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_SEEK_CERTAIN,
|
||||||
|
GST_SEEK_FUZZY,
|
||||||
|
} GstSeekAccuracy;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstFormat format;
|
||||||
|
gint64 value;
|
||||||
|
} GstFormatValue;
|
||||||
|
|
||||||
#define GST_EVENT_SEEK_TYPE(event) (GST_EVENT(event)->event_data.seek.type)
|
#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_OFFSET(event) (GST_EVENT(event)->event_data.seek.offset)
|
||||||
#define GST_EVENT_SEEK_FLUSH(event) (GST_EVENT(event)->event_data.seek.flush)
|
#define GST_EVENT_SEEK_ACCURACY(event) (GST_EVENT(event)->event_data.seek.accuracy)
|
||||||
|
|
||||||
|
#define GST_EVENT_DISCONT_NEW_MEDIA(event) (GST_EVENT(event)->event_data.discont.new_media)
|
||||||
|
#define GST_EVENT_DISCONT_FLUSH(event) (GST_EVENT(event)->event_data.discont.flush)
|
||||||
|
#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)
|
||||||
|
|
||||||
struct _GstEvent {
|
struct _GstEvent {
|
||||||
GstData data;
|
GstData data;
|
||||||
|
@ -80,8 +104,15 @@ struct _GstEvent {
|
||||||
struct {
|
struct {
|
||||||
GstSeekType type;
|
GstSeekType type;
|
||||||
gint64 offset;
|
gint64 offset;
|
||||||
gboolean flush;
|
GstSeekAccuracy accuracy;
|
||||||
} seek;
|
} seek;
|
||||||
|
struct {
|
||||||
|
GstFormatValue offsets[8];
|
||||||
|
gint noffsets;
|
||||||
|
gboolean new_media;
|
||||||
|
gboolean flush;
|
||||||
|
GstSeekAccuracy accuracy;
|
||||||
|
} discont;
|
||||||
} event_data;
|
} event_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,13 +123,16 @@ GstEvent* gst_event_copy (GstEvent *event);
|
||||||
void gst_event_free (GstEvent *event);
|
void gst_event_free (GstEvent *event);
|
||||||
|
|
||||||
/* seek events */
|
/* seek events */
|
||||||
GstEvent* gst_event_new_seek (GstSeekType type, gint64 offset, gboolean flush);
|
GstEvent* gst_event_new_seek (GstSeekType type, gint64 offset);
|
||||||
|
GstEvent* gst_event_new_discontinuous (gboolean new_media,
|
||||||
|
GstFormat format1, ...);
|
||||||
|
gboolean gst_event_discont_get_value (GstEvent *event, GstFormat format, gint64 *value);
|
||||||
|
|
||||||
|
#define gst_event_new_filler() gst_event_new(GST_EVENT_FILLER)
|
||||||
|
|
||||||
/* flush events */
|
/* flush events */
|
||||||
#define gst_event_new_flush() gst_event_new(GST_EVENT_FLUSH)
|
#define gst_event_new_flush() gst_event_new(GST_EVENT_FLUSH)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
G_END_DECLS
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#endif /* __GST_EVENT_H__ */
|
#endif /* __GST_EVENT_H__ */
|
||||||
|
|
49
gst/gstformat.h
Normal file
49
gst/gstformat.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
* 2000 Wim Taymans <wim.taymans@chello.be>
|
||||||
|
*
|
||||||
|
* gstevent.h: Header for GstEvent subsystem
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GST_FORMAT_H__
|
||||||
|
#define __GST_FORMAT_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_FORMAT_NONE = 0,
|
||||||
|
GST_FORMAT_DEFAULT = 1,
|
||||||
|
GST_FORMAT_BYTES = 2,
|
||||||
|
GST_FORMAT_TIME = 6,
|
||||||
|
GST_FORMAT_BUFFERS = 7,
|
||||||
|
GST_FORMAT_PERCENT = 8,
|
||||||
|
|
||||||
|
/* audio related */
|
||||||
|
GST_FORMAT_SAMPLES = 3,
|
||||||
|
|
||||||
|
/* video related */
|
||||||
|
GST_FORMAT_FRAMES = 4,
|
||||||
|
GST_FORMAT_FIELDS = 5,
|
||||||
|
} GstFormat;
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_FORMAT_H__ */
|
480
gst/gstpad.c
480
gst/gstpad.c
|
@ -31,6 +31,15 @@
|
||||||
#include "gstscheduler.h"
|
#include "gstscheduler.h"
|
||||||
#include "gstevent.h"
|
#include "gstevent.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TEMPL_PAD_CREATED,
|
||||||
|
/* FILL ME */
|
||||||
|
TEMPL_LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstObject *padtemplate_parent_class = NULL;
|
||||||
|
static guint gst_pad_template_signals[TEMPL_LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
GType _gst_pad_type = 0;
|
GType _gst_pad_type = 0;
|
||||||
|
|
||||||
/***** Start with the base GstPad class *****/
|
/***** Start with the base GstPad class *****/
|
||||||
|
@ -206,11 +215,9 @@ gst_real_pad_init (GstRealPad *pad)
|
||||||
|
|
||||||
pad->chainfunc = NULL;
|
pad->chainfunc = NULL;
|
||||||
pad->getfunc = NULL;
|
pad->getfunc = NULL;
|
||||||
pad->getregionfunc = NULL;
|
|
||||||
|
|
||||||
pad->chainhandler = GST_DEBUG_FUNCPTR (gst_pad_push_func);
|
pad->chainhandler = GST_DEBUG_FUNCPTR (gst_pad_push_func);
|
||||||
pad->gethandler = NULL;
|
pad->gethandler = NULL;
|
||||||
pad->pullregionfunc = NULL;
|
|
||||||
|
|
||||||
pad->bufferpoolfunc = NULL;
|
pad->bufferpoolfunc = NULL;
|
||||||
pad->ghostpads = NULL;
|
pad->ghostpads = NULL;
|
||||||
|
@ -218,6 +225,12 @@ gst_real_pad_init (GstRealPad *pad)
|
||||||
|
|
||||||
pad->connectfunc = NULL;
|
pad->connectfunc = NULL;
|
||||||
pad->getcapsfunc = NULL;
|
pad->getcapsfunc = NULL;
|
||||||
|
|
||||||
|
pad->convertfunc = gst_pad_convert_default;
|
||||||
|
pad->eventfunc = gst_pad_event_default;
|
||||||
|
pad->convertfunc = gst_pad_convert_default;
|
||||||
|
pad->queryfunc = gst_pad_query_default;
|
||||||
|
pad->intconnfunc = gst_pad_get_internal_connections_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -258,6 +271,32 @@ gst_real_pad_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_custom_new:
|
||||||
|
* @type: the type of the pad
|
||||||
|
* @name: name of new pad
|
||||||
|
* @direction: either GST_PAD_SRC or GST_PAD_SINK
|
||||||
|
*
|
||||||
|
* Create a new pad with given name from the given type.
|
||||||
|
*
|
||||||
|
* Returns: new pad
|
||||||
|
*/
|
||||||
|
GstPad*
|
||||||
|
gst_pad_custom_new (GType type, const gchar *name,
|
||||||
|
GstPadDirection direction)
|
||||||
|
{
|
||||||
|
GstRealPad *pad;
|
||||||
|
|
||||||
|
g_return_val_if_fail (name != NULL, NULL);
|
||||||
|
g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
|
||||||
|
|
||||||
|
pad = g_object_new (type, NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (pad), name);
|
||||||
|
GST_RPAD_DIRECTION (pad) = direction;
|
||||||
|
|
||||||
|
return GST_PAD (pad);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_pad_new:
|
* gst_pad_new:
|
||||||
* @name: name of new pad
|
* @name: name of new pad
|
||||||
|
@ -268,19 +307,38 @@ gst_real_pad_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
||||||
* Returns: new pad
|
* Returns: new pad
|
||||||
*/
|
*/
|
||||||
GstPad*
|
GstPad*
|
||||||
gst_pad_new (gchar *name,
|
gst_pad_new (const gchar *name,
|
||||||
GstPadDirection direction)
|
GstPadDirection direction)
|
||||||
{
|
{
|
||||||
GstRealPad *pad;
|
return gst_pad_custom_new (gst_real_pad_get_type (), name, direction);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* gst_pad_custom_new_from_template:
|
||||||
|
* @type: the custom GType for this pad
|
||||||
|
* @templ: the pad template to use
|
||||||
|
* @name: the name of the element
|
||||||
|
*
|
||||||
|
* Create a new pad with given name from the given template.
|
||||||
|
*
|
||||||
|
* Returns: new pad
|
||||||
|
*/
|
||||||
|
GstPad*
|
||||||
|
gst_pad_custom_new_from_template (GType type, GstPadTemplate *templ,
|
||||||
|
const gchar *name)
|
||||||
|
{
|
||||||
|
GstPad *pad;
|
||||||
|
|
||||||
g_return_val_if_fail (name != NULL, NULL);
|
g_return_val_if_fail (name != NULL, NULL);
|
||||||
g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
|
g_return_val_if_fail (templ != NULL, NULL);
|
||||||
|
|
||||||
pad = g_object_new (gst_real_pad_get_type (), NULL);
|
pad = gst_pad_new (name, templ->direction);
|
||||||
gst_object_set_name (GST_OBJECT (pad), name);
|
|
||||||
GST_RPAD_DIRECTION (pad) = direction;
|
|
||||||
|
|
||||||
return GST_PAD (pad);
|
gst_object_ref (GST_OBJECT (templ));
|
||||||
|
GST_PAD_PAD_TEMPLATE (pad) = templ;
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (templ), gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad);
|
||||||
|
|
||||||
|
return pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -294,19 +352,9 @@ gst_pad_new (gchar *name,
|
||||||
*/
|
*/
|
||||||
GstPad*
|
GstPad*
|
||||||
gst_pad_new_from_template (GstPadTemplate *templ,
|
gst_pad_new_from_template (GstPadTemplate *templ,
|
||||||
gchar *name)
|
const gchar *name)
|
||||||
{
|
{
|
||||||
GstPad *pad;
|
return gst_pad_custom_new_from_template (gst_real_pad_get_type (), templ, name);
|
||||||
|
|
||||||
g_return_val_if_fail (name != NULL, NULL);
|
|
||||||
g_return_val_if_fail (templ != NULL, NULL);
|
|
||||||
|
|
||||||
pad = gst_pad_new (name, templ->direction);
|
|
||||||
|
|
||||||
gst_object_ref (GST_OBJECT (templ));
|
|
||||||
GST_PAD_PAD_TEMPLATE (pad) = templ;
|
|
||||||
|
|
||||||
return pad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -418,24 +466,43 @@ gst_pad_set_event_function (GstPad *pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_pad_set_getregion_function:
|
* gst_pad_set_convert_function:
|
||||||
* @pad: the pad to set the getregion function for
|
* @pad: the pad to set the event handler for
|
||||||
* @getregion: the getregion function
|
* @convert: the convert function
|
||||||
*
|
*
|
||||||
* Set the given getregion function for the pad.
|
* Set the given convert function for the pad.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_pad_set_getregion_function (GstPad *pad,
|
gst_pad_set_convert_function (GstPad *pad,
|
||||||
GstPadGetRegionFunction getregion)
|
GstPadConvertFunction convert)
|
||||||
{
|
{
|
||||||
g_return_if_fail (pad != NULL);
|
g_return_if_fail (pad != NULL);
|
||||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||||
|
|
||||||
GST_RPAD_GETREGIONFUNC(pad) = getregion;
|
GST_RPAD_CONVERTFUNC(pad) = convert;
|
||||||
GST_DEBUG (GST_CAT_PADS, "getregionfunc for %s:%s set to %s",
|
GST_DEBUG (GST_CAT_PADS, "convertfunc for %s:%s set to %s",
|
||||||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getregion));
|
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (convert));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_set_query_function:
|
||||||
|
* @pad: the pad to set the event handler for
|
||||||
|
* @query: the query function
|
||||||
|
*
|
||||||
|
* Set the given query function for the pad.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query)
|
||||||
|
{
|
||||||
|
g_return_if_fail (pad != NULL);
|
||||||
|
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||||
|
|
||||||
|
GST_RPAD_QUERYFUNC(pad) = query;
|
||||||
|
GST_DEBUG (GST_CAT_PADS, "queryfunc for %s:%s set to %s",
|
||||||
|
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (query));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_pad_set_connect_function:
|
* gst_pad_set_connect_function:
|
||||||
* @pad: the pad to set the connect function for
|
* @pad: the pad to set the connect function for
|
||||||
|
@ -1832,56 +1899,6 @@ gst_pad_pull (GstPad *pad)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef gst_pad_pullregion
|
|
||||||
/**
|
|
||||||
* gst_pad_pullregion:
|
|
||||||
* @pad: the pad to pull the region from
|
|
||||||
* @type: the regiontype
|
|
||||||
* @offset: the offset/start of the buffer to pull
|
|
||||||
* @len: the length of the buffer to pull
|
|
||||||
*
|
|
||||||
* Pull a buffer region from the peer pad. The region to pull can be
|
|
||||||
* specified with a offset/lenght pair or with a start/legnth time
|
|
||||||
* indicator as specified by the type parameter.
|
|
||||||
*
|
|
||||||
* Returns: a new buffer from the peer pad with data in the specified
|
|
||||||
* region.
|
|
||||||
*/
|
|
||||||
GstBuffer*
|
|
||||||
gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len)
|
|
||||||
{
|
|
||||||
GstRealPad *peer;
|
|
||||||
GstBuffer *result = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, NULL);
|
|
||||||
|
|
||||||
do {
|
|
||||||
peer = GST_RPAD_PEER(pad);
|
|
||||||
g_return_val_if_fail (peer != NULL, NULL);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
gst_buffer_unref (result);
|
|
||||||
|
|
||||||
GST_DEBUG_ENTER("(%s:%s,%d,%lld,%lld)",GST_DEBUG_PAD_NAME(pad),type,offset,len);
|
|
||||||
|
|
||||||
if (peer->pullregionfunc) {
|
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW, "calling pullregionfunc &%s of peer pad %s:%s",
|
|
||||||
GST_DEBUG_FUNCPTR_NAME (peer->pullregionfunc), GST_DEBUG_PAD_NAME(GST_PAD_CAST (peer)));
|
|
||||||
result = (peer->pullregionfunc) (GST_PAD_CAST (peer), type, offset, len);
|
|
||||||
} else {
|
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW,"no pullregionfunc");
|
|
||||||
result = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* FIXME */
|
|
||||||
while (result && !(GST_BUFFER_OFFSET (result) == offset &&
|
|
||||||
GST_BUFFER_SIZE (result) == len));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_pad_peek:
|
* gst_pad_peek:
|
||||||
* @pad: the pad to peek
|
* @pad: the pad to peek
|
||||||
|
@ -1959,15 +1976,6 @@ gst_pad_selectv (GstPad *pad, ...)
|
||||||
static void gst_pad_template_class_init (GstPadTemplateClass *klass);
|
static void gst_pad_template_class_init (GstPadTemplateClass *klass);
|
||||||
static void gst_pad_template_init (GstPadTemplate *templ);
|
static void gst_pad_template_init (GstPadTemplate *templ);
|
||||||
|
|
||||||
enum {
|
|
||||||
TEMPL_PAD_CREATED,
|
|
||||||
/* FILL ME */
|
|
||||||
TEMPL_LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
static GstObject *padtemplate_parent_class = NULL;
|
|
||||||
static guint gst_pad_template_signals[TEMPL_LAST_SIGNAL] = { 0 };
|
|
||||||
|
|
||||||
GType
|
GType
|
||||||
gst_pad_template_get_type (void)
|
gst_pad_template_get_type (void)
|
||||||
{
|
{
|
||||||
|
@ -2238,7 +2246,72 @@ gst_ghost_pad_new (gchar *name,
|
||||||
return GST_PAD (ghostpad);
|
return GST_PAD (ghostpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/**
|
||||||
|
* gst_pad_get_internal_connections_default:
|
||||||
|
* @pad: the pad to get the internal connections of
|
||||||
|
*
|
||||||
|
* Get a GList of pads that this pad is connected to internally
|
||||||
|
* to the parent element.
|
||||||
|
*
|
||||||
|
* Returns: a GList of pads, g_list_free after use.
|
||||||
|
*/
|
||||||
|
GList*
|
||||||
|
gst_pad_get_internal_connections_default (GstPad *pad)
|
||||||
|
{
|
||||||
|
GList *res = NULL;
|
||||||
|
GstElement *parent;
|
||||||
|
GList *parent_pads;
|
||||||
|
GstPadDirection direction;
|
||||||
|
GstRealPad *rpad;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||||
|
|
||||||
|
rpad = GST_PAD_REALIZE (pad);
|
||||||
|
direction = rpad->direction;
|
||||||
|
|
||||||
|
parent = GST_PAD_PARENT (rpad);
|
||||||
|
parent_pads = parent->pads;
|
||||||
|
|
||||||
|
while (parent_pads) {
|
||||||
|
GstRealPad *parent_pad = GST_PAD_REALIZE (parent_pads->data);
|
||||||
|
|
||||||
|
if (parent_pad->direction != direction) {
|
||||||
|
res = g_list_prepend (res, parent_pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_pads = g_list_next (parent_pads);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_get_internal_connections:
|
||||||
|
* @pad: the pad to get the internal connections of
|
||||||
|
*
|
||||||
|
* Get a GList of pads that this pad is connected to internally
|
||||||
|
* to the parent element.
|
||||||
|
*
|
||||||
|
* Returns: a GList of pads, g_list_free after use.
|
||||||
|
*/
|
||||||
|
GList*
|
||||||
|
gst_pad_get_internal_connections (GstPad *pad)
|
||||||
|
{
|
||||||
|
GList *res = NULL;
|
||||||
|
GstRealPad *rpad;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||||
|
|
||||||
|
rpad = GST_PAD_REALIZE (pad);
|
||||||
|
|
||||||
|
if (GST_RPAD_INTCONNFUNC (rpad))
|
||||||
|
res = GST_RPAD_INTCONNFUNC (rpad) (GST_PAD_CAST (rpad));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *event)
|
gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *event)
|
||||||
{
|
{
|
||||||
GList *pads = element->pads;
|
GList *pads = element->pads;
|
||||||
|
@ -2255,10 +2328,13 @@ gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *even
|
||||||
else {
|
else {
|
||||||
GstPad *peerpad = GST_PAD_CAST (GST_RPAD_PEER (eventpad));
|
GstPad *peerpad = GST_PAD_CAST (GST_RPAD_PEER (eventpad));
|
||||||
|
|
||||||
gst_pad_send_event (peerpad, gst_event_copy (event));
|
/* we only send the event on one pad, multi-sinkpad elements should implement
|
||||||
|
* a handler */
|
||||||
|
return gst_pad_send_event (peerpad, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2267,8 +2343,10 @@ gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *even
|
||||||
* @event: the event to handle
|
* @event: the event to handle
|
||||||
*
|
*
|
||||||
* Invoke the default event handler for the given pad.
|
* Invoke the default event handler for the given pad.
|
||||||
|
*
|
||||||
|
* Returns: TRUE if the event was sent succesfully.
|
||||||
*/
|
*/
|
||||||
void
|
gboolean
|
||||||
gst_pad_event_default (GstPad *pad, GstEvent *event)
|
gst_pad_event_default (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
GstElement *element = GST_PAD_PARENT (pad);
|
GstElement *element = GST_PAD_PARENT (pad);
|
||||||
|
@ -2282,11 +2360,61 @@ gst_pad_event_default (GstPad *pad, GstEvent *event)
|
||||||
/* we have to try to schedule another element because this one is disabled */
|
/* we have to try to schedule another element because this one is disabled */
|
||||||
gst_element_yield (element);
|
gst_element_yield (element);
|
||||||
break;
|
break;
|
||||||
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
|
{
|
||||||
|
guint64 time;
|
||||||
|
|
||||||
|
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)) {
|
||||||
|
if (element->setclockfunc && element->clock) {
|
||||||
|
gst_clock_handle_discont (element->clock, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case GST_EVENT_FLUSH:
|
case GST_EVENT_FLUSH:
|
||||||
default:
|
default:
|
||||||
gst_pad_event_default_dispatch (pad, element, event);
|
return gst_pad_event_default_dispatch (pad, element, event);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_dispatcher:
|
||||||
|
* @pad: the pad to dispatch
|
||||||
|
* @dispatch: the GstDispatcherFunc to call
|
||||||
|
* @data: data passed to the dispatcher function.
|
||||||
|
*
|
||||||
|
* Invoke the given dispatcher function on all internally connected
|
||||||
|
* pads of the given pad. The GstPadDispatcherFunc should return
|
||||||
|
* TRUE when no further pads need to be preocessed.
|
||||||
|
*
|
||||||
|
* Returns: TRUE if one of the dispatcher functions returned TRUE.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunc dispatch, gpointer data)
|
||||||
|
{
|
||||||
|
gboolean res = FALSE;
|
||||||
|
GList *int_pads, *orig;
|
||||||
|
|
||||||
|
g_return_val_if_fail (pad, FALSE);
|
||||||
|
g_return_val_if_fail (data, FALSE);
|
||||||
|
|
||||||
|
orig = int_pads = gst_pad_get_internal_connections (pad);
|
||||||
|
|
||||||
|
while (int_pads) {
|
||||||
|
GstRealPad *int_rpad = GST_PAD_REALIZE (int_pads->data);
|
||||||
|
GstRealPad *int_peer = GST_RPAD_PEER (int_rpad);
|
||||||
|
|
||||||
|
if (int_peer && GST_PAD_IS_CONNECTED (int_peer)) {
|
||||||
|
res = dispatch (GST_PAD_CAST (int_peer), data);
|
||||||
|
if (res)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
int_pads = g_list_next (int_pads);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (orig);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2301,10 +2429,13 @@ gst_pad_event_default (GstPad *pad, GstEvent *event)
|
||||||
gboolean
|
gboolean
|
||||||
gst_pad_send_event (GstPad *pad, GstEvent *event)
|
gst_pad_send_event (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
gboolean handled = FALSE;
|
gboolean success = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (event, FALSE);
|
g_return_val_if_fail (event, FALSE);
|
||||||
|
|
||||||
|
if (!pad || (GST_PAD_IS_SINK (pad) && !GST_PAD_IS_CONNECTED (pad)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (GST_EVENT_SRC (event) == NULL)
|
if (GST_EVENT_SRC (event) == NULL)
|
||||||
GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (pad));
|
GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (pad));
|
||||||
|
|
||||||
|
@ -2312,17 +2443,166 @@ gst_pad_send_event (GstPad *pad, GstEvent *event)
|
||||||
GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
|
GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
if (GST_RPAD_EVENTFUNC (pad))
|
if (GST_RPAD_EVENTFUNC (pad))
|
||||||
handled = GST_RPAD_EVENTFUNC (pad) (pad, event);
|
success = GST_RPAD_EVENTFUNC (pad) (pad, event);
|
||||||
else {
|
else {
|
||||||
GST_DEBUG(GST_CAT_EVENT, "there's no event function for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
GST_DEBUG(GST_CAT_EVENT, "there's no event function for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handled) {
|
return success;
|
||||||
GST_DEBUG(GST_CAT_EVENT, "proceeding with default event behavior here");
|
|
||||||
gst_pad_event_default (pad, event);
|
|
||||||
handled = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handled;
|
typedef struct
|
||||||
|
{
|
||||||
|
GstFormat src_format;
|
||||||
|
gint64 src_value;
|
||||||
|
GstFormat *dest_format;
|
||||||
|
gint64 *dest_value;
|
||||||
|
} GstPadConvertData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_pad_convert_dispatcher (GstPad *pad, GstPadConvertData *data)
|
||||||
|
{
|
||||||
|
return gst_pad_convert (pad, data->src_format, data->src_value,
|
||||||
|
data->dest_format, data->dest_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_convert_default:
|
||||||
|
* @pad: the pad to invoke the default converter on
|
||||||
|
* @src_format: the source format
|
||||||
|
* @src_value: the source value
|
||||||
|
* @dest_format: a pointer to the destination format
|
||||||
|
* @dest_value: a pointer to the destination value
|
||||||
|
*
|
||||||
|
* Invoke the default converter on a pad. This will forward the
|
||||||
|
* call to the pad obtained using the internal connection of
|
||||||
|
* the element.
|
||||||
|
*
|
||||||
|
* Returns: TRUE if the conversion could be performed.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_pad_convert_default (GstPad *pad,
|
||||||
|
GstFormat src_format, gint64 src_value,
|
||||||
|
GstFormat *dest_format, gint64 *dest_value)
|
||||||
|
{
|
||||||
|
GstPadConvertData data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (pad, FALSE);
|
||||||
|
g_return_val_if_fail (dest_format, FALSE);
|
||||||
|
g_return_val_if_fail (dest_value, FALSE);
|
||||||
|
|
||||||
|
data.src_format = src_format;
|
||||||
|
data.src_value = src_value;
|
||||||
|
data.dest_format = dest_format;
|
||||||
|
data.dest_value = dest_value;
|
||||||
|
|
||||||
|
return gst_pad_dispatcher (pad, (GstPadDispatcherFunc) gst_pad_convert_dispatcher, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_convert:
|
||||||
|
* @pad: the pad to invoke the converter on
|
||||||
|
* @src_format: the source format
|
||||||
|
* @src_value: the source value
|
||||||
|
* @dest_format: a pointer to the destination format
|
||||||
|
* @dest_value: a pointer to the destination value
|
||||||
|
*
|
||||||
|
* Invoke a conversion on the pad.
|
||||||
|
*
|
||||||
|
* Returns: TRUE if the conversion could be performed.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_pad_convert (GstPad *pad,
|
||||||
|
GstFormat src_format, gint64 src_value,
|
||||||
|
GstFormat *dest_format, gint64 *dest_value)
|
||||||
|
{
|
||||||
|
GstRealPad *rpad;
|
||||||
|
|
||||||
|
g_return_val_if_fail (pad, FALSE);
|
||||||
|
g_return_val_if_fail (dest_format, FALSE);
|
||||||
|
g_return_val_if_fail (dest_value, FALSE);
|
||||||
|
|
||||||
|
rpad = GST_PAD_REALIZE (pad);
|
||||||
|
|
||||||
|
g_return_val_if_fail (rpad, FALSE);
|
||||||
|
|
||||||
|
if (GST_RPAD_CONVERTFUNC (rpad)) {
|
||||||
|
return GST_RPAD_CONVERTFUNC (rpad) (GST_PAD_CAST (rpad), src_format, src_value, dest_format, dest_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstPadQueryType type;
|
||||||
|
GstFormat *format;
|
||||||
|
gint64 *value;
|
||||||
|
} GstPadQueryData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_pad_query_dispatcher (GstPad *pad, GstPadQueryData *data)
|
||||||
|
{
|
||||||
|
return gst_pad_query (pad, data->type, data->format, data->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_query_default:
|
||||||
|
* @pad: the pad to invoke the default query on
|
||||||
|
* @type: the type of query to perform
|
||||||
|
* @format: a pointer to the format of the query
|
||||||
|
* @value: a pointer to the result of the query
|
||||||
|
*
|
||||||
|
* Invoke the default query function on a pad.
|
||||||
|
*
|
||||||
|
* Returns: TRUE if the query could be performed.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_pad_query_default (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstFormat *format, gint64 *value)
|
||||||
|
{
|
||||||
|
GstPadQueryData data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (pad, FALSE);
|
||||||
|
g_return_val_if_fail (format, FALSE);
|
||||||
|
g_return_val_if_fail (value, FALSE);
|
||||||
|
|
||||||
|
data.type = type;
|
||||||
|
data.format = format;
|
||||||
|
data.value = value;
|
||||||
|
|
||||||
|
return gst_pad_dispatcher (pad, (GstPadDispatcherFunc) gst_pad_query_dispatcher, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_pad_query:
|
||||||
|
* @pad: the pad to invoke the query on
|
||||||
|
* @type: the type of query to perform
|
||||||
|
* @format: a pointer to the format of the query
|
||||||
|
* @value: a pointer to the result of the query
|
||||||
|
*
|
||||||
|
* Query a pad for one of the available GstPadQuery properties.
|
||||||
|
*
|
||||||
|
* Returns: TRUE if the query could be performed.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_pad_query (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstFormat *format, gint64 *value)
|
||||||
|
{
|
||||||
|
GstRealPad *rpad;
|
||||||
|
|
||||||
|
if (pad == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_return_val_if_fail (format, FALSE);
|
||||||
|
g_return_val_if_fail (value, FALSE);
|
||||||
|
|
||||||
|
rpad = GST_PAD_REALIZE (pad);
|
||||||
|
|
||||||
|
g_return_val_if_fail (rpad, FALSE);
|
||||||
|
|
||||||
|
if (GST_RPAD_QUERYFUNC (rpad))
|
||||||
|
return GST_RPAD_QUERYFUNC (rpad) (GST_PAD_CAST (pad), type, format, value);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
80
gst/gstpad.h
80
gst/gstpad.h
|
@ -111,12 +111,6 @@ typedef struct _GstGhostPadClass GstGhostPadClass;
|
||||||
/*typedef struct _GstPadTemplateClass GstPadTemplateClass;*/
|
/*typedef struct _GstPadTemplateClass GstPadTemplateClass;*/
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
GST_REGION_VOID,
|
|
||||||
GST_REGION_OFFSET_LEN,
|
|
||||||
GST_REGION_TIME_LEN,
|
|
||||||
} GstRegionType;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_PAD_CONNECT_REFUSED = -1,
|
GST_PAD_CONNECT_REFUSED = -1,
|
||||||
GST_PAD_CONNECT_DELAYED = 0,
|
GST_PAD_CONNECT_DELAYED = 0,
|
||||||
|
@ -124,21 +118,31 @@ typedef enum {
|
||||||
GST_PAD_CONNECT_DONE = 2,
|
GST_PAD_CONNECT_DONE = 2,
|
||||||
} GstPadConnectReturn;
|
} GstPadConnectReturn;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_PAD_QUERY_TOTAL,
|
||||||
|
GST_PAD_QUERY_POSITION,
|
||||||
|
GST_PAD_QUERY_LATENCY,
|
||||||
|
} GstPadQueryType;
|
||||||
|
|
||||||
/* this defines the functions used to chain buffers
|
/* this defines the functions used to chain buffers
|
||||||
* pad is the sink pad (so the same chain function can be used for N pads)
|
* pad is the sink pad (so the same chain function can be used for N pads)
|
||||||
* buf is the buffer being passed */
|
* buf is the buffer being passed */
|
||||||
typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
|
typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
|
||||||
typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
|
typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
|
||||||
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
|
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
|
||||||
|
typedef gboolean (*GstPadConvertFunction) (GstPad *pad,
|
||||||
|
GstSeekType src_format, gint64 src_value,
|
||||||
|
GstSeekType *dest_format, gint64 *dest_value);
|
||||||
|
typedef gboolean (*GstPadQueryFunction) (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstSeekType *format, gint64 *value);
|
||||||
|
typedef GList* (*GstPadIntConnFunction) (GstPad *pad);
|
||||||
|
|
||||||
typedef GstBuffer* (*GstPadGetRegionFunction) (GstPad *pad, GstRegionType type,
|
|
||||||
guint64 offset, guint64 len);
|
|
||||||
typedef GstBuffer* (*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type,
|
|
||||||
guint64 offset, guint64 len);
|
|
||||||
typedef GstPadConnectReturn (*GstPadConnectFunction) (GstPad *pad, GstCaps *caps);
|
typedef GstPadConnectReturn (*GstPadConnectFunction) (GstPad *pad, GstCaps *caps);
|
||||||
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad, GstCaps *caps);
|
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad, GstCaps *caps);
|
||||||
typedef GstBufferPool* (*GstPadBufferPoolFunction) (GstPad *pad);
|
typedef GstBufferPool* (*GstPadBufferPoolFunction) (GstPad *pad);
|
||||||
|
|
||||||
|
typedef gboolean (*GstPadDispatcherFunc) (GstPad *pad, gpointer data);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_PAD_UNKNOWN,
|
GST_PAD_UNKNOWN,
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
|
@ -178,10 +182,6 @@ struct _GstRealPad {
|
||||||
GstRealPad *peer;
|
GstRealPad *peer;
|
||||||
|
|
||||||
GstBuffer *bufpen;
|
GstBuffer *bufpen;
|
||||||
/* CR1: FIXME: regiontype should go away */
|
|
||||||
GstRegionType regiontype;
|
|
||||||
guint64 offset;
|
|
||||||
guint64 len;
|
|
||||||
|
|
||||||
GstPadChainFunction chainfunc;
|
GstPadChainFunction chainfunc;
|
||||||
GstPadChainFunction chainhandler;
|
GstPadChainFunction chainhandler;
|
||||||
|
@ -190,9 +190,9 @@ struct _GstRealPad {
|
||||||
|
|
||||||
GstPadEventFunction eventfunc;
|
GstPadEventFunction eventfunc;
|
||||||
GstPadEventFunction eventhandler;
|
GstPadEventFunction eventhandler;
|
||||||
|
GstPadConvertFunction convertfunc;
|
||||||
GstPadGetRegionFunction getregionfunc;
|
GstPadQueryFunction queryfunc;
|
||||||
GstPadPullRegionFunction pullregionfunc;
|
GstPadIntConnFunction intconnfunc;
|
||||||
|
|
||||||
GstPadGetCapsFunction getcapsfunc;
|
GstPadGetCapsFunction getcapsfunc;
|
||||||
GstPadConnectFunction connectfunc;
|
GstPadConnectFunction connectfunc;
|
||||||
|
@ -247,18 +247,14 @@ struct _GstGhostPadClass {
|
||||||
#define GST_RPAD_GETHANDLER(pad) (((GstRealPad *)(pad))->gethandler)
|
#define GST_RPAD_GETHANDLER(pad) (((GstRealPad *)(pad))->gethandler)
|
||||||
#define GST_RPAD_EVENTFUNC(pad) (((GstRealPad *)(pad))->eventfunc)
|
#define GST_RPAD_EVENTFUNC(pad) (((GstRealPad *)(pad))->eventfunc)
|
||||||
#define GST_RPAD_EVENTHANDLER(pad) (((GstRealPad *)(pad))->eventhandler)
|
#define GST_RPAD_EVENTHANDLER(pad) (((GstRealPad *)(pad))->eventhandler)
|
||||||
|
#define GST_RPAD_CONVERTFUNC(pad) (((GstRealPad *)(pad))->convertfunc)
|
||||||
#define GST_RPAD_GETREGIONFUNC(pad) (((GstRealPad *)(pad))->getregionfunc)
|
#define GST_RPAD_QUERYFUNC(pad) (((GstRealPad *)(pad))->queryfunc)
|
||||||
#define GST_RPAD_PULLREGIONFUNC(pad) (((GstRealPad *)(pad))->pullregionfunc)
|
#define GST_RPAD_INTCONNFUNC(pad) (((GstRealPad *)(pad))->intconnfunc)
|
||||||
|
|
||||||
#define GST_RPAD_CONNECTFUNC(pad) (((GstRealPad *)(pad))->connectfunc)
|
#define GST_RPAD_CONNECTFUNC(pad) (((GstRealPad *)(pad))->connectfunc)
|
||||||
#define GST_RPAD_GETCAPSFUNC(pad) (((GstRealPad *)(pad))->getcapsfunc)
|
#define GST_RPAD_GETCAPSFUNC(pad) (((GstRealPad *)(pad))->getcapsfunc)
|
||||||
#define GST_RPAD_BUFFERPOOLFUNC(pad) (((GstRealPad *)(pad))->bufferpoolfunc)
|
#define GST_RPAD_BUFFERPOOLFUNC(pad) (((GstRealPad *)(pad))->bufferpoolfunc)
|
||||||
|
|
||||||
#define GST_RPAD_REGIONTYPE(pad) (((GstRealPad *)(pad))->regiontype)
|
|
||||||
#define GST_RPAD_OFFSET(pad) (((GstRealPad *)(pad))->offset)
|
|
||||||
#define GST_RPAD_LEN(pad) (((GstRealPad *)(pad))->len)
|
|
||||||
|
|
||||||
/* GstGhostPad */
|
/* GstGhostPad */
|
||||||
#define GST_GPAD_REALPAD(pad) (((GstGhostPad *)(pad))->realpad)
|
#define GST_GPAD_REALPAD(pad) (((GstGhostPad *)(pad))->realpad)
|
||||||
|
|
||||||
|
@ -342,17 +338,20 @@ GType gst_pad_get_type (void);
|
||||||
GType gst_real_pad_get_type (void);
|
GType gst_real_pad_get_type (void);
|
||||||
GType gst_ghost_pad_get_type (void);
|
GType gst_ghost_pad_get_type (void);
|
||||||
|
|
||||||
GstPad* gst_pad_new (gchar *name, GstPadDirection direction);
|
GstPad* gst_pad_new (const gchar *name, GstPadDirection direction);
|
||||||
#define gst_pad_destroy(pad) gst_object_destroy (GST_OBJECT (pad))
|
#define gst_pad_destroy(pad) gst_object_destroy (GST_OBJECT (pad))
|
||||||
GstPad* gst_pad_new_from_template (GstPadTemplate *templ, gchar *name);
|
GstPad* gst_pad_new_from_template (GstPadTemplate *templ, const gchar *name);
|
||||||
|
GstPad* gst_pad_custom_new (GType type, const gchar *name, GstPadDirection direction);
|
||||||
|
GstPad* gst_pad_custom_new_from_template (GType type, GstPadTemplate *templ, const gchar *name);
|
||||||
|
|
||||||
GstPadDirection gst_pad_get_direction (GstPad *pad);
|
GstPadDirection gst_pad_get_direction (GstPad *pad);
|
||||||
|
|
||||||
void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
|
void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
|
||||||
void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get);
|
void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get);
|
||||||
void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
|
void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
|
||||||
|
void gst_pad_set_convert_function (GstPad *pad, GstPadConvertFunction convert);
|
||||||
void gst_pad_set_getregion_function (GstPad *pad, GstPadGetRegionFunction getregion);
|
void gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query);
|
||||||
|
void gst_pad_set_internal_connection_function (GstPad *pad, GstPadIntConnFunction intconn);
|
||||||
|
|
||||||
void gst_pad_set_connect_function (GstPad *pad, GstPadConnectFunction connect);
|
void gst_pad_set_connect_function (GstPad *pad, GstPadConnectFunction connect);
|
||||||
void gst_pad_set_getcaps_function (GstPad *pad, GstPadGetCapsFunction getcaps);
|
void gst_pad_set_getcaps_function (GstPad *pad, GstPadGetCapsFunction getcaps);
|
||||||
|
@ -411,22 +410,33 @@ void gst_pad_push (GstPad *pad, GstBuffer *buf);
|
||||||
#endif
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
GstBuffer* gst_pad_pull (GstPad *pad);
|
GstBuffer* gst_pad_pull (GstPad *pad);
|
||||||
GstBuffer* gst_pad_pullregion (GstPad *pad, GstRegionType type,
|
|
||||||
guint64 offset, guint64 len);
|
|
||||||
#else
|
#else
|
||||||
#define gst_pad_pull(pad) \
|
#define gst_pad_pull(pad) \
|
||||||
( (((GstRealPad *)(pad))->peer->gethandler) ? \
|
( (((GstRealPad *)(pad))->peer->gethandler) ? \
|
||||||
(((GstRealPad *)(pad))->peer->gethandler)((GstPad *)(((GstRealPad *)(pad))->peer)) : \
|
(((GstRealPad *)(pad))->peer->gethandler)((GstPad *)(((GstRealPad *)(pad))->peer)) : \
|
||||||
NULL )
|
NULL )
|
||||||
#define gst_pad_pullregion(pad,type,offset,len) \
|
|
||||||
( (((GstRealPad *)(pad))->peer->pullregionfunc) ? \
|
|
||||||
(((GstRealPad *)(pad))->peer->pullregionfunc)((GstPad *)(((GstRealPad *)(pad))->peer),(type),(offset),(len)) : \
|
|
||||||
NULL )
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
|
gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
|
||||||
void gst_pad_event_default (GstPad *pad, GstEvent *event);
|
gboolean gst_pad_event_default (GstPad *pad, GstEvent *event);
|
||||||
|
|
||||||
|
gboolean gst_pad_convert (GstPad *pad,
|
||||||
|
GstFormat src_format, gint64 src_value,
|
||||||
|
GstFormat *dest_format, gint64 *dest_value);
|
||||||
|
gboolean gst_pad_convert_default (GstPad *pad,
|
||||||
|
GstFormat src_format, gint64 src_value,
|
||||||
|
GstFormat *dest_format, gint64 *dest_value);
|
||||||
|
|
||||||
|
gboolean gst_pad_query (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstFormat *format, gint64 *value);
|
||||||
|
gboolean gst_pad_query_default (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstFormat *format, gint64 *value);
|
||||||
|
|
||||||
|
GList* gst_pad_get_internal_connections (GstPad *pad);
|
||||||
|
GList* gst_pad_get_internal_connections_default (GstPad *pad);
|
||||||
|
|
||||||
|
gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunc dispatch,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
|
||||||
GstBuffer* gst_pad_peek (GstPad *pad);
|
GstBuffer* gst_pad_peek (GstPad *pad);
|
||||||
|
|
|
@ -82,9 +82,13 @@ static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
|
||||||
static GstBuffer * gst_queue_get (GstPad *pad);
|
static GstBuffer * gst_queue_get (GstPad *pad);
|
||||||
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
|
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
|
||||||
|
|
||||||
|
static gboolean gst_queue_handle_src_event (GstPad *pad, GstEvent *event);
|
||||||
|
|
||||||
|
|
||||||
static void gst_queue_locked_flush (GstQueue *queue);
|
static void gst_queue_locked_flush (GstQueue *queue);
|
||||||
|
|
||||||
static GstElementStateReturn gst_queue_change_state (GstElement *element);
|
static GstElementStateReturn gst_queue_change_state (GstElement *element);
|
||||||
|
static gboolean gst_queue_release_locks (GstElement *element);
|
||||||
|
|
||||||
|
|
||||||
#define GST_TYPE_QUEUE_LEAKY (queue_leaky_get_type())
|
#define GST_TYPE_QUEUE_LEAKY (queue_leaky_get_type())
|
||||||
|
@ -158,6 +162,7 @@ gst_queue_class_init (GstQueueClass *klass)
|
||||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_queue_get_property);
|
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_queue_get_property);
|
||||||
|
|
||||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
|
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
|
||||||
|
gstelement_class->release_locks = GST_DEBUG_FUNCPTR(gst_queue_release_locks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPadConnectReturn
|
static GstPadConnectReturn
|
||||||
|
@ -207,6 +212,7 @@ gst_queue_init (GstQueue *queue)
|
||||||
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
|
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
|
||||||
gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
||||||
gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
||||||
|
gst_pad_set_event_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_handle_src_event));
|
||||||
|
|
||||||
queue->leaky = GST_QUEUE_NO_LEAK;
|
queue->leaky = GST_QUEUE_NO_LEAK;
|
||||||
queue->queue = NULL;
|
queue->queue = NULL;
|
||||||
|
@ -301,6 +307,9 @@ restart:
|
||||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n",
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n",
|
||||||
GST_ELEMENT_NAME (queue), queue->level_buffers);
|
GST_ELEMENT_NAME (queue), queue->level_buffers);
|
||||||
break;
|
break;
|
||||||
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
|
//gst_queue_locked_flush (queue);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/*gst_pad_event_default (pad, GST_EVENT (buf)); */
|
/*gst_pad_event_default (pad, GST_EVENT (buf)); */
|
||||||
break;
|
break;
|
||||||
|
@ -350,7 +359,8 @@ restart:
|
||||||
while (queue->level_buffers == queue->size_buffers) {
|
while (queue->level_buffers == queue->size_buffers) {
|
||||||
/* if there's a pending state change for this queue or its manager, switch */
|
/* if there's a pending state change for this queue or its manager, switch */
|
||||||
/* back to iterator so bottom half of state change executes */
|
/* back to iterator so bottom half of state change executes */
|
||||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||||
|
if (queue->interrupt) {
|
||||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
||||||
g_mutex_unlock (queue->qlock);
|
g_mutex_unlock (queue->qlock);
|
||||||
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
||||||
|
@ -435,7 +445,8 @@ restart:
|
||||||
/* if there's a pending state change for this queue or its manager, switch
|
/* if there's a pending state change for this queue or its manager, switch
|
||||||
* back to iterator so bottom half of state change executes
|
* back to iterator so bottom half of state change executes
|
||||||
*/
|
*/
|
||||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||||
|
if (queue->interrupt) {
|
||||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
||||||
g_mutex_unlock (queue->qlock);
|
g_mutex_unlock (queue->qlock);
|
||||||
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
||||||
|
@ -507,6 +518,51 @@ restart:
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_queue_handle_src_event (GstPad *pad, GstEvent *event)
|
||||||
|
{
|
||||||
|
GstQueue *queue;
|
||||||
|
|
||||||
|
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||||
|
|
||||||
|
g_mutex_lock (queue->qlock);
|
||||||
|
|
||||||
|
if (gst_element_get_state (GST_ELEMENT (queue)) == GST_STATE_PLAYING) {
|
||||||
|
g_warning ("queue event in playing state");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_FLUSH:
|
||||||
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "FLUSH event, flushing queue\n");
|
||||||
|
gst_queue_locked_flush (queue);
|
||||||
|
break;
|
||||||
|
case GST_EVENT_SEEK:
|
||||||
|
gst_queue_locked_flush (queue);
|
||||||
|
default:
|
||||||
|
gst_pad_event_default (pad, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_mutex_unlock (queue->qlock);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_queue_release_locks (GstElement *element)
|
||||||
|
{
|
||||||
|
GstQueue *queue;
|
||||||
|
|
||||||
|
queue = GST_QUEUE (element);
|
||||||
|
|
||||||
|
g_mutex_lock (queue->qlock);
|
||||||
|
queue->interrupt = TRUE;
|
||||||
|
g_cond_signal (queue->not_full);
|
||||||
|
g_cond_signal (queue->not_empty);
|
||||||
|
g_mutex_unlock (queue->qlock);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
gst_queue_change_state (GstElement *element)
|
gst_queue_change_state (GstElement *element)
|
||||||
{
|
{
|
||||||
|
@ -543,6 +599,7 @@ gst_queue_change_state (GstElement *element)
|
||||||
|
|
||||||
return GST_STATE_FAILURE;
|
return GST_STATE_FAILURE;
|
||||||
}
|
}
|
||||||
|
queue->interrupt = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||||
|
|
|
@ -75,6 +75,7 @@ struct _GstQueue {
|
||||||
|
|
||||||
gint leaky; /* whether the queue is leaky, and if so at which end */
|
gint leaky; /* whether the queue is leaky, and if so at which end */
|
||||||
gboolean may_deadlock; /* it the queue should fail on possible deadlocks */
|
gboolean may_deadlock; /* it the queue should fail on possible deadlocks */
|
||||||
|
gboolean interrupt;
|
||||||
|
|
||||||
GMutex *qlock; /* lock for queue (vs object lock) */
|
GMutex *qlock; /* lock for queue (vs object lock) */
|
||||||
/* we are single reader and single writer queue */
|
/* we are single reader and single writer queue */
|
||||||
|
|
|
@ -548,12 +548,13 @@ gst_scheduler_auto_clock (GstScheduler *sched)
|
||||||
* Returns: the status of the operation
|
* Returns: the status of the operation
|
||||||
*/
|
*/
|
||||||
GstClockReturn
|
GstClockReturn
|
||||||
gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element, GstClock *clock, GstClockTime time)
|
gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element, GstClock *clock, GstClockTime time,
|
||||||
|
GstClockTimeDiff *jitter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_CLOCK_ERROR);
|
g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_CLOCK_ERROR);
|
||||||
|
|
||||||
if (CLASS (sched)->clock_wait)
|
if (CLASS (sched)->clock_wait)
|
||||||
return CLASS (sched)->clock_wait (sched, element, clock, time);
|
return CLASS (sched)->clock_wait (sched, element, clock, time, jitter);
|
||||||
|
|
||||||
return GST_CLOCK_TIMEOUT;
|
return GST_CLOCK_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ struct _GstSchedulerClass {
|
||||||
void (*pad_disconnect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
void (*pad_disconnect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
||||||
void (*pad_select) (GstScheduler *sched, GList *padlist);
|
void (*pad_select) (GstScheduler *sched, GList *padlist);
|
||||||
GstClockReturn (*clock_wait) (GstScheduler *sched, GstElement *element,
|
GstClockReturn (*clock_wait) (GstScheduler *sched, GstElement *element,
|
||||||
GstClock *clock, GstClockTime time);
|
GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
|
||||||
GstSchedulerState (*iterate) (GstScheduler *sched);
|
GstSchedulerState (*iterate) (GstScheduler *sched);
|
||||||
/* for debugging */
|
/* for debugging */
|
||||||
void (*show) (GstScheduler *sched);
|
void (*show) (GstScheduler *sched);
|
||||||
|
@ -129,7 +129,7 @@ void gst_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *s
|
||||||
void gst_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
void gst_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
||||||
GstPad* gst_scheduler_pad_select (GstScheduler *sched, GList *padlist);
|
GstPad* gst_scheduler_pad_select (GstScheduler *sched, GList *padlist);
|
||||||
GstClockReturn gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
|
GstClockReturn gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
|
||||||
GstClock *clock, GstClockTime time);
|
GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
|
||||||
gboolean gst_scheduler_iterate (GstScheduler *sched);
|
gboolean gst_scheduler_iterate (GstScheduler *sched);
|
||||||
|
|
||||||
void gst_scheduler_use_clock (GstScheduler *sched, GstClock *clock);
|
void gst_scheduler_use_clock (GstScheduler *sched, GstClock *clock);
|
||||||
|
|
|
@ -108,14 +108,16 @@ static GstClockTime
|
||||||
gst_system_clock_get_internal_time (GstClock *clock)
|
gst_system_clock_get_internal_time (GstClock *clock)
|
||||||
{
|
{
|
||||||
GTimeVal timeval;
|
GTimeVal timeval;
|
||||||
|
|
||||||
g_get_current_time (&timeval);
|
g_get_current_time (&timeval);
|
||||||
|
|
||||||
return GST_TIMEVAL_TO_TIME (timeval);
|
return GST_TIMEVAL_TO_TIME (timeval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint64
|
static guint64
|
||||||
gst_system_clock_get_resolution (GstClock *clock)
|
gst_system_clock_get_resolution (GstClock *clock)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1 * GST_USECOND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -318,7 +318,7 @@ gst_thread_change_state (GstElement * element)
|
||||||
* to perform each elements' change_state() (by calling gstbin.c::
|
* to perform each elements' change_state() (by calling gstbin.c::
|
||||||
* change_state()).
|
* change_state()).
|
||||||
* + the pending state was already set by gstelement.c::set_state()
|
* + the pending state was already set by gstelement.c::set_state()
|
||||||
* + find every queue we manage, and signal its empty and full conditions
|
* + unlock all elements so the bottom half can start the state change.
|
||||||
*/
|
*/
|
||||||
g_mutex_lock (thread->lock);
|
g_mutex_lock (thread->lock);
|
||||||
|
|
||||||
|
@ -326,26 +326,18 @@ gst_thread_change_state (GstElement * element)
|
||||||
|
|
||||||
while (elements) {
|
while (elements) {
|
||||||
GstElement *element = GST_ELEMENT (elements->data);
|
GstElement *element = GST_ELEMENT (elements->data);
|
||||||
|
GList *pads;
|
||||||
|
|
||||||
|
|
||||||
g_assert (element);
|
g_assert (element);
|
||||||
THR_DEBUG (" element \"%s\"", GST_ELEMENT_NAME (element));
|
THR_DEBUG (" waking element \"%s\"", GST_ELEMENT_NAME (element));
|
||||||
elements = g_list_next (elements);
|
elements = g_list_next (elements);
|
||||||
if (GST_IS_QUEUE (element)) {
|
|
||||||
GstQueue *queue = GST_QUEUE (element);
|
if (!gst_element_release_locks (element)) {
|
||||||
/* FIXME make this more efficient by only waking queues that are asleep
|
g_warning ("element %s could not release locks", GST_ELEMENT_NAME (element));
|
||||||
* FIXME and only waking the appropriate condition (depending on if it's
|
|
||||||
* FIXME on up- or down-stream side)
|
|
||||||
* FIXME also make this more efficient by keeping list of managed queues
|
|
||||||
*/
|
|
||||||
THR_DEBUG ("waking queue \"%s\"", GST_ELEMENT_NAME (element));
|
|
||||||
g_mutex_lock (queue->qlock);
|
|
||||||
GST_STATE_PENDING (element) = GST_STATE_PAUSED;
|
|
||||||
g_cond_signal (queue->not_full);
|
|
||||||
g_cond_signal (queue->not_empty);
|
|
||||||
g_mutex_unlock (queue->qlock);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
GList *pads = GST_ELEMENT_PADS (element);
|
pads = GST_ELEMENT_PADS (element);
|
||||||
|
|
||||||
while (pads) {
|
while (pads) {
|
||||||
GstRealPad *peer = GST_REAL_PAD (GST_PAD_PEER (pads->data));
|
GstRealPad *peer = GST_REAL_PAD (GST_PAD_PEER (pads->data));
|
||||||
|
@ -365,26 +357,14 @@ gst_thread_change_state (GstElement * element)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME this needs to go away eventually */
|
|
||||||
if (!GST_IS_QUEUE (peerelement)) {
|
|
||||||
GST_DEBUG (GST_CAT_THREAD, "peer element isn't a Queue");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_ELEMENT_SCHED (peerelement) != GST_ELEMENT_SCHED (thread)) {
|
if (GST_ELEMENT_SCHED (peerelement) != GST_ELEMENT_SCHED (thread)) {
|
||||||
GstQueue *queue = GST_QUEUE (peerelement);
|
|
||||||
|
|
||||||
THR_DEBUG (" element \"%s\" has pad cross sched boundary", GST_ELEMENT_NAME (element));
|
THR_DEBUG (" element \"%s\" has pad cross sched boundary", GST_ELEMENT_NAME (element));
|
||||||
/* FIXME!! */
|
if (!gst_element_release_locks (element)) {
|
||||||
g_mutex_lock (queue->qlock);
|
g_warning ("element %s could not release locks", GST_ELEMENT_NAME (element));
|
||||||
g_cond_signal (queue->not_full);
|
|
||||||
g_cond_signal (queue->not_empty);
|
|
||||||
g_mutex_unlock (queue->qlock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_element_disable_threadsafe_properties (element);
|
|
||||||
}
|
}
|
||||||
THR_DEBUG ("telling thread to pause, signaling");
|
THR_DEBUG ("telling thread to pause, signaling");
|
||||||
g_cond_signal (thread->cond);
|
g_cond_signal (thread->cond);
|
||||||
|
@ -392,6 +372,12 @@ gst_thread_change_state (GstElement * element)
|
||||||
g_cond_wait (thread->cond, thread->lock);
|
g_cond_wait (thread->cond, thread->lock);
|
||||||
THR_DEBUG ("got ack");
|
THR_DEBUG ("got ack");
|
||||||
g_mutex_unlock (thread->lock);
|
g_mutex_unlock (thread->lock);
|
||||||
|
|
||||||
|
elements = gst_bin_get_list (GST_BIN (thread));
|
||||||
|
while (elements) {
|
||||||
|
gst_element_disable_threadsafe_properties ((GstElement*)elements->data);
|
||||||
|
elements = g_list_next (elements);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_STATE_READY_TO_NULL:
|
case GST_STATE_READY_TO_NULL:
|
||||||
|
|
|
@ -29,5 +29,10 @@ typedef enum {
|
||||||
GST_STATE_ASYNC = 2,
|
GST_STATE_ASYNC = 2,
|
||||||
} GstElementStateReturn;
|
} GstElementStateReturn;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_RESULT_OK,
|
||||||
|
GST_RESULT_NOK,
|
||||||
|
GST_RESULT_NOT_IMPL,
|
||||||
|
} GstResult;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -117,7 +117,7 @@ static void gst_basic_scheduler_pad_connect (GstScheduler *sched, GstPad *
|
||||||
static void gst_basic_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
static void gst_basic_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
||||||
static GstPad* gst_basic_scheduler_pad_select (GstScheduler *sched, GList *padlist);
|
static GstPad* gst_basic_scheduler_pad_select (GstScheduler *sched, GList *padlist);
|
||||||
static GstClockReturn gst_basic_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
|
static GstClockReturn gst_basic_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
|
||||||
GstClock *clock, GstClockTime time);
|
GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
|
||||||
static GstSchedulerState
|
static GstSchedulerState
|
||||||
gst_basic_scheduler_iterate (GstScheduler *sched);
|
gst_basic_scheduler_iterate (GstScheduler *sched);
|
||||||
|
|
||||||
|
@ -289,7 +289,6 @@ gst_basic_scheduler_chain_wrapper (int argc, char *argv[])
|
||||||
buf = gst_pad_pull (pad);
|
buf = gst_pad_pull (pad);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
if (GST_IS_EVENT (buf) && !GST_ELEMENT_IS_EVENT_AWARE (element)) {
|
if (GST_IS_EVENT (buf) && !GST_ELEMENT_IS_EVENT_AWARE (element)) {
|
||||||
/*gst_pad_event_default (pad, GST_EVENT (buf)); */
|
|
||||||
gst_pad_send_event (pad, GST_EVENT (buf));
|
gst_pad_send_event (pad, GST_EVENT (buf));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -299,12 +298,6 @@ gst_basic_scheduler_chain_wrapper (int argc, char *argv[])
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function of element %s done", name);
|
GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function of element %s done", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
else {
|
|
||||||
gst_element_error (element, "NULL buffer detected. Is \"%s:%s\" connected?",
|
|
||||||
name, GST_PAD_NAME (pad), NULL);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
|
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
|
||||||
|
@ -341,29 +334,15 @@ gst_basic_scheduler_src_wrapper (int argc, char *argv[])
|
||||||
pads = g_list_next (pads);
|
pads = g_list_next (pads);
|
||||||
if (GST_RPAD_DIRECTION (realpad) == GST_PAD_SRC) {
|
if (GST_RPAD_DIRECTION (realpad) == GST_PAD_SRC) {
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW, "calling _getfunc for %s:%s", GST_DEBUG_PAD_NAME (realpad));
|
GST_DEBUG (GST_CAT_DATAFLOW, "calling _getfunc for %s:%s", GST_DEBUG_PAD_NAME (realpad));
|
||||||
if (realpad->regiontype != GST_REGION_VOID) {
|
|
||||||
g_return_val_if_fail (GST_RPAD_GETREGIONFUNC (realpad) != NULL, 0);
|
|
||||||
/* if (GST_RPAD_GETREGIONFUNC(realpad) == NULL) */
|
|
||||||
/* fprintf(stderr,"error, no getregionfunc in \"%s\"\n", name); */
|
|
||||||
/* else */
|
|
||||||
buf =
|
|
||||||
(GST_RPAD_GETREGIONFUNC (realpad)) (GST_PAD_CAST (realpad), realpad->regiontype,
|
|
||||||
realpad->offset, realpad->len);
|
|
||||||
realpad->regiontype = GST_REGION_VOID;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g_return_val_if_fail (GST_RPAD_GETFUNC (realpad) != NULL, 0);
|
g_return_val_if_fail (GST_RPAD_GETFUNC (realpad) != NULL, 0);
|
||||||
/* if (GST_RPAD_GETFUNC(realpad) == NULL) */
|
|
||||||
/* fprintf(stderr,"error, no getfunc in \"%s\"\n", name); */
|
|
||||||
/* else */
|
|
||||||
buf = GST_RPAD_GETFUNC (realpad) (GST_PAD_CAST (realpad));
|
buf = GST_RPAD_GETFUNC (realpad) (GST_PAD_CAST (realpad));
|
||||||
}
|
if (buf) {
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW, "calling gst_pad_push on pad %s:%s",
|
GST_DEBUG (GST_CAT_DATAFLOW, "calling gst_pad_push on pad %s:%s",
|
||||||
GST_DEBUG_PAD_NAME (realpad));
|
GST_DEBUG_PAD_NAME (realpad));
|
||||||
gst_pad_push (GST_PAD_CAST (realpad), buf);
|
gst_pad_push (GST_PAD_CAST (realpad), buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
|
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
|
||||||
|
|
||||||
GST_FLAG_UNSET (element, GST_ELEMENT_COTHREAD_STOPPING);
|
GST_FLAG_UNSET (element, GST_ELEMENT_COTHREAD_STOPPING);
|
||||||
|
@ -483,46 +462,6 @@ gst_basic_scheduler_gethandler_proxy (GstPad * pad)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstBuffer *
|
|
||||||
gst_basic_scheduler_pullregionfunc_proxy (GstPad * pad, GstRegionType type, guint64 offset, guint64 len)
|
|
||||||
{
|
|
||||||
GstBuffer *buf;
|
|
||||||
GstElement *parent;
|
|
||||||
GstRealPad *peer;
|
|
||||||
|
|
||||||
parent = GST_PAD_PARENT (pad);
|
|
||||||
peer = GST_RPAD_PEER (pad);
|
|
||||||
|
|
||||||
GST_DEBUG_ENTER ("%s:%s,%d,%lld,%lld", GST_DEBUG_PAD_NAME (pad), type, offset, len);
|
|
||||||
|
|
||||||
/* put the region info into the pad */
|
|
||||||
GST_RPAD_REGIONTYPE (pad) = type;
|
|
||||||
GST_RPAD_OFFSET (pad) = offset;
|
|
||||||
GST_RPAD_LEN (pad) = len;
|
|
||||||
|
|
||||||
/* FIXME this should be bounded */
|
|
||||||
/* we will loop switching to the peer until it's filled up the bufferpen */
|
|
||||||
while (GST_RPAD_BUFPEN (pad) == NULL) {
|
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW, "switching to %p to fill bufpen",
|
|
||||||
GST_ELEMENT_THREADSTATE (parent));
|
|
||||||
|
|
||||||
do_element_switch (parent);
|
|
||||||
|
|
||||||
/* we may no longer be the same pad, check. */
|
|
||||||
if (GST_RPAD_PEER (peer) != (GstRealPad *) pad) {
|
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW, "new pad in mid-switch!");
|
|
||||||
pad = (GstPad *) GST_RPAD_PEER (peer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GST_DEBUG (GST_CAT_DATAFLOW, "done switching");
|
|
||||||
|
|
||||||
/* now grab the buffer from the pen, clear the pen, and return the buffer */
|
|
||||||
buf = GST_RPAD_BUFPEN (pad);
|
|
||||||
GST_RPAD_BUFPEN (pad) = NULL;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
|
gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
|
||||||
{
|
{
|
||||||
|
@ -607,7 +546,6 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
|
||||||
GST_DEBUG (GST_CAT_SCHEDULING, "copying get function into pull proxy for %s:%s",
|
GST_DEBUG (GST_CAT_SCHEDULING, "copying get function into pull proxy for %s:%s",
|
||||||
GST_DEBUG_PAD_NAME (pad));
|
GST_DEBUG_PAD_NAME (pad));
|
||||||
GST_RPAD_GETHANDLER (pad) = GST_RPAD_GETFUNC (pad);
|
GST_RPAD_GETHANDLER (pad) = GST_RPAD_GETFUNC (pad);
|
||||||
GST_RPAD_PULLREGIONFUNC (pad) = GST_RPAD_GETREGIONFUNC (pad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -622,7 +560,6 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
|
||||||
GST_DEBUG (GST_CAT_SCHEDULING, "setting cothreaded pull proxy for srcpad %s:%s",
|
GST_DEBUG (GST_CAT_SCHEDULING, "setting cothreaded pull proxy for srcpad %s:%s",
|
||||||
GST_DEBUG_PAD_NAME (pad));
|
GST_DEBUG_PAD_NAME (pad));
|
||||||
GST_RPAD_GETHANDLER (pad) = GST_DEBUG_FUNCPTR (gst_basic_scheduler_gethandler_proxy);
|
GST_RPAD_GETHANDLER (pad) = GST_DEBUG_FUNCPTR (gst_basic_scheduler_gethandler_proxy);
|
||||||
GST_RPAD_PULLREGIONFUNC (pad) = GST_DEBUG_FUNCPTR (gst_basic_scheduler_pullregionfunc_proxy);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1116,10 +1053,12 @@ gst_basic_scheduler_yield (GstScheduler *sched, GstElement *element)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_basic_scheduler_interrupt (GstScheduler *sched, GstElement *element)
|
gst_basic_scheduler_interrupt (GstScheduler *sched, GstElement *element)
|
||||||
{
|
{
|
||||||
|
GstElement *current = SCHED (element)->current;
|
||||||
|
|
||||||
GST_FLAG_SET (element, GST_ELEMENT_COTHREAD_STOPPING);
|
GST_FLAG_SET (element, GST_ELEMENT_COTHREAD_STOPPING);
|
||||||
|
|
||||||
if (element->post_run_func)
|
if (current->post_run_func)
|
||||||
element->post_run_func (element);
|
current->post_run_func (current);
|
||||||
|
|
||||||
SCHED (element)->current = NULL;
|
SCHED (element)->current = NULL;
|
||||||
do_cothread_switch (do_cothread_get_main (((GstBasicScheduler *) sched)->context));
|
do_cothread_switch (do_cothread_get_main (((GstBasicScheduler *) sched)->context));
|
||||||
|
@ -1257,9 +1196,9 @@ gst_basic_scheduler_pad_select (GstScheduler * sched, GList * padlist)
|
||||||
|
|
||||||
static GstClockReturn
|
static GstClockReturn
|
||||||
gst_basic_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
|
gst_basic_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
|
||||||
GstClock *clock, GstClockTime time)
|
GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
|
||||||
{
|
{
|
||||||
return gst_clock_wait (clock, time);
|
return gst_clock_wait (clock, time, jitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstSchedulerState
|
static GstSchedulerState
|
||||||
|
|
|
@ -58,6 +58,7 @@ gst_bytestream_new (GstPad * pad)
|
||||||
bs->listavail = 0;
|
bs->listavail = 0;
|
||||||
bs->assembled = NULL;
|
bs->assembled = NULL;
|
||||||
bs->offset = 0LL;
|
bs->offset = 0LL;
|
||||||
|
bs->in_seek = FALSE;
|
||||||
|
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +123,9 @@ gst_bytestream_get_next_buf (GstByteStream * bs)
|
||||||
GstBuffer *nextbuf, *lastbuf, *headbuf;
|
GstBuffer *nextbuf, *lastbuf, *headbuf;
|
||||||
GSList *end;
|
GSList *end;
|
||||||
|
|
||||||
g_assert (!bs->event);
|
/* if there is an event pending, return FALSE */
|
||||||
|
if (bs->event)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
bs_print ("get_next_buf: pulling buffer");
|
bs_print ("get_next_buf: pulling buffer");
|
||||||
nextbuf = gst_pad_pull (bs->pad);
|
nextbuf = gst_pad_pull (bs->pad);
|
||||||
|
@ -429,33 +432,30 @@ gst_bytestream_flush_fast (GstByteStream * bs, guint32 len)
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_bytestream_seek (GstByteStream *bs, GstSeekType type, gint64 offset)
|
gst_bytestream_seek (GstByteStream *bs, gint64 offset, GstSeekType method)
|
||||||
{
|
{
|
||||||
GstRealPad *peer = GST_RPAD_PEER (bs->pad);
|
GstRealPad *peer;
|
||||||
guint32 waiting;
|
|
||||||
GstEvent *event = NULL;
|
|
||||||
GstBuffer *headbuf;
|
|
||||||
|
|
||||||
if (gst_pad_send_event (GST_PAD (peer), gst_event_new_seek (type, offset, TRUE))) {
|
g_return_val_if_fail (bs != NULL, FALSE);
|
||||||
|
|
||||||
|
peer = GST_RPAD_PEER (bs->pad);
|
||||||
|
|
||||||
|
bs_print ("bs: send event\n");
|
||||||
|
if (gst_pad_send_event (GST_PAD (peer), gst_event_new_seek (
|
||||||
|
GST_FORMAT_BYTES |
|
||||||
|
(method & GST_SEEK_METHOD_MASK) |
|
||||||
|
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
|
||||||
|
offset)))
|
||||||
|
{
|
||||||
gst_bytestream_flush_fast (bs, bs->listavail);
|
gst_bytestream_flush_fast (bs, bs->listavail);
|
||||||
|
|
||||||
while (!gst_bytestream_get_next_buf(bs)) {
|
/* we set the seek flag here. We cannot pull the pad here
|
||||||
gst_bytestream_get_status(bs, &waiting, &event);
|
* bacause a seek might occur outisde of the pads cothread context */
|
||||||
|
bs->in_seek = TRUE;
|
||||||
/* it is valid for a seek to cause eos, so lets say it succeeded */
|
|
||||||
if (GST_EVENT_TYPE(event) == GST_EVENT_EOS){
|
|
||||||
bs->offset = 0LL;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
headbuf = GST_BUFFER (bs->buflist->data);
|
|
||||||
/* we have a new offset */
|
|
||||||
bs->offset = GST_BUFFER_OFFSET(headbuf);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
bs_print ("bs: send event failed\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,9 @@ struct _GstByteStream {
|
||||||
|
|
||||||
/* this is needed for gst_bytestream_tell */
|
/* this is needed for gst_bytestream_tell */
|
||||||
guint64 offset;
|
guint64 offset;
|
||||||
|
|
||||||
|
/* if we are in the seek state (waiting for DISCONT) */
|
||||||
|
gboolean in_seek;
|
||||||
};
|
};
|
||||||
|
|
||||||
GstByteStream* gst_bytestream_new (GstPad *pad);
|
GstByteStream* gst_bytestream_new (GstPad *pad);
|
||||||
|
@ -50,7 +53,7 @@ void gst_bytestream_destroy (GstByteStream *bs);
|
||||||
|
|
||||||
guint32 gst_bytestream_read (GstByteStream *bs, GstBuffer** buf, guint32 len);
|
guint32 gst_bytestream_read (GstByteStream *bs, GstBuffer** buf, guint32 len);
|
||||||
guint64 gst_bytestream_tell (GstByteStream *bs);
|
guint64 gst_bytestream_tell (GstByteStream *bs);
|
||||||
gboolean gst_bytestream_seek (GstByteStream *bs, GstSeekType type, gint64 offset);
|
gboolean gst_bytestream_seek (GstByteStream *bs, gint64 offset, GstSeekType type);
|
||||||
guint32 gst_bytestream_peek (GstByteStream *bs, GstBuffer** buf, guint32 len);
|
guint32 gst_bytestream_peek (GstByteStream *bs, GstBuffer** buf, guint32 len);
|
||||||
guint32 gst_bytestream_peek_bytes (GstByteStream *bs, guint8** data, guint32 len);
|
guint32 gst_bytestream_peek_bytes (GstByteStream *bs, guint8** data, guint32 len);
|
||||||
gboolean gst_bytestream_flush (GstByteStream *bs, guint32 len);
|
gboolean gst_bytestream_flush (GstByteStream *bs, guint32 len);
|
||||||
|
|
|
@ -149,6 +149,8 @@ gst_fakesink_init (GstFakeSink *fakesink)
|
||||||
fakesink->last_message = NULL;
|
fakesink->last_message = NULL;
|
||||||
|
|
||||||
GST_ELEMENT (fakesink)->setclockfunc = gst_fakesink_set_clock;
|
GST_ELEMENT (fakesink)->setclockfunc = gst_fakesink_set_clock;
|
||||||
|
|
||||||
|
GST_FLAG_SET (fakesink, GST_ELEMENT_EVENT_AWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -251,8 +253,26 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
|
||||||
|
|
||||||
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
|
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
if (fakesink->sync) {
|
if (GST_IS_EVENT (buf)) {
|
||||||
gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf));
|
GstEvent *event = GST_EVENT (buf);
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
|
if (fakesink->sync && fakesink->clock) {
|
||||||
|
gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
|
||||||
|
gst_clock_handle_discont (fakesink->clock, value);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
gst_pad_event_default (pad, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_event_free (event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fakesink->sync && fakesink->clock) {
|
||||||
|
gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fakesink->silent) {
|
if (!fakesink->silent) {
|
||||||
|
|
|
@ -322,7 +322,7 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
||||||
|
|
||||||
if (!GST_EVENT_SEEK_FLUSH (event)) {
|
if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
|
||||||
gst_event_free (event);
|
gst_event_free (event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,24 +271,29 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
/* we need to seek */
|
/* we need to seek */
|
||||||
if (GST_EVENT_SEEK_FLUSH(event))
|
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
|
||||||
if (fflush(filesink->file))
|
if (fflush(filesink->file))
|
||||||
gst_element_error(GST_ELEMENT(filesink),
|
gst_element_error(GST_ELEMENT(filesink),
|
||||||
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
"Error flushing the buffer cache of file \'%s\' to disk: %s",
|
||||||
gst_filesink_getcurrentfilename(filesink), sys_errlist[errno]);
|
gst_filesink_getcurrentfilename(filesink), sys_errlist[errno]);
|
||||||
switch (GST_EVENT_SEEK_TYPE(event))
|
|
||||||
|
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||||
|
g_warning("Any other then byte-offset seeking is not supported!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GST_EVENT_SEEK_METHOD(event))
|
||||||
{
|
{
|
||||||
case GST_SEEK_BYTEOFFSET_SET:
|
case GST_SEEK_METHOD_SET:
|
||||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
|
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_CUR:
|
case GST_SEEK_METHOD_CUR:
|
||||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
|
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_END:
|
case GST_SEEK_METHOD_END:
|
||||||
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
|
fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_warning("Any other then byte-offset seeking is not supported!\n");
|
g_warning("unkown seek method!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -110,6 +110,8 @@ static void gst_filesrc_get_property (GObject *object, guint prop_id,
|
||||||
|
|
||||||
static GstBuffer * gst_filesrc_get (GstPad *pad);
|
static GstBuffer * gst_filesrc_get (GstPad *pad);
|
||||||
static gboolean gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event);
|
static gboolean gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event);
|
||||||
|
static gboolean gst_filesrc_srcpad_query (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstSeekType *format, gint64 *value);
|
||||||
|
|
||||||
static GstElementStateReturn gst_filesrc_change_state (GstElement *element);
|
static GstElementStateReturn gst_filesrc_change_state (GstElement *element);
|
||||||
|
|
||||||
|
@ -186,6 +188,7 @@ gst_filesrc_init (GstFileSrc *src)
|
||||||
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
|
gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
|
||||||
gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
|
gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
|
||||||
|
gst_pad_set_query_function (src->srcpad, gst_filesrc_srcpad_query);
|
||||||
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
||||||
|
|
||||||
src->pagesize = getpagesize();
|
src->pagesize = getpagesize();
|
||||||
|
@ -445,12 +448,19 @@ gst_filesrc_get (GstPad *pad)
|
||||||
|
|
||||||
/* check for seek */
|
/* check for seek */
|
||||||
if (src->seek_happened) {
|
if (src->seek_happened) {
|
||||||
|
GstEvent *event;
|
||||||
|
|
||||||
src->seek_happened = FALSE;
|
src->seek_happened = FALSE;
|
||||||
return GST_BUFFER (gst_event_new (GST_EVENT_DISCONTINUOUS));
|
GST_DEBUG (GST_CAT_EVENT, "filesrc sending discont\n");
|
||||||
|
event = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset, NULL);
|
||||||
|
GST_EVENT_DISCONT_FLUSH (event) = src->need_flush;
|
||||||
|
src->need_flush = FALSE;
|
||||||
|
return GST_BUFFER (event);
|
||||||
}
|
}
|
||||||
/* check for flush */
|
/* check for flush */
|
||||||
if (src->need_flush) {
|
if (src->need_flush) {
|
||||||
src->need_flush = FALSE;
|
src->need_flush = FALSE;
|
||||||
|
GST_DEBUG (GST_CAT_EVENT, "filesrc sending flush\n");
|
||||||
return GST_BUFFER (gst_event_new_flush ());
|
return GST_BUFFER (gst_event_new_flush ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,6 +655,7 @@ gst_filesrc_change_state (GstElement *element)
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
src->curoffset = 0;
|
src->curoffset = 0;
|
||||||
|
src->seek_happened = TRUE;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -655,6 +666,32 @@ gst_filesrc_change_state (GstElement *element)
|
||||||
return GST_STATE_SUCCESS;
|
return GST_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_filesrc_srcpad_query (GstPad *pad, GstPadQueryType type,
|
||||||
|
GstFormat *format, gint64 *value)
|
||||||
|
{
|
||||||
|
GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case GST_PAD_QUERY_TOTAL:
|
||||||
|
if (*format != GST_FORMAT_BYTES) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*value = src->filelen;
|
||||||
|
break;
|
||||||
|
case GST_PAD_QUERY_POSITION:
|
||||||
|
if (*format != GST_FORMAT_BYTES) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*value = src->curoffset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
||||||
{
|
{
|
||||||
|
@ -662,14 +699,17 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
switch (GST_EVENT_SEEK_TYPE (event)) {
|
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||||
case GST_SEEK_BYTEOFFSET_SET:
|
return FALSE;
|
||||||
|
}
|
||||||
|
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||||
|
case GST_SEEK_METHOD_SET:
|
||||||
src->curoffset = (guint64) GST_EVENT_SEEK_OFFSET (event);
|
src->curoffset = (guint64) GST_EVENT_SEEK_OFFSET (event);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_CUR:
|
case GST_SEEK_METHOD_CUR:
|
||||||
src->curoffset += GST_EVENT_SEEK_OFFSET (event);
|
src->curoffset += GST_EVENT_SEEK_OFFSET (event);
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_BYTEOFFSET_END:
|
case GST_SEEK_METHOD_END:
|
||||||
src->curoffset = src->filelen - ABS (GST_EVENT_SEEK_OFFSET (event));
|
src->curoffset = src->filelen - ABS (GST_EVENT_SEEK_OFFSET (event));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -678,9 +718,7 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
||||||
}
|
}
|
||||||
g_object_notify (G_OBJECT (src), "offset");
|
g_object_notify (G_OBJECT (src), "offset");
|
||||||
src->seek_happened = TRUE;
|
src->seek_happened = TRUE;
|
||||||
src->need_flush = GST_EVENT_SEEK_FLUSH(event);
|
src->need_flush = GST_EVENT_SEEK_FLAGS(event) & GST_SEEK_FLAG_FLUSH;
|
||||||
gst_event_free (event);
|
|
||||||
/* push a discontinuous event? */
|
|
||||||
break;
|
break;
|
||||||
case GST_EVENT_FLUSH:
|
case GST_EVENT_FLUSH:
|
||||||
src->need_flush = TRUE;
|
src->need_flush = TRUE;
|
||||||
|
|
|
@ -82,9 +82,13 @@ static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
|
||||||
static GstBuffer * gst_queue_get (GstPad *pad);
|
static GstBuffer * gst_queue_get (GstPad *pad);
|
||||||
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
|
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
|
||||||
|
|
||||||
|
static gboolean gst_queue_handle_src_event (GstPad *pad, GstEvent *event);
|
||||||
|
|
||||||
|
|
||||||
static void gst_queue_locked_flush (GstQueue *queue);
|
static void gst_queue_locked_flush (GstQueue *queue);
|
||||||
|
|
||||||
static GstElementStateReturn gst_queue_change_state (GstElement *element);
|
static GstElementStateReturn gst_queue_change_state (GstElement *element);
|
||||||
|
static gboolean gst_queue_release_locks (GstElement *element);
|
||||||
|
|
||||||
|
|
||||||
#define GST_TYPE_QUEUE_LEAKY (queue_leaky_get_type())
|
#define GST_TYPE_QUEUE_LEAKY (queue_leaky_get_type())
|
||||||
|
@ -158,6 +162,7 @@ gst_queue_class_init (GstQueueClass *klass)
|
||||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_queue_get_property);
|
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_queue_get_property);
|
||||||
|
|
||||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
|
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
|
||||||
|
gstelement_class->release_locks = GST_DEBUG_FUNCPTR(gst_queue_release_locks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPadConnectReturn
|
static GstPadConnectReturn
|
||||||
|
@ -207,6 +212,7 @@ gst_queue_init (GstQueue *queue)
|
||||||
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
|
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
|
||||||
gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
||||||
gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
||||||
|
gst_pad_set_event_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_handle_src_event));
|
||||||
|
|
||||||
queue->leaky = GST_QUEUE_NO_LEAK;
|
queue->leaky = GST_QUEUE_NO_LEAK;
|
||||||
queue->queue = NULL;
|
queue->queue = NULL;
|
||||||
|
@ -301,6 +307,9 @@ restart:
|
||||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n",
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n",
|
||||||
GST_ELEMENT_NAME (queue), queue->level_buffers);
|
GST_ELEMENT_NAME (queue), queue->level_buffers);
|
||||||
break;
|
break;
|
||||||
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
|
//gst_queue_locked_flush (queue);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/*gst_pad_event_default (pad, GST_EVENT (buf)); */
|
/*gst_pad_event_default (pad, GST_EVENT (buf)); */
|
||||||
break;
|
break;
|
||||||
|
@ -350,7 +359,8 @@ restart:
|
||||||
while (queue->level_buffers == queue->size_buffers) {
|
while (queue->level_buffers == queue->size_buffers) {
|
||||||
/* if there's a pending state change for this queue or its manager, switch */
|
/* if there's a pending state change for this queue or its manager, switch */
|
||||||
/* back to iterator so bottom half of state change executes */
|
/* back to iterator so bottom half of state change executes */
|
||||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||||
|
if (queue->interrupt) {
|
||||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
||||||
g_mutex_unlock (queue->qlock);
|
g_mutex_unlock (queue->qlock);
|
||||||
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
||||||
|
@ -435,7 +445,8 @@ restart:
|
||||||
/* if there's a pending state change for this queue or its manager, switch
|
/* if there's a pending state change for this queue or its manager, switch
|
||||||
* back to iterator so bottom half of state change executes
|
* back to iterator so bottom half of state change executes
|
||||||
*/
|
*/
|
||||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||||
|
if (queue->interrupt) {
|
||||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
|
||||||
g_mutex_unlock (queue->qlock);
|
g_mutex_unlock (queue->qlock);
|
||||||
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
if (gst_element_interrupt (GST_ELEMENT (queue)))
|
||||||
|
@ -507,6 +518,51 @@ restart:
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_queue_handle_src_event (GstPad *pad, GstEvent *event)
|
||||||
|
{
|
||||||
|
GstQueue *queue;
|
||||||
|
|
||||||
|
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||||
|
|
||||||
|
g_mutex_lock (queue->qlock);
|
||||||
|
|
||||||
|
if (gst_element_get_state (GST_ELEMENT (queue)) == GST_STATE_PLAYING) {
|
||||||
|
g_warning ("queue event in playing state");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_FLUSH:
|
||||||
|
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "FLUSH event, flushing queue\n");
|
||||||
|
gst_queue_locked_flush (queue);
|
||||||
|
break;
|
||||||
|
case GST_EVENT_SEEK:
|
||||||
|
gst_queue_locked_flush (queue);
|
||||||
|
default:
|
||||||
|
gst_pad_event_default (pad, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_mutex_unlock (queue->qlock);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_queue_release_locks (GstElement *element)
|
||||||
|
{
|
||||||
|
GstQueue *queue;
|
||||||
|
|
||||||
|
queue = GST_QUEUE (element);
|
||||||
|
|
||||||
|
g_mutex_lock (queue->qlock);
|
||||||
|
queue->interrupt = TRUE;
|
||||||
|
g_cond_signal (queue->not_full);
|
||||||
|
g_cond_signal (queue->not_empty);
|
||||||
|
g_mutex_unlock (queue->qlock);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
gst_queue_change_state (GstElement *element)
|
gst_queue_change_state (GstElement *element)
|
||||||
{
|
{
|
||||||
|
@ -543,6 +599,7 @@ gst_queue_change_state (GstElement *element)
|
||||||
|
|
||||||
return GST_STATE_FAILURE;
|
return GST_STATE_FAILURE;
|
||||||
}
|
}
|
||||||
|
queue->interrupt = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||||
|
|
|
@ -75,6 +75,7 @@ struct _GstQueue {
|
||||||
|
|
||||||
gint leaky; /* whether the queue is leaky, and if so at which end */
|
gint leaky; /* whether the queue is leaky, and if so at which end */
|
||||||
gboolean may_deadlock; /* it the queue should fail on possible deadlocks */
|
gboolean may_deadlock; /* it the queue should fail on possible deadlocks */
|
||||||
|
gboolean interrupt;
|
||||||
|
|
||||||
GMutex *qlock; /* lock for queue (vs object lock) */
|
GMutex *qlock; /* lock for queue (vs object lock) */
|
||||||
/* we are single reader and single writer queue */
|
/* we are single reader and single writer queue */
|
||||||
|
|
|
@ -435,8 +435,6 @@ print_element_info (GstElementFactory *factory)
|
||||||
printf(" Has chainfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->chainfunc));
|
printf(" Has chainfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->chainfunc));
|
||||||
if (realpad->getfunc)
|
if (realpad->getfunc)
|
||||||
printf(" Has getfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->getfunc));
|
printf(" Has getfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->getfunc));
|
||||||
if (realpad->getregionfunc)
|
|
||||||
printf(" Has getregionfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->getregionfunc));
|
|
||||||
|
|
||||||
if (pad->padtemplate)
|
if (pad->padtemplate)
|
||||||
printf(" Pad Template: '%s'\n",pad->padtemplate->name_template);
|
printf(" Pad Template: '%s'\n",pad->padtemplate->name_template);
|
||||||
|
|
Loading…
Reference in a new issue