static bool upipe_dveo_asi_sink_write(struct upipe *upipe, struct uref *uref, bool *reset_first_timestamp) { struct upipe_dveo_asi_sink *upipe_dveo_asi_sink = upipe_dveo_asi_sink_from_upipe(upipe); for (;;) { int iovec_count = uref_block_iovec_count(uref, 0, -1); if (unlikely(iovec_count == -1)) { upipe_warn(upipe, "cannot read ubuf buffer"); break; } if (unlikely(iovec_count == 0)) { break; } struct iovec iovecs[iovec_count]; if (unlikely(!ubase_check(uref_block_iovec_read(uref, 0, -1, iovecs)))) { upipe_warn(upipe, "cannot read ubuf buffer"); break; } ssize_t ret = writev(upipe_dveo_asi_sink->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_notice_va(upipe, "polling"); upipe_dveo_asi_sink_poll(upipe); return false; default: break; } upipe_warn_va(upipe, "write error to device %d (%m)", upipe_dveo_asi_sink->card_idx); upipe_dveo_asi_sink_set_upump(upipe, NULL); upipe_throw_sink_end(upipe); break; } size_t uref_size; if (ubase_check(uref_block_size(uref, &uref_size)) && uref_size == ret) { /* wrote succeeded */ *reset_first_timestamp = false; break; } uref_block_resize(uref, ret, -1); } return true; }
/** @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; }