| /* -*- C -*- */ |
| |
| _TYPE_ *data_in, *data_out, *filter_data; |
| |
| filter_data = (_TYPE_ *) filter->buffer; |
| num_filter = filter->buffer_bytes / sizeof(_TYPE_); |
| |
| do { |
| /****************************************************************************/ |
| /* 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); |
| } |
| |
| in = gst_pad_pull(filter->sinkpad); |
| } |
| |
| /****************************************************************************/ |
| /* handle data from the input buffer. */ |
| |
| if (! filter->eos) { |
| register guint j, w = filter->write; |
| |
| data_in = (_TYPE_ *) GST_BUFFER_DATA(in); |
| num_in = GST_BUFFER_SIZE(in) / sizeof(_TYPE_); |
| |
| for (j = 0; (j < num_in) && (w+j < num_filter); j++) |
| filter_data[w+j] = data_in[j]; |
| |
| filter->write += j; |
| |
| if (filter->write >= num_filter) filter->eos = TRUE; |
| |
| out = in; |
| } else { |
| out = gst_buffer_new_from_pool(filter->bufpool, 0, 0); |
| } |
| |
| /****************************************************************************/ |
| /* check to see if we have to add new play pointers. */ |
| |
| if (filter->clock) { |
| register gint t, tick_offset; |
| |
| 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; |
| } |
| |
| /****************************************************************************/ |
| /* handle output data. */ |
| |
| { |
| register guint k, p; |
| |
| data_out = (_TYPE_ *) GST_BUFFER_DATA(out); |
| num_out = GST_BUFFER_SIZE(out) / sizeof(_TYPE_); |
| |
| 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) { |
| |
| /* 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; |
| } |
| } |
| |
| /****************************************************************************/ |
| /* push out the buffer. */ |
| |
| gst_pad_push(filter->srcpad, out); |
| |
| in = (! filter->eos) ? gst_pad_pull(filter->sinkpad) : NULL; |
| |
| if (gst_element_interrupt (GST_ELEMENT (filter))) break; |
| |
| } while (TRUE); |