Skip to content

Commit 3160815

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

File tree

1 file changed

+230
-23
lines changed

1 file changed

+230
-23
lines changed

lib/upipe-framers/upipe_s302_framer.c

Lines changed: 230 additions & 23 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,14 +156,44 @@ 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;
135169
}
136170

171+
static void set_dates(struct uref *uref, struct uref *au_uref_s, int num_samples)
172+
{
173+
uint64_t duration = num_samples * UCLOCK_FREQ / S302_FREQUENCY;
174+
175+
/* We work on encoded data so in the DTS domain. Rebase on DTS */
176+
uint64_t date;
177+
struct urational drift_rate;
178+
drift_rate.den = 0;
179+
uref_clock_get_rate(uref, &drift_rate);
180+
#define SET_DATE(dv) \
181+
if (ubase_check(uref_clock_get_dts_##dv(uref, &date))) \
182+
uref_clock_set_dts_##dv(au_uref_s, date); \
183+
if (ubase_check(uref_clock_get_dts_##dv(au_uref_s, &date))) { \
184+
uref_clock_set_dts_##dv(uref, date); \
185+
uref_clock_set_dts_##dv(au_uref_s, date + duration); \
186+
}
187+
SET_DATE(sys)
188+
SET_DATE(prog)
189+
SET_DATE(orig)
190+
#undef SET_DATE
191+
192+
uref_clock_set_dts_pts_delay(uref, 0);
193+
if (drift_rate.den)
194+
uref_clock_set_rate(uref, drift_rate);
195+
}
196+
137197
/** @internal @This works on a s302 frame and outputs it.
138198
*
139199
* @param upipe description structure of the pipe
@@ -207,36 +267,75 @@ static void upipe_s302f_work(struct upipe *upipe, struct upump **upump_p)
207267
upipe_s302f_store_flow_def(upipe, flow_def);
208268
upipe_s302f_sync_acquired(upipe);
209269

210-
uint64_t duration = num_samples * UCLOCK_FREQ / S302_FREQUENCY;
211-
212-
/* We work on encoded data so in the DTS domain. Rebase on DTS */
213-
uint64_t date;
214-
struct urational drift_rate;
215-
drift_rate.den = 0;
216-
uref_clock_get_rate(upipe_s302f->next_uref, &drift_rate);
217-
#define SET_DATE(dv) \
218-
if (ubase_check(uref_clock_get_dts_##dv(upipe_s302f->next_uref, &date)))\
219-
uref_clock_set_dts_##dv(&upipe_s302f->au_uref_s, date); \
220-
if (ubase_check(uref_clock_get_dts_##dv(&upipe_s302f->au_uref_s, \
221-
&date))) { \
222-
uref_clock_set_dts_##dv(upipe_s302f->next_uref, date); \
223-
uref_clock_set_dts_##dv(&upipe_s302f->au_uref_s, date + duration); \
224-
}
225-
SET_DATE(sys)
226-
SET_DATE(prog)
227-
SET_DATE(orig)
228-
#undef SET_DATE
229-
230-
uref_clock_set_dts_pts_delay(upipe_s302f->next_uref, 0);
231-
if (drift_rate.den)
232-
uref_clock_set_rate(upipe_s302f->next_uref, drift_rate);
270+
set_dates(upipe_s302f->next_uref, &upipe_s302f->au_uref_s, num_samples);
233271

234272
upipe_s302f_output(upipe, upipe_s302f->next_uref, upump_p);
235273
upipe_s302f_work_err:
236274
upipe_s302f->next_uref = NULL;
237275
upipe_s302f->next_uref_size = 0;
238276
}
239277

278+
static int reframe(struct upipe_s302f *upipe_s302f, struct uref *uref, int num_samples, int uref_size, int uref_offset)
279+
{
280+
struct upipe *upipe = upipe_s302f_to_upipe(upipe_s302f);
281+
282+
int audio_packet_size = num_samples * (upipe_s302f->pair_length * (upipe_s302f->num_channels / 2));
283+
upipe_s302f->header[0] = audio_packet_size >> 8;
284+
upipe_s302f->header[1] = audio_packet_size;
285+
286+
/* Create new block. */
287+
struct ubuf *ubuf = ubuf_block_alloc(upipe_s302f->ubuf_mgr,
288+
S302_HEADER_SIZE + audio_packet_size);
289+
if (unlikely(ubuf == NULL)) {
290+
upipe_throw_error(upipe, UBASE_ERR_ALLOC);
291+
return UBASE_ERR_ALLOC;
292+
}
293+
294+
int size = -1;
295+
uint8_t *data;
296+
int ret = ubuf_block_write(ubuf, 0, &size, &data);
297+
if (!ubase_check(ret)) {
298+
upipe_throw_error(upipe, ret);
299+
ubuf_free(ubuf);
300+
return ret;
301+
}
302+
303+
/* Copy header. */
304+
memcpy(data, upipe_s302f->header, S302_HEADER_SIZE);
305+
data += S302_HEADER_SIZE;
306+
307+
/* Copy tail of previous packet. */
308+
memcpy(data, upipe_s302f->scratch_buffer, upipe_s302f->scratch_buffer_count);
309+
data += upipe_s302f->scratch_buffer_count;
310+
311+
/* Copy audio data. */
312+
ret = uref_block_extract(uref, uref_offset, audio_packet_size - upipe_s302f->scratch_buffer_count, data);
313+
if (!ubase_check(ret)) {
314+
upipe_throw_error(upipe, ret);
315+
ubuf_block_unmap(ubuf, 0);
316+
ubuf_free(ubuf);
317+
return ret;
318+
}
319+
uref_offset += audio_packet_size - upipe_s302f->scratch_buffer_count;
320+
321+
/* Store tail of data that must be output next time. */
322+
ret = uref_block_extract(uref, uref_offset, -1, upipe_s302f->scratch_buffer);
323+
if (!ubase_check(ret)) {
324+
upipe_throw_error(upipe, ret);
325+
ubuf_block_unmap(ubuf, 0);
326+
ubuf_free(ubuf);
327+
return ret;
328+
}
329+
upipe_s302f->scratch_buffer_count = uref_size - uref_offset;
330+
331+
ubuf_block_unmap(ubuf, 0);
332+
uref_attach_ubuf(uref, ubuf);
333+
334+
set_dates(uref, &upipe_s302f->au_uref_s, num_samples);
335+
336+
return UBASE_ERR_NONE;
337+
}
338+
240339
/** @internal @This receives data.
241340
*
242341
* @param upipe description structure of the pipe
@@ -254,6 +353,97 @@ static void upipe_s302f_input(struct upipe *upipe, struct uref *uref,
254353
}
255354
bool end = ubase_check(uref_block_get_end(uref));
256355

356+
#define LOW_LATENCY 1
357+
if (LOW_LATENCY) {
358+
if (ubase_check(uref_block_get_start(uref))) {
359+
uint8_t num_channels;
360+
uint8_t bits_per_sample;
361+
uint8_t pair_length;
362+
int num_samples;
363+
364+
/* This should be 0 when a start attribute is set. Packet loss
365+
* might cause it to be otherwise. Reset to ensure that the rest of
366+
* the stream isn't garbage. */
367+
upipe_s302f->scratch_buffer_count = 0;
368+
369+
/* Get header properties. */
370+
if (!ubase_check(uref_block_extract(uref, 0, S302_HEADER_SIZE, upipe_s302f->header))) {
371+
uref_free(uref);
372+
upipe_s302f->have_valid_header = false;
373+
return;
374+
}
375+
upipe_s302f->num_channels = num_channels = ((upipe_s302f->header[2] >> 6) + 1) * 2;
376+
bits_per_sample = (upipe_s302f->header[3] >> 4) & 0x3;
377+
378+
upipe_s302f->pair_length = pair_length = pair_lengths[bits_per_sample];
379+
if (!pair_length) {
380+
uref_free(uref);
381+
upipe_s302f->have_valid_header = false;
382+
return;
383+
}
384+
upipe_s302f->have_valid_header = true;
385+
386+
/* Make/update output flow_def. */
387+
struct uref *flow_def = upipe_s302f_alloc_flow_def_attr(upipe);
388+
if (unlikely(flow_def == NULL)) {
389+
upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
390+
uref_free(uref);
391+
return;
392+
}
393+
394+
UBASE_FATAL(upipe, uref_flow_set_def(flow_def, "block.s302m.sound."))
395+
UBASE_FATAL(upipe, uref_sound_flow_set_rate(flow_def, S302_FREQUENCY))
396+
UBASE_FATAL(upipe, uref_sound_flow_set_channels(flow_def, num_channels))
397+
398+
flow_def = upipe_s302f_store_flow_def_attr(upipe, flow_def);
399+
if (unlikely(flow_def == NULL)) {
400+
upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
401+
uref_free(uref);
402+
return;
403+
}
404+
upipe_s302f_sync_acquired(upipe);
405+
406+
/* Get a ubuf_mgr to alloc new blocks. */
407+
if (!upipe_s302f->ubuf_mgr
408+
|| !ubase_check(ubuf_mgr_check(upipe_s302f->ubuf_mgr, flow_def)))
409+
upipe_s302f_require_ubuf_mgr(upipe, flow_def);
410+
else
411+
uref_free(flow_def);
412+
413+
if (!upipe_s302f->ubuf_mgr) {
414+
upipe_verbose(upipe, "no ubuf_mgr, dropping uref");
415+
uref_free(uref);
416+
return;
417+
}
418+
419+
/* Set header size to the max data that is in the uref. */
420+
num_samples = (uref_size - S302_HEADER_SIZE) / (pair_length * (num_channels / 2));
421+
422+
if (ubase_check(reframe(upipe_s302f, uref, num_samples, uref_size, S302_HEADER_SIZE)))
423+
upipe_s302f_output(upipe, uref, upump_p);
424+
else
425+
uref_free(uref);
426+
}
427+
428+
else if (upipe_s302f->have_valid_header) {
429+
/* Number of whole samples in uref and scratch buffer. */
430+
int num_samples = (upipe_s302f->scratch_buffer_count + uref_size) / (upipe_s302f->pair_length * (upipe_s302f->num_channels / 2));
431+
432+
if (ubase_check(reframe(upipe_s302f, uref, num_samples, uref_size, 0)))
433+
upipe_s302f_output(upipe, uref, upump_p);
434+
else
435+
uref_free(uref);
436+
}
437+
438+
else {
439+
upipe_verbose(upipe, "no valid header, dropping uref");
440+
uref_free(uref);
441+
}
442+
443+
return;
444+
}
445+
#undef LOW_LATENCY
446+
257447
if (ubase_check(uref_block_get_start(uref))) {
258448
if (upipe_s302f->next_uref != NULL)
259449
upipe_s302f_work(upipe, upump_p);
@@ -316,6 +506,22 @@ static int upipe_s302f_control(struct upipe *upipe, int command, va_list args)
316506
{
317507
UBASE_HANDLED_RETURN(upipe_s302f_control_output(upipe, command, args));
318508
switch (command) {
509+
case UPIPE_REGISTER_REQUEST: {
510+
struct urequest *request = va_arg(args, struct urequest *);
511+
if (request->type == UREQUEST_UBUF_MGR ||
512+
request->type == UREQUEST_FLOW_FORMAT)
513+
return upipe_throw_provide_request(upipe, request);
514+
return upipe_s302f_alloc_output_proxy(upipe, request);
515+
}
516+
517+
case UPIPE_UNREGISTER_REQUEST: {
518+
struct urequest *request = va_arg(args, struct urequest *);
519+
if (request->type == UREQUEST_UBUF_MGR ||
520+
request->type == UREQUEST_FLOW_FORMAT)
521+
return UBASE_ERR_NONE;
522+
return upipe_s302f_free_output_proxy(upipe, request);
523+
}
524+
319525
case UPIPE_SET_FLOW_DEF: {
320526
struct uref *flow_def = va_arg(args, struct uref *);
321527
return upipe_s302f_set_flow_def(upipe, flow_def);
@@ -339,6 +545,7 @@ static void upipe_s302f_free(struct upipe *upipe)
339545
upipe_s302f_clean_flow_def(upipe);
340546
upipe_s302f_clean_sync(upipe);
341547

548+
upipe_s302f_clean_ubuf_mgr(upipe);
342549
upipe_s302f_clean_urefcount(upipe);
343550
upipe_s302f_free_void(upipe);
344551
}

0 commit comments

Comments
 (0)