diff --git a/gst/playondemand/demo-mp3.c b/gst/playondemand/demo-mp3.c index 1c23805b0c..e239961df6 100644 --- a/gst/playondemand/demo-mp3.c +++ b/gst/playondemand/demo-mp3.c @@ -3,24 +3,29 @@ #include #include -#define NUM_BEATS 16 -#define SPEED 1e-9 +#define NUM_BEATS 12 GtkWidget *window, *vbox, *beat_box, *button_box; GtkWidget *play_button, *clear_button, *reset_button, *quit_button; GtkWidget **beat_button; GtkWidget *speed_scale; GtkObject *speed_adj; -GstElement *src, *mad, *pod, *osssink, *pipeline; +GstElement *src, *mad, *pod, *sink, *pipeline; GstClock *element_clock; -GSList *beats; +guint32 *beats; void played (GstElement *pod, gpointer data) { - g_print("Played beat at %u\n", - ((guint) (gst_clock_get_time(element_clock) * - (GTK_ADJUSTMENT(speed_adj))->value * SPEED)) % NUM_BEATS); + gint i; + + g_print("Played beat at %02u, beats are ", + (guint) (gst_clock_get_time(element_clock) / GST_SECOND * + (GTK_ADJUSTMENT(speed_adj))->value) % NUM_BEATS); + + for (i = 0; i <= NUM_BEATS / 32; i++) g_print ("%08x ", beats[i]); + + g_print("\n"); } void @@ -47,18 +52,19 @@ reset (GtkButton *button, gpointer data) void beat (GtkToggleButton *button, gpointer data) { + guint b = GPOINTER_TO_UINT(data); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) - beats = g_slist_append(beats, data); + beats[b / 32] |= 1 << (b % 32); else - beats = g_slist_remove(beats, data); - g_object_set(G_OBJECT(pod), "tick-list", beats, NULL); + beats[b / 32] &= ~ (1 << (b % 32)); } void speed (GtkAdjustment *adjustment, gpointer data) { - g_object_set(G_OBJECT(pod), "clock-speed", adjustment->value * SPEED, NULL); - /*gst_clock_set_speed(element_clock, adjustment->value * SPEED);*/ + g_object_set(G_OBJECT(pod), "tick-rate", adjustment->value, NULL); + /*gst_clock_set_speed(element_clock, adjustment->value);*/ } void @@ -67,17 +73,21 @@ setup_pipeline (gchar *filename) src = gst_element_factory_make("filesrc", "filesrc"); mad = gst_element_factory_make("mad", "mad"); pod = gst_element_factory_make("playondemand", "playondemand"); - osssink = gst_element_factory_make("osssink", "osssink"); + sink = gst_element_factory_make("alsasink", "alsasink"); g_object_set(G_OBJECT(src), "location", filename, NULL); - g_object_set(G_OBJECT(osssink), "fragment", 0x00180008, NULL); + g_object_set(G_OBJECT(sink), "period-count", 32, + "period-size", 512, NULL); g_object_set(G_OBJECT(pod), "total-ticks", NUM_BEATS, - "clock-speed", SPEED, NULL); + "tick-rate", 1.0, + "max-plays", NUM_BEATS * 2, NULL); + + g_object_get(G_OBJECT(pod), "ticks", &beats, NULL); pipeline = gst_pipeline_new("app"); - gst_bin_add_many(GST_BIN(pipeline), src, mad, pod, osssink, NULL); - gst_element_link_many(src, mad, pod, osssink, NULL); + gst_bin_add_many(GST_BIN(pipeline), src, mad, pod, sink, NULL); + gst_element_link_many(src, mad, pod, sink, NULL); element_clock = gst_bin_get_clock(GST_BIN(pipeline)); gst_element_set_clock(GST_ELEMENT(pod), element_clock); @@ -106,9 +116,9 @@ setup_gui (void) quit_button = gtk_button_new_with_label("Quit"); for (i = 0; i < NUM_BEATS; i++) - beat_button[i] = gtk_toggle_button_new_with_label(g_strdup_printf("%2d", i)); + beat_button[i] = gtk_toggle_button_new_with_label(g_strdup_printf("%2d", i+1)); - speed_adj = gtk_adjustment_new(1, 0.0, 2, 0.01, 0.1, 0.0); + speed_adj = gtk_adjustment_new(1, 0.0, 10.0, 0.1, 1.0, 0.0); speed_scale = gtk_hscale_new(GTK_ADJUSTMENT(speed_adj)); gtk_scale_set_digits(GTK_SCALE(speed_scale), 4); gtk_range_set_update_policy(GTK_RANGE(speed_scale), GTK_UPDATE_DISCONTINUOUS); @@ -140,19 +150,7 @@ setup_gui (void) g_signal_connect(G_OBJECT(beat_button[i]), "toggled", G_CALLBACK(beat), GUINT_TO_POINTER(i)); /* show the gui. */ - gtk_widget_show(play_button); - gtk_widget_show(clear_button); - gtk_widget_show(reset_button); - gtk_widget_show(quit_button); - - for (i = 0; i < NUM_BEATS; i++) - gtk_widget_show(beat_button[i]); - - gtk_widget_show(beat_box); - gtk_widget_show(button_box); - gtk_widget_show(speed_scale); - gtk_widget_show(vbox); - gtk_widget_show(window); + gtk_widget_show_all(window); gtk_idle_add((GtkFunction)gst_bin_iterate, pipeline); } diff --git a/gst/playondemand/filter.func b/gst/playondemand/filter.func index 038ad119b6..cb5d54ca26 100644 --- a/gst/playondemand/filter.func +++ b/gst/playondemand/filter.func @@ -5,18 +5,23 @@ _TYPE_ *data_in, *data_out, *filter_data; filter_data = (_TYPE_ *) filter->buffer; num_filter = filter->buffer_bytes / sizeof(_TYPE_); -/******************************************************************************/ -/* see if we've got any events coming through ... */ - do { - while (GST_IS_EVENT(in)) { + /****************************************************************************/ + /* see if we've got any events coming through ... */ + + while (! filter->eos && GST_IS_EVENT(in)) { if (GST_EVENT_TYPE(in) == GST_EVENT_EOS) { + gst_event_unref(in); filter->eos = TRUE; } else if ((GST_EVENT_TYPE(in) == GST_EVENT_SEEK) || (GST_EVENT_TYPE(in) == GST_EVENT_FLUSH)) { filter->eos = FALSE; filter->write = 0; } else { + if ((GST_EVENT_TYPE(in) == GST_EVENT_SEEK) || + (GST_EVENT_TYPE(in) == GST_EVENT_FLUSH)) + filter->write = 0; + gst_pad_push(filter->srcpad, in); } @@ -24,76 +29,81 @@ do { } /****************************************************************************/ - /* first handle data from the input buffer. */ + /* handle data from the input buffer. */ - /* only update the input if there hasn't been an eos yet. */ if (! filter->eos) { + register guint j, w = filter->write; + data_in = (_TYPE_ *) GST_BUFFER_DATA(in); num_in = GST_BUFFER_SIZE(in) / sizeof(_TYPE_); - w = filter->write; + for (j = 0; (j < num_in) && (w+j < num_filter); j++) + filter_data[w+j] = data_in[j]; - /* copy the input data to the filter's internal buffer. */ - for (j = 0; (j < num_in) && ((w + j) < num_filter); j++) - filter_data[(w + j) % num_filter] = data_in[j]; + filter->write += j; - filter->write = (w + j) % num_filter; - - if ((w + j) >= num_filter) - filter->eos = TRUE; + if (filter->write >= num_filter) filter->eos = TRUE; out = in; } else { - j = num_filter; - w = 0; - out = gst_buffer_new_from_pool(filter->bufpool, 0, 0); } /****************************************************************************/ - /* check to see if we have to add a new play pointer. */ + /* check to see if we have to add new play pointers. */ if (filter->clock) { - current_tick = ((guint) (gst_clock_get_time(filter->clock) * - filter->clock_speed)) % filter->total_ticks; + register gint t, tick_offset; - if (current_tick != last_tick) { - /* now we go through the tick list and play samples */ - tick_list = filter->tick_list; - while (tick_list) { - tick = GPOINTER_TO_UINT(tick_list->data); - if (current_tick == tick) - play_on_demand_add_play_pointer(filter, 0); - else if (GST_POD_TICK_ELAPSED(tick, current_tick, last_tick)) - play_on_demand_add_play_pointer(filter, GST_POD_SAMPLE_OFFSET(filter, current_tick - tick)); - tick_list = g_slist_next(tick_list); - } - last_tick = current_tick; + guint total_ticks = filter->total_ticks; + guint current_tick = \ + ((guint) (gst_clock_get_time(filter->clock) * filter->tick_rate / + GST_SECOND)) % total_ticks; + + /* for some reason modulo arithmetic isn't working for me here, i suspect + some unsigned/signed voodoo. but it's probably safe to do this with an if + statement since it doesn't happen all that often ... */ + + tick_offset = current_tick - last_tick; + if (tick_offset < 0) tick_offset += total_ticks; + + for (tick_offset -= 1, t = current_tick - tick_offset; + tick_offset >= 0; + tick_offset--, t--) { + + if (t < 0) t += total_ticks; + + if (filter->ticks[t / 32] & (1 << t % 32)) + play_on_demand_add_play_pointer( + filter, filter->rate * tick_offset / filter->tick_rate); } + + last_tick = current_tick; } /****************************************************************************/ - /* now handle output data. */ + /* handle output data. */ - data_out = (_TYPE_ *) GST_BUFFER_DATA(out); - num_out = GST_BUFFER_SIZE(out) / sizeof(_TYPE_); + { + register guint k, p; - for (k = 0; k < num_out; k++) - data_out[k] = zero; + data_out = (_TYPE_ *) GST_BUFFER_DATA(out); + num_out = GST_BUFFER_SIZE(out) / sizeof(_TYPE_); - /* output play pointer data. */ - if (! filter->mute) - for (t = 0; t < filter->max_plays; t++) { - offset = filter->plays[t]; + for (k = 0; k < num_out; k++) data_out[k] = zero; + + for (p = 0; p < filter->max_plays; p++) { + guint offset = filter->plays[p]; if (offset != G_MAXUINT) { - for (k = 0; (k < num_out) && (offset + k < num_filter); k++) - data_out[k] = CLAMP(data_out[k] + filter_data[offset + k], min, max); - if ((offset + k) == num_filter) - filter->plays[t] = G_MAXUINT; - else - filter->plays[t] = offset + k; + /* only copy audio data if the element's not muted. */ + if (! filter->mute) + for (k = 0; (k < num_out) && (offset+k < num_filter); k++) + data_out[k] = CLAMP(data_out[k] + filter_data[offset+k], min, max); + + /* update the play pointer. k > 0 even if the filter is muted. */ + filter->plays[p] = (offset+k >= num_filter) ? G_MAXUINT : offset + k; } } @@ -102,9 +112,8 @@ do { gst_pad_push(filter->srcpad, out); - if (! filter->eos) - in = gst_pad_pull(filter->sinkpad); + in = (! filter->eos) ? gst_pad_pull(filter->sinkpad) : NULL; - gst_element_interrupt (GST_ELEMENT (filter)); + if (gst_element_interrupt (GST_ELEMENT (filter))) break; } while (TRUE); diff --git a/gst/playondemand/gstplayondemand.c b/gst/playondemand/gstplayondemand.c index b108bec201..2d8832349b 100644 --- a/gst/playondemand/gstplayondemand.c +++ b/gst/playondemand/gstplayondemand.c @@ -24,11 +24,14 @@ #include "gstplayondemand.h" +/* in these files, a 'tick' is a discrete unit of time, usually around the 1ms + * range. a tick is not divisible into smaller units of time. 1ms is probably + * way beyond what a real computer can actually keep track of, but hey ... */ /* some default values */ #define GST_POD_MAX_PLAYS 100 /* maximum simultaneous plays */ #define GST_POD_BUFFER_TIME 5.0 /* buffer length in seconds */ -#define GST_POD_CLOCK_SPEED 1e-8 /* 0.1 sec/tick default */ +#define GST_POD_TICK_RATE 1e-6 /* ticks per second */ /* buffer pool fallback values ... use if no buffer pool is available */ #define GST_POD_BUFPOOL_SIZE 4096 @@ -88,6 +91,7 @@ static void play_on_demand_class_init (GstPlayOnDemandClass *klass); static void play_on_demand_init (GstPlayOnDemand *filter); static void play_on_demand_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void play_on_demand_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void play_on_demand_dispose (GObject *object); /* GStreamer functionality */ static GstBufferPool* play_on_demand_get_bufferpool (GstPad *pad); @@ -144,9 +148,9 @@ enum { PROP_MUTE, PROP_BUFFER_TIME, PROP_MAX_PLAYS, - PROP_CLOCK_SPEED, + PROP_TICK_RATE, PROP_TOTAL_TICKS, - PROP_TICK_LIST, + PROP_TICKS, }; static guint gst_pod_filter_signals[LAST_SIGNAL] = { 0 }; @@ -163,40 +167,24 @@ play_on_demand_class_init (GstPlayOnDemandClass *klass) gstelement_class = (GstElementClass *) klass; gst_pod_filter_signals[PLAYED_SIGNAL] = - g_signal_new("played", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, + g_signal_new("played", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GstPlayOnDemandClass, played), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gst_pod_filter_signals[PLAY_SIGNAL] = - g_signal_new("play", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, + g_signal_new("play", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GstPlayOnDemandClass, play), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gst_pod_filter_signals[CLEAR_SIGNAL] = - g_signal_new("clear", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, + g_signal_new("clear", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GstPlayOnDemandClass, clear), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gst_pod_filter_signals[RESET_SIGNAL] = - g_signal_new("reset", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, + g_signal_new("reset", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GstPlayOnDemandClass, reset), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); klass->play = play_on_demand_play_handler; klass->clear = play_on_demand_clear_handler; @@ -206,45 +194,33 @@ play_on_demand_class_init (GstPlayOnDemandClass *klass) gobject_class->set_property = play_on_demand_set_property; gobject_class->get_property = play_on_demand_get_property; + gobject_class->dispose = play_on_demand_dispose; gstelement_class->set_clock = play_on_demand_set_clock; g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_MUTE, - g_param_spec_boolean("mute", "Silence output", - "Do not output any sound", - FALSE, G_PARAM_READWRITE)); - + g_param_spec_boolean("mute", "Silence output", "Do not output any sound", + FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_BUFFER_TIME, - g_param_spec_float("buffer-time", "Buffer length in seconds", - "Number of seconds of audio the buffer holds", - 0.0, G_MAXUINT - 2, GST_POD_BUFFER_TIME, G_PARAM_READWRITE)); - + g_param_spec_float("buffer-time", "Buffer length in seconds", "Number of seconds of audio the buffer holds", + 0.0, G_MAXUINT / GST_AUDIO_MAX_RATE - 10, GST_POD_BUFFER_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_MAX_PLAYS, - g_param_spec_uint("plays", "Maximum simultaneous playback", - "Maximum allowed number of simultaneous plays from the buffer", - 1, G_MAXUINT, GST_POD_MAX_PLAYS, G_PARAM_READWRITE)); - - g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_CLOCK_SPEED, - g_param_spec_float("clock-speed", "Clock speed (ticks/second)", - "The relative speed of a musical tick", - 0, G_MAXFLOAT, 1, G_PARAM_READWRITE)); - + g_param_spec_uint("max-plays", "Maximum simultaneous playbacks", "Maximum allowed number of simultaneous plays from the buffer", + 1, G_MAXUINT, GST_POD_MAX_PLAYS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TICK_RATE, + g_param_spec_float("tick-rate", "Tick rate (ticks/second)", "The rate of musical ticks, the smallest time unit in a song", + 0, G_MAXFLOAT, GST_POD_TICK_RATE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TOTAL_TICKS, - g_param_spec_uint("total-ticks", "Total number of ticks", - "Total number of ticks (only relevant for tick lists)", - 1, G_MAXUINT, 1, G_PARAM_READWRITE)); - - g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TICK_LIST, - g_param_spec_pointer("tick-list", "List of ticks to play", - "A list of ticks (musical times) at which to play the sample", - G_PARAM_WRITABLE)); + g_param_spec_uint("total-ticks", "Total number of ticks", "Total number of ticks in the tick array", + 1, G_MAXUINT, 1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TICKS, + g_param_spec_pointer("ticks", "Ticks to play sample on", "An array of ticks (musical times) at which to play the sample", + G_PARAM_READWRITE)); } static void play_on_demand_init (GstPlayOnDemand *filter) { - guint i; - filter->srcpad = gst_pad_new_from_template(play_on_demand_src_factory(), "src"); filter->sinkpad = gst_pad_new_from_template(play_on_demand_sink_factory(), "sink"); @@ -258,23 +234,14 @@ play_on_demand_init (GstPlayOnDemand *filter) filter->clock = NULL; - /* filter properties */ - filter->mute = FALSE; - filter->buffer_time = GST_POD_BUFFER_TIME; - filter->max_plays = GST_POD_MAX_PLAYS; - filter->clock_speed = GST_POD_CLOCK_SPEED; - filter->total_ticks = 1; - filter->tick_list = NULL; + filter->rate = 0; + + filter->ticks = g_new(guint32, filter->total_ticks / 32 + 1); + filter->plays = g_new(guint, filter->max_plays); - /* internal buffer stuff */ play_on_demand_resize_buffer(filter); - filter->eos = FALSE; - - /* play pointers, stored as an array of buffer offsets */ - filter->write = 0; - filter->plays = g_new(guint, filter->max_plays); - for (i = 0; i < filter->max_plays; i++) - filter->plays[i] = G_MAXUINT; + play_on_demand_clear_handler(GST_ELEMENT(filter)); + play_on_demand_reset_handler(GST_ELEMENT(filter)); } static void @@ -284,6 +251,7 @@ play_on_demand_set_property (GObject *object, guint prop_id, GstPlayOnDemand *filter; register guint i; guint new_size, min_size, *new_plays; + guint *new_ticks; g_return_if_fail(GST_IS_PLAYONDEMAND(object)); filter = GST_PLAYONDEMAND(object); @@ -296,10 +264,9 @@ play_on_demand_set_property (GObject *object, guint prop_id, filter->buffer_time = g_value_get_float(value); play_on_demand_resize_buffer(filter); - /* clear out now-invalid play pointers, if there are any. */ + /* clear out now-invalid play pointers */ for (i = 0; i < filter->max_plays; i++) - if (filter->plays[i] > filter->buffer_bytes) - filter->plays[i] = G_MAXUINT; + filter->plays[i] = G_MAXUINT; break; case PROP_MAX_PLAYS: @@ -308,21 +275,35 @@ play_on_demand_set_property (GObject *object, guint prop_id, new_plays = g_new(guint, new_size); for (i = 0; i < min_size; i++) new_plays[i] = filter->plays[i]; - for (i = min_size; i < filter->max_plays; i++) new_plays[i] = G_MAXUINT; + for (i = min_size; i < new_size; i++) new_plays[i] = G_MAXUINT; g_free(filter->plays); filter->plays = new_plays; filter->max_plays = new_size; break; - case PROP_CLOCK_SPEED: - filter->clock_speed = g_value_get_float(value); + case PROP_TICK_RATE: + filter->tick_rate = g_value_get_float(value); break; case PROP_TOTAL_TICKS: - filter->total_ticks = g_value_get_uint(value); + new_size = g_value_get_uint(value); + min_size = (new_size < filter->total_ticks) ? new_size : filter->total_ticks; + + new_ticks = g_new(guint32, new_size / 32 + 1); + for (i = 0; i <= min_size / 32; i++) new_ticks[i] = filter->ticks[i]; + for (i = min_size / 32 + 1; i <= new_size / 32; i++) new_ticks[i] = 0; + + g_free(filter->ticks); + filter->ticks = new_ticks; + filter->total_ticks = new_size; + break; - case PROP_TICK_LIST: - filter->tick_list = (GSList *) g_value_get_pointer(value); + case PROP_TICKS: + new_ticks = (guint *) g_value_get_pointer(value); + if (new_ticks) { + g_free(filter->ticks); + filter->ticks = new_ticks; + } break; default: break; @@ -348,18 +329,33 @@ play_on_demand_get_property (GObject *object, guint prop_id, case PROP_MAX_PLAYS: g_value_set_uint(value, filter->max_plays); break; - case PROP_CLOCK_SPEED: - g_value_set_float(value, filter->clock_speed); + case PROP_TICK_RATE: + g_value_set_float(value, filter->tick_rate); break; case PROP_TOTAL_TICKS: g_value_set_uint(value, filter->total_ticks); break; + case PROP_TICKS: + g_value_set_pointer(value, (gpointer) filter->ticks); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } +static void +play_on_demand_dispose (GObject *object) +{ + GstPlayOnDemand *filter = GST_PLAYONDEMAND (object); + + G_OBJECT_CLASS (parent_class)->dispose (object); + + g_free (filter->ticks); + g_free (filter->plays); + g_free (filter->buffer); +} + static GstBufferPool* play_on_demand_get_bufferpool (GstPad *pad) { @@ -380,7 +376,7 @@ play_on_demand_pad_link (GstPad *pad, GstCaps *caps) filter = GST_PLAYONDEMAND(GST_PAD_PARENT(pad)); gst_caps_get_string(caps, "format", &format); - gst_caps_get_int(caps, "rate", &filter->rate); + gst_caps_get_int(caps, "rate", &filter->rate); gst_caps_get_int(caps, "channels", &filter->channels); if (strcmp(format, "int") == 0) { @@ -397,21 +393,22 @@ play_on_demand_pad_link (GstPad *pad, GstCaps *caps) return GST_PAD_LINK_DELAYED; } -/* clock check macros. in these macros, - f == filter - t == tick in question - c == current tick (from the clock) - l == last tick (last tick when clock was checked) - dt == ticks between c and t */ -#define GST_POD_SAMPLE_OFFSET(f, dt) \ - ((guint) (dt * (f)->rate / (f)->clock_speed)) +inline static void +play_on_demand_add_play_pointer (GstPlayOnDemand *filter, guint pos) +{ + register guint i; -/* play a sample if the tick in question came between the last time we checked - the clock and the current clock time. only looks complicated because the last - clock time could have been at the end of the total_ticks, so the clock might - have wrapped around ... */ -#define GST_POD_TICK_ELAPSED(t, c, l) \ - (((l < c) && (l < t) && (t < c)) || ((l > c) && ((l < t) || (t < c)))) + if (filter->rate && ((filter->buffer_time * filter->rate) > pos)) { + for (i = 0; i < filter->max_plays; i++) { + if (filter->plays[i] == G_MAXUINT) { + filter->plays[i] = pos; + /* emit a signal to indicate a sample being played */ + g_signal_emit(filter, gst_pod_filter_signals[PLAYED_SIGNAL], 0); + break; + } + } + } +} static void play_on_demand_loop (GstElement *elem) @@ -419,37 +416,30 @@ play_on_demand_loop (GstElement *elem) GstPlayOnDemand *filter = GST_PLAYONDEMAND(elem); guint num_in, num_out, num_filter; GstBuffer *in, *out; - register guint j, k, t; - guint w, offset; - - /* variables for clock check. */ static guint last_tick = 0; - GSList *tick_list; - guint tick, current_tick; g_return_if_fail(filter != NULL); g_return_if_fail(GST_IS_PLAYONDEMAND(filter)); filter->bufpool = gst_pad_get_bufferpool(filter->srcpad); - if (filter->bufpool == NULL) { + if (filter->bufpool == NULL) filter->bufpool = gst_buffer_pool_get_default(GST_POD_BUFPOOL_SIZE, GST_POD_BUFPOOL_NUM); - } in = gst_pad_pull(filter->sinkpad); if (filter->format == GST_PLAYONDEMAND_FORMAT_INT) { if (filter->width == 16) { - gint16 min = -32768; - gint16 max = 32767; + gint16 min = 0xffff; + gint16 max = 0x7fff; gint16 zero = 0; #define _TYPE_ gint16 #include "filter.func" #undef _TYPE_ } else if (filter->width == 8) { - gint8 min = -128; - gint8 max = 127; + gint8 min = 0xff; + gint8 max = 0x7f; gint8 zero = 0; #define _TYPE_ gint8 #include "filter.func" @@ -493,6 +483,7 @@ static void play_on_demand_clear_handler (GstElement *elem) { GstPlayOnDemand *filter; + register guint i; g_return_if_fail(elem != NULL); g_return_if_fail(GST_IS_PLAYONDEMAND(elem)); @@ -500,6 +491,9 @@ play_on_demand_clear_handler (GstElement *elem) filter->write = 0; filter->eos = FALSE; + + for (i = 0; i < filter->max_plays; i++) filter->plays[i] = G_MAXUINT; + for (i = 0; i < filter->buffer_bytes; i++) filter->buffer[i] = 0; } static void @@ -508,39 +502,21 @@ play_on_demand_reset_handler (GstElement *elem) GstPlayOnDemand *filter; register guint i; + play_on_demand_clear_handler (elem); + g_return_if_fail(elem != NULL); g_return_if_fail(GST_IS_PLAYONDEMAND(elem)); filter = GST_PLAYONDEMAND(elem); - for (i = 0; i < filter->max_plays; i++) { - filter->plays[i] = G_MAXUINT; - } - - filter->write = 0; - filter->eos = FALSE; -} - -static void -play_on_demand_add_play_pointer (GstPlayOnDemand *filter, guint pos) -{ - register guint i; - - if (filter->rate && ((filter->buffer_time * filter->rate) > pos)) - for (i = 0; i < filter->max_plays; i++) - if (filter->plays[i] == G_MAXUINT) { - filter->plays[i] = pos; - /* emit a signal to indicate a sample being played */ - g_signal_emit(filter, gst_pod_filter_signals[PLAYED_SIGNAL], 0); - return; - } + for (i = 0; i <= filter->total_ticks / 32; i++) filter->ticks[i] = 0; } static void play_on_demand_resize_buffer (GstPlayOnDemand *filter) { - register guint i; - guint new_size, min_size; - gchar *new_buffer; + register guint i; + guint new_size, min_size; + gchar *new_buffer; /* use a default sample rate of 44100, 1 channel, 1 byte per sample if caps haven't been set yet */ @@ -557,7 +533,7 @@ play_on_demand_resize_buffer (GstPlayOnDemand *filter) new_buffer = g_new(gchar, new_size); for (i = 0; i < min_size; i++) new_buffer[i] = filter->buffer[i]; - for (i = min_size; i < filter->buffer_bytes; i++) new_buffer[i] = 0; + for (i = min_size; i < new_size; i++) new_buffer[i] = 0; g_free(filter->buffer); filter->buffer = new_buffer; diff --git a/gst/playondemand/gstplayondemand.h b/gst/playondemand/gstplayondemand.h index b48d6c8a7e..893d77a20f 100644 --- a/gst/playondemand/gstplayondemand.h +++ b/gst/playondemand/gstplayondemand.h @@ -63,9 +63,9 @@ struct _GstPlayOnDemand { gboolean mute; gfloat buffer_time; guint max_plays; - gfloat clock_speed; + gfloat tick_rate; guint total_ticks; - GSList *tick_list; + guint32 *ticks; /* internal buffer info */ gchar *buffer;