/** @internal @This merges a PSI section. * * @param upipe description structure of the pipe * @param uref uref pointing to (part of) a PSI section * @param upump_p reference to pump that generated the buffer * @return false if the uref has been entirely consumed */ static bool upipe_ts_psim_merge(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_ts_psim *upipe_ts_psim = upipe_ts_psim_from_upipe(upipe); if (upipe_ts_psim->next_uref != NULL) { struct ubuf *ubuf = ubuf_dup(uref->ubuf); if (unlikely(ubuf == NULL || !ubase_check(uref_block_append(upipe_ts_psim->next_uref, ubuf)))) { upipe_ts_psim_flush(upipe); if (ubuf != NULL) ubuf_free(ubuf); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } } else { /* Check for stuffing */ uint8_t table_id; if (unlikely(!ubase_check(uref_block_extract(uref, 0, 1, &table_id)) || table_id == 0xff)) { return false; } upipe_ts_psim->next_uref = uref_dup(uref); if (unlikely(upipe_ts_psim->next_uref == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } } size_t size = 0; UBASE_FATAL(upipe, uref_block_size(upipe_ts_psim->next_uref, &size)) if (size < PSI_HEADER_SIZE) return false; uint8_t buffer[PSI_HEADER_SIZE]; const uint8_t *psi_header = uref_block_peek(upipe_ts_psim->next_uref, 0, PSI_HEADER_SIZE, buffer); assert(psi_header != NULL); uint16_t length = psi_get_length(psi_header); UBASE_FATAL(upipe, uref_block_peek_unmap(upipe_ts_psim->next_uref, 0, buffer, psi_header)); if (unlikely(!psi_validate(psi_header) || length + PSI_HEADER_SIZE > PSI_PRIVATE_MAX_SIZE)) { upipe_warn(upipe, "wrong PSI header"); upipe_ts_psim_flush(upipe); return false; } if (length + PSI_HEADER_SIZE > size) return false; UBASE_FATAL(upipe, uref_block_resize(upipe_ts_psim->next_uref, 0, length + PSI_HEADER_SIZE)); upipe_ts_psim_output(upipe, upipe_ts_psim->next_uref, upump_p); upipe_ts_psim->next_uref = NULL; if (length + PSI_HEADER_SIZE == size) return false; size_t uref_size = 0; UBASE_FATAL(upipe, uref_block_size(uref, &uref_size)) UBASE_FATAL(upipe, uref_block_resize(uref, length + PSI_HEADER_SIZE - (size - uref_size), -1)); return true; }
/** @internal @This handles the input uref. * * @param upipe description structure of the pipe * @param uref input uref * @param upump_p reference to pump that generated the buffer */ static void upipe_vblk_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_vblk *upipe_vblk = upipe_vblk_from_upipe(upipe); struct uref *flow_def = upipe_vblk->flow_def; struct uref *input_flow_def = upipe_vblk->input_flow_def; if (uref->ubuf) { upipe_vblk_output(upipe, uref, upump_p); return; } if (unlikely(!input_flow_def)) { upipe_warn(upipe, "no input flow definition"); uref_free(uref); return; } if (unlikely(!flow_def)) { upipe_warn(upipe, "no output flow definition"); uref_free(uref); return; } if (unlikely(!upipe_vblk->ubuf_mgr)) { upipe_warn(upipe, "no ubuf manager set"); uref_free(uref); return; } if (unlikely(!upipe_vblk->ubuf)) { upipe_verbose(upipe, "allocate blank picture"); uint64_t hsize, vsize; ubase_assert(uref_pic_flow_get_hsize(upipe_vblk->flow_def, &hsize)); ubase_assert(uref_pic_flow_get_vsize(upipe_vblk->flow_def, &vsize)); upipe_vblk->ubuf = ubuf_pic_alloc(upipe_vblk->ubuf_mgr, hsize, vsize); if (unlikely(!upipe_vblk->ubuf)) { upipe_err(upipe, "fail to allocate picture"); uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } ubuf_pic_clear(upipe_vblk->ubuf, 0, 0, -1, -1, 1); } struct ubuf *ubuf = ubuf_dup(upipe_vblk->ubuf); if (unlikely(!ubuf)) { upipe_err(upipe, "fail to duplicate blank picture"); uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } uref_attach_ubuf(uref, ubuf); if (ubase_check(uref_pic_get_progressive(flow_def))) uref_pic_set_progressive(uref); upipe_vblk_output(upipe, uref, upump_p); }
int main(int argc, char **argv) { struct umem_mgr *umem_mgr = umem_alloc_mgr_alloc(); assert(umem_mgr != NULL); struct ubuf_mgr *mgr; struct ubuf *ubuf1, *ubuf2; const char *channel; size_t size; uint8_t sample_size; uint8_t *w; const uint8_t *r; /* packed s16 stereo */ mgr = ubuf_sound_mem_mgr_alloc(UBUF_POOL_DEPTH, UBUF_POOL_DEPTH, umem_mgr, 4, 32); assert(mgr != NULL); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "lr")); ubuf1 = ubuf_sound_alloc(mgr, 32); assert(ubuf1 != NULL); ubase_assert(ubuf_sound_size(ubuf1, &size, &sample_size)); assert(size == 32); assert(sample_size == 4); channel = NULL; unsigned int nb_planes = 0; while (ubase_check(ubuf_sound_plane_iterate(ubuf1, &channel)) && channel != NULL) { nb_planes++; assert(!strcmp(channel, "lr")); } assert(nb_planes == 1); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "lr", 0, -1, &r)); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "lr", 0, -1)); fill_in(ubuf1); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "lr", 2, 1, &r)); assert(*r == 'l' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "lr", 2, 1)); ubuf2 = ubuf_dup(ubuf1); assert(ubuf2 != NULL); ubase_nassert(ubuf_sound_plane_write_uint8_t(ubuf1, "lr", 0, -1, &w)); ubuf_free(ubuf2); ubase_nassert(ubuf_sound_resize(ubuf1, 0, 33)); ubase_assert(ubuf_sound_resize(ubuf1, 2, -1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "lr", 0, -1, &r)); assert(r[0] == 'l' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "lr", 0, -1)); ubase_assert(ubuf_sound_resize(ubuf1, 0, 29)); ubuf_free(ubuf1); ubuf_mgr_release(mgr); /* planar float 5.1 */ mgr = ubuf_sound_mem_mgr_alloc(UBUF_POOL_DEPTH, UBUF_POOL_DEPTH, umem_mgr, sizeof(float), 32); assert(mgr != NULL); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "l")); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "r")); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "c")); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "L")); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "R")); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "S")); ubuf1 = ubuf_sound_alloc(mgr, 32); assert(ubuf1 != NULL); ubase_assert(ubuf_sound_size(ubuf1, &size, &sample_size)); assert(size == 32); assert(sample_size == sizeof(float)); channel = NULL; nb_planes = 0; while (ubase_check(ubuf_sound_plane_iterate(ubuf1, &channel)) && channel != NULL) nb_planes++; assert(nb_planes == 6); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "l", 0, -1, &r)); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "l", 0, -1)); fill_in(ubuf1); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "l", 2, 1, &r)); assert(*r == 'l' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "l", 2, 1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "r", 2, 1, &r)); assert(*r == 'r' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "r", 2, 1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "c", 2, 1, &r)); assert(*r == 'c' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "c", 2, 1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "L", 2, 1, &r)); assert(*r == 'L' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "L", 2, 1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "R", 2, 1, &r)); assert(*r == 'R' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "R", 2, 1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "S", 2, 1, &r)); assert(*r == 'S' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "S", 2, 1)); ubuf2 = ubuf_dup(ubuf1); assert(ubuf2 != NULL); ubase_nassert(ubuf_sound_plane_write_uint8_t(ubuf1, "l", 0, -1, &w)); ubuf_free(ubuf2); ubase_nassert(ubuf_sound_resize(ubuf1, 0, 33)); ubase_assert(ubuf_sound_resize(ubuf1, 2, -1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "l", 0, -1, &r)); assert(r[0] == 'l' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "l", 0, -1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "r", 0, -1, &r)); assert(r[0] == 'r' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "r", 0, -1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "c", 0, -1, &r)); assert(r[0] == 'c' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "c", 0, -1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "L", 0, -1, &r)); assert(r[0] == 'L' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "L", 0, -1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "R", 0, -1, &r)); assert(r[0] == 'R' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "R", 0, -1)); ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "S", 0, -1, &r)); assert(r[0] == 'S' + 8); ubase_assert(ubuf_sound_plane_unmap(ubuf1, "S", 0, -1)); ubase_assert(ubuf_sound_resize(ubuf1, 0, 29)); ubuf_free(ubuf1); ubuf_mgr_release(mgr); /* sound -> block transformation */ mgr = ubuf_sound_mem_mgr_alloc(UBUF_POOL_DEPTH, UBUF_POOL_DEPTH, umem_mgr, 4, 32); assert(mgr != NULL); ubase_assert(ubuf_sound_mem_mgr_add_plane(mgr, "lr")); ubuf1 = ubuf_sound_alloc(mgr, 32); assert(ubuf1 != NULL); fill_in(ubuf1); struct ubuf_mgr *block_mgr = ubuf_block_mem_mgr_alloc(UBUF_POOL_DEPTH, UBUF_POOL_DEPTH, umem_mgr, 0, 0, 0, 0); struct ubuf *ubuf_block = ubuf_block_mem_alloc_from_sound(block_mgr, ubuf1, "lr"); assert(ubuf_block != NULL); ubase_assert(ubuf_block_size(ubuf_block, &size)); assert(size == 32 * 4); int size2 = -1; ubase_assert(ubuf_block_read(ubuf_block, 0, &size2, &r)); assert(size2 == 32 * 4); assert(r[0] == 'l'); ubuf_free(ubuf_block); ubuf_mgr_release(block_mgr); ubuf_free(ubuf1); ubuf_mgr_release(mgr); umem_mgr_release(umem_mgr); return 0; }