@@ -71,6 +71,13 @@ const int16_t test_values_int[3][2] = {
7171 { INT16_MAX /4 , 0 },
7272};
7373
74+ const int32_t test_values_interleaved [4 ][2 ] = {
75+ { INT32_MIN /2 , INT32_MIN /2 + 1 },
76+ { INT32_MAX /4 * 3 , INT32_MAX /4 * 3 - 1 },
77+ { 0xdeafbeef , 0xcafebabe },
78+ { 0xabcdcba , 0x12345678 },
79+ };
80+
7481int count = 0 ;
7582
7683// Fill ubuf with the provided value.
@@ -112,6 +119,26 @@ static void fill_in_int(struct ubuf *ubuf, int16_t value)
112119 }
113120}
114121
122+ static void fill_in_interleaved (struct ubuf * ubuf , const int32_t * value )
123+ {
124+ size_t size ;
125+ uint8_t sample_size ;
126+ ubase_assert (ubuf_sound_size (ubuf , & size , & sample_size ));
127+
128+ const char * channel = NULL ;
129+ while (ubase_check (ubuf_sound_iterate_plane (ubuf , & channel )) &&
130+ channel != NULL ) {
131+ int32_t * buffer ;
132+ ubase_assert (ubuf_sound_plane_write_int32_t (ubuf , channel , 0 , -1 ,
133+ & buffer ));
134+
135+ for (int x = 0 ; x < size ; x ++ ) {
136+ buffer [2 * x + 0 ] = value [0 ];
137+ buffer [2 * x + 1 ] = value [1 ];
138+ }
139+ ubase_assert (ubuf_sound_plane_unmap (ubuf , channel , 0 , -1 ));
140+ }
141+ }
115142
116143/** definition of our uprobe */
117144static int catch (struct uprobe * uprobe , struct upipe * upipe ,
@@ -219,6 +246,40 @@ static void test_input_idx(struct upipe *upipe, struct uref *uref,
219246 uref_free (uref );
220247}
221248
249+ static void test_input_interleaved (struct upipe * upipe , struct uref * uref ,
250+ struct upump * * upump_p )
251+ {
252+ assert (uref != NULL );
253+ const uint8_t * r ;
254+
255+ const int32_t data [3 ][16 ] = { {
256+ [2 ] = test_values_interleaved [0 ][0 ],
257+ [3 ] = test_values_interleaved [0 ][1 ],
258+ [4 ] = test_values_interleaved [1 ][0 ],
259+ [5 ] = test_values_interleaved [1 ][1 ],
260+ }, {
261+ [4 ] = test_values_interleaved [2 ][0 ],
262+ [5 ] = test_values_interleaved [2 ][1 ],
263+ }, {
264+ [2 ] = test_values_interleaved [3 ][0 ],
265+ [3 ] = test_values_interleaved [3 ][1 ],
266+ } };
267+
268+ size_t size ;
269+ uint8_t sample_size ;
270+ ubase_assert (ubuf_sound_size (uref -> ubuf , & size , & sample_size ));
271+
272+ ubase_assert (uref_sound_plane_read_uint8_t (uref , "lrcLRS0123456789" , 0 , -1 , & r ));
273+ for (int x = 0 ; x < size ; x ++ )
274+ assert (memcmp (r + sample_size * x , data [count ], sample_size ) == 0 );
275+ ubase_assert (uref_sound_plane_unmap (uref , "lrcLRS0123456789" , 0 , -1 ));
276+
277+ upipe_notice (upipe , "interleaved data good" );
278+
279+ count ++ ;
280+ uref_free (uref );
281+ }
282+
222283/** helper phony pipe */
223284static int test_control (struct upipe * upipe , int command , va_list args )
224285{
@@ -565,6 +626,121 @@ int main(int argc, char *argv[])
565626 uref_free (output_flow );
566627 upipe_release (upipe_audio_merge );
567628
629+ /* Test interleaved */
630+
631+ uprobe_notice (logger , NULL , "testing interleaved" );
632+
633+ count = 0 ;
634+ merge_test_mgr .upipe_input = test_input_interleaved ;
635+
636+ /* merge superpipe */
637+ output_flow = uref_sound_flow_alloc_def (uref_mgr , "s32." , 16 , 64 );
638+ assert (output_flow );
639+ ubase_assert (uref_sound_flow_set_rate (output_flow , 48000 ));
640+ ubase_assert (uref_sound_flow_set_samples (output_flow , SAMPLES ));
641+
642+ ubase_assert (uref_sound_flow_set_channels (output_flow , 16 ));
643+ uref_sound_flow_add_plane (output_flow , "lrcLRS0123456789" );
644+ upipe_audio_merge = upipe_flow_alloc (upipe_audio_merge_mgr ,
645+ uprobe_pfx_alloc (uprobe_use (logger ), UPROBE_LOG_LEVEL , "merge" ), output_flow );
646+ assert (upipe_audio_merge != NULL );
647+
648+ /* connect output of merge pipe to sink */
649+ ubase_assert (upipe_set_output (upipe_audio_merge , upipe_sink ));
650+
651+ /* merge subpipe 0 */
652+ flow0 = uref_sound_flow_alloc_def (uref_mgr , "s32." , 2 , 8 );
653+ assert (flow0 );
654+ ubase_assert (uref_sound_flow_add_plane (flow0 , "lr" ));
655+ ubase_assert (uref_sound_flow_set_channels (flow0 , 2 ));
656+ ubase_assert (uref_sound_flow_set_channel_idx (flow0 , 2 ));
657+ uref_dump (flow0 , logger );
658+ upipe_audio_merge_input0 = upipe_void_alloc_sub (upipe_audio_merge ,
659+ uprobe_pfx_alloc (uprobe_use (logger ), UPROBE_LOG_LEVEL ,
660+ "merge input 0" ));
661+ assert (upipe_audio_merge_input0 != NULL );
662+ ubase_assert (upipe_set_flow_def (upipe_audio_merge_input0 , flow0 ));
663+
664+ /* merge subpipe 1 */
665+ flow1 = uref_sound_flow_alloc_def (uref_mgr , "s32." , 2 , 8 );
666+ assert (flow1 );
667+ ubase_assert (uref_sound_flow_add_plane (flow1 , "lr" ));
668+ ubase_assert (uref_sound_flow_set_channels (flow1 , 2 ));
669+ ubase_assert (uref_sound_flow_set_channel_idx (flow1 , 4 ));
670+ uref_dump (flow1 , logger );
671+ upipe_audio_merge_input1 = upipe_void_alloc_sub (upipe_audio_merge ,
672+ uprobe_pfx_alloc (uprobe_use (logger ), UPROBE_LOG_LEVEL ,
673+ "merge input 1" ));
674+ assert (upipe_audio_merge_input1 != NULL );
675+ ubase_assert (upipe_set_flow_def (upipe_audio_merge_input1 , flow1 ));
676+
677+ /* input 0 sound ubuf manager */
678+ sound_mgr_0 = ubuf_mem_mgr_alloc_from_flow_def (
679+ UBUF_POOL_DEPTH , UBUF_POOL_DEPTH , umem_mgr , flow0 );
680+ assert (sound_mgr_0 );
681+
682+ /* First, feed a "real" sample to input 0 to test the pipe's function...*/
683+ uref = uref_sound_alloc (uref_mgr , sound_mgr_0 , SAMPLES );
684+ assert (uref != NULL );
685+ fill_in_interleaved (uref -> ubuf , test_values_interleaved [0 ]);
686+ ubase_assert (uref_sound_flow_set_samples (uref , SAMPLES ));
687+ upipe_input (upipe_audio_merge_input0 , uref , NULL );
688+
689+ /* input 1 sound ubuf manager */
690+ sound_mgr_1 = ubuf_mem_mgr_alloc_from_flow_def (
691+ UBUF_POOL_DEPTH , UBUF_POOL_DEPTH , umem_mgr , flow1 );
692+ assert (sound_mgr_1 );
693+
694+ /* .. and then to input 1. */
695+ uref = uref_sound_alloc (uref_mgr , sound_mgr_1 , SAMPLES );
696+ assert (uref != NULL );
697+ fill_in_interleaved (uref -> ubuf , test_values_interleaved [1 ]);
698+ ubase_assert (uref_sound_flow_set_samples (uref , SAMPLES ));
699+ upipe_input (upipe_audio_merge_input1 , uref , NULL );
700+
701+ /* Then feed a dummy sample with no attached ubuf to test error handling to input 0... */
702+ uref = uref_sound_alloc (uref_mgr , sound_mgr_0 , SAMPLES );
703+ assert (uref != NULL );
704+ ubuf_free (uref -> ubuf );
705+ uref -> ubuf = NULL ;
706+ ubase_assert (uref_sound_flow_set_samples (uref , SAMPLES ));
707+ upipe_input (upipe_audio_merge_input0 , uref , NULL );
708+
709+ /* .. and a real one to input 1. */
710+ uref = uref_sound_alloc (uref_mgr , sound_mgr_1 , SAMPLES );
711+ assert (uref != NULL );
712+ fill_in_interleaved (uref -> ubuf , test_values_interleaved [2 ]);
713+ ubase_assert (uref_sound_flow_set_samples (uref , SAMPLES ));
714+ upipe_input (upipe_audio_merge_input1 , uref , NULL );
715+
716+ /* Then a real one to input 0. */
717+ uref = uref_sound_alloc (uref_mgr , sound_mgr_0 , SAMPLES );
718+ assert (uref != NULL );
719+ fill_in_interleaved (uref -> ubuf , test_values_interleaved [3 ]);
720+ ubase_assert (uref_sound_flow_set_samples (uref , SAMPLES ));
721+ upipe_input (upipe_audio_merge_input0 , uref , NULL );
722+
723+ /* ... and a fake one to input 1 */
724+ uref = uref_sound_alloc (uref_mgr , sound_mgr_1 , SAMPLES );
725+ assert (uref != NULL );
726+ ubuf_free (uref -> ubuf );
727+ uref -> ubuf = NULL ;
728+ ubase_assert (uref_sound_flow_set_samples (uref , SAMPLES ));
729+ upipe_input (upipe_audio_merge_input1 , uref , NULL );
730+
731+ upipe_release (upipe_audio_merge_input0 );
732+ upipe_release (upipe_audio_merge_input1 );
733+
734+ assert (count == 3 );
735+
736+ /* clean */
737+ uref_free (flow0 );
738+ uref_free (flow1 );
739+ ubuf_mgr_release (sound_mgr_0 );
740+ ubuf_mgr_release (sound_mgr_1 );
741+ uref_free (output_flow );
742+ upipe_release (upipe_audio_merge );
743+
568744 upipe_mgr_release (upipe_audio_merge_mgr ); // nop
569745
570746 test_free (upipe_sink );
0 commit comments