Bug 1359451 - Update cubeb from upstream to 17503c4. r?padenot draft
authorAlex Chronopoulos <achronop@gmail.com>
Tue, 25 Apr 2017 18:25:01 +0300
changeset 567803 93b5559648a1ad8a3c0e7d6e985448c1c455cdbc
parent 567802 f229b7e5d91eb70d23d3e31db7caff9d69a2ef04
child 625775 8cf7399cb14da779cf432031455ddb467c417cfa
push id55707
push userachronop@gmail.com
push dateTue, 25 Apr 2017 15:28:42 +0000
reviewerspadenot
bugs1359451
milestone55.0a1
Bug 1359451 - Update cubeb from upstream to 17503c4. r?padenot MozReview-Commit-ID: C3NXIvjwjgD
media/libcubeb/README_MOZILLA
media/libcubeb/gtest/test_record.cpp
media/libcubeb/src/cubeb_audiounit.cpp
media/libcubeb/src/cubeb_mixer.cpp
media/libcubeb/src/cubeb_mixer.h
media/libcubeb/src/cubeb_pulse.c
media/libcubeb/src/cubeb_wasapi.cpp
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 6e52314f24bba463d6ca97951f7d9fcc677d76a4 (2017-04-18 17:28:50 +0200)
+The git commit ID used was 17503c41318ec7a18ba3d728fb803a66ec60cf84 (2017-04-25 15:26:11 +0200)
--- a/media/libcubeb/gtest/test_record.cpp
+++ b/media/libcubeb/gtest/test_record.cpp
@@ -87,17 +87,17 @@ TEST(cubeb, record)
    * have one. */
   if (!has_available_input_device(ctx)) {
     return;
   }
 
   params.format = STREAM_FORMAT;
   params.rate = SAMPLE_FREQUENCY;
   params.channels = 1;
-  params.layout = CUBEB_LAYOUT_MONO;
+  params.layout = CUBEB_LAYOUT_UNDEFINED;
 
   r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, &params, NULL, nullptr,
                         4096, data_cb_record, state_cb_record, &stream_state);
   ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream";
 
   std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)>
     cleanup_stream_at_exit(stream, cubeb_stream_destroy);
 
--- a/media/libcubeb/src/cubeb_audiounit.cpp
+++ b/media/libcubeb/src/cubeb_audiounit.cpp
@@ -221,16 +221,17 @@ channel_label_to_cubeb_channel(UInt32 la
     case kAudioChannelLabel_Right: return CHANNEL_RIGHT;
     case kAudioChannelLabel_Center: return CHANNEL_CENTER;
     case kAudioChannelLabel_LFEScreen: return CHANNEL_LFE;
     case kAudioChannelLabel_LeftSurround: return CHANNEL_LS;
     case kAudioChannelLabel_RightSurround: return CHANNEL_RS;
     case kAudioChannelLabel_RearSurroundLeft: return CHANNEL_RLS;
     case kAudioChannelLabel_RearSurroundRight: return CHANNEL_RRS;
     case kAudioChannelLabel_CenterSurround: return CHANNEL_RCENTER;
+    case kAudioChannelLabel_Unknown: return CHANNEL_UNMAPPED;
     default: return CHANNEL_INVALID;
   }
 }
 
 AudioChannelLabel
 cubeb_channel_to_channel_label(cubeb_channel channel)
 {
   switch (channel) {
@@ -239,16 +240,17 @@ cubeb_channel_to_channel_label(cubeb_cha
     case CHANNEL_RIGHT: return kAudioChannelLabel_Right;
     case CHANNEL_CENTER: return kAudioChannelLabel_Center;
     case CHANNEL_LFE: return kAudioChannelLabel_LFEScreen;
     case CHANNEL_LS: return kAudioChannelLabel_LeftSurround;
     case CHANNEL_RS: return kAudioChannelLabel_RightSurround;
     case CHANNEL_RLS: return kAudioChannelLabel_RearSurroundLeft;
     case CHANNEL_RRS: return kAudioChannelLabel_RearSurroundRight;
     case CHANNEL_RCENTER: return kAudioChannelLabel_CenterSurround;
+    case CHANNEL_UNMAPPED: return kAudioChannelLabel_Unknown;
     default: return kAudioChannelLabel_Unknown;
   }
 }
 
 #if TARGET_OS_IPHONE
 typedef UInt32 AudioDeviceID;
 typedef UInt32 AudioObjectID;
 
@@ -638,20 +640,20 @@ audiounit_get_input_device_id(AudioDevic
 
   return CUBEB_OK;
 }
 
 static int audiounit_stream_get_volume(cubeb_stream * stm, float * volume);
 static int audiounit_stream_set_volume(cubeb_stream * stm, float volume);
 
 static int
-audiounit_reinit_stream(cubeb_stream * stm, bool is_started)
+audiounit_reinit_stream(cubeb_stream * stm)
 {
   auto_lock context_lock(stm->context->mutex);
-  if (is_started) {
+  if (!stm->shutdown) {
     audiounit_stream_stop_internal(stm);
   }
 
   {
     auto_lock lock(stm->mutex);
     float volume = 0.0;
     int vol_rv = audiounit_stream_get_volume(stm, &volume);
 
@@ -666,32 +668,30 @@ audiounit_reinit_stream(cubeb_stream * s
       audiounit_stream_set_volume(stm, volume);
     }
 
     // Reset input frames to force new stream pre-buffer
     // silence if needed, check `is_extra_input_needed()`
     stm->frames_read = 0;
 
     // If the stream was running, start it again.
-    if (is_started) {
+    if (!stm->shutdown) {
       audiounit_stream_start_internal(stm);
     }
   }
   return CUBEB_OK;
 }
 
 static OSStatus
 audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_count,
                                      const AudioObjectPropertyAddress * addresses,
                                      void * user)
 {
   cubeb_stream * stm = (cubeb_stream*) user;
   stm->switching_device = true;
-  // Note if the stream was running or not
-  bool was_running = !stm->shutdown;
 
   LOG("(%p) Audio device changed, %u events.", stm, (unsigned int) address_count);
   for (UInt32 i = 0; i < address_count; i++) {
     switch(addresses[i].mSelector) {
       case kAudioHardwarePropertyDefaultOutputDevice: {
           LOG("Event[%u] - mSelector == kAudioHardwarePropertyDefaultOutputDevice", (unsigned int) i);
           // Allow restart to choose the new default
           stm->output_device = 0;
@@ -710,18 +710,22 @@ audiounit_property_listener_callback(Aud
           if (stm->is_default_input) {
             LOG("It's the default input device, ignore the event");
             return noErr;
           }
           // Allow restart to choose the new default. Event register only for input.
           stm->input_device = 0;
         }
         break;
-      case kAudioDevicePropertyDataSource:
-        LOG("Event[%u] - mSelector == kAudioHardwarePropertyDataSource", (unsigned int) i);
+      case kAudioDevicePropertyDataSource: {
+          LOG("Event[%u] - mSelector == kAudioHardwarePropertyDataSource", (unsigned int) i);
+          if (has_output(stm)) {
+              stm->output_device = 0;
+          }
+        }
         break;
       default:
         LOG("Event[%u] - mSelector == Unexpected Event id %d, return", (unsigned int) i, addresses[i].mSelector);
         return noErr;
     }
   }
 
   for (UInt32 i = 0; i < address_count; i++) {
@@ -738,17 +742,17 @@ audiounit_property_listener_callback(Aud
         break;
       }
     }
   }
 
   // Use a new thread, through the queue, to avoid deadlock when calling
   // Get/SetProperties method from inside notify callback
   dispatch_async(stm->context->serial_queue, ^() {
-    if (audiounit_reinit_stream(stm, was_running) != CUBEB_OK) {
+    if (audiounit_reinit_stream(stm) != CUBEB_OK) {
       stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
       LOG("(%p) Could not reopen the stream after switching.", stm);
     }
     stm->switching_device = false;
   });
 
   return noErr;
 }
@@ -1084,16 +1088,22 @@ audiounit_convert_channel_layout(AudioCh
     // kAudioChannelLayoutTag_UseChannelBitmap
     // kAudioChannelLayoutTag_Mono
     // kAudioChannelLayoutTag_Stereo
     // ....
     LOG("Only handle UseChannelDescriptions for now.\n");
     return CUBEB_LAYOUT_UNDEFINED;
   }
 
+  // This devices has more channels that we can support, bail out.
+  if (layout->mNumberChannelDescriptions >= CHANNEL_MAX) {
+    LOG("Audio device has more than %d channels, bailing out.", CHANNEL_MAX);
+    return CUBEB_LAYOUT_UNDEFINED;
+  }
+
   cubeb_channel_map cm;
   cm.channels = layout->mNumberChannelDescriptions;
   for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; ++i) {
     cm.map[i] = channel_label_to_cubeb_channel(layout->mChannelDescriptions[i].mChannelLabel);
   }
 
   return cubeb_channel_map_to_layout(&cm);
 }
@@ -2574,20 +2584,20 @@ audiounit_stream_start_internal(cubeb_st
     r = AudioOutputUnitStart(stm->output_unit);
     assert(r == 0);
   }
 }
 
 static int
 audiounit_stream_start(cubeb_stream * stm)
 {
+  auto_lock context_lock(stm->context->mutex);
   stm->shutdown = false;
   stm->draining = false;
 
-  auto_lock context_lock(stm->context->mutex);
   audiounit_stream_start_internal(stm);
 
   stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
 
   LOG("Cubeb stream (%p) started successfully.", stm);
   return CUBEB_OK;
 }
 
@@ -2603,19 +2613,19 @@ audiounit_stream_stop_internal(cubeb_str
     r = AudioOutputUnitStop(stm->output_unit);
     assert(r == 0);
   }
 }
 
 static int
 audiounit_stream_stop(cubeb_stream * stm)
 {
+  auto_lock context_lock(stm->context->mutex);
   stm->shutdown = true;
 
-  auto_lock context_lock(stm->context->mutex);
   audiounit_stream_stop_internal(stm);
 
   stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
 
   LOG("Cubeb stream (%p) stopped successfully.", stm);
   return CUBEB_OK;
 }
 
--- a/media/libcubeb/src/cubeb_mixer.cpp
+++ b/media/libcubeb/src/cubeb_mixer.cpp
@@ -26,17 +26,18 @@
 #define MASK_3F2_LFE      (MASK_3F2 | (1 << CHANNEL_LFE))
 #define MASK_3F3R_LFE     (MASK_3F2_LFE | (1 << CHANNEL_RCENTER))
 #define MASK_3F4_LFE      (MASK_3F2_LFE | (1 << CHANNEL_RLS) | (1 << CHANNEL_RRS))
 
 cubeb_channel_layout cubeb_channel_map_to_layout(cubeb_channel_map const * channel_map)
 {
   uint32_t channel_mask = 0;
   for (uint8_t i = 0 ; i < channel_map->channels ; ++i) {
-    if (channel_map->map[i] == CHANNEL_INVALID) {
+    if (channel_map->map[i] == CHANNEL_INVALID ||
+        channel_map->map[i] == CHANNEL_UNMAPPED) {
       return CUBEB_LAYOUT_UNDEFINED;
     }
     channel_mask |= 1 << channel_map->map[i];
   }
 
   switch(channel_mask) {
     case MASK_MONO: return CUBEB_LAYOUT_MONO;
     case MASK_MONO_LFE: return CUBEB_LAYOUT_MONO_LFE;
--- a/media/libcubeb/src/cubeb_mixer.h
+++ b/media/libcubeb/src/cubeb_mixer.h
@@ -22,17 +22,18 @@ typedef enum {
   CHANNEL_RIGHT,
   CHANNEL_CENTER,
   CHANNEL_LS,
   CHANNEL_RS,
   CHANNEL_RLS,
   CHANNEL_RCENTER,
   CHANNEL_RRS,
   CHANNEL_LFE,
-  CHANNEL_MAX // Max number of supported channels.
+  CHANNEL_UNMAPPED,
+  CHANNEL_MAX = 256 // Max number of supported channels.
 } cubeb_channel;
 
 static cubeb_channel const CHANNEL_INDEX_TO_ORDER[CUBEB_LAYOUT_MAX][CHANNEL_MAX] = {
   { CHANNEL_INVALID },                                                                                            // UNDEFINED
   { CHANNEL_LEFT, CHANNEL_RIGHT },                                                                                // DUAL_MONO
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE },                                                                   // DUAL_MONO_LFE
   { CHANNEL_MONO },                                                                                               // MONO
   { CHANNEL_MONO, CHANNEL_LFE },                                                                                  // MONO_LFE
@@ -45,16 +46,18 @@ static cubeb_channel const CHANNEL_INDEX
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_RCENTER },                                               // 3F1
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER },                                  // 3F1_LFE
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LS, CHANNEL_RS },                                                        // 2F2
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS },                                           // 2F2_LFE
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LS, CHANNEL_RS },                                        // 3F2
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS },                           // 3F2_LFE
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER, CHANNEL_LS, CHANNEL_RS },          // 3F3R_LFE
   { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RLS, CHANNEL_RRS, CHANNEL_LS, CHANNEL_RS }  // 3F4_LFE
+  // When more channels are present, the stream is considered unmapped to a
+  // particular speaker set.
 };
 
 typedef struct {
   unsigned int channels;
   cubeb_channel map[CHANNEL_MAX];
 } cubeb_channel_map;
 
 cubeb_channel_layout cubeb_channel_map_to_layout(cubeb_channel_map const * channel_map);
--- a/media/libcubeb/src/cubeb_pulse.c
+++ b/media/libcubeb/src/cubeb_pulse.c
@@ -743,30 +743,35 @@ to_pulse_format(cubeb_sample_format form
 }
 
 static int
 create_pa_stream(cubeb_stream * stm,
                  pa_stream ** pa_stm,
                  cubeb_stream_params * stream_params,
                  char const * stream_name)
 {
-  assert(stm && stream_params && stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
-         CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels == stream_params->channels);
+  assert(stm && stream_params);
+  assert(&stm->input_stream == pa_stm || (&stm->output_stream == pa_stm &&
+         stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
+         CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels == stream_params->channels));
   *pa_stm = NULL;
   pa_sample_spec ss;
   ss.format = to_pulse_format(stream_params->format);
   if (ss.format == PA_SAMPLE_INVALID)
     return CUBEB_ERROR_INVALID_FORMAT;
   ss.rate = stream_params->rate;
   ss.channels = stream_params->channels;
 
-  pa_channel_map cm;
-  layout_to_channel_map(stream_params->layout, &cm);
-
-  *pa_stm = WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, &cm);
+  if (stream_params->layout == CUBEB_LAYOUT_UNDEFINED) {
+    *pa_stm = WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, NULL);
+  } else {
+    pa_channel_map cm;
+    layout_to_channel_map(stream_params->layout, &cm);
+    *pa_stm = WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, &cm);
+  }
   return (*pa_stm == NULL) ? CUBEB_ERROR : CUBEB_OK;
 }
 
 static pa_buffer_attr
 set_buffering_attribute(unsigned int latency_frames, pa_sample_spec * sample_spec)
 {
   pa_buffer_attr battr;
   battr.maxlength = -1;
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -1551,21 +1551,16 @@ int setup_wasapi_stream_one_side(cubeb_s
   mix_format->wBitsPerSample = stm->bytes_per_sample * 8;
   format_pcm->SubFormat = stm->waveformatextensible_sub_format;
   waveformatex_update_derived_properties(mix_format.get());
 
   /* Set channel layout only when there're more than two channels. Otherwise,
    * use the default setting retrieved from the stream format of the audio
    * engine's internal processing by GetMixFormat. */
   if (mix_format->nChannels > 2) {
-    /* Currently, we only support mono and stereo for capture stream. */
-    if (direction == eCapture) {
-      XASSERT(false && "Multichannel recording is not supported.");
-    }
-
     handle_channel_layout(stm, mix_format, stream_params);
   }
 
   mix_params->format = stream_params->format;
   mix_params->rate = mix_format->nSamplesPerSec;
   mix_params->channels = mix_format->nChannels;
   mix_params->layout = mask_to_channel_layout(format_pcm->dwChannelMask);
   if (mix_params->layout == CUBEB_LAYOUT_UNDEFINED) {