/** helper phony pipe */ static void test_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct x264_test *x264_test = x264_test_from_upipe(upipe); uint64_t pts = 0, dts = 0; if (uref->udict != NULL) { udict_dump(uref->udict, upipe->uprobe); } if (!ubase_check(uref_clock_get_pts_prog(uref, &pts))) { upipe_warn(upipe, "received packet with no pts"); } if (!ubase_check(uref_clock_get_dts_prog(uref, &dts))) { upipe_warn(upipe, "received packet with no dts"); } upipe_dbg_va(upipe, "received pic %d, pts: %"PRIu64" , dts: %"PRIu64, x264_test->counter, pts, dts); x264_test->counter++; uref_free(uref); }
/** @internal @This handles data. * * @param upipe description structure of the pipe * @param uref uref structure describing the picture * @param upump_p reference to pump that generated the buffer * @return true if the packet was handled */ static bool upipe_audiobar_handle(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_audiobar *upipe_audiobar = upipe_audiobar_from_upipe(upipe); const char *def; if (unlikely(ubase_check(uref_flow_get_def(uref, &def)))) { UBASE_FATAL(upipe, uref_sound_flow_get_channels(uref, &upipe_audiobar->channels)) uref_sound_flow_clear_format(uref); UBASE_FATAL(upipe, uref_attr_import(uref, upipe_audiobar->flow_def_config)) uref_pic_flow_clear_format(uref); UBASE_FATAL(upipe, uref_pic_flow_set_planes(uref, 0)) UBASE_FATAL(upipe, uref_pic_flow_set_macropixel(uref, 1)) UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 1, 1, 1, "y8")) UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 2, 1, 1, "u8")) UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 2, 1, 1, "v8")) UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 1, 1, 1, "a8")) UBASE_FATAL(upipe, uref_pic_set_progressive(uref)) upipe_audiobar->hsize = upipe_audiobar->vsize = upipe_audiobar->sep_width = upipe_audiobar->pad_width = UINT64_MAX; upipe_audiobar_require_flow_format(upipe, uref); return true; } if (!upipe_audiobar->ubuf_mgr) return false; if (unlikely(upipe_audiobar->hsize == UINT64_MAX)) return false; struct ubuf *ubuf = ubuf_pic_alloc(upipe_audiobar->ubuf_mgr, upipe_audiobar->hsize, upipe_audiobar->vsize); uref_attach_ubuf(uref, ubuf); uint8_t *dst[4]; size_t strides[4]; uint8_t hsubs[4]; uint8_t vsubs[4]; static const char *chroma[4] = { "y8", "u8", "v8", "a8" }; for (int i = 0; i < 4; i++) { if (unlikely(!ubase_check(uref_pic_plane_write(uref, chroma[i], 0, 0, -1, -1, &dst[i])) || !ubase_check(uref_pic_plane_size(uref, chroma[i], &strides[i], &hsubs[i], &vsubs[i], NULL)))) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(uref); return true; } } uint8_t alpha = upipe_audiobar->alpha; uint64_t h = upipe_audiobar->vsize; const int hred = h - (iec_scale(-8.) * h); const int hyellow = h - (iec_scale(-18.) * h); uint8_t transparent[4] = { 0x10, 0x80, 0x80, 0 }; uint8_t black[4] = { 0x10, 0x80, 0x80, alpha }; uint8_t red[2][4] = { { 76, 85, 0xff, alpha }, { 37, 106, 191, alpha } }; uint8_t green[2][4] = { { 150, 44, 21, alpha }, { 74, 85, 74, alpha } }; uint8_t yellow[2][4] = { { 226, 1, 148, alpha }, { 112, 64, 138, alpha } }; uint64_t pts = 0; if (unlikely(!ubase_check(uref_clock_get_pts_prog(uref, &pts)))) { upipe_warn(upipe, "unable to read pts"); } for (uint8_t chan = 0; chan < upipe_audiobar->channels; chan++) { double amplitude = 0.; if (unlikely(!ubase_check(uref_amax_get_amplitude(uref, &litude, chan)))) upipe_warn_va(upipe, "unable to get amplitude for channel %"PRIu8", assuming silence", chan); double scale = log10(amplitude) * 20; // IEC-268-18 return time speed is 20dB per 1.7s (+/- .3) if (upipe_audiobar->peak_date[chan]) upipe_audiobar->peak[chan] -= 20 * (pts - upipe_audiobar->peak_date[chan]) / (1.7 * UCLOCK_FREQ); upipe_audiobar->peak_date[chan] = pts; if (scale >= upipe_audiobar->peak[chan]) /* higher than lowered peak */ upipe_audiobar->peak[chan] = scale; else /* Current amplitude can not go below the lowered peak value */ scale = upipe_audiobar->peak[chan]; scale = iec_scale(scale); const int hmax = h - scale * h; for (int row = 0; row < h; row++) { bool bright = row > hmax; const uint8_t *color = row < hred ? red[!bright] : row < hyellow ? yellow[!bright] : green[!bright]; copy_color(dst, strides, hsubs, vsubs, color, row, chan * upipe_audiobar->chan_width, upipe_audiobar->chan_width); if (chan && upipe_audiobar->sep_width) copy_color(dst, strides, hsubs, vsubs, black, row, chan * upipe_audiobar->chan_width - upipe_audiobar->sep_width / 2, upipe_audiobar->sep_width); if (chan == upipe_audiobar->channels - 1 && upipe_audiobar->pad_width) copy_color(dst, strides, hsubs, vsubs, transparent, row, (chan + 1) * upipe_audiobar->chan_width, upipe_audiobar->pad_width); } } /* dB marks */ for (int i = 1; i <= 6; i++) { int row = h - (iec_scale(-10 * i) * h); copy_color(dst, strides, hsubs, vsubs, black, row, 0, upipe_audiobar->hsize); } for (int i = 0; i < 4; i++) ubuf_pic_plane_unmap(ubuf, chroma[i], 0, 0, -1, -1); upipe_audiobar_output(upipe, uref, upump_p); return true; }
/** @internal @This prepends a PES header to a logical unit. * * @param upipe description structure of the pipe * @param upump_p reference to pump that generated the buffer */ static void upipe_ts_pese_work(struct upipe *upipe, struct upump **upump_p) { struct upipe_ts_pese *upipe_ts_pese = upipe_ts_pese_from_upipe(upipe); if (ulist_empty(&upipe_ts_pese->next_pes)) return; uint64_t pts = UINT64_MAX, dts = UINT64_MAX; struct uref *uref = uref_from_uchain(ulist_pop(&upipe_ts_pese->next_pes)); size_t header_size; if (upipe_ts_pese->pes_id != PES_STREAM_ID_PRIVATE_2) { uref_clock_get_pts_prog(uref, &pts); uref_clock_get_dts_prog(uref, &dts); if (pts != UINT64_MAX) { if (dts != UINT64_MAX && ((pts / CLOCK_SCALE) % POW2_33) != ((dts / CLOCK_SCALE) % POW2_33)) header_size = PES_HEADER_SIZE_PTSDTS; else header_size = PES_HEADER_SIZE_PTS; } else header_size = PES_HEADER_SIZE_NOPTS; } else header_size = PES_HEADER_SIZE; if (header_size < upipe_ts_pese->pes_header_size) header_size = upipe_ts_pese->pes_header_size; struct ubuf *ubuf = ubuf_block_alloc(upipe_ts_pese->ubuf_mgr, header_size); if (unlikely(ubuf == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); goto upipe_ts_pese_work_err; } uint8_t *buffer; int size = -1; if (unlikely(!ubase_check(ubuf_block_write(ubuf, 0, &size, &buffer)))) { ubuf_free(ubuf); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); goto upipe_ts_pese_work_err; } pes_init(buffer); pes_set_streamid(buffer, upipe_ts_pese->pes_id); size_t pes_length = upipe_ts_pese->next_pes_size + header_size - PES_HEADER_SIZE; if (pes_length > UINT16_MAX) { if (unlikely((upipe_ts_pese->pes_id & PES_STREAM_ID_VIDEO_MPEG) != PES_STREAM_ID_VIDEO_MPEG)) upipe_warn(upipe, "PES length > 65535 for a non-video stream"); pes_set_length(buffer, 0); } else pes_set_length(buffer, pes_length); if (upipe_ts_pese->pes_id != PES_STREAM_ID_PRIVATE_2) { pes_set_headerlength(buffer, header_size - PES_HEADER_SIZE_NOPTS); pes_set_dataalignment(buffer); if (pts != UINT64_MAX) { pes_set_pts(buffer, (pts / CLOCK_SCALE) % POW2_33); if (dts != UINT64_MAX && ((pts / CLOCK_SCALE) % POW2_33) != ((dts / CLOCK_SCALE) % POW2_33)) pes_set_dts(buffer, (dts / CLOCK_SCALE) % POW2_33); } } ubuf_block_unmap(ubuf, 0); struct ubuf *payload = uref_detach_ubuf(uref); uref_attach_ubuf(uref, ubuf); if (unlikely(!ubase_check(uref_block_append(uref, payload)))) { uref_free(uref); ubuf_free(payload); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } /* intended pass-through */ upipe_ts_pese_work_err: uref_block_set_start(uref); upipe_ts_pese_output(upipe, uref, upump_p); struct uchain *uchain; while ((uchain = ulist_pop(&upipe_ts_pese->next_pes)) != NULL) upipe_ts_pese_output(upipe, uref_from_uchain(uchain), upump_p); upipe_ts_pese->next_pes_size = 0; upipe_ts_pese->next_pes_duration = 0; }