static u32 gf_ar_fill_output(void *ptr, char *buffer, u32 buffer_size) { u32 written; GF_AudioRenderer *ar = (GF_AudioRenderer *) ptr; if (!ar->need_reconfig) { u32 delay_ms = ar->disable_resync ? 0 : ar->audio_delay; if (ar->filter_chain.enable_filters) { char *ptr = buffer; u32 res = buffer_size; written = 0; delay_ms += ar->filter_chain.delay_ms; while (buffer_size) { u32 to_copy; if (!ar->nb_used) { u32 nb_bytes; /*fill input block*/ nb_bytes = gf_mixer_get_output(ar->mixer, ar->filter_chain.tmp_block1, ar->filter_chain.min_block_size, delay_ms); if (!nb_bytes) return written; /*delay used to check for late frames - we only use it on the first call to gf_mixer_get_output()*/ delay_ms = 0; ar->nb_filled = gf_afc_process(&ar->filter_chain, nb_bytes); if (!ar->nb_filled) continue; } to_copy = ar->nb_filled - ar->nb_used; if (to_copy>buffer_size) to_copy = buffer_size; memcpy(ptr, ar->filter_chain.tmp_block1 + ar->nb_used, to_copy); ptr += to_copy; buffer_size -= to_copy; written += to_copy; ar->nb_used += to_copy; if (ar->nb_used==ar->nb_filled) ar->nb_used = 0; } assert(res==written); } else { written = gf_mixer_get_output(ar->mixer, buffer, buffer_size, delay_ms); } if (ar->audio_listeners) { u32 k=0; GF_AudioListener *l; while ((l = gf_list_enum(ar->audio_listeners, &k))) { l->on_audio_frame(l->udta, buffer, written, gf_sc_ar_get_clock(ar), delay_ms); } } return written; } return 0; }
static char *audiobuffer_fetch_frame(void *callback, u32 *size, u32 audio_delay_ms) { u32 blockAlign; AudioBufferStack *st = (AudioBufferStack *) gf_node_get_private( ((GF_AudioInput *) callback)->owner); M_AudioBuffer *ab = (M_AudioBuffer*)st->output.owner; if (!st->is_init) return NULL; if (!st->buffer) { st->done = 0; st->buffer_size = (u32) ceil(FIX2FLT(ab->length) * st->output.input_ifce.bps*st->output.input_ifce.samplerate*st->output.input_ifce.chan/8); blockAlign = gf_mixer_get_block_align(st->am); /*BLOCK ALIGN*/ while (st->buffer_size%blockAlign) st->buffer_size++; st->buffer = (char*)gf_malloc(sizeof(char) * st->buffer_size); memset(st->buffer, 0, sizeof(char) * st->buffer_size); st->read_pos = st->write_pos = 0; } if (st->done) return NULL; /*even if not active, fill the buffer*/ if (st->write_pos < st->buffer_size) { u32 written; while (1) { /*just try to completely fill it*/ written = gf_mixer_get_output(st->am, st->buffer + st->write_pos, st->buffer_size - st->write_pos, 0); if (!written) break; st->write_pos += written; assert(st->write_pos<=st->buffer_size); } } /*not playing*/ if (! ab->isActive) return NULL; *size = st->write_pos - st->read_pos; return st->buffer + st->read_pos; }
static u32 gf_ar_fill_output(void *ptr, char *buffer, u32 buffer_size) { u32 written; GF_AudioRenderer *ar = (GF_AudioRenderer *) ptr; if (!ar->need_reconfig) { u32 delay_ms = ar->disable_resync ? 0 : ar->audio_delay; if (ar->Frozen) { memset(buffer, 0, buffer_size); return buffer_size; } gf_mixer_lock(ar->mixer, GF_TRUE); if (ar->filter_chain.enable_filters) { char *ptr = buffer; written = 0; delay_ms += ar->filter_chain.delay_ms; while (buffer_size) { u32 to_copy; if (!ar->nb_used) { u32 nb_bytes; /*fill input block*/ nb_bytes = gf_mixer_get_output(ar->mixer, ar->filter_chain.tmp_block1, ar->filter_chain.min_block_size, delay_ms); if (!nb_bytes) return written; /*delay used to check for late frames - we only use it on the first call to gf_mixer_get_output()*/ delay_ms = 0; ar->nb_filled = gf_afc_process(&ar->filter_chain, nb_bytes); if (!ar->nb_filled) continue; } to_copy = ar->nb_filled - ar->nb_used; if (to_copy>buffer_size) to_copy = buffer_size; memcpy(ptr, ar->filter_chain.tmp_block1 + ar->nb_used, to_copy); ptr += to_copy; buffer_size -= to_copy; written += to_copy; ar->nb_used += to_copy; if (ar->nb_used==ar->nb_filled) ar->nb_used = 0; } } else { written = gf_mixer_get_output(ar->mixer, buffer, buffer_size, delay_ms); } gf_mixer_lock(ar->mixer, GF_FALSE); //done with one sim step, go back in pause if (ar->step_mode) { ar->step_mode = GF_FALSE; gf_ar_pause(ar, GF_TRUE, GF_FALSE, GF_FALSE); } if (!ar->need_reconfig) { if (ar->audio_listeners) { u32 k=0; GF_AudioListener *l; while ((l = (GF_AudioListener*)gf_list_enum(ar->audio_listeners, &k))) { l->on_audio_frame(l->udta, buffer, buffer_size, gf_sc_ar_get_clock(ar), delay_ms); } } ar->bytes_requested += buffer_size; ar->current_time = ar->time_at_last_config + (u32) (ar->bytes_requested * 1000 / ar->bytes_per_second); } //always return buffer size (eg requested input size to be filled), since the clock is always increased by buffer_size (cf above line) return buffer_size; } return 0; }