/** @internal @This creates regularly empty urefs. * * @param upump description structure of the timer */ static void upipe_voidsrc_worker(struct upump *upump) { struct upipe *upipe = upump_get_opaque(upump, struct upipe *); struct upipe_voidsrc *upipe_voidsrc = upipe_voidsrc_from_upipe(upipe); uint64_t now; if (upipe_voidsrc->pts == UINT64_MAX) upipe_voidsrc->pts = uclock_now(upipe_voidsrc->uclock); for (now = uclock_now(upipe_voidsrc->uclock); !upipe_single(upipe) && upipe_voidsrc->pts <= now; now = uclock_now(upipe_voidsrc->uclock)) { struct uref *uref = uref_alloc(upipe_voidsrc->uref_mgr); if (unlikely(!uref)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } uref_clock_set_duration(uref, upipe_voidsrc->interval); uref_clock_set_pts_sys(uref, upipe_voidsrc->pts); uref_clock_set_pts_prog(uref, upipe_voidsrc->pts); upipe_voidsrc->pts += upipe_voidsrc->interval; upipe_voidsrc_output(upipe, uref, &upipe_voidsrc->timer); } if (!upipe_single(upipe)) upipe_voidsrc_wait_timer(upipe, upipe_voidsrc->pts - now, upipe_voidsrc_worker); }
/** @internal @This is called to consume frames out of the first buffered uref. * * @param upipe description structure of the pipe * @param frames number of frames to consume */ static void upipe_nacl_audio_consume(struct upipe *upipe, uint32_t frames) { struct upipe_nacl_audio *upipe_nacl_audio = upipe_nacl_audio_from_upipe(upipe); struct uref *uref = upipe_nacl_audio->uref; assert(uref != NULL); size_t uref_size; if (ubase_check(uref_sound_size(uref, &uref_size, NULL)) && uref_size <= frames) { upipe_nacl_audio->uref = NULL; uref_free(uref); } else { uref_sound_resize(uref, frames, -1); uint64_t pts; if (ubase_check(uref_clock_get_pts_sys(uref, &pts))) uref_clock_set_pts_sys(uref, pts + frames * UCLOCK_FREQ / SAMPLE_RATE); /* We should also change the duration but we don't use it. */ } }
/** @internal @This inputs data. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_nacl_audio_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_nacl_audio *upipe_nacl_audio = upipe_nacl_audio_from_upipe(upipe); size_t uref_size; if (unlikely(!ubase_check(uref_sound_size(uref, &uref_size, NULL)))) { upipe_warn(upipe, "unable to read uref"); uref_free(uref); return; } if (unlikely(!upipe_nacl_audio->started && !upipe_nacl_audio_open(upipe))) { upipe_warn(upipe, "unable to open device"); uref_free(uref); return; } uint64_t uref_pts; if (likely(ubase_check(uref_clock_get_pts_sys(uref, &uref_pts)))) { uref_pts += upipe_nacl_audio->latency; uref_clock_set_pts_sys(uref, uref_pts); } if (!upipe_nacl_audio_check_input(upipe)) { upipe_nacl_audio_hold_input(upipe, uref); upipe_nacl_audio_block_input(upipe, upump_p); } else if (!upipe_nacl_audio_handle(upipe, uref, upump_p)) { if (!upipe_nacl_audio_check_watcher(upipe)) { upipe_warn(upipe, "unable to spool uref"); uref_free(uref); return; } upipe_nacl_audio_hold_input(upipe, uref); upipe_nacl_audio_block_input(upipe, upump_p); upump_start(upipe_nacl_audio->upump); } }