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>
5859/* Length in bytes of two audio samples */
5960static 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. */
6266struct 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)
105123UPIPE_HELPER_OUTPUT (upipe_s302f , output , flow_def , output_state , request_list )
106124UPIPE_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 );
235273upipe_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