コード例 #1
0
ファイル: upipe_void_source.c プロジェクト: cmassiot/upipe
/** @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);
}
コード例 #2
0
ファイル: upipe_file_sink.c プロジェクト: marcinklimek/upipe
/** @internal @This outputs data to the file sink.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to pump that generated the buffer
 * @return true if the uref was processed
 */
static bool upipe_fsink_output(struct upipe *upipe, struct uref *uref,
                               struct upump **upump_p)
{
    struct upipe_fsink *upipe_fsink = upipe_fsink_from_upipe(upipe);
    const char *def;
    if (unlikely(ubase_check(uref_flow_get_def(uref, &def)))) {
        uint64_t latency = 0;
        uref_clock_get_latency(uref, &latency);
        if (latency > upipe_fsink->latency)
            upipe_fsink->latency = latency;
        uref_free(uref);
        return true;
    }

    if (unlikely(upipe_fsink->fd == -1)) {
        uref_free(uref);
        upipe_warn(upipe, "received a buffer before opening a file");
        return true;
    }

    if (likely(upipe_fsink->uclock == NULL))
        goto write_buffer;

    uint64_t cr_sys = 0;
    if (unlikely(!ubase_check(uref_clock_get_cr_sys(uref, &cr_sys)))) {
        upipe_warn(upipe, "received non-dated buffer");
        goto write_buffer;
    }

    uint64_t now = uclock_now(upipe_fsink->uclock);
    cr_sys += upipe_fsink->latency;
    if (unlikely(now < cr_sys)) {
        upipe_fsink_wait_upump(upipe, cr_sys - now, upipe_fsink_watcher);
        return false;
    }

write_buffer:
    for ( ; ; ) {
        int iovec_count = uref_block_iovec_count(uref, 0, -1);
        if (unlikely(iovec_count == -1)) {
            uref_free(uref);
            upipe_warn(upipe, "cannot read ubuf buffer");
            break;
        }
        if (unlikely(iovec_count == 0)) {
            uref_free(uref);
            break;
        }

        struct iovec iovecs[iovec_count];
        if (unlikely(!ubase_check(uref_block_iovec_read(uref, 0, -1,
                                                        iovecs)))) {
            uref_free(uref);
            upipe_warn(upipe, "cannot read ubuf buffer");
            break;
        }

        ssize_t ret = writev(upipe_fsink->fd, iovecs, iovec_count);
        uref_block_iovec_unmap(uref, 0, -1, iovecs);

        if (unlikely(ret == -1)) {
            switch (errno) {
                case EINTR:
                    continue;
                case EAGAIN:
#if EAGAIN != EWOULDBLOCK
                case EWOULDBLOCK:
#endif
                    upipe_fsink_poll(upipe);
                    return false;
                case EBADF:
                case EFBIG:
                case EINVAL:
                case EIO:
                case ENOSPC:
                case EPIPE:
                default:
                    break;
            }
            uref_free(uref);
            upipe_warn_va(upipe, "write error to %s (%m)", upipe_fsink->path);
            upipe_fsink_set_upump(upipe, NULL);
            upipe_throw_sink_end(upipe);
            return true;
        }

        size_t uref_size;
        if (ubase_check(uref_block_size(uref, &uref_size)) &&
            uref_size == ret) {
            uref_free(uref);
            break;
        }
        uref_block_resize(uref, ret, -1);
    }
    return true;
}
コード例 #3
0
ファイル: upipe_nacl_audio.c プロジェクト: digideskio/upipe
/** @internal @This is called back to fill NaCl audio buffer.
 * Please note that this function runs in a different thread.
 *
 * @param sample_buffer buffer to fill
 * @param buffer_size size of the buffer in octets
 * @param latency how long before the audio data is to be presented
 * @param user_data opaque pointing to the pipe
 */
static void upipe_nacl_audio_worker(void *sample_buffer, uint32_t buffer_size,
                                    PP_TimeDelta latency, void *user_data)
{
    struct upipe *upipe = (struct upipe *)user_data;
    struct upipe_nacl_audio *upipe_nacl_audio =
        upipe_nacl_audio_from_upipe(upipe);
    uint64_t next_pts = UINT64_MAX;

    if (likely(upipe_nacl_audio->uclock != NULL)) {
        /* This is slightly off. */
        next_pts = uclock_now(upipe_nacl_audio->uclock) +
                   (uint64_t)(latency * UCLOCK_FREQ);
    }

    uint32_t frames = buffer_size / 4;

    while (frames > 0) {
        if (upipe_nacl_audio->uref == NULL)
            upipe_nacl_audio->uref = uqueue_pop(&upipe_nacl_audio->uqueue,
                                                struct uref *);
        if (unlikely(upipe_nacl_audio->uref == NULL)) {
            upipe_dbg_va(upipe, "playing %u frames of silence (empty)", frames);
            memset(sample_buffer, 0, frames * 4);
            break;
        }

        struct uref *uref = upipe_nacl_audio->uref;
        if (next_pts != UINT64_MAX) {
            uint64_t uref_pts;
            if (unlikely(!ubase_check(uref_clock_get_pts_sys(uref,
                                &uref_pts)))) {
                upipe_nacl_audio->uref = NULL;
                uref_free(uref);
                upipe_warn(upipe, "non-dated uref received");
                continue;
            }

            int64_t tolerance = uref_pts - next_pts;
            if (tolerance > (int64_t)PTS_TOLERANCE) {
                uint32_t silence_frames =
                    tolerance * SAMPLE_RATE / UCLOCK_FREQ;
                if (silence_frames > frames)
                    silence_frames = frames;
                upipe_dbg_va(upipe, "playing %u frames of silence (wait)",
                             silence_frames);
                memset(sample_buffer, 0, silence_frames * 4);
                sample_buffer += silence_frames * 4;
                frames -= silence_frames;
                continue;
            } else if (-tolerance > (int64_t)PTS_TOLERANCE) {
                uint32_t dropped_frames =
                    (-tolerance) * SAMPLE_RATE / UCLOCK_FREQ;
                upipe_warn_va(upipe, "late buffer received, dropping %u frames",
                              dropped_frames);
                upipe_nacl_audio_consume(upipe, dropped_frames);
                continue;
            }
        }

        size_t size;
        const void *uref_buffer;
        if (unlikely(!ubase_check(uref_sound_size(uref, &size, NULL)) ||
                     !ubase_check(uref_sound_plane_read_void(uref, "lr", 0, -1,
                                                             &uref_buffer)))) {
            upipe_nacl_audio->uref = NULL;
            uref_free(uref);
            upipe_warn(upipe, "cannot read ubuf buffer");
            continue;
        }

        uint32_t copied_frames = size < frames ? size : frames;
        memcpy(sample_buffer, uref_buffer, copied_frames * 4);
        uref_sound_plane_unmap(uref, "lr", 0, -1);
        sample_buffer += copied_frames * 4;

        upipe_nacl_audio_consume(upipe, copied_frames);
        frames -= copied_frames;
    }
}