Bug 1722440 - Update cubeb to e1456788. r=cubeb-reviewers,padenot
authorMatthew Gregan <kinetik@flim.org>
Tue, 27 Jul 2021 20:56:30 +0000
changeset 586784 952d19f991b39cf4f718d96caa37eb24c4a71f91
parent 586783 c0e958baeeb7e6c0d3668a1be4d65ddadf173e8a
child 586785 b54c6448f3f32630917dea55a00a2a4d747dad4e
push id146987
push usermgregan@mozilla.com
push dateTue, 27 Jul 2021 20:58:55 +0000
treeherderautoland@952d19f991b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscubeb-reviewers, padenot
bugs1722440
milestone92.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1722440 - Update cubeb to e1456788. r=cubeb-reviewers,padenot Differential Revision: https://phabricator.services.mozilla.com/D120925
media/libcubeb/gtest/test_duplex.cpp
media/libcubeb/include/cubeb.h
media/libcubeb/moz.yaml
media/libcubeb/src/cubeb_wasapi.cpp
--- a/media/libcubeb/gtest/test_duplex.cpp
+++ b/media/libcubeb/gtest/test_duplex.cpp
@@ -174,8 +174,142 @@ TEST(cubeb, duplex_collection_change)
   ASSERT_EQ(r, CUBEB_OK) << "Could not get minimal latency";
 
   r = cubeb_stream_init(ctx, &stream, "Cubeb duplex",
                         NULL, &input_params, NULL, &output_params,
                         latency_frames, data_cb_duplex, state_cb_duplex, nullptr);
   ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream";
   cubeb_stream_destroy(stream);
 }
+
+long data_cb_input(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
+{
+  if (stream == NULL || inputbuffer == NULL || outputbuffer != NULL) {
+    return CUBEB_ERROR;
+  }
+
+  return nframes;
+}
+
+void state_cb_input(cubeb_stream * stream, void * /*user*/, cubeb_state state)
+{
+  if (stream == NULL)
+    return;
+
+  switch (state) {
+  case CUBEB_STATE_STARTED:
+    fprintf(stderr, "stream started\n"); break;
+  case CUBEB_STATE_STOPPED:
+    fprintf(stderr, "stream stopped\n"); break;
+  case CUBEB_STATE_DRAINED:
+    fprintf(stderr, "stream drained\n"); break;
+  case CUBEB_STATE_ERROR:
+    fprintf(stderr, "stream runs into error state\n"); break;
+  default:
+    fprintf(stderr, "unknown stream state %d\n", state);
+  }
+
+  return;
+}
+
+std::vector<cubeb_devid> get_devices(cubeb * ctx, cubeb_device_type type) {
+  std::vector<cubeb_devid> devices;
+
+  cubeb_device_collection collection;
+  int r = cubeb_enumerate_devices(ctx, type, &collection);
+
+  if (r != CUBEB_OK) {
+    fprintf(stderr, "Failed to enumerate devices\n");
+    return devices;
+  }
+
+  for (uint32_t i = 0; i < collection.count; i++) {
+    if (collection.device[i].state == CUBEB_DEVICE_STATE_ENABLED) {
+      devices.emplace_back(collection.device[i].devid);
+    }
+  }
+
+  cubeb_device_collection_destroy(ctx, &collection);
+
+  return devices;
+}
+
+TEST(cubeb, one_duplex_one_input)
+{
+  cubeb *ctx;
+  cubeb_stream *duplex_stream;
+  cubeb_stream_params input_params;
+  cubeb_stream_params output_params;
+  int r;
+  user_state_duplex duplex_stream_state;
+  uint32_t latency_frames = 0;
+
+  r = common_init(&ctx, "Cubeb duplex example");
+  ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
+
+  std::unique_ptr<cubeb, decltype(&cubeb_destroy)>
+    cleanup_cubeb_at_exit(ctx, cubeb_destroy);
+
+  /* This test needs at least two available input devices. */
+  std::vector<cubeb_devid> input_devices = get_devices(ctx, CUBEB_DEVICE_TYPE_INPUT);
+  if (input_devices.size() < 2) {
+    return;
+  }
+
+  /* This test needs at least one available output device. */
+  std::vector<cubeb_devid> output_devices = get_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT);
+  if (output_devices.size() < 1) {
+    return;
+  }
+
+  cubeb_devid duplex_input = input_devices.front();
+  cubeb_devid duplex_output = nullptr; // default device
+  cubeb_devid input_only = input_devices.back();
+
+  /* typical use-case: mono voice input, stereo output, low latency. */
+  input_params.format = STREAM_FORMAT;
+  input_params.rate = SAMPLE_FREQUENCY;
+  input_params.channels = INPUT_CHANNELS;
+  input_params.layout = CUBEB_LAYOUT_UNDEFINED;
+  input_params.prefs = CUBEB_STREAM_PREF_VOICE;
+
+  output_params.format = STREAM_FORMAT;
+  output_params.rate = SAMPLE_FREQUENCY;
+  output_params.channels = OUTPUT_CHANNELS;
+  output_params.layout = OUTPUT_LAYOUT;
+  output_params.prefs = CUBEB_STREAM_PREF_NONE;
+
+  r = cubeb_get_min_latency(ctx, &output_params, &latency_frames);
+  ASSERT_EQ(r, CUBEB_OK) << "Could not get minimal latency";
+
+  r = cubeb_stream_init(ctx, &duplex_stream, "Cubeb duplex",
+                        duplex_input, &input_params, duplex_output, &output_params,
+                        latency_frames, data_cb_duplex, state_cb_duplex, &duplex_stream_state);
+  ASSERT_EQ(r, CUBEB_OK) << "Error initializing duplex cubeb stream";
+
+  std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)>
+    cleanup_stream_at_exit(duplex_stream, cubeb_stream_destroy);
+
+  r = cubeb_stream_start(duplex_stream);
+  ASSERT_EQ(r, CUBEB_OK) << "Could not start duplex stream";
+  delay(500);
+
+  cubeb_stream *input_stream;
+  r = cubeb_stream_init(ctx, &input_stream, "Cubeb input",
+                        input_only, &input_params, NULL, NULL,
+                        latency_frames, data_cb_input, state_cb_input, nullptr);
+  ASSERT_EQ(r, CUBEB_OK) << "Error initializing input-only cubeb stream";
+
+  std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)>
+    cleanup_input_stream_at_exit(input_stream, cubeb_stream_destroy);
+  
+  r = cubeb_stream_start(input_stream);
+  ASSERT_EQ(r, CUBEB_OK) << "Could not start input stream";
+  delay(500);
+
+  r = cubeb_stream_stop(duplex_stream);
+  ASSERT_EQ(r, CUBEB_OK) << "Could not stop duplex stream";
+
+  r = cubeb_stream_stop(input_stream);
+  ASSERT_EQ(r, CUBEB_OK) << "Could not stop input stream";
+
+  ASSERT_FALSE(duplex_stream_state.invalid_audio_value.load());
+}
--- a/media/libcubeb/include/cubeb.h
+++ b/media/libcubeb/include/cubeb.h
@@ -235,19 +235,18 @@ typedef enum {
                                        change the audio input or output devices
                                        selected, as well as the quality of the stream,
                                        for example to accomodate bluetooth SCO modes on
                                        bluetooth devices. */
   CUBEB_STREAM_PREF_RAW = 0x08, /**< Windows only. Bypass all signal processing
                                      except for always on APO, driver and hardware. */
   CUBEB_STREAM_PREF_PERSIST = 0x10, /**< Request that the volume and mute settings
                                          should persist across restarts of the stream
-                                         and/or application. May not be honored for
-                                         all backends and platforms. */
-
+                                         and/or application. This is obsolete and ignored
+                                         by all backends. */
   CUBEB_STREAM_PREF_JACK_NO_AUTO_CONNECT = 0x20  /**< Don't automatically try to connect
                                                       ports.  Only affects the jack
                                                       backend. */
 } cubeb_stream_prefs;
 
 /** Stream format initialization parameters. */
 typedef struct {
   cubeb_sample_format format;   /**< Requested sample format.  One of
--- a/media/libcubeb/moz.yaml
+++ b/media/libcubeb/moz.yaml
@@ -14,10 +14,10 @@ bugzilla:
 origin:
   name: "cubeb"
   description: "Cross platform audio library"
 
   url: "https://github.com/kinetiknz/cubeb"
   license: "ISC"
 
   # update.sh will update this value
-  release: "b2f60c983df34f8cac0e061ef32da531c6d82536 (2021-07-13 13:51:30 +0200)"
+  release: "e1456788c48c5ed6b55bc107a7342d63f2a08413 (2021-07-27 16:11:10 +1200)"
 
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -1910,20 +1910,16 @@ initialize_iaudioclient3(com_ptr<IAudioC
 
   if (flags & AUDCLNT_STREAMFLAGS_LOOPBACK) {
     // IAudioClient3 doesn't work with loopback streams, and will return error
     // 88890021: AUDCLNT_E_INVALID_STREAM_FLAG
     LOG("Audio stream is loopback, not using IAudioClient3");
     return false;
   }
 
-  // IAudioClient3 doesn't support AUDCLNT_STREAMFLAGS_NOPERSIST, and will return
-  // AUDCLNT_E_INVALID_STREAM_FLAG. This is undocumented.
-  flags = flags & ~AUDCLNT_STREAMFLAGS_NOPERSIST;
-
   // Some people have reported glitches with capture streams:
   // http://blog.nirbheek.in/2018/03/low-latency-audio-on-windows-with.html
   if (direction == eCapture) {
     LOG("Audio stream is capture, not using IAudioClient3");
     return false;
   }
 
   // Possibly initialize a shared-mode stream using IAudioClient3. Initializing
@@ -2129,21 +2125,16 @@ int setup_wasapi_stream_one_side(cubeb_s
       stream_params->format, stream_params->rate, stream_params->channels,
       stream_params->layout,
       mix_params->format, mix_params->rate, mix_params->channels,
       mix_params->layout);
 
 
   DWORD flags = 0;
 
-  bool is_persist = stream_params->prefs & CUBEB_STREAM_PREF_PERSIST;
-  if (!is_persist) {
-    flags |= AUDCLNT_STREAMFLAGS_NOPERSIST;
-  }
-
   // Check if a loopback device should be requested. Note that event callbacks
   // do not work with loopback devices, so only request these if not looping.
   if (is_loopback) {
     flags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
   } else {
     flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
   }
 
@@ -2267,25 +2258,24 @@ void wasapi_find_matching_output_device(
   int rv = wasapi_enumerate_devices(stm->context, (cubeb_device_type)(CUBEB_DEVICE_TYPE_INPUT|CUBEB_DEVICE_TYPE_OUTPUT), &collection);
   if (rv != CUBEB_OK) {
     return;
   }
 
   // Find the input device, and then find the output device with the same group
   // id and the same rate.
   for (uint32_t i = 0; i < collection.count; i++) {
-    cubeb_device_info dev = collection.device[i];
-    if (dev.devid == input_device_id) {
-      input_device = &dev;
+    if (collection.device[i].devid == input_device_id) {
+      input_device = &collection.device[i];
       break;
     }
   }
 
   for (uint32_t i = 0; i < collection.count; i++) {
-    cubeb_device_info dev = collection.device[i];
+    cubeb_device_info & dev = collection.device[i];
     if (dev.type == CUBEB_DEVICE_TYPE_OUTPUT && dev.group_id && input_device &&
         !strcmp(dev.group_id, input_device->group_id) &&
         dev.default_rate == input_device->default_rate) {
       LOG("Found matching device for %s: %s", input_device->friendly_name,
           dev.friendly_name);
       stm->output_device_id =
           utf8_to_wstr(reinterpret_cast<char const *>(dev.devid));
     }