Skip to content

Commit 15d8c76

Browse files
committed
upipe_s302_framer: add low latency output
Quite a hack with lots of duplicated code and no option to control it.
1 parent 1414224 commit 15d8c76

1 file changed

Lines changed: 289 additions & 0 deletions

File tree

lib/upipe-framers/upipe_s302_framer.c

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <upipe/upipe_helper_sync.h>
4141
#include <upipe/upipe_helper_output.h>
4242
#include <upipe/upipe_helper_flow_def.h>
43+
#include <upipe/upipe_helper_ubuf_mgr.h>
4344
#include <upipe-framers/upipe_s302_framer.h>
4445

4546
#include <stdlib.h>
@@ -58,6 +59,9 @@
5859
/* Length in bytes of two audio samples */
5960
static const uint8_t pair_lengths[] = {5, 6, 7, 0};
6061

62+
#define S302_MAX_PAIR_LENGTH 7
63+
#define S302_MAX_CHANNELS 8
64+
6165
/** @internal @This is the private context of an s302f pipe. */
6266
struct upipe_s302f {
6367
/** refcount management structure */
@@ -77,6 +81,13 @@ struct upipe_s302f {
7781
/** attributes in the sequence header */
7882
struct uref *flow_def_attr;
7983

84+
/** ubuf manager */
85+
struct ubuf_mgr *ubuf_mgr;
86+
/** flow format packet */
87+
struct uref *flow_format;
88+
/** ubuf manager request */
89+
struct urequest ubuf_mgr_request;
90+
8091
/** currently detected frame rate */
8192
struct urational fps;
8293
/** currently detected octet rate */
@@ -93,6 +104,13 @@ struct upipe_s302f {
93104
* sequence header) */
94105
bool acquired;
95106

107+
uint8_t scratch_buffer[S302_MAX_PAIR_LENGTH * S302_MAX_CHANNELS/2];
108+
uint8_t scratch_buffer_count;
109+
110+
bool have_valid_header;
111+
uint8_t pair_length, num_channels;
112+
uint8_t header[S302_HEADER_SIZE];
113+
96114
/** public upipe structure */
97115
struct upipe upipe;
98116
};
@@ -105,6 +123,18 @@ UPIPE_HELPER_SYNC(upipe_s302f, acquired)
105123
UPIPE_HELPER_OUTPUT(upipe_s302f, output, flow_def, output_state, request_list)
106124
UPIPE_HELPER_FLOW_DEF(upipe_s302f, flow_def_input, flow_def_attr)
107125

126+
static int upipe_s302f_check(struct upipe *upipe, struct uref *flow_format)
127+
{
128+
if (flow_format != NULL)
129+
upipe_s302f_store_flow_def(upipe, flow_format);
130+
return UBASE_ERR_NONE;
131+
}
132+
133+
UPIPE_HELPER_UBUF_MGR(upipe_s302f, ubuf_mgr, flow_format, ubuf_mgr_request,
134+
upipe_s302f_check,
135+
upipe_s302f_register_output_request,
136+
upipe_s302f_unregister_output_request)
137+
108138
/** @internal @This allocates an s302f pipe.
109139
*
110140
* @param mgr common management structure
@@ -126,9 +156,13 @@ static struct upipe *upipe_s302f_alloc(struct upipe_mgr *mgr,
126156
upipe_s302f_init_sync(upipe);
127157
upipe_s302f_init_output(upipe);
128158
upipe_s302f_init_flow_def(upipe);
159+
upipe_s302f_init_ubuf_mgr(upipe);
129160
upipe_s302f->octetrate = 0;
130161
upipe_s302f->next_uref = NULL;
131162
upipe_s302f->next_uref_size = 0;
163+
upipe_s302f->scratch_buffer_count = 0;
164+
upipe_s302f->have_valid_header = false;
165+
upipe_s302f->pair_length = upipe_s302f->num_channels = 0;
132166
uref_init(&upipe_s302f->au_uref_s);
133167
upipe_throw_ready(upipe);
134168
return upipe;
@@ -254,6 +288,7 @@ static void upipe_s302f_input(struct upipe *upipe, struct uref *uref,
254288
}
255289
bool end = ubase_check(uref_block_get_end(uref));
256290

291+
#if 0
257292
if (ubase_check(uref_block_get_start(uref))) {
258293
if (upipe_s302f->next_uref != NULL)
259294
upipe_s302f_work(upipe, upump_p);
@@ -277,6 +312,243 @@ static void upipe_s302f_input(struct upipe *upipe, struct uref *uref,
277312

278313
if (end)
279314
upipe_s302f_work(upipe, upump_p);
315+
#else
316+
317+
if (ubase_check(uref_block_get_start(uref))) {
318+
int audio_packet_size;
319+
uint8_t num_channels;
320+
uint8_t bits_per_sample;
321+
uint8_t pair_length;
322+
int num_samples;
323+
324+
/* Get header properties. */
325+
if (!ubase_check(uref_block_extract(uref, 0, S302_HEADER_SIZE, upipe_s302f->header))) {
326+
uref_free(uref);
327+
return;
328+
}
329+
audio_packet_size = (upipe_s302f->header[0] << 8) | upipe_s302f->header[1];
330+
upipe_s302f->num_channels = num_channels = ((upipe_s302f->header[2] >> 6) + 1) * 2;
331+
bits_per_sample = (upipe_s302f->header[3] >> 4) & 0x3;
332+
333+
upipe_s302f->pair_length = pair_length = pair_lengths[bits_per_sample];
334+
if (!pair_length) {
335+
uref_free(uref);
336+
upipe_s302f->have_valid_header = false;
337+
return;
338+
}
339+
upipe_s302f->have_valid_header = true;
340+
341+
342+
/* Make/update output flow_def. */
343+
struct uref *flow_def = upipe_s302f_alloc_flow_def_attr(upipe);
344+
if (unlikely(flow_def == NULL)) {
345+
upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
346+
uref_free(uref);
347+
return;
348+
}
349+
350+
UBASE_FATAL(upipe, uref_flow_set_def(flow_def, "block.s302m.sound."))
351+
UBASE_FATAL(upipe, uref_sound_flow_set_rate(flow_def, S302_FREQUENCY))
352+
UBASE_FATAL(upipe, uref_sound_flow_set_channels(flow_def, num_channels))
353+
354+
flow_def = upipe_s302f_store_flow_def_attr(upipe, flow_def);
355+
if (unlikely(flow_def == NULL)) {
356+
upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
357+
uref_free(uref);
358+
return;
359+
}
360+
upipe_s302f_sync_acquired(upipe);
361+
362+
/* Get a ubuf_mgr to alloc new blocks. */
363+
if (!upipe_s302f->ubuf_mgr
364+
|| !ubase_check(ubuf_mgr_check(upipe_s302f->ubuf_mgr, flow_def)))
365+
upipe_s302f_require_ubuf_mgr(upipe, flow_def);
366+
else
367+
uref_free(flow_def);
368+
369+
/* Set header size to the max data that is in the uref. */
370+
num_samples = (uref_size - S302_HEADER_SIZE) / (pair_length * (num_channels / 2));
371+
audio_packet_size = num_samples * (pair_length * (num_channels / 2));
372+
upipe_s302f->header[0] = audio_packet_size >> 8;
373+
upipe_s302f->header[1] = audio_packet_size;
374+
375+
if (!upipe_s302f->ubuf_mgr) {
376+
upipe_verbose(upipe, "no ubuf_mgr, dropping uref");
377+
uref_free(uref);
378+
return;
379+
}
380+
381+
/* Create new block. */
382+
struct ubuf *ubuf = ubuf_block_alloc(upipe_s302f->ubuf_mgr,
383+
S302_HEADER_SIZE + audio_packet_size);
384+
if (unlikely(ubuf == NULL)) {
385+
upipe_throw_error(upipe, UBASE_ERR_ALLOC);
386+
uref_free(uref);
387+
return;
388+
}
389+
390+
int size = -1;
391+
uint8_t *data;
392+
int ret = ubuf_block_write(ubuf, 0, &size, &data);
393+
if (!ubase_check(ret)) {
394+
upipe_throw_error(upipe, ret);
395+
uref_free(uref);
396+
ubuf_free(ubuf);
397+
return;
398+
}
399+
400+
/* Copy header. */
401+
memcpy(data, upipe_s302f->header, S302_HEADER_SIZE);
402+
/* Copy audio data. */
403+
ret = uref_block_extract(uref, S302_HEADER_SIZE, audio_packet_size, data + S302_HEADER_SIZE);
404+
if (!ubase_check(ret)) {
405+
upipe_throw_error(upipe, ret);
406+
uref_free(uref);
407+
ubuf_block_unmap(ubuf, 0);
408+
ubuf_free(ubuf);
409+
return;
410+
}
411+
412+
assert((uref_size - S302_HEADER_SIZE - audio_packet_size) <= S302_MAX_PAIR_LENGTH * S302_MAX_CHANNELS/2);
413+
414+
/* Store tail of data that must be output next time. */
415+
ret = uref_block_extract(uref, S302_HEADER_SIZE + audio_packet_size, -1,
416+
upipe_s302f->scratch_buffer);
417+
if (!ubase_check(ret)) {
418+
upipe_throw_error(upipe, ret);
419+
uref_free(uref);
420+
ubuf_block_unmap(ubuf, 0);
421+
ubuf_free(ubuf);
422+
return;
423+
}
424+
upipe_s302f->scratch_buffer_count = uref_size - S302_HEADER_SIZE - audio_packet_size;
425+
426+
ubuf_block_unmap(ubuf, 0);
427+
uref_attach_ubuf(uref, ubuf);
428+
429+
/* Set clocks. */
430+
uint64_t duration = num_samples * UCLOCK_FREQ / S302_FREQUENCY;
431+
432+
/* We work on encoded data so in the DTS domain. Rebase on DTS */
433+
uint64_t date;
434+
struct urational drift_rate;
435+
drift_rate.den = 0;
436+
uref_clock_get_rate(uref, &drift_rate);
437+
#define SET_DATE(dv) \
438+
if (ubase_check(uref_clock_get_dts_##dv(uref, &date)))\
439+
uref_clock_set_dts_##dv(&upipe_s302f->au_uref_s, date); \
440+
if (ubase_check(uref_clock_get_dts_##dv(&upipe_s302f->au_uref_s, \
441+
&date))) { \
442+
uref_clock_set_dts_##dv(uref, date); \
443+
uref_clock_set_dts_##dv(&upipe_s302f->au_uref_s, date + duration); \
444+
}
445+
SET_DATE(sys)
446+
SET_DATE(prog)
447+
SET_DATE(orig)
448+
#undef SET_DATE
449+
450+
uref_clock_set_dts_pts_delay(uref, 0);
451+
if (drift_rate.den)
452+
uref_clock_set_rate(uref, drift_rate);
453+
454+
upipe_s302f_output(upipe, uref, upump_p);
455+
}
456+
457+
else if (upipe_s302f->have_valid_header) {
458+
/* Number of whole samples in uref and scratch buffer. */
459+
int num_samples = (upipe_s302f->scratch_buffer_count + uref_size) / (upipe_s302f->pair_length * (upipe_s302f->num_channels / 2));
460+
int audio_packet_size = num_samples * (upipe_s302f->pair_length * (upipe_s302f->num_channels / 2));
461+
462+
upipe_s302f->header[0] = audio_packet_size >> 8;
463+
upipe_s302f->header[1] = audio_packet_size;
464+
465+
/* Create new block. */
466+
struct ubuf *ubuf = ubuf_block_alloc(upipe_s302f->ubuf_mgr,
467+
S302_HEADER_SIZE + audio_packet_size);
468+
if (unlikely(ubuf == NULL)) {
469+
upipe_throw_error(upipe, UBASE_ERR_ALLOC);
470+
uref_free(uref);
471+
return;
472+
}
473+
474+
int size = -1;
475+
uint8_t *data;
476+
int ret = ubuf_block_write(ubuf, 0, &size, &data);
477+
if (!ubase_check(ret)) {
478+
upipe_throw_error(upipe, ret);
479+
uref_free(uref);
480+
ubuf_free(ubuf);
481+
return;
482+
}
483+
484+
/* Copy header. */
485+
memcpy(data, upipe_s302f->header, S302_HEADER_SIZE);
486+
/* Copy tail of previous packet. */
487+
memcpy(data + S302_HEADER_SIZE, upipe_s302f->scratch_buffer, upipe_s302f->scratch_buffer_count);
488+
/* Copy audio data. */
489+
ret = uref_block_extract(uref, 0, audio_packet_size - upipe_s302f->scratch_buffer_count,
490+
data + S302_HEADER_SIZE + upipe_s302f->scratch_buffer_count);
491+
if (!ubase_check(ret)) {
492+
upipe_throw_error(upipe, ret);
493+
uref_free(uref);
494+
ubuf_block_unmap(ubuf, 0);
495+
ubuf_free(ubuf);
496+
return;
497+
}
498+
499+
assert(uref_size - audio_packet_size + upipe_s302f->scratch_buffer_count <= S302_MAX_PAIR_LENGTH * S302_MAX_CHANNELS/2);
500+
if (end)
501+
assert(uref_size - audio_packet_size + upipe_s302f->scratch_buffer_count == 0);
502+
503+
/* Store tail of data that must be output next time. */
504+
ret = uref_block_extract(uref, audio_packet_size - upipe_s302f->scratch_buffer_count, -1,
505+
upipe_s302f->scratch_buffer);
506+
if (!ubase_check(ret)) {
507+
upipe_throw_error(upipe, ret);
508+
uref_free(uref);
509+
ubuf_block_unmap(ubuf, 0);
510+
ubuf_free(ubuf);
511+
return;
512+
}
513+
upipe_s302f->scratch_buffer_count = (uref_size + upipe_s302f->scratch_buffer_count) - audio_packet_size;
514+
515+
ubuf_block_unmap(ubuf, 0);
516+
uref_attach_ubuf(uref, ubuf);
517+
518+
/* Set clocks. */
519+
uint64_t duration = num_samples * UCLOCK_FREQ / S302_FREQUENCY;
520+
521+
/* We work on encoded data so in the DTS domain. Rebase on DTS */
522+
uint64_t date;
523+
struct urational drift_rate;
524+
drift_rate.den = 0;
525+
uref_clock_get_rate(uref, &drift_rate);
526+
#define SET_DATE(dv) \
527+
if (ubase_check(uref_clock_get_dts_##dv(uref, &date)))\
528+
uref_clock_set_dts_##dv(&upipe_s302f->au_uref_s, date); \
529+
if (ubase_check(uref_clock_get_dts_##dv(&upipe_s302f->au_uref_s, \
530+
&date))) { \
531+
uref_clock_set_dts_##dv(uref, date); \
532+
uref_clock_set_dts_##dv(&upipe_s302f->au_uref_s, date + duration); \
533+
}
534+
SET_DATE(sys)
535+
SET_DATE(prog)
536+
SET_DATE(orig)
537+
#undef SET_DATE
538+
539+
uref_clock_set_dts_pts_delay(uref, 0);
540+
if (drift_rate.den)
541+
uref_clock_set_rate(uref, drift_rate);
542+
543+
upipe_s302f_output(upipe, uref, upump_p);
544+
}
545+
546+
else {
547+
upipe_verbose(upipe, "no valid header, dropping uref");
548+
uref_free(uref);
549+
}
550+
551+
#endif
280552
}
281553

282554
/** @internal @This sets the input flow definition.
@@ -316,6 +588,22 @@ static int upipe_s302f_control(struct upipe *upipe, int command, va_list args)
316588
{
317589
UBASE_HANDLED_RETURN(upipe_s302f_control_output(upipe, command, args));
318590
switch (command) {
591+
case UPIPE_REGISTER_REQUEST: {
592+
struct urequest *request = va_arg(args, struct urequest *);
593+
if (request->type == UREQUEST_UBUF_MGR ||
594+
request->type == UREQUEST_FLOW_FORMAT)
595+
return upipe_throw_provide_request(upipe, request);
596+
return upipe_s302f_alloc_output_proxy(upipe, request);
597+
}
598+
599+
case UPIPE_UNREGISTER_REQUEST: {
600+
struct urequest *request = va_arg(args, struct urequest *);
601+
if (request->type == UREQUEST_UBUF_MGR ||
602+
request->type == UREQUEST_FLOW_FORMAT)
603+
return UBASE_ERR_NONE;
604+
return upipe_s302f_free_output_proxy(upipe, request);
605+
}
606+
319607
case UPIPE_SET_FLOW_DEF: {
320608
struct uref *flow_def = va_arg(args, struct uref *);
321609
return upipe_s302f_set_flow_def(upipe, flow_def);
@@ -339,6 +627,7 @@ static void upipe_s302f_free(struct upipe *upipe)
339627
upipe_s302f_clean_flow_def(upipe);
340628
upipe_s302f_clean_sync(upipe);
341629

630+
upipe_s302f_clean_ubuf_mgr(upipe);
342631
upipe_s302f_clean_urefcount(upipe);
343632
upipe_s302f_free_void(upipe);
344633
}

0 commit comments

Comments
 (0)