/** @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; }
/** @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_dveo_asi_sink_output(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_dveo_asi_sink *upipe_dveo_asi_sink = upipe_dveo_asi_sink_from_upipe(upipe); const char *def; if (unlikely(ubase_check(uref_flow_get_def(uref, &def)))) { uref_free(uref); return true; } int fd = upipe_dveo_asi_sink->fd; if (unlikely(fd == -1)) { upipe_warn(upipe, "received a buffer before opening the device"); uref_free(uref); return true; } uint64_t cr_sys = 0; if (unlikely(!ubase_check(uref_clock_get_cr_sys(uref, &cr_sys))) || cr_sys == -1) { upipe_warn(upipe, "received non-dated buffer"); uref_free(uref); return true; } if (ubase_check(uref_flow_get_discontinuity(uref))) { upipe_warn_va(upipe, "DISCONTINUITY, resetting timestamp"); upipe_dveo_asi_sink->first_timestamp = true; } if (unlikely(upipe_dveo_asi_sink->first_timestamp)) { int val; if (ioctl(fd, ASI_IOC_TXGETTXD, &val) < 0) { upipe_err_va(upipe, "ioctl TXGETTXDfailed (%m)"); upipe_throw_fatal(upipe, UBASE_ERR_UNKNOWN); uref_free(uref); return true; } else if (val) { upipe_warn(upipe, "Waiting for transmission to stop"); uref_free(uref); return true; } } /* Make sure we set the counter */ bool reset_first_timestamp = upipe_dveo_asi_sink->first_timestamp; if (upipe_dveo_asi_sink_add_header(upipe, uref, cr_sys)) { uref_free(uref); return true; /* invalid uref, discarded */ } if (!upipe_dveo_asi_sink_write(upipe, uref, &reset_first_timestamp)) return false; /* would block */ uref_free(uref); if (reset_first_timestamp) upipe_dveo_asi_sink->first_timestamp = true; upipe_dveo_asi_sink_stats(upipe); return true; }