зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1803765 - Update libcubeb to revision b8765e13. r=cubeb-reviewers,kinetik
Differential Revision: https://phabricator.services.mozilla.com/D163720
This commit is contained in:
Родитель
5c9197d6a9
Коммит
41f19649c9
|
@ -9,8 +9,8 @@ origin:
|
|||
description: "Cross platform audio library"
|
||||
url: https://github.com/mozilla/cubeb
|
||||
license: ISC
|
||||
release: 93d1fa3fccdc22da37aa59f67b213591797db369 (2022-09-22T21:52:54Z).
|
||||
revision: 93d1fa3fccdc22da37aa59f67b213591797db369
|
||||
release: cfc5692bf7c556d5c9f66f782fa15d1e8b80e761 (2022-12-05T16:27:36Z).
|
||||
revision: cfc5692bf7c556d5c9f66f782fa15d1e8b80e761
|
||||
|
||||
vendoring:
|
||||
url: https://github.com/mozilla/cubeb
|
||||
|
|
|
@ -351,6 +351,8 @@ cubeb_destroy(cubeb * context)
|
|||
}
|
||||
|
||||
context->ops->destroy(context);
|
||||
|
||||
cubeb_set_log_callback(CUBEB_LOG_DISABLED, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -65,47 +65,67 @@ public:
|
|||
void push(char const str[CUBEB_LOG_MESSAGE_MAX_SIZE])
|
||||
{
|
||||
cubeb_log_message msg(str);
|
||||
msg_queue.enqueue(msg);
|
||||
msg_queue->enqueue(msg);
|
||||
}
|
||||
void run()
|
||||
{
|
||||
std::thread([this]() {
|
||||
assert(logging_thread.get_id() == std::thread::id());
|
||||
assert(msg_queue);
|
||||
logging_thread = std::thread([this]() {
|
||||
CUBEB_REGISTER_THREAD("cubeb_log");
|
||||
while (true) {
|
||||
while (!shutdown_thread) {
|
||||
cubeb_log_message msg;
|
||||
while (msg_queue.dequeue(&msg, 1)) {
|
||||
while (msg_queue->dequeue(&msg, 1)) {
|
||||
cubeb_log_internal_no_format(msg.get());
|
||||
}
|
||||
#ifdef _WIN32
|
||||
Sleep(CUBEB_LOG_BATCH_PRINT_INTERVAL_MS);
|
||||
#else
|
||||
timespec sleep_duration = sleep_for;
|
||||
timespec remainder;
|
||||
do {
|
||||
if (nanosleep(&sleep_duration, &remainder) == 0 || errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
sleep_duration = remainder;
|
||||
} while (remainder.tv_sec || remainder.tv_nsec);
|
||||
#endif
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(CUBEB_LOG_BATCH_PRINT_INTERVAL_MS));
|
||||
}
|
||||
CUBEB_UNREGISTER_THREAD();
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
// Tell the underlying queue the producer thread has changed, so it does not
|
||||
// assert in debug. This should be called with the thread stopped.
|
||||
void reset_producer_thread() { msg_queue.reset_thread_ids(); }
|
||||
void reset_producer_thread() { msg_queue->reset_thread_ids(); }
|
||||
void start()
|
||||
{
|
||||
msg_queue.reset(
|
||||
new lock_free_queue<cubeb_log_message>(CUBEB_LOG_MESSAGE_QUEUE_DEPTH));
|
||||
shutdown_thread = false;
|
||||
run();
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
shutdown_thread = true;
|
||||
if (logging_thread.get_id() != std::thread::id()) {
|
||||
logging_thread.join();
|
||||
logging_thread = std::thread();
|
||||
// This is OK, because at this point, we know the consumer has stopped
|
||||
// consuming.
|
||||
msg_queue->reset_thread_ids();
|
||||
purge_queue();
|
||||
msg_queue.reset(nullptr);
|
||||
}
|
||||
}
|
||||
void purge_queue()
|
||||
{
|
||||
assert(logging_thread.get_id() == std::thread::id() &&
|
||||
"Only purge the async logger queue when the thread is stopped");
|
||||
if (!msg_queue) {
|
||||
return;
|
||||
}
|
||||
cubeb_log_message msg;
|
||||
while (msg_queue->dequeue(&msg, 1)) { /* nothing */
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
#ifndef _WIN32
|
||||
const struct timespec sleep_for = {
|
||||
CUBEB_LOG_BATCH_PRINT_INTERVAL_MS / 1000,
|
||||
(CUBEB_LOG_BATCH_PRINT_INTERVAL_MS % 1000) * 1000 * 1000};
|
||||
#endif
|
||||
cubeb_async_logger() : msg_queue(CUBEB_LOG_MESSAGE_QUEUE_DEPTH) { run(); }
|
||||
cubeb_async_logger() {}
|
||||
/** This is quite a big data structure, but is only instantiated if the
|
||||
* asynchronous logger is used.*/
|
||||
lock_free_queue<cubeb_log_message> msg_queue;
|
||||
std::unique_ptr<lock_free_queue<cubeb_log_message>> msg_queue;
|
||||
std::atomic<bool> shutdown_thread = {false};
|
||||
std::thread logging_thread;
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -115,8 +135,8 @@ cubeb_log_internal(char const * file, uint32_t line, char const * fmt, ...)
|
|||
va_start(args, fmt);
|
||||
char msg[CUBEB_LOG_MESSAGE_MAX_SIZE];
|
||||
vsnprintf(msg, CUBEB_LOG_MESSAGE_MAX_SIZE, fmt, args);
|
||||
g_cubeb_log_callback.load()("%s:%d:%s", file, line, msg);
|
||||
va_end(args);
|
||||
g_cubeb_log_callback.load()("%s:%d:%s", file, line, msg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -148,11 +168,28 @@ cubeb_async_log_reset_threads(void)
|
|||
cubeb_async_logger::get().reset_producer_thread();
|
||||
}
|
||||
|
||||
void
|
||||
cubeb_noop_log_callback(char const * /* fmt */, ...)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
cubeb_log_set(cubeb_log_level log_level, cubeb_log_callback log_callback)
|
||||
{
|
||||
g_cubeb_log_level = log_level;
|
||||
g_cubeb_log_callback = log_callback;
|
||||
// Once a callback has a been set, `g_cubeb_log_callback` is never set back to
|
||||
// nullptr, to prevent a TOCTOU race between checking the pointer
|
||||
if (log_callback && log_level != CUBEB_LOG_DISABLED) {
|
||||
g_cubeb_log_callback = log_callback;
|
||||
cubeb_async_logger::get().start();
|
||||
} else if (!log_callback || CUBEB_LOG_DISABLED) {
|
||||
// This returns once the thread has joined.
|
||||
cubeb_async_logger::get().stop();
|
||||
g_cubeb_log_callback = cubeb_noop_log_callback;
|
||||
cubeb_async_logger::get().purge_queue();
|
||||
} else {
|
||||
assert(false && "Incorrect parameters passed to cubeb_log_set");
|
||||
}
|
||||
}
|
||||
|
||||
cubeb_log_level
|
||||
|
@ -164,5 +201,8 @@ cubeb_log_get_level()
|
|||
cubeb_log_callback
|
||||
cubeb_log_get_callback()
|
||||
{
|
||||
if (g_cubeb_log_callback == cubeb_noop_log_callback) {
|
||||
return nullptr;
|
||||
}
|
||||
return g_cubeb_log_callback;
|
||||
}
|
||||
|
|
|
@ -33,9 +33,9 @@ extern "C" {
|
|||
void
|
||||
cubeb_log_set(cubeb_log_level log_level, cubeb_log_callback log_callback);
|
||||
cubeb_log_level
|
||||
cubeb_log_get_level();
|
||||
cubeb_log_get_level(void);
|
||||
cubeb_log_callback
|
||||
cubeb_log_get_callback();
|
||||
cubeb_log_get_callback(void);
|
||||
void
|
||||
cubeb_log_internal_no_format(const char * msg);
|
||||
void
|
||||
|
@ -54,14 +54,14 @@ cubeb_async_log_reset_threads(void);
|
|||
|
||||
#define LOG_INTERNAL(level, fmt, ...) \
|
||||
do { \
|
||||
if (cubeb_log_get_level() <= level && cubeb_log_get_callback()) { \
|
||||
if (cubeb_log_get_level() >= level && cubeb_log_get_callback()) { \
|
||||
cubeb_log_internal(__FILENAME__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ALOG_INTERNAL(level, fmt, ...) \
|
||||
do { \
|
||||
if (cubeb_log_get_level() <= level && cubeb_log_get_callback()) { \
|
||||
if (cubeb_log_get_level() >= level && cubeb_log_get_callback()) { \
|
||||
cubeb_async_log(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
|
|
@ -26,11 +26,6 @@
|
|||
using namespace std;
|
||||
|
||||
#define MAX_NUM_CHANNELS 32
|
||||
|
||||
#if !defined(M_PI)
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define VOLUME 0.2
|
||||
|
||||
float get_frequency(int channel_index)
|
||||
|
@ -242,3 +237,7 @@ TEST(cubeb, run_channel_rate_test)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#undef MAX_NUM_CHANNELS
|
||||
#undef VOLUME
|
||||
|
|
|
@ -258,3 +258,5 @@ TEST(cubeb, run_deadlock_test)
|
|||
|
||||
cubeb_stream_stop(stream);
|
||||
}
|
||||
|
||||
#undef CALL_THREAD_KILLER
|
||||
|
|
|
@ -107,3 +107,10 @@ TEST(cubeb, device_changed_callbacks)
|
|||
|
||||
cubeb_stream_destroy(stream);
|
||||
}
|
||||
|
||||
#undef SAMPLE_FREQUENCY
|
||||
#undef STREAM_FORMAT
|
||||
#undef INPUT_CHANNELS
|
||||
#undef INPUT_LAYOUT
|
||||
#undef OUTPUT_CHANNELS
|
||||
#undef OUTPUT_LAYOUT
|
||||
|
|
|
@ -337,3 +337,10 @@ TEST(cubeb, one_duplex_one_input)
|
|||
|
||||
ASSERT_FALSE(duplex_stream_state.invalid_audio_value.load());
|
||||
}
|
||||
|
||||
#undef SAMPLE_FREQUENCY
|
||||
#undef STREAM_FORMAT
|
||||
#undef INPUT_CHANNELS
|
||||
#undef INPUT_LAYOUT
|
||||
#undef OUTPUT_CHANNELS
|
||||
#undef OUTPUT_LAYOUT
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright © 2016 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
|
||||
/* cubeb_logging test */
|
||||
#include "gtest/gtest.h"
|
||||
#if !defined(_XOPEN_SOURCE)
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
#include "cubeb/cubeb.h"
|
||||
#include <atomic>
|
||||
#include <math.h>
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define PRINT_LOGS_TO_STDERR 0
|
||||
|
||||
std::atomic<uint32_t> log_statements_received = {0};
|
||||
std::atomic<uint32_t> data_callback_call_count = {0};
|
||||
|
||||
void
|
||||
test_logging_callback(char const * fmt, ...)
|
||||
{
|
||||
log_statements_received++;
|
||||
#if PRINT_LOGS_TO_STDERR == 1
|
||||
char buf[1024];
|
||||
va_list argslist;
|
||||
va_start(argslist, fmt);
|
||||
vsnprintf(buf, 1024, fmt, argslist);
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
va_end(argslist);
|
||||
#endif // PRINT_LOGS_TO_STDERR
|
||||
}
|
||||
|
||||
long
|
||||
data_cb_load(cubeb_stream * stream, void * user, const void * inputbuffer,
|
||||
void * outputbuffer, long nframes)
|
||||
{
|
||||
data_callback_call_count++;
|
||||
return nframes;
|
||||
}
|
||||
|
||||
void
|
||||
state_cb(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;
|
||||
default:
|
||||
fprintf(stderr, "unknown stream state %d\n", state);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Waits for at least one audio callback to have occured.
|
||||
void wait_for_audio_callback() {
|
||||
uint32_t audio_callback_index =
|
||||
data_callback_call_count.load(std::memory_order_acquire);
|
||||
while (audio_callback_index ==
|
||||
data_callback_call_count.load(std::memory_order_acquire)) {
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(cubeb, logging)
|
||||
{
|
||||
cubeb * ctx;
|
||||
cubeb_stream * stream;
|
||||
cubeb_stream_params output_params;
|
||||
int r;
|
||||
uint32_t latency_frames = 0;
|
||||
|
||||
cubeb_set_log_callback(CUBEB_LOG_NORMAL, test_logging_callback);
|
||||
|
||||
r = common_init(&ctx, "Cubeb logging test");
|
||||
ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
|
||||
|
||||
std::unique_ptr<cubeb, decltype(&cubeb_destroy)> cleanup_cubeb_at_exit(
|
||||
ctx, cubeb_destroy);
|
||||
|
||||
output_params.format = CUBEB_SAMPLE_FLOAT32LE;
|
||||
output_params.rate = 48000;
|
||||
output_params.channels = 2;
|
||||
output_params.layout = CUBEB_LAYOUT_STEREO;
|
||||
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, &stream, "Cubeb logging", NULL, NULL, NULL,
|
||||
&output_params, latency_frames, data_cb_load, state_cb,
|
||||
NULL);
|
||||
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);
|
||||
|
||||
ASSERT_NE(log_statements_received.load(std::memory_order_acquire), 0u);
|
||||
|
||||
cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr);
|
||||
log_statements_received.store(0, std::memory_order_release);
|
||||
|
||||
// This is synchronous and we'll receive log messages on all backends that we
|
||||
// test
|
||||
cubeb_stream_start(stream);
|
||||
|
||||
ASSERT_EQ(log_statements_received.load(std::memory_order_acquire), 0u);
|
||||
|
||||
cubeb_set_log_callback(CUBEB_LOG_VERBOSE, test_logging_callback);
|
||||
|
||||
wait_for_audio_callback();
|
||||
|
||||
ASSERT_NE(log_statements_received.load(std::memory_order_acquire), 0u);
|
||||
|
||||
bool log_callback_set = true;
|
||||
uint32_t iterations = 100;
|
||||
while (iterations--) {
|
||||
wait_for_audio_callback();
|
||||
|
||||
if (!log_callback_set) {
|
||||
ASSERT_EQ(log_statements_received.load(std::memory_order_acquire), 0u);
|
||||
// Set a logging callback, start logging
|
||||
cubeb_set_log_callback(CUBEB_LOG_VERBOSE, test_logging_callback);
|
||||
log_callback_set = true;
|
||||
} else {
|
||||
// Disable the logging callback, stop logging.
|
||||
ASSERT_NE(log_statements_received.load(std::memory_order_acquire), 0u);
|
||||
cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr);
|
||||
log_statements_received.store(0, std::memory_order_release);
|
||||
// Disabling logging should flush any log message -- wait a bit and check
|
||||
// that this is true.
|
||||
ASSERT_EQ(log_statements_received.load(std::memory_order_acquire), 0u);
|
||||
log_callback_set = false;
|
||||
}
|
||||
}
|
||||
|
||||
cubeb_stream_stop(stream);
|
||||
}
|
|
@ -90,3 +90,6 @@ TEST(cubeb, overload_callback)
|
|||
delay(500);
|
||||
cubeb_stream_stop(stream);
|
||||
}
|
||||
|
||||
#undef SAMPLE_FREQUENCY
|
||||
#undef STREAM_FORMAT
|
||||
|
|
|
@ -114,3 +114,6 @@ TEST(cubeb, record)
|
|||
ASSERT_FALSE(stream_state.invalid_audio_value.load());
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SAMPLE_FREQUENCY
|
||||
#undef STREAM_FORMAT
|
||||
|
|
|
@ -53,7 +53,7 @@ const uint32_t max_chunks = 30; /* ms */
|
|||
const uint32_t chunk_increment = 10;
|
||||
#endif
|
||||
|
||||
#define DUMP_ARRAYS
|
||||
// #define DUMP_ARRAYS
|
||||
#ifdef DUMP_ARRAYS
|
||||
/**
|
||||
* Files produced by dump(...) can be converted to .wave files using:
|
||||
|
@ -1084,3 +1084,6 @@ TEST(cubeb, individual_methods) {
|
|||
ASSERT_EQ(frames_needed2, 0u);
|
||||
}
|
||||
|
||||
|
||||
#undef NOMINMAX
|
||||
#undef DUMP_ARRAYS
|
||||
|
|
|
@ -225,3 +225,5 @@ TEST(cubeb, ring_buffer)
|
|||
|
||||
test_reset_api();
|
||||
}
|
||||
|
||||
#undef NOMINMAX
|
||||
|
|
|
@ -690,3 +690,9 @@ TEST(cubeb, stable_devid)
|
|||
ASSERT_EQ(r, CUBEB_OK);
|
||||
cubeb_destroy(ctx);
|
||||
}
|
||||
|
||||
#undef STREAM_RATE
|
||||
#undef STREAM_LATENCY
|
||||
#undef STREAM_CHANNELS
|
||||
#undef STREAM_LAYOUT
|
||||
#undef STREAM_FORMAT
|
||||
|
|
|
@ -119,3 +119,6 @@ TEST(cubeb, tone)
|
|||
|
||||
ASSERT_TRUE(user_data->position.load());
|
||||
}
|
||||
|
||||
#undef SAMPLE_FREQUENCY
|
||||
#undef STREAM_FORMAT
|
||||
|
|
Загрузка…
Ссылка в новой задаче