/** @internal @This handles input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static void upipe_htons_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct ubuf *ubuf; size_t size = 0; int remain, bufsize = -1, offset = 0; uint8_t *buf = NULL; /* block size */ if (unlikely(!ubase_check(uref_block_size(uref, &size)))) { upipe_warn(upipe, "could not read uref block size"); uref_free(uref); return; } /* copy ubuf if shared or not 16b-unaligned or segmented */ bufsize = -1; if (!ubase_check(uref_block_write(uref, 0, &bufsize, &buf)) || ((uintptr_t)buf & 1) || bufsize != size) { ubuf = ubuf_block_copy(uref->ubuf->mgr, uref->ubuf, 0, size); if (unlikely(!ubuf)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(uref); return; } uref_attach_ubuf(uref, ubuf); } else { uref_block_unmap(uref, 0); } /* process ubuf chunks */ while (size > 0) { bufsize = -1; if (unlikely(!ubase_check(uref_block_write(uref, offset, &bufsize, &buf)))) { upipe_warn(upipe, "unexpected buffer error"); uref_free(uref); return; } if (unlikely((uintptr_t)buf & 1)) { upipe_warn_va(upipe, "unaligned buffer: %p", buf); } for (remain = bufsize; remain > 1; remain -= 2) { *(uint16_t *)buf = htons(*(uint16_t *)buf); buf += 2; } uref_block_unmap(uref, offset); offset += bufsize; size -= bufsize; } upipe_htons_output(upipe, uref, upump_p); }
static bool upipe_dveo_asi_sink_add_header(struct upipe *upipe, struct uref *uref, uint64_t pts) { struct upipe_dveo_asi_sink *upipe_dveo_asi_sink = upipe_dveo_asi_sink_from_upipe(upipe); uint64_t hdr_size; if (!ubase_check(uref_block_get_header_size(uref, &hdr_size))) hdr_size = 0; if (hdr_size != 0) return false; /* alloc header */ struct ubuf *header = ubuf_block_alloc(uref->ubuf->mgr, 8); if (unlikely(!header)) { return true; } /* 63-bits timestamp */ union { uint8_t timestamp[8]; uint64_t pts; } timestamp; timestamp.pts = pts; if (upipe_dveo_asi_sink->first_timestamp) { upipe_dveo_asi_sink->first_timestamp = false; // FIXME: set the counter in an empty packet, and account for latency timestamp.pts |= 1LLU << 63; /* Set MSB = Set the counter */ } /* write header, 64 bits little-endian : * https://github.com/kierank/dveo-linux-master/blob/450e4b9e4292c2f71acd4d3d2e0a0cd0879d473a/doc/ASI/features.txt#L62 */ int size = 8; uint8_t *header_write_ptr; if (!ubase_check(ubuf_block_write(header, 0, &size, &header_write_ptr))) { upipe_err(upipe, "could not write header"); ubuf_free(header); return true; } memcpy(header_write_ptr, timestamp.timestamp, 8); uref_block_unmap(uref, 0); /* append payload (current ubuf) to header to form segmented ubuf */ struct ubuf *payload = uref_detach_ubuf(uref); if (unlikely(!ubase_check(ubuf_block_append(header, payload)))) { upipe_warn(upipe, "could not append payload to header"); ubuf_free(header); ubuf_free(payload); return true; } uref_attach_ubuf(uref, header); uref_block_set_header_size(uref, 8); return false; }
static void upipe_dump_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_dump *upipe_dump = upipe_dump_from_upipe(upipe); uref_dump(uref, upipe->uprobe); size_t total_size; ubase_assert(uref_block_size(uref, &total_size)); upipe_notice_va(upipe, "dumping ubuf %p of size %zu", uref->ubuf, total_size); if (upipe_dump->max_len != (size_t)-1 && total_size > upipe_dump->max_len) total_size = upipe_dump->max_len; unsigned int count = 0; uint8_t line[16]; int offset = 0; while (total_size) { const uint8_t *buf; int size = total_size; ubase_assert(uref_block_read(uref, offset, &size, &buf)); assert(size != 0); total_size -= size; for (unsigned i = 0; i < size; i++, count++) { line[count % 16] = buf[i]; if (!((count + 1) % 16) || (!total_size && (i + 1 == size))) upipe_dump_line(upipe, count - (count % 16), line, (count % 16) + 1); } ubase_assert(uref_block_unmap(uref, offset)); offset += size; } #define UPIPE_DUMP_SEP \ "--------------------------------------------" \ "-------------------------------------------" upipe_notice(upipe, UPIPE_DUMP_SEP); upipe_dump_output(upipe, uref, upump_p); }
/** @internal @This checks the presence of the sync word. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static bool upipe_ts_check_check(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { const uint8_t *buffer; int size = 1; uint8_t word; if (unlikely(!ubase_check(uref_block_read(uref, 0, &size, &buffer)))) { uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } assert(size == 1); word = *buffer; uref_block_unmap(uref, 0); if (word != TS_SYNC) { uref_free(uref); upipe_warn_va(upipe, "invalid TS sync 0x%"PRIx8, word); return false; } upipe_ts_check_output(upipe, uref, upump_p); return true; }
/** @internal @This outputs audio buffers * * @param upipe description structure of the pipe * @param frame AVFrame structure * @param upump upump structure */ static void upipe_avcdec_output_audio(struct upipe *upipe, AVFrame *frame, struct upump *upump) { struct ubuf *ubuf; struct upipe_avcdec *upipe_avcdec = upipe_avcdec_from_upipe(upipe); struct uref *uref = frame->opaque; int bufsize = -1, avbufsize; size_t size = 0; uint8_t *buf; AVCodecContext *context = upipe_avcdec->context; /* fetch audio sample size (in case it has been reduced) */ avbufsize = av_samples_get_buffer_size(NULL, context->channels, frame->nb_samples, context->sample_fmt, 1); /* if uref has no attached ubuf (ie DR not supported) */ if (unlikely(!uref->ubuf)) { ubuf = ubuf_block_alloc(upipe_avcdec->ubuf_mgr, avbufsize); if (unlikely(!ubuf)) { upipe_throw_aerror(upipe); return; } ubuf_block_write(ubuf, 0, &bufsize, &buf); memcpy(buf, frame->data[0], bufsize); uref_attach_ubuf(uref, ubuf); } /* unmap, reduce block if needed */ uref_block_unmap(uref, 0); uref_block_size(uref, &size); if (unlikely(size != avbufsize)) { uref_block_resize(uref, 0, avbufsize); } /* TODO: set attributes/need a real ubuf_audio structure (?) */ if (!upipe_avcdec->output_flow) { #if 0 struct uref *outflow = uref_sound_flow_alloc_def(upipe_avcdec->uref_mgr, context->channels, av_get_bytes_per_sample(context->sample_fmt)); #else struct uref *outflow = uref_block_flow_alloc_def(upipe_avcdec->uref_mgr, "sound."); #endif uref_sound_flow_set_channels(outflow, context->channels); uref_sound_flow_set_sample_size(outflow, av_get_bytes_per_sample(context->sample_fmt)); uref_sound_flow_set_rate(outflow, context->sample_rate); upipe_avcdec_store_flow_def(upipe, outflow); } /* samples in uref */ uref_sound_flow_set_samples(uref, frame->nb_samples); /* index rap attribute */ upipe_avcdec_set_index_rap(upipe, uref); upipe_avcdec_output(upipe, uref, upump); }
/** @internal @This handles data. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static bool upipe_s337_encaps_handle(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_s337_encaps *upipe_s337_encaps = upipe_s337_encaps_from_upipe(upipe); if (!upipe_s337_encaps->ubuf_mgr) return false; size_t block_size; if (!ubase_check(uref_block_size(uref, &block_size))) { upipe_err(upipe, "Couldn't read block size"); uref_free(uref); return true; } struct ubuf *ubuf = ubuf_sound_alloc(upipe_s337_encaps->ubuf_mgr, A52_FRAME_SAMPLES); if (!ubuf) return false; if (block_size / 2 > A52_FRAME_SAMPLES - 4) { upipe_err_va(upipe, "AC-3 block size %zu too big", block_size); block_size = (A52_FRAME_SAMPLES - 4) * 2; } int32_t *out_data; ubuf_sound_write_int32_t(ubuf, 0, -1, &out_data, 1); /* Pa, Pb, Pc, Pd */ out_data[0] = (S337_PREAMBLE_A1 << 24) | (S337_PREAMBLE_A2 << 16); out_data[1] = (S337_PREAMBLE_B1 << 24) | (S337_PREAMBLE_B2 << 16); out_data[2] = (S337_TYPE_A52 << 16) | (S337_MODE_16 << 21) | (S337_TYPE_A52_REP_RATE_FLAG << 24); out_data[3] = ((block_size * 8) & 0xffff) << 16; int offset = 0; uint8_t tmp = 0; while (block_size) { const uint8_t *buf; int size = block_size; if (!ubase_check(uref_block_read(uref, offset, &size, &buf)) || size == 0) { ubuf_sound_unmap(ubuf, 0, -1, 1); ubuf_free(ubuf); uref_free(uref); return true; } if (offset & 1) { out_data[4 + offset/2] = (tmp << 24) | (buf[0] << 16); buf++; offset++; block_size--; size--; } for (int i = 0; i < size/2; i++) out_data[4 + offset/2 + i] = (buf[2*i + 0] << 24) | (buf[2*i + 1] << 16); if (size & 1) tmp = buf[size-1]; uref_block_unmap(uref, offset); block_size -= size; offset += size; } memset(&out_data[4 + offset/2], 0, 4 * (A52_FRAME_SAMPLES*2 - 4 - offset/2)); ubuf_sound_unmap(ubuf, 0, -1, 1); uref_attach_ubuf(uref, ubuf); upipe_s337_encaps_output(upipe, uref, upump_p); return true; }