Skip to content
  • mrk501's avatar
    audioringbuffer: Fix wrong memcpy address when reordering channels · 36183597
    mrk501 authored and Sebastian Dröge's avatar Sebastian Dröge committed
    When using multichannel audio data and being needed to reorder channels,
    audio data is not copied correctly because destination address of
    memcpy is wrong.
    
    For example, the following command
    $ gst-launch-1.0 pulsesrc ! audio/x-raw,channels=6,format=S16LE ! filesink location=test.raw
    will reproduce this issue if there is 6-ch audio input device.
    
    This commit fixes that.
    
    The detailed process of this issue is as follows:
    1. gst-launch-1.0 calls gst_pulsesrc_prepare (gst-plugins-good/ext/pulse/pulsesrc.c)
    
       1466 gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
       1467 {
       (skip...)
       1480   {
       1481     GstAudioRingBufferSpec s = *spec;
       1482     const pa_channel_map *m;
       1483
       1484     m = pa_stream_get_channel_map (pulsesrc->stream);
       1485     gst_pulse_channel_map_to_gst (m, &s);
       1486     gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
       1487         (pulsesrc)->ringbuffer, s.info.position);
       1488   }
    
       In my environment, after line 1485 is processed, position of spec and s are
         spec->info.position[0] = 0
         spec->info.position[1] = 1
         spec->info.position[2] = 2
         spec->info.position[3] = 6
         spec->info.position[4] = 7
         spec->info.position[5] = 8
    
         s.info.position[0] = 0
         s.info.position[1] = 6
         s.info.position[2] = 2
         s.info.position[3] = 1
         s.info.position[4] = 7
         s.info.position[5] = 8
    
       The values of spec->info.positions equal
       GST_AUDIO_BASE_SRC(pulsesrc)->ringbuffer->spec->info.positions.
    
    2. gst_audio_ring_buffer_set_channel_positions calls
       gst_audio_get_channel_reorder_map.
    
    3. Arguments of gst_audio_get_channel_reorder_map are
        from = s.info.position
        to = GST_AUDIO_BASE_SRC(pulsesrc)->ringbuffer->spec->info.positions
    
       At the end of this function, reorder_map is set to
         reorder_map[0] = 0
         reorder_map[1] = 3
         reorder_map[2] = 2
         reorder_map[3] = 1
         reorder_map[4] = 4
         reorder_map[5] = 5
    
    4. Go back to gst_audio_ring_buffer_set_channel_positions and
       2065       buf->need_reorder = TRUE;
       is processed.
    
    5. Finally, in gst_audio_ring_buffer_read,
    
       1821     if (need_reorder) {
       (skip...)
       1829           memcpy (data + i * bpf + reorder_map[j] * bps, ptr + j * bps, bps);
    
       is processed and makes this issue.
    36183597