Commit 9920b88c authored by Wim Taymans's avatar Wim Taymans

This is the audio/video sync release.

Original commit message from CVS:
This is the audio/video sync release.
Changed the mpegvideoparser to parse complete pictures. Added the PTS
timestamps to the pictures.
Added PTS timestamps to the MPEG audio frames.
Made the clock a littlebit better.
Gstplay now uses two more threads one for video, one for audio playback.
Added the first QoS callbacks for the pads.
hopefully fix an mmx compilation problem.
parent 37576c7d
......@@ -101,19 +101,6 @@ AC_CHECK_LIB(ghttp, ghttp_request_new,
AC_SUBST(GHTTP_LIBS)
AC_SUBST(GST_HTTPSRC_GET_TYPE)
dnl Check for X11 extensions
AC_PATH_XTRA
if test "-DX_DISPLAY_MISSING" = "$X_CFLAGS"; then
AC_MSG_ERROR(can not find X11)
fi
AC_SUBST(X_CFLAGS)
AC_SUBST(X_PRE_LIBS)
AC_SUBST(X_EXTRA_LIBS)
AC_SUBST(X_LIBS)
AC_CHECK_LIB(Xv, XvQueryExtension,,,
$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS)
dnl Check for atomic.h
dnl Note: use AC_CHECK_HEADER not AC_CHECK_HEADERS, because the latter
dnl defines the wrong default symbol as well (HAVE_ASM_ATOMIC_H)
......@@ -155,6 +142,19 @@ HAVE_LIBMMX="no"
AC_MSG_RESULT(no)
)
dnl Check for X11 extensions
AC_PATH_XTRA
if test "-DX_DISPLAY_MISSING" = "$X_CFLAGS"; then
AC_MSG_ERROR(can not find X11)
fi
AC_SUBST(X_CFLAGS)
AC_SUBST(X_PRE_LIBS)
AC_SUBST(X_EXTRA_LIBS)
AC_SUBST(X_LIBS)
AC_CHECK_LIB(Xv, XvQueryExtension,,,
$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS)
dnl Check for xaudio
AC_CHECK_HEADER(xaudio/decoder.h,[
AC_DEFINE(HAVE_XAUDIO)
......
Since the plan generation only happens as a result of the state mechanism,
I'll describe that first.
It's supposed to be recursive, such that setting the state on a Bin
recursively sets all the children. However, this needs to be rethought
somewhat, in light of some recent ideas on the actual definition of some
of the states.
The mechanism is thus: When you call gst_element_set_state(element,state),
it calls the change_state() class method. The basic Element-provided
version just sets or unsets the state. A more complex element like the
audiosink will switch on the state and do certain things like open or
close the sound card on transition to/from various states. The success or
failure of these actions can determine whether or not the state gets
[un]set as requested.
GtkObject signals enter in here, as whenever a state is successfully
changed, the STATE_CHANGE signal is fired, which gives higher-level code
the ability to do something based on the change.
The Bin's change_state function walks through all its children and sets
their state. This is where things get interesting, and where things are
going to need to be changed.
The issue is what the states are and mean. Currently the states are as
follows (from gstelement.h):
typedef enum {
GST_STATE_COMPLETE = (1 << 0),
GST_STATE_RUNNING = (1 << 1),
GST_STATE_DISCOVERY = (1 << 2),
GST_STATE_PREROLL = (1 << 3),
GST_STATE_PLAYING = (1 << 4),
GST_STATE_PAUSED = (1 << 5),
GST_STATE_MAX = (1 << 15),
} GstElementState;
COMPLETE means all the necesary information is available to run, i.e. the
filename for the disksrc, etc. RUNNING means that it's actually doing
something, but that's fuzzy. PLAYING means there really is data flowing
through the graph, where PAUSED temporary stops the flow. PLAYING &&
PAUSED is the same idea as !PLAYING, but there are probably going to be
many cases where there really is a distinction.
DISCOVERY is intended for the autoconnect case, in those instances where
the only way to determine the input or output type of some pad is for an
element to actually process some data. The idea in that case is that the
source element would be responsible for sending the data non-destructively
(in the case of a network client, it would have to save it all up, unless
it has seek capabilities over the network), and all downstream elements
process it in such a way as to not hose their own state. Or rather, when
they cease to do discovery, they completely wipe their state as if nothing
ever happened.
PREROLL is a local state, used for things like sending the first half of
an MPEG GOP through the decoder in order to start playback at a frame
somewhere in the middle of said GOP. Not sure how that will work,
exactly.
The issue is that these states aren't layered, and it most certainly isn't
the case that a container isn't able to be of a certain state unless all
of its children are. I guess I should explain the idea of reconfigurable
pipelines:
Build an MP3 player, give it the ability to use audio effects plugins.
Since you don't want to have to start the stream over again (especially if
it's a network stream) every time you change the effect. This means you
need to be able to freeze the pipeline in place to change it, without
taking too much time.
This matters when you consider that certain state changes should render
various state bits invalid. In the FROZEN state these won't happen,
because the assumption is that they're temporary.
If you haven't noticed by now, the state system isn't entirely
self-consistent yet. It needs work, and it needs discussion.
......@@ -147,9 +147,8 @@ static void gst_audiosink_init(GstAudioSink *audiosink) {
audiosink->fd = -1;
audiosink->clock = gst_clock_get_system();
gst_clock_register(audiosink->clock, GST_OBJECT(audiosink));
audiosink->clocktime = 0LL;
//audiosink->clocktime = 0LL;
gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE);
}
void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
......@@ -173,19 +172,20 @@ void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
audiosink->frequency,audiosink->format,
(audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes, frag);
}
GstElement *gst_audiosink_new(gchar *name) {
GstElement *audiosink = GST_ELEMENT(gtk_type_new(GST_TYPE_AUDIOSINK));
gst_element_set_name(GST_ELEMENT(audiosink),name);
gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE);
return audiosink;
}
void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
GstAudioSink *audiosink;
MetaAudioRaw *meta;
count_info info;
gboolean in_flush;
audio_buf_info ospace;
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
......@@ -197,6 +197,12 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
audiosink = GST_AUDIOSINK(pad->parent);
// g_return_if_fail(GST_FLAG_IS_SET(audiosink,GST_STATE_RUNNING));
if (in_flush = GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLUSH)) {
DEBUG("audiosink: flush\n");
ioctl(audiosink->fd,SNDCTL_DSP_RESET,0);
}
meta = (MetaAudioRaw *)gst_buffer_get_first_meta(buf);
if (meta != NULL) {
if ((meta->format != audiosink->format) ||
......@@ -217,20 +223,20 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard");
//g_print("audiosink: writing to soundcard\n");
if (audiosink->fd > 2) {
if (audiosink->clocktime == 0LL)
gst_clock_wait(audiosink->clock, audiosink->clocktime, GST_OBJECT(audiosink));
ioctl(audiosink->fd,SNDCTL_DSP_GETOPTR,&info);
audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels);
//g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime);
gst_clock_set(audiosink->clock, audiosink->clocktime);
if (!audiosink->mute)
write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
//audiosink->clocktime += (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels*
// (audiosink->format/8)*(audiosink->frequency)));
//g_print("audiosink: writing to soundcard ok\n");
if (!audiosink->mute) {
if (gst_clock_current_diff(audiosink->clock, GST_BUFFER_TIMESTAMP(buf)) > 500000) {
}
else {
gst_clock_wait(audiosink->clock, GST_BUFFER_TIMESTAMP(buf), GST_OBJECT(audiosink));
ioctl(audiosink->fd,SNDCTL_DSP_GETOSPACE,&ospace);
DEBUG("audiosink: (%d bytes buffer)\n", ospace.bytes);
write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
//gst_clock_set(audiosink->clock, GST_BUFFER_TIMESTAMP(buf));
}
}
}
}
end:
//g_print("a unref\n");
gst_buffer_unref(buf);
//g_print("a done\n");
......
......@@ -54,7 +54,7 @@ struct _GstAudioSink {
GstPad *sinkpad;
GstClockTime clocktime;
//GstClockTime clocktime;
GstClock *clock;
/* soundcard state */
int fd;
......
......@@ -20,7 +20,7 @@
//#define DEBUG_ENABLED
//#define STATUS_ENABLED
#ifdef STATUS_ENABLED
#define STATUS(A) g_print(A)
#define STATUS(A) DEBUG(A, gst_element_get_name(GST_ELEMENT(queue)))
#else
#define STATUS(A)
#endif
......@@ -144,6 +144,12 @@ static GstBuffer *gst_queue_pull(GstPad *pad) {
else return NULL;
}
static void gst_queue_cleanup_buffers(gpointer data, gpointer user_data)
{
DEBUG("queue: %s cleaning buffer %p\n", (gchar *)user_data, data);
gst_buffer_unref(GST_BUFFER(data));
}
void gst_queue_chain(GstPad *pad,GstBuffer *buf) {
GstQueue *queue;
gboolean tosignal = FALSE;
......@@ -157,8 +163,19 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) {
name = gst_element_get_name(GST_ELEMENT(queue));
/* we have to lock the queue since we span threads */
DEBUG("queue: %s adding buffer %p\n", name, buf);
GST_LOCK(queue);
if (GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLUSH)) {
g_list_foreach(queue->queue, gst_queue_cleanup_buffers, name);
g_list_free(queue->queue);
queue->queue = NULL;
queue->level_buffers = 0;
}
DEBUG("queue: %s: chain %d %p\n", name, queue->level_buffers, buf);
if (queue->level_buffers >= queue->max_buffers) {
......@@ -166,7 +183,7 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) {
while (queue->level_buffers >= queue->max_buffers) {
GST_UNLOCK(queue);
g_mutex_lock(queue->fulllock);
STATUS("O");
STATUS("%s: O\n");
g_cond_wait(queue->fullcond,queue->fulllock);
g_mutex_unlock(queue->fulllock);
GST_LOCK(queue);
......@@ -186,7 +203,7 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) {
// queue->tail = g_list_next(queue->tail);
queue->queue = g_list_append(queue->queue,buf);
}
STATUS("+");
STATUS("%s: +\n");
/* if we were empty, but aren't any more, signal a condition */
tosignal = (queue->level_buffers <= 0);
......@@ -213,19 +230,17 @@ void gst_queue_push(GstConnection *connection) {
name = gst_element_get_name(GST_ELEMENT(queue));
DEBUG("queue: %s push %d\n", name, queue->level_buffers);
/* have to lock for thread-safety */
GST_LOCK(queue);
DEBUG("queue: %s push %d\n", name, queue->level_buffers);
if (!queue->level_buffers) {
while (!queue->level_buffers) {
GST_UNLOCK(queue);
g_mutex_lock(queue->emptylock);
STATUS("U");
g_cond_wait(queue->emptycond,queue->emptylock);
g_mutex_unlock(queue->emptylock);
GST_LOCK(queue);
}
while (!queue->level_buffers) {
GST_UNLOCK(queue);
g_mutex_lock(queue->emptylock);
STATUS("%s: U\n");
g_cond_wait(queue->emptycond,queue->emptylock);
g_mutex_unlock(queue->emptylock);
GST_LOCK(queue);
}
front = queue->queue;
......@@ -233,7 +248,7 @@ void gst_queue_push(GstConnection *connection) {
queue->queue = g_list_remove_link(queue->queue,front);
g_list_free(front);
queue->level_buffers--;
STATUS("-");
STATUS("%s: -\n");
tosignal = queue->level_buffers < queue->max_buffers;
GST_UNLOCK(queue);
......
......@@ -43,7 +43,7 @@ GstElementDetails gst_queue_details;
#define GST_IS_QUEUE(obj) \
(GTK_CHECK_TYPE((obj),GST_TYPE_QUEUE))
#define GST_IS_QUEUE_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE)))
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE))
typedef struct _GstQueue GstQueue;
typedef struct _GstQueueClass GstQueueClass;
......
......@@ -21,6 +21,8 @@
#ifndef __GST_H__
#define __GST_H__
#include <unistd.h>
#include <gtk/gtk.h>
#include <gst/gstlog.h>
......@@ -51,9 +53,9 @@ void gst_init(int *argc,char **argv[]);
/* debugging */
#ifndef DEBUG
#ifdef DEBUG_ENABLED
#define DEBUG(format,args...) g_print("DEBUG: " format, ##args)
#define DEBUG(format, args...) g_print("DEBUG:(%d) " format, getpid() , ##args)
#else
#define DEBUG(format,args...)
#define DEBUG(format, args...)
#endif
#endif
......
......@@ -151,7 +151,7 @@ void gst_bin_add(GstBin *bin,GstElement *element) {
the children are, I think. */
// if (GST_STATE_IS_SET(element,GST_STATE_COMPLETE)) {
if (!GST_STATE_IS_SET(bin,GST_STATE_COMPLETE)) {
g_print("GstBin: adding complete element - ");
g_print("GstBin: adding complete element - \n");
gst_bin_change_state_norecurse(GST_ELEMENT(bin),GST_STATE_COMPLETE);
}
// } else {
......@@ -199,10 +199,10 @@ static gboolean gst_bin_change_state(GstElement *element,
children = bin->children;
while (children) {
child = GST_ELEMENT(children->data);
// g_print("gst_bin_change_state setting state on \"%s\"\n",
// gst_object_get_name(GST_OBJECT(child)));
//g_print("gst_bin_change_state setting state on \"%s\"\n",
// gst_element_get_name(GST_ELEMENT(child)));
if (!gst_element_set_state(child,state)) {
g_print("child %p failed to set state 0x%08x\n",child,state);
g_print("GstBin: child %p failed to set state 0x%08x\n",child,state);
return FALSE;
}
// g_print("\n");
......@@ -255,7 +255,6 @@ static gboolean gst_bin_change_state_type(GstBin *bin,
// g_print("\n");
children = g_list_next(children);
}
// g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin)));
if (type == GST_TYPE_BIN)
gst_element_change_state(GST_ELEMENT(bin),state);
......@@ -394,7 +393,7 @@ static void gst_bin_create_plan_func(GstBin *bin) {
bin->numentries = 0;
g_print("attempting to create a plan for bin %p\n",bin);
g_print("GstBin: attempting to create a plan for bin %p\n",bin);
/* walk through all the elements to figure out all kinds of things */
elements = GST_BIN(bin)->children;
......@@ -404,11 +403,11 @@ static void gst_bin_create_plan_func(GstBin *bin) {
// have to use cothreads if any elements use loop functions
if (element->loopfunc != NULL) {
if (bin->threadcontext == NULL) {
g_print("initializing cothread context\n");
g_print("GstBin: initializing cothread context\n");
bin->threadcontext = cothread_init();
}
if (element->threadstate == NULL) {
g_print("creating thread state for element\n");
g_print("GstBin: creating thread state for element\n");
element->threadstate = cothread_create(bin->threadcontext);
cothread_setfunc(element->threadstate,gst_element_loopfunc_wrapper,
0,element);
......@@ -417,7 +416,7 @@ static void gst_bin_create_plan_func(GstBin *bin) {
/* we need to find all the entry points into the bin */
if (GST_IS_SRC(element)) {
g_print("element '%s' is a source entry point for the bin\n",
g_print("GstBin: element '%s' is a source entry point for the bin\n",
gst_element_get_name(GST_ELEMENT(element)));
bin->entries = g_list_prepend(bin->entries,element);
bin->numentries++;
......@@ -437,7 +436,7 @@ static void gst_bin_create_plan_func(GstBin *bin) {
/* if it's a connection and it's not ours... */
if (GST_IS_CONNECTION(outside) &&
(gst_object_get_parent(GST_OBJECT(outside)) != GST_OBJECT(bin))) {
g_print("element '%s' is the external source Connection \
g_print("GstBin: element '%s' is the external source Connection \
for internal element '%s'\n",
gst_element_get_name(GST_ELEMENT(outside)),
gst_element_get_name(GST_ELEMENT(element)));
......@@ -450,7 +449,7 @@ for internal element '%s'\n",
}
elements = g_list_next(elements);
}
g_print("have %d entries into bin\n",bin->numentries);
g_print("GstBin: have %d entries into bin\n",bin->numentries);
}
void gst_bin_iterate_func(GstBin *bin) {
......@@ -464,7 +463,7 @@ void gst_bin_iterate_func(GstBin *bin) {
entries = bin->entries;
g_print("iterating\n");
g_print("GstBin: iterating\n");
while (entries) {
entry = GST_ELEMENT(entries->data);
......
......@@ -30,8 +30,7 @@ extern "C" {
#define GST_BUFFER(buf) \
((GstBuffer *)(buf))
((GstBuffer *)(buf))
#define GST_BUFFER_FLAGS(buf) \
(GST_BUFFER(buf)->flags)
......
......@@ -22,7 +22,6 @@
#include <gstclock.h>
static GstClock *the_system_clock = NULL;
static int num;
/**
* gst_clock_new:
......@@ -39,8 +38,9 @@ GstClock *gst_clock_new(gchar *name) {
clock->sinkmutex = g_mutex_new();
clock->lock = g_mutex_new();
g_mutex_lock(clock->sinkmutex);
num =0;
clock->locking = TRUE;
clock->num = 0;
clock->num_locked = 0;
clock->locking = FALSE;
return clock;
}
......@@ -56,87 +56,83 @@ void gst_clock_register(GstClock *clock, GstObject *obj) {
if (GST_IS_SINK(obj)) {
DEBUG("gst_clock: setting registered sink object 0x%p\n", obj);
clock->sinkobjects = g_list_append(clock->sinkobjects, obj);
num++;
clock->num++;
}
}
void gst_clock_set(GstClock *clock, GstClockTime time) {
struct timeval tfnow;
GstClockTime target, now;
GstClockTime now;
gettimeofday(&tfnow, (struct timezone *)NULL);
now = tfnow.tv_sec*1000000LL+tfnow.tv_usec;
g_mutex_lock(clock->lock);
clock->start_time = now - time;
g_mutex_unlock(clock->lock);
DEBUG("gst_clock: setting clock to %llu %llu %llu\n", time, now, clock->start_time);
}
GstClockTimeDiff gst_clock_current_diff(GstClock *clock, GstClockTime time)
{
struct timeval tfnow;
GstClockTime now;
gettimeofday(&tfnow, (struct timezone *)NULL);
now = tfnow.tv_sec*1000000+tfnow.tv_usec;
clock->adjust = now - (clock->start_time + time);
clock->current_time = (clock->start_time + time);
//DEBUG("gst_clock: setting clock to %llu %llu %lld\n", (guint64)clock->start_time+time, (guint64)now, (gint64)clock->adjust);
g_mutex_lock(clock->lock);
now = ((guint64)tfnow.tv_sec*1000000LL+tfnow.tv_usec) - (guint64)clock->start_time;
//if (clock->locking) now = 0;
g_mutex_unlock(clock->lock);
//DEBUG("gst_clock: diff with for time %08llu %08lld %08lld %08llu\n", time, now, GST_CLOCK_DIFF(time, now), clock->start_time);
return GST_CLOCK_DIFF(time, now);
}
void gst_clock_reset(GstClock *clock) {
struct timeval tfnow;
gettimeofday(&tfnow, (struct timezone *)NULL);
clock->start_time = tfnow.tv_sec*1000000+tfnow.tv_usec;
g_mutex_lock(clock->lock);
clock->start_time = ((guint64)tfnow.tv_sec)*1000000LL+tfnow.tv_usec;
clock->current_time = clock->start_time;
clock->adjust = 0LL;
DEBUG("gst_clock: setting start clock %llu\n", clock->start_time);
//clock->locking = TRUE;
g_mutex_unlock(clock->lock);
}
void gst_clock_wait(GstClock *clock, GstClockTime time, GstObject *obj) {
struct timeval tfnow;
GstClockTime target, now;
GstClockTime now;
GstClockTimeDiff diff;
GList *elements;
DEBUG("gst_clock: requesting clock object 0x%p\n", obj);
g_mutex_lock(clock->lock);
elements = clock->sinkobjects;
while (elements && clock->locking) {
if (elements->data == obj) {
DEBUG("gst_clock: registered sink object 0x%p\n", obj);
num--;
if (num) {
DEBUG("gst_clock: 0x%p locked\n", obj);
g_mutex_unlock(clock->lock);
g_mutex_lock(clock->sinkmutex);
g_mutex_lock(clock->lock);
clock->locking = FALSE;
}
else {
gst_clock_reset(clock);
DEBUG("gst_clock: unlock all %p\n", obj);
g_mutex_unlock(clock->sinkmutex);
clock->locking = FALSE;
}
break;
}
elements = g_list_next(elements);
}
//DEBUG("gst_clock: requesting clock object 0x%p %08llu %08llu\n", obj, time, clock->current_time);
target = clock->start_time + time;
gettimeofday(&tfnow, (struct timezone *)NULL);
now = tfnow.tv_sec*1000000+tfnow.tv_usec + clock->adjust;
g_mutex_lock(clock->lock);
now = tfnow.tv_sec*1000000LL+tfnow.tv_usec - clock->start_time;
//now = clock->current_time + clock->adjust;
//DEBUG("gst_clock: 0x%p waiting for time %llu %llu\n", obj, time, target);
diff = GST_CLOCK_DIFF(target, now);
diff = GST_CLOCK_DIFF(time, now);
// if we are not behind wait a bit
DEBUG("gst_clock: %s waiting for time %08llu %08llu %08lld\n", gst_element_get_name(GST_ELEMENT(obj)), time, now, diff);
if (diff > 1000 ) {
tfnow.tv_usec = diff % 1000000;
g_mutex_unlock(clock->lock);
if (diff > 10000 ) {
tfnow.tv_usec = (diff % 1000000);
tfnow.tv_sec = diff / 1000000;
// FIXME, this piece of code does not work with egcs optimisations on, had to use the following line
if (tfnow.tv_sec) fprintf(stderr, "gst_clock: waiting %u %llu %llu %llu seconds\n", (int)tfnow.tv_sec, now, diff, target);
g_mutex_unlock(clock->lock);
if (!tfnow.tv_sec) {
select(0, NULL, NULL, NULL, &tfnow);
}
else fprintf(stderr, "gst_clock: waiting %u %llu %llu %llu seconds\n", (int)tfnow.tv_sec, now, diff, time);
//DEBUG("gst_clock: 0x%p waiting for time %llu %llu %lld %llu\n", obj, time, target, diff, now);
select(0, NULL, NULL, NULL, &tfnow);
//DEBUG("gst_clock: 0x%p waiting done time %llu %llu\n", obj, time, target);
g_mutex_lock(clock->lock);
//DEBUG("waiting %d.%08d\n",tfnow.tv_sec, tfnow.tv_usec);
//DEBUG("gst_clock: 0x%p waiting done time %llu \n", obj, time);
}
DEBUG("gst_clock: %s waiting for time %08llu %08llu %08lld done \n", gst_element_get_name(GST_ELEMENT(obj)), time, now, diff);
// clock->current_time = clock->start_time + time;
g_mutex_unlock(clock->lock);
//gst_clock_set(clock, time);
}
......@@ -43,6 +43,7 @@ struct _GstClock {
GstClockTimeDiff adjust;
gboolean locking;
GList *sinkobjects;
gint num, num_locked;
GMutex *sinkmutex;
GMutex *lock;
};
......@@ -54,6 +55,7 @@ void gst_clock_register(GstClock *clock, GstObject *obj);
void gst_clock_set(GstClock *clock, GstClockTime time);
void gst_clock_reset(GstClock *clock);
void gst_clock_wait(GstClock *clock, GstClockTime time, GstObject *obj);
GstClockTimeDiff gst_clock_current_diff(GstClock *clock, GstClockTime time);
#ifdef __cplusplus
}
......
......@@ -39,7 +39,6 @@ static void gst_element_class_init(GstElementClass *klass);
static void gst_element_init(GstElement *element);
static void gst_element_real_destroy(GtkObject *object);
static GstObjectClass *parent_class = NULL;
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
......@@ -265,7 +264,7 @@ void gst_element_connect(GstElement *src,gchar *srcpadname,
* condition. It results in the "error" signal.
*/
void gst_element_error(GstElement *element,gchar *error) {
g_error("error in element '%s': %s\n",element->name,error);
g_error("GstElement: error in element '%s': %s\n",element->name,error);
gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[ERROR],error);
}
......@@ -331,7 +330,7 @@ gboolean gst_element_change_state(GstElement *element,
// element->name,state);
/* deal with the inverted state */
// g_print("changing element state, was %08lx",GST_STATE(element));
//g_print("changing element state, was %08lx\n",GST_STATE(element));
if (state & GST_STATE_MAX)
GST_STATE_UNSET(element,~state);
else
......@@ -497,7 +496,7 @@ xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent) {