Bug 1314514 - Update libcubeb to 8bab182c. r=padenot

--HG--
rename : media/libcubeb/tests/common.h => media/libcubeb/gtest/common.h
rename : media/libcubeb/tests/moz.build => media/libcubeb/gtest/moz.build
rename : media/libcubeb/tests/test_audio.cpp => media/libcubeb/gtest/test_audio.cpp
rename : media/libcubeb/tests/test_devices.cpp => media/libcubeb/gtest/test_devices.cpp
rename : media/libcubeb/tests/test_duplex.cpp => media/libcubeb/gtest/test_duplex.cpp
rename : media/libcubeb/tests/test_record.cpp => media/libcubeb/gtest/test_record.cpp
rename : media/libcubeb/tests/test_resampler.cpp => media/libcubeb/gtest/test_resampler.cpp
rename : media/libcubeb/tests/test_sanity.cpp => media/libcubeb/gtest/test_sanity.cpp
rename : media/libcubeb/tests/test_tone.cpp => media/libcubeb/gtest/test_tone.cpp
This commit is contained in:
Matthew Gregan 2016-11-11 15:01:56 +13:00
Родитель c82aff30be
Коммит 2b9aa95d4c
26 изменённых файлов: 990 добавлений и 1021 удалений

Просмотреть файл

@ -5,4 +5,4 @@ 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 f8467510a8b36793b1b8b7e85461e2e189eb7015.
The git commit ID used was 8bab182cd70ff66dec5bbecb69a69422f5d57647.

Просмотреть файл

@ -4,6 +4,8 @@
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(TEST_COMMON)
#define TEST_COMMON
#if defined( _WIN32)
#ifndef WIN32_LEAN_AND_MEAN
@ -59,3 +61,4 @@ int has_available_input_device(cubeb * ctx)
return 1;
}
#endif /* TEST_COMMON */

Просмотреть файл

@ -4,26 +4,24 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DEFINES['CUBEB_GECKO_BUILD'] = True
GeckoCppUnitTests([
'test_duplex',
'test_record',
'test_tone',
'test_utils'
])
UNIFIED_SOURCES += [
# 'test_duplex.cpp', # DISABLED: See bug 1314514.
# 'test_record.cpp', # DISABLED: See bug 1314514.
'test_tone.cpp',
'test_utils.cpp'
]
if CONFIG['MOZ_PULSEAUDIO'] or CONFIG['OS_TARGET'] in ('Darwin', 'WINNT', 'Android'):
GeckoCppUnitTests([
'test_resampler',
])
UNIFIED_SOURCES += [
'test_resampler.cpp',
]
if CONFIG['OS_TARGET'] != 'Android':
GeckoCppUnitTests([
'test_audio',
'test_latency',
'test_sanity'
])
UNIFIED_SOURCES += [
'test_audio.cpp',
'test_latency.cpp',
'test_sanity.cpp'
]
LOCAL_INCLUDES += [
'../include',
@ -78,3 +76,5 @@ else:
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']
FINAL_LIBRARY = 'xul-gtest'

Просмотреть файл

@ -7,21 +7,16 @@
/* libcubeb api/function exhaustive test. Plays a series of tones in different
* conditions. */
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "gtest/gtest.h"
#if !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include "cubeb/cubeb.h"
#include "common.h"
#ifdef CUBEB_GECKO_BUILD
#include "TestHarness.h"
#endif
#define MAX_NUM_CHANNELS 32
@ -99,7 +94,7 @@ long data_cb_short(cubeb_stream * /*stream*/, void * user, const void * /*inputb
return nframes;
}
void state_cb(cubeb_stream * /*stream*/, void * /*user*/, cubeb_state /*state*/)
void state_cb_audio(cubeb_stream * /*stream*/, void * /*user*/, cubeb_state /*state*/)
{
}
@ -161,7 +156,7 @@ int run_test(int num_channels, int sampling_rate, int is_float)
}
r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, &params,
4096, is_float ? data_cb_float : data_cb_short, state_cb, synth);
4096, is_float ? data_cb_float : data_cb_short, state_cb_audio, synth);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
goto cleanup;
@ -214,7 +209,7 @@ int run_panning_volume_test(int is_float)
r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, &params,
4096, is_float ? data_cb_float : data_cb_short,
state_cb, synth);
state_cb_audio, synth);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
goto cleanup;
@ -252,7 +247,17 @@ cleanup:
return r;
}
void run_channel_rate_test()
TEST(cubeb, run_panning_volume_test_short)
{
ASSERT_EQ(run_panning_volume_test(0), CUBEB_OK);
}
TEST(cubeb, run_panning_volume_test_float)
{
ASSERT_EQ(run_panning_volume_test(1), CUBEB_OK);
}
TEST(cubeb, run_channel_rate_test)
{
int channel_values[] = {
1,
@ -271,24 +276,11 @@ void run_channel_rate_test()
for(int j = 0; j < NELEMS(channel_values); ++j) {
for(int i = 0; i < NELEMS(freq_values); ++i) {
assert(channel_values[j] < MAX_NUM_CHANNELS);
ASSERT_TRUE(channel_values[j] < MAX_NUM_CHANNELS);
fprintf(stderr, "--------------------------\n");
assert(run_test(channel_values[j], freq_values[i], 0) == CUBEB_OK);
assert(run_test(channel_values[j], freq_values[i], 1) == CUBEB_OK);
ASSERT_EQ(run_test(channel_values[j], freq_values[i], 0), CUBEB_OK);
ASSERT_EQ(run_test(channel_values[j], freq_values[i], 1), CUBEB_OK);
}
}
}
int main(int /*argc*/, char * /*argv*/[])
{
#ifdef CUBEB_GECKO_BUILD
ScopedXPCOM xpcom("test_audio");
#endif
assert(run_panning_volume_test(0) == CUBEB_OK);
assert(run_panning_volume_test(1) == CUBEB_OK);
run_channel_rate_test();
return CUBEB_OK;
}

Просмотреть файл

@ -7,17 +7,12 @@
/* libcubeb enumerate device test/example.
* Prints out a list of devices enumerated. */
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "gtest/gtest.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cubeb/cubeb.h"
static void
print_device_info(cubeb_device_info * info, FILE * f)
{
@ -89,14 +84,14 @@ print_device_info(cubeb_device_info * info, FILE * f)
"\tCh: %u\n"
"\tFormat: %s (0x%x) (default: %s)\n"
"\tRate: %u - %u (default: %u)\n"
"\tLatency: lo %ums, hi %ums\n",
"\tLatency: lo %u frames, hi %u frames\n",
info->device_id, info->preferred ? " (PREFERRED)" : "",
info->friendly_name, info->group_id, info->vendor_name,
devtype, devstate, info->max_channels,
(devfmts[0] == ' ') ? &devfmts[1] : devfmts,
(devfmts[0] == '\0') ? devfmts : devfmts + 1,
(unsigned int)info->format, devdeffmt,
info->min_rate, info->max_rate, info->default_rate,
info->latency_lo_ms, info->latency_hi_ms);
info->latency_lo, info->latency_hi);
}
static void
@ -108,23 +103,28 @@ print_device_collection(cubeb_device_collection * collection, FILE * f)
print_device_info(collection->device[i], f);
}
static int
run_enumerate_devices(void)
TEST(cubeb, enumerate_devices)
{
int r = CUBEB_OK;
int r;
cubeb * ctx = NULL;
cubeb_device_collection * collection = NULL;
r = cubeb_init(&ctx, "Cubeb audio test");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
fprintf(stdout, "Enumerating input devices for backend %s\n",
cubeb_get_backend_id(ctx));
r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_INPUT, &collection);
if (r == CUBEB_ERROR_NOT_SUPPORTED) {
fprintf(stderr, "Device enumeration not supported"
" for this backend, skipping this test.\n");
r = CUBEB_OK;
goto cleanup;
}
if (r != CUBEB_OK) {
fprintf(stderr, "Error enumerating devices %d\n", r);
goto cleanup;
@ -149,14 +149,6 @@ run_enumerate_devices(void)
cleanup:
cubeb_destroy(ctx);
return r;
ASSERT_EQ(r, CUBEB_OK);
}
int main(int argc, char *argv[])
{
int ret;
ret = run_enumerate_devices();
return ret;
}

Просмотреть файл

@ -7,20 +7,15 @@
/* libcubeb api/function test. Loops input back to output and check audio
* is flowing. */
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "gtest/gtest.h"
#if !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "cubeb/cubeb.h"
#include "common.h"
#ifdef CUBEB_GECKO_BUILD
#include "TestHarness.h"
#endif
#define SAMPLE_FREQUENCY 48000
#if (defined(_WIN32) || defined(__WIN32__))
@ -31,16 +26,14 @@
#define SILENT_SAMPLE 0
#endif
struct user_state
struct user_state_duplex
{
bool seen_noise;
};
long data_cb(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
long data_cb_duplex(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
{
user_state * u = reinterpret_cast<user_state*>(user);
user_state_duplex * u = reinterpret_cast<user_state_duplex*>(user);
#if (defined(_WIN32) || defined(__WIN32__))
float *ib = (float *)inputbuffer;
float *ob = (float *)outputbuffer;
@ -70,7 +63,7 @@ long data_cb(cubeb_stream * stream, void * user, const void * inputbuffer, void
return nframes;
}
void state_cb(cubeb_stream * stream, void * /*user*/, cubeb_state state)
void state_cb_duplex(cubeb_stream * stream, void * /*user*/, cubeb_state state)
{
if (stream == NULL)
return;
@ -89,30 +82,26 @@ void state_cb(cubeb_stream * stream, void * /*user*/, cubeb_state state)
return;
}
int main(int /*argc*/, char * /*argv*/[])
TEST(cubeb, duplex)
{
#ifdef CUBEB_GECKO_BUILD
ScopedXPCOM xpcom("test_duplex");
#endif
cubeb *ctx;
cubeb_stream *stream;
cubeb_stream_params input_params;
cubeb_stream_params output_params;
int r;
user_state stream_state = { false };
user_state_duplex stream_state = { false };
uint32_t latency_frames = 0;
r = cubeb_init(&ctx, "Cubeb duplex example");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
/* This test needs an available input device, skip it if this host does not
* have one. */
if (!has_available_input_device(ctx)) {
return 0;
return;
}
/* typical user-case: mono input, stereo output, low latency. */
@ -127,15 +116,15 @@ int main(int /*argc*/, char * /*argv*/[])
if (r != CUBEB_OK) {
fprintf(stderr, "Could not get minimal latency\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
r = cubeb_stream_init(ctx, &stream, "Cubeb duplex",
NULL, &input_params, NULL, &output_params,
latency_frames, data_cb, state_cb, &stream_state);
latency_frames, data_cb_duplex, state_cb_duplex, &stream_state);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
cubeb_stream_start(stream);
@ -145,7 +134,5 @@ int main(int /*argc*/, char * /*argv*/[])
cubeb_stream_destroy(stream);
cubeb_destroy(ctx);
assert(stream_state.seen_noise);
return CUBEB_OK;
ASSERT_TRUE(stream_state.seen_noise);
}

Просмотреть файл

@ -0,0 +1,40 @@
#include "gtest/gtest.h"
#include <stdlib.h>
#include "cubeb/cubeb.h"
TEST(cubeb, latency)
{
cubeb * ctx = NULL;
int r;
uint32_t max_channels;
uint32_t preferred_rate;
uint32_t latency_frames;
r = cubeb_init(&ctx, "Cubeb audio test");
ASSERT_EQ(r, CUBEB_OK);
r = cubeb_get_max_channel_count(ctx, &max_channels);
ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
ASSERT_GT(max_channels, 0u);
}
r = cubeb_get_preferred_sample_rate(ctx, &preferred_rate);
ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
ASSERT_GT(preferred_rate, 0u);
}
cubeb_stream_params params = {
CUBEB_SAMPLE_FLOAT32NE,
preferred_rate,
max_channels
};
r = cubeb_get_min_latency(ctx, params, &latency_frames);
ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
ASSERT_GT(latency_frames, 0u);
}
cubeb_destroy(ctx);
}

Просмотреть файл

@ -6,20 +6,15 @@
*/
/* libcubeb api/function test. Record the mic and check there is sound. */
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "gtest/gtest.h"
#if !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "cubeb/cubeb.h"
#include "common.h"
#ifdef CUBEB_GECKO_BUILD
#include "TestHarness.h"
#endif
#define SAMPLE_FREQUENCY 48000
#if (defined(_WIN32) || defined(__WIN32__))
@ -28,14 +23,14 @@
#define STREAM_FORMAT CUBEB_SAMPLE_S16LE
#endif
struct user_state
struct user_state_record
{
bool seen_noise;
};
long data_cb(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
long data_cb_record(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
{
user_state * u = reinterpret_cast<user_state*>(user);
user_state_record * u = reinterpret_cast<user_state_record*>(user);
#if STREAM_FORMAT != CUBEB_SAMPLE_FLOAT32LE
short *b = (short *)inputbuffer;
#else
@ -58,7 +53,7 @@ long data_cb(cubeb_stream * stream, void * user, const void * inputbuffer, void
return nframes;
}
void state_cb(cubeb_stream * stream, void * /*user*/, cubeb_state state)
void state_cb_record(cubeb_stream * stream, void * /*user*/, cubeb_state state)
{
if (stream == NULL)
return;
@ -77,28 +72,24 @@ void state_cb(cubeb_stream * stream, void * /*user*/, cubeb_state state)
return;
}
int main(int /*argc*/, char * /*argv*/[])
TEST(cubeb, record)
{
#ifdef CUBEB_GECKO_BUILD
ScopedXPCOM xpcom("test_record");
#endif
cubeb *ctx;
cubeb_stream *stream;
cubeb_stream_params params;
int r;
user_state stream_state = { false };
user_state_record stream_state = { false };
r = cubeb_init(&ctx, "Cubeb record example");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
/* This test needs an available input device, skip it if this host does not
* have one. */
if (!has_available_input_device(ctx)) {
return 0;
return;
}
params.format = STREAM_FORMAT;
@ -106,10 +97,10 @@ int main(int /*argc*/, char * /*argv*/[])
params.channels = 1;
r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, &params, NULL, nullptr,
4096, data_cb, state_cb, &stream_state);
4096, data_cb_record, state_cb_record, &stream_state);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
cubeb_stream_start(stream);
@ -119,7 +110,5 @@ int main(int /*argc*/, char * /*argv*/[])
cubeb_stream_destroy(stream);
cubeb_destroy(ctx);
assert(stream_state.seen_noise);
return CUBEB_OK;
ASSERT_TRUE(stream_state.seen_noise);
}

Просмотреть файл

@ -7,12 +7,8 @@
#ifndef NOMINMAX
#define NOMINMAX
#endif // NOMINMAX
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "gtest/gtest.h"
#include "cubeb_resampler_internal.h"
#include <assert.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
@ -154,7 +150,7 @@ void test_delay_lines(uint32_t delay_frames, uint32_t channels, uint32_t chunk_m
// Check the diracs have been shifted by `delay_frames` frames.
for (uint32_t i = 0; i < output.length() - delay_frames * channels + 1; i+=100) {
assert(output.data()[i + channel + delay_frames * channels] == 0.5);
ASSERT_EQ(output.data()[i + channel + delay_frames * channels], 0.5);
channel = (channel + 1) % channels;
}
@ -232,7 +228,7 @@ void test_resampler_one_way(uint32_t channels, uint32_t source_rate, uint32_t ta
fuzzy_equal = false;
}
}
assert(fuzzy_equal);
ASSERT_TRUE(fuzzy_equal);
}
template<typename T>
@ -283,7 +279,7 @@ uint32_t fill_with_sine(float * buf, uint32_t rate, uint32_t channels,
return initial_phase;
}
long data_cb(cubeb_stream * /*stm*/, void * user_ptr,
long data_cb_resampler(cubeb_stream * /*stm*/, void * user_ptr,
const void * input_buffer, void * output_buffer, long frame_count)
{
osc_state * state = reinterpret_cast<osc_state*>(user_ptr);
@ -341,7 +337,7 @@ void test_resampler_duplex(uint32_t input_channels, uint32_t output_channels,
cubeb_resampler * resampler =
cubeb_resampler_create((cubeb_stream*)nullptr, &input_params, &output_params, target_rate,
data_cb, (void*)&state, CUBEB_RESAMPLER_QUALITY_VOIP);
data_cb_resampler, (void*)&state, CUBEB_RESAMPLER_QUALITY_VOIP);
long latency = cubeb_resampler_latency(resampler);
@ -397,15 +393,15 @@ void test_resampler_duplex(uint32_t input_channels, uint32_t output_channels,
dump("input.raw", state.input.data(), state.input.length());
dump("output.raw", state.output.data(), state.output.length());
assert(array_fuzzy_equal(state.input, expected_resampled_input, epsilon<T>(input_rate/target_rate)));
assert(array_fuzzy_equal(state.output, expected_resampled_output, epsilon<T>(output_rate/target_rate)));
ASSERT_TRUE(array_fuzzy_equal(state.input, expected_resampled_input, epsilon<T>(input_rate/target_rate)));
ASSERT_TRUE(array_fuzzy_equal(state.output, expected_resampled_output, epsilon<T>(output_rate/target_rate)));
cubeb_resampler_destroy(resampler);
}
#define array_size(x) (sizeof(x) / sizeof(x[0]))
void test_resamplers_one_way()
TEST(cubeb, resampler_one_way)
{
/* Test one way resamplers */
for (uint32_t channels = 1; channels <= max_channels; channels++) {
@ -422,9 +418,11 @@ void test_resamplers_one_way()
}
}
void test_resamplers_duplex()
// This is disabled because the latency estimation in the resampler code is
// slightly off so we can generate expected vectors.
// See https://github.com/kinetiknz/cubeb/issues/93
TEST(cubeb, DISABLED_resampler_duplex)
{
/* Test duplex resamplers */
for (uint32_t input_channels = 1; input_channels <= max_channels; input_channels++) {
for (uint32_t output_channels = 1; output_channels <= max_channels; output_channels++) {
for (uint32_t source_rate_input = 0; source_rate_input < array_size(sample_rates); source_rate_input++) {
@ -451,7 +449,7 @@ void test_resamplers_duplex()
}
}
void test_delay_line()
TEST(cubeb, resampler_delay_line)
{
for (uint32_t channel = 1; channel <= 2; channel++) {
for (uint32_t delay_frames = 4; delay_frames <= 40; delay_frames+=chunk_increment) {
@ -468,12 +466,12 @@ long test_output_only_noop_data_cb(cubeb_stream * /*stm*/, void * /*user_ptr*/,
const void * input_buffer,
void * output_buffer, long frame_count)
{
assert(output_buffer);
assert(!input_buffer);
EXPECT_TRUE(output_buffer);
EXPECT_TRUE(!input_buffer);
return frame_count;
}
void test_output_only_noop()
TEST(cubeb, resampler_output_only_noop)
{
cubeb_stream_params output_params;
int target_rate;
@ -495,7 +493,7 @@ void test_output_only_noop()
got = cubeb_resampler_fill(resampler, nullptr, nullptr,
out_buffer, out_frames);
assert(got == out_frames);
ASSERT_EQ(got, out_frames);
cubeb_resampler_destroy(resampler);
}
@ -504,12 +502,12 @@ long test_drain_data_cb(cubeb_stream * /*stm*/, void * /*user_ptr*/,
const void * input_buffer,
void * output_buffer, long frame_count)
{
assert(output_buffer);
assert(!input_buffer);
EXPECT_TRUE(output_buffer);
EXPECT_TRUE(!input_buffer);
return frame_count - 10;
}
void test_resampler_drain()
TEST(cubeb, resampler_drain)
{
cubeb_stream_params output_params;
int target_rate;
@ -535,20 +533,8 @@ void test_resampler_drain()
/* If the above is not an infinite loop, the drain was a success, just mark
* this test as such. */
assert(true);
ASSERT_TRUE(true);
cubeb_resampler_destroy(resampler);
}
int main()
{
test_resamplers_one_way();
test_delay_line();
// This is disabled because the latency estimation in the resampler code is
// slightly off so we can generate expected vectors.
// test_resamplers_duplex();
test_output_only_noop();
test_resampler_drain();
return 0;
}

Просмотреть файл

@ -0,0 +1,73 @@
#include "gtest/gtest.h"
#ifdef __APPLE__
#include <string.h>
#include <iostream>
#include <CoreAudio/CoreAudioTypes.h>
#include "cubeb/cubeb.h"
#include "cubeb_ring_array.h"
TEST(cubeb, ring_array)
{
ring_array ra;
ASSERT_EQ(ring_array_init(&ra, 0, 0, 1, 1), CUBEB_ERROR_INVALID_PARAMETER);
ASSERT_EQ(ring_array_init(&ra, 1, 0, 0, 1), CUBEB_ERROR_INVALID_PARAMETER);
unsigned int capacity = 8;
ring_array_init(&ra, capacity, sizeof(int), 1, 1);
int verify_data[capacity] ;// {1,2,3,4,5,6,7,8};
AudioBuffer * p_data = NULL;
for (unsigned int i = 0; i < capacity; ++i) {
verify_data[i] = i; // in case capacity change value
*(int*)ra.buffer_array[i].mData = i;
ASSERT_EQ(ra.buffer_array[i].mDataByteSize, sizeof(int));
ASSERT_EQ(ra.buffer_array[i].mNumberChannels, 1u);
}
/* Get store buffers*/
for (unsigned int i = 0; i < capacity; ++i) {
p_data = ring_array_get_free_buffer(&ra);
ASSERT_NE(p_data, nullptr);
ASSERT_EQ(*(int*)p_data->mData, verify_data[i]);
}
/*Now array is full extra store should give NULL*/
ASSERT_EQ(ring_array_get_free_buffer(&ra), nullptr);
/* Get fetch buffers*/
for (unsigned int i = 0; i < capacity; ++i) {
p_data = ring_array_get_data_buffer(&ra);
ASSERT_NE(p_data, nullptr);
ASSERT_EQ(*(int*)p_data->mData, verify_data[i]);
}
/*Now array is empty extra fetch should give NULL*/
ASSERT_EQ(ring_array_get_data_buffer(&ra), nullptr);
p_data = NULL;
/* Repeated store fetch should can go for ever*/
for (unsigned int i = 0; i < 2*capacity; ++i) {
p_data = ring_array_get_free_buffer(&ra);
ASSERT_NE(p_data, nullptr);
ASSERT_EQ(ring_array_get_data_buffer(&ra), p_data);
}
p_data = NULL;
/* Verify/modify buffer data*/
for (unsigned int i = 0; i < capacity; ++i) {
p_data = ring_array_get_free_buffer(&ra);
ASSERT_NE(p_data, nullptr);
ASSERT_EQ(*((int*)p_data->mData), verify_data[i]);
(*((int*)p_data->mData))++; // Modify data
}
for (unsigned int i = 0; i < capacity; ++i) {
p_data = ring_array_get_data_buffer(&ra);
ASSERT_NE(p_data, nullptr);
ASSERT_EQ(*((int*)p_data->mData), verify_data[i]+1); // Verify modified data
}
ring_array_destroy(&ra);
}
#else
TEST(cubeb, DISABLED_ring_array)
{
}
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -6,21 +6,16 @@
*/
/* libcubeb api/function test. Plays a simple tone. */
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "gtest/gtest.h"
#if !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <limits.h>
#include "cubeb/cubeb.h"
#include "common.h"
#ifdef CUBEB_GECKO_BUILD
#include "TestHarness.h"
#endif
#define SAMPLE_FREQUENCY 48000
#if (defined(_WIN32) || defined(__WIN32__))
@ -34,7 +29,7 @@ struct cb_user_data {
long position;
};
long data_cb(cubeb_stream *stream, void *user, const void* /*inputbuffer*/, void *outputbuffer, long nframes)
long data_cb_tone(cubeb_stream *stream, void *user, const void* /*inputbuffer*/, void *outputbuffer, long nframes)
{
struct cb_user_data *u = (struct cb_user_data *)user;
#if (defined(_WIN32) || defined(__WIN32__))
@ -77,7 +72,7 @@ long data_cb(cubeb_stream *stream, void *user, const void* /*inputbuffer*/, void
return nframes;
}
void state_cb(cubeb_stream *stream, void *user, cubeb_state state)
void state_cb_tone(cubeb_stream *stream, void *user, cubeb_state state)
{
struct cb_user_data *u = (struct cb_user_data *)user;
@ -98,12 +93,8 @@ void state_cb(cubeb_stream *stream, void *user, cubeb_state state)
return;
}
int main(int /*argc*/, char * /*argv*/[])
TEST(cubeb, tone)
{
#ifdef CUBEB_GECKO_BUILD
ScopedXPCOM xpcom("test_tone");
#endif
cubeb *ctx;
cubeb_stream *stream;
cubeb_stream_params params;
@ -113,7 +104,7 @@ int main(int /*argc*/, char * /*argv*/[])
r = cubeb_init(&ctx, "Cubeb tone example");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
params.format = STREAM_FORMAT;
@ -123,15 +114,15 @@ int main(int /*argc*/, char * /*argv*/[])
user_data = (struct cb_user_data *) malloc(sizeof(*user_data));
if (user_data == NULL) {
fprintf(stderr, "Error allocating user data\n");
return CUBEB_ERROR;
ASSERT_EQ(r, CUBEB_OK);
}
user_data->position = 0;
r = cubeb_stream_init(ctx, &stream, "Cubeb tone (mono)", NULL, NULL, NULL, &params,
4096, data_cb, state_cb, user_data);
4096, data_cb_tone, state_cb_tone, user_data);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream\n");
return r;
ASSERT_EQ(r, CUBEB_OK);
}
cubeb_stream_start(stream);
@ -141,9 +132,7 @@ int main(int /*argc*/, char * /*argv*/[])
cubeb_stream_destroy(stream);
cubeb_destroy(ctx);
assert(user_data->position);
ASSERT_TRUE(user_data->position);
free(user_data);
return CUBEB_OK;
}

Просмотреть файл

@ -0,0 +1,72 @@
#include "gtest/gtest.h"
#include "cubeb_utils.h"
TEST(cubeb, auto_array)
{
auto_array<uint32_t> array;
auto_array<uint32_t> array2(10);
uint32_t a[10];
ASSERT_EQ(array2.length(), 0u);
ASSERT_EQ(array2.capacity(), 10u);
for (uint32_t i = 0; i < 10; i++) {
a[i] = i;
}
ASSERT_EQ(array.capacity(), 0u);
ASSERT_EQ(array.length(), 0u);
array.push(a, 10);
ASSERT_TRUE(!array.reserve(9));
for (uint32_t i = 0; i < 10; i++) {
ASSERT_EQ(array.data()[i], i);
}
ASSERT_EQ(array.capacity(), 10u);
ASSERT_EQ(array.length(), 10u);
uint32_t b[10];
array.pop(b, 5);
ASSERT_EQ(array.capacity(), 10u);
ASSERT_EQ(array.length(), 5u);
for (uint32_t i = 0; i < 5; i++) {
ASSERT_EQ(b[i], i);
ASSERT_EQ(array.data()[i], 5 + i);
}
uint32_t* bb = b + 5;
array.pop(bb, 5);
ASSERT_EQ(array.capacity(), 10u);
ASSERT_EQ(array.length(), 0u);
for (uint32_t i = 0; i < 5; i++) {
ASSERT_EQ(bb[i], 5 + i);
}
ASSERT_TRUE(!array.pop(nullptr, 1));
array.push(a, 10);
array.push(a, 10);
for (uint32_t j = 0; j < 2; j++) {
for (uint32_t i = 0; i < 10; i++) {
ASSERT_EQ(array.data()[10 * j + i], i);
}
}
ASSERT_EQ(array.length(), 20u);
ASSERT_EQ(array.capacity(), 20u);
array.pop(nullptr, 5);
for (uint32_t i = 0; i < 5; i++) {
ASSERT_EQ(array.data()[i], 5 + i);
}
ASSERT_EQ(array.length(), 15u);
ASSERT_EQ(array.capacity(), 20u);
}

Просмотреть файл

@ -167,7 +167,7 @@ typedef enum {
/** An opaque handle used to refer a particular input or output device
* across calls. */
typedef void * cubeb_devid;
typedef void const * cubeb_devid;
/** Level (verbosity) of logging for a particular cubeb context. */
typedef enum {
@ -276,10 +276,10 @@ typedef enum {
* `cubeb_device_info_destroy`. */
typedef struct {
cubeb_devid devid; /**< Device identifier handle. */
char * device_id; /**< Device identifier which might be presented in a UI. */
char * friendly_name; /**< Friendly device name which might be presented in a UI. */
char * group_id; /**< Two devices have the same group identifier if they belong to the same physical device; for example a headset and microphone. */
char * vendor_name; /**< Optional vendor name, may be NULL. */
char const * device_id; /**< Device identifier which might be presented in a UI. */
char const * friendly_name; /**< Friendly device name which might be presented in a UI. */
char const * group_id; /**< Two devices have the same group identifier if they belong to the same physical device; for example a headset and microphone. */
char const * vendor_name; /**< Optional vendor name, may be NULL. */
cubeb_device_type type; /**< Type of device (Input/Output). */
cubeb_device_state state; /**< State of device disabled/enabled/unplugged. */
@ -322,7 +322,7 @@ typedef struct {
and the stream will enter a shutdown state. */
typedef long (* cubeb_data_callback)(cubeb_stream * stream,
void * user_ptr,
const void * input_buffer,
void const * input_buffer,
void * output_buffer,
long nframes);
@ -347,7 +347,7 @@ typedef void (* cubeb_device_collection_changed_callback)(cubeb * context,
void * user_ptr);
/** User supplied callback called when a message needs logging. */
typedef void (* cubeb_log_callback)(const char * fmt, ...);
typedef void (* cubeb_log_callback)(char const * fmt, ...);
/** Initialize an application context. This will perform any library or
application scoped initialization.

Просмотреть файл

@ -5,5 +5,5 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ['include', 'src']
TEST_DIRS += ['tests']
TEST_DIRS += ['gtest']

Просмотреть файл

@ -514,10 +514,10 @@ int cubeb_device_info_destroy(cubeb_device_info * info)
return CUBEB_ERROR_INVALID_PARAMETER;
}
free(info->device_id);
free(info->friendly_name);
free(info->group_id);
free(info->vendor_name);
free((void *) info->device_id);
free((void *) info->friendly_name);
free((void *) info->group_id);
free((void *) info->vendor_name);
free(info);
return CUBEB_OK;

Просмотреть файл

@ -168,9 +168,9 @@ struct cubeb_stream {
/* Stream creation parameters */
cubeb_stream_params input_stream_params;
cubeb_stream_params output_stream_params;
cubeb_devid input_device;
bool is_default_input;
cubeb_devid output_device;
AudioDeviceID input_device;
AudioDeviceID output_device;
/* User pointer of data_callback */
void * user_ptr;
/* Format descriptions */
@ -192,7 +192,7 @@ struct cubeb_stream {
/* Frames on input buffer */
std::atomic<uint32_t> input_buffer_frames;
/* Frame counters */
uint64_t frames_played;
std::atomic<uint64_t> frames_played;
uint64_t frames_queued;
std::atomic<int64_t> frames_read;
std::atomic<bool> shutdown;
@ -601,13 +601,13 @@ audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_coun
case kAudioHardwarePropertyDefaultOutputDevice: {
LOG("Event[%d] - mSelector == kAudioHardwarePropertyDefaultOutputDevice", i);
// Allow restart to choose the new default
stm->output_device = nullptr;
stm->output_device = 0;
}
break;
case kAudioHardwarePropertyDefaultInputDevice: {
LOG("Event[%d] - mSelector == kAudioHardwarePropertyDefaultInputDevice", i);
// Allow restart to choose the new default
stm->input_device = nullptr;
stm->input_device = 0;
}
break;
case kAudioDevicePropertyDeviceIsAlive: {
@ -619,7 +619,7 @@ audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_coun
return noErr;
}
// Allow restart to choose the new default. Event register only for input.
stm->input_device = nullptr;
stm->input_device = 0;
}
break;
case kAudioDevicePropertyDataSource:
@ -758,7 +758,7 @@ audiounit_install_device_changed_callback(cubeb_stream * stm)
}
/* Event to notify when the input is going away. */
AudioDeviceID dev = stm->input_device ? reinterpret_cast<intptr_t>(stm->input_device) :
AudioDeviceID dev = stm->input_device ? stm->input_device :
audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
r = audiounit_add_listener(stm, dev, kAudioDevicePropertyDeviceIsAlive,
kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
@ -1043,7 +1043,7 @@ static int
audiounit_create_unit(AudioUnit * unit,
bool is_input,
const cubeb_stream_params * /* stream_params */,
cubeb_devid device)
AudioDeviceID device)
{
AudioComponentDescription desc;
AudioComponent comp;
@ -1060,7 +1060,7 @@ audiounit_create_unit(AudioUnit * unit,
// so we retain automatic output device switching when the default
// changes. Once we have complete support for device notifications
// and switching, we can use the AUHAL for everything.
bool use_default_output = device == NULL && !is_input;
bool use_default_output = device == 0 && !is_input;
if (use_default_output) {
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
} else {
@ -1101,11 +1101,11 @@ audiounit_create_unit(AudioUnit * unit,
return CUBEB_ERROR;
}
if (device == NULL) {
if (device == 0) {
assert(is_input);
devid = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
} else {
devid = reinterpret_cast<intptr_t>(device);
devid = device;
}
rv = AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
@ -1560,14 +1560,13 @@ audiounit_stream_init(cubeb * context,
stm->device_changed_callback = NULL;
if (input_stream_params) {
stm->input_stream_params = *input_stream_params;
stm->input_device = input_device;
stm->is_default_input = input_device == nullptr ||
(audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT) ==
reinterpret_cast<intptr_t>(input_device));
stm->input_device = reinterpret_cast<uintptr_t>(input_device);
stm->is_default_input = stm->input_device == 0 ||
(audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT) == stm->input_device);
}
if (output_stream_params) {
stm->output_stream_params = *output_stream_params;
stm->output_device = output_device;
stm->output_device = reinterpret_cast<uintptr_t>(output_device);
}
/* Init data members where necessary */
@ -1821,7 +1820,7 @@ int audiounit_stream_set_panning(cubeb_stream * stm, float panning)
}
int audiounit_stream_get_current_device(cubeb_stream * stm,
cubeb_device ** const device)
cubeb_device ** const device)
{
#if TARGET_OS_IPHONE
//TODO
@ -2111,7 +2110,8 @@ audiounit_create_device_from_hwdev(AudioObjectID devid, cubeb_device_type type)
adr.mSelector = kAudioDevicePropertyDeviceUID;
if (AudioObjectGetPropertyData(devid, &adr, 0, NULL, &size, &str) == noErr && str != NULL) {
ret->device_id = audiounit_strref_to_cstr_utf8(str);
ret->devid = (cubeb_devid)(size_t)devid;
static_assert(sizeof(cubeb_devid) >= sizeof(decltype(devid)), "cubeb_devid can't represent devid");
ret->devid = reinterpret_cast<cubeb_devid>(devid);
ret->group_id = strdup(ret->device_id);
CFRelease(str);
}

Просмотреть файл

@ -993,9 +993,9 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
const char * j_out = "JACK playback";
if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
context->devinfo[i] = (cubeb_device_info *)malloc(sizeof(cubeb_device_info));
context->devinfo[i] = (cubeb_device_info *) malloc(sizeof(cubeb_device_info));
context->devinfo[i]->device_id = strdup(j_out);
context->devinfo[i]->devid = context->devinfo[i]->device_id;
context->devinfo[i]->devid = (cubeb_devid) context->devinfo[i]->device_id;
context->devinfo[i]->friendly_name = strdup(j_out);
context->devinfo[i]->group_id = strdup(j_out);
context->devinfo[i]->vendor_name = strdup(j_out);
@ -1014,9 +1014,9 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
}
if (type & CUBEB_DEVICE_TYPE_INPUT) {
context->devinfo[i] = (cubeb_device_info *)malloc(sizeof(cubeb_device_info));
context->devinfo[i] = (cubeb_device_info *) malloc(sizeof(cubeb_device_info));
context->devinfo[i]->device_id = strdup(j_in);
context->devinfo[i]->devid = context->devinfo[i]->device_id;
context->devinfo[i]->devid = (cubeb_devid) context->devinfo[i]->device_id;
context->devinfo[i]->friendly_name = strdup(j_in);
context->devinfo[i]->group_id = strdup(j_in);
context->devinfo[i]->vendor_name = strdup(j_in);

Просмотреть файл

@ -181,9 +181,9 @@ static void
stream_drain_callback(pa_mainloop_api * a, pa_time_event * e, struct timeval const * tv, void * u)
{
(void)a;
(void)e;
(void)tv;
cubeb_stream * stm = u;
assert(stm->drain_timer == e);
stream_state_change_callback(stm, CUBEB_STATE_DRAINED);
/* there's no pa_rttime_free, so use this instead. */
a->time_free(stm->drain_timer);
@ -267,6 +267,7 @@ trigger_user_callback(pa_stream * s, void const * input_data, size_t nbytes, cub
assert(r == 0 || r == -PA_ERR_NODATA);
/* pa_stream_drain is useless, see PA bug# 866. this is a workaround. */
/* arbitrary safety margin: double the current latency. */
assert(!stm->drain_timer);
stm->drain_timer = WRAP(pa_context_rttime_new)(stm->context->context, WRAP(pa_rtclock_now)() + 2 * latency, stream_drain_callback, stm);
stm->shutdown = 1;
return;
@ -752,7 +753,7 @@ pulse_stream_init(cubeb * context,
battr = set_buffering_attribute(latency_frames, &stm->output_sample_spec);
WRAP(pa_stream_connect_playback)(stm->output_stream,
output_device,
(char const *) output_device,
&battr,
PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY,
@ -775,7 +776,7 @@ pulse_stream_init(cubeb * context,
battr = set_buffering_attribute(latency_frames, &stm->input_sample_spec);
WRAP(pa_stream_connect_record)(stm->input_stream,
input_device,
(char const *) input_device,
&battr,
PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY);
@ -851,6 +852,9 @@ pulse_defer_event_cb(pa_mainloop_api * a, void * userdata)
{
(void)a;
cubeb_stream * stm = userdata;
if (stm->shutdown) {
return;
}
size_t writable_size = WRAP(pa_stream_writable_size)(stm->output_stream);
trigger_user_callback(stm->output_stream, NULL, writable_size, stm);
}
@ -1070,7 +1074,7 @@ pulse_get_state_from_sink_port(pa_sink_port_info * info)
static void
pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
int eol, void * user_data)
int eol, void * user_data)
{
pulse_dev_list_data * list_data = user_data;
cubeb_device_info * devinfo;
@ -1084,7 +1088,7 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
devinfo = calloc(1, sizeof(cubeb_device_info));
devinfo->device_id = strdup(info->name);
devinfo->devid = devinfo->device_id;
devinfo->devid = (cubeb_devid) devinfo->device_id;
devinfo->friendly_name = strdup(info->description);
prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
if (prop)
@ -1144,7 +1148,7 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
devinfo = calloc(1, sizeof(cubeb_device_info));
devinfo->device_id = strdup(info->name);
devinfo->devid = devinfo->device_id;
devinfo->devid = (cubeb_devid) devinfo->device_id;
devinfo->friendly_name = strdup(info->description);
prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
if (prop)

Просмотреть файл

@ -263,9 +263,15 @@ public:
* number of output frames will be exactly equal. */
uint32_t input_needed_for_output(uint32_t output_frame_count)
{
return (uint32_t)ceilf((output_frame_count - samples_to_frames(resampling_out_buffer.length()))
* resampling_ratio);
int32_t unresampled_frames_left = samples_to_frames(resampling_in_buffer.length());
int32_t resampled_frames_left = samples_to_frames(resampling_out_buffer.length());
float input_frames_needed =
(output_frame_count - unresampled_frames_left) * resampling_ratio
- resampled_frames_left;
if (input_frames_needed < 0) {
return 0;
}
return (uint32_t)ceilf(input_frames_needed);
}
/** Returns a pointer to the input buffer, that contains empty space for at

Просмотреть файл

@ -22,6 +22,7 @@
#include <algorithm>
#include <memory>
#include <limits>
#include <atomic>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
@ -105,8 +106,8 @@ int wasapi_stream_stop(cubeb_stream * stm);
int wasapi_stream_start(cubeb_stream * stm);
void close_wasapi_stream(cubeb_stream * stm);
int setup_wasapi_stream(cubeb_stream * stm);
static char * wstr_to_utf8(const wchar_t * str);
static std::unique_ptr<const wchar_t[]> utf8_to_wstr(char* str);
static char const * wstr_to_utf8(wchar_t const * str);
static std::unique_ptr<wchar_t const []> utf8_to_wstr(char const * str);
}
@ -144,8 +145,8 @@ struct cubeb_stream
cubeb_stream_params input_stream_params;
cubeb_stream_params output_stream_params;
/* The input and output device, or NULL for default. */
cubeb_devid input_device;
cubeb_devid output_device;
std::unique_ptr<const wchar_t[]> input_device;
std::unique_ptr<const wchar_t[]> output_device;
/* The latency initially requested for this stream, in frames. */
unsigned latency;
cubeb_state_callback state_callback;
@ -220,9 +221,11 @@ struct cubeb_stream
float volume;
/* True if the stream is draining. */
bool draining;
/* True when we've destroyed the stream. This pointer is leaked on stream
* destruction if we could not join the thread. */
std::atomic<std::atomic<bool>*> emergency_bailout;
};
class wasapi_endpoint_notification_client : public IMMNotificationClient
{
public:
@ -781,6 +784,7 @@ static unsigned int __stdcall
wasapi_stream_render_loop(LPVOID stream)
{
cubeb_stream * stm = static_cast<cubeb_stream *>(stream);
std::atomic<bool> * emergency_bailout = stm->emergency_bailout;
bool is_playing = true;
HANDLE wait_array[4] = {
@ -820,6 +824,10 @@ wasapi_stream_render_loop(LPVOID stream)
wait_array,
FALSE,
1000);
if (*emergency_bailout) {
delete emergency_bailout;
return 0;
}
if (waitResult != WAIT_TIMEOUT) {
timeout_count = 0;
}
@ -1134,12 +1142,13 @@ int wasapi_init(cubeb ** context, char const * context_name)
}
namespace {
void stop_and_join_render_thread(cubeb_stream * stm)
bool stop_and_join_render_thread(cubeb_stream * stm)
{
bool rv = true;
LOG("Stop and join render thread.");
if (!stm->thread) {
LOG("No thread present.");
return;
return true;
}
BOOL ok = SetEvent(stm->shutdown_event);
@ -1153,11 +1162,15 @@ void stop_and_join_render_thread(cubeb_stream * stm)
if (r == WAIT_TIMEOUT) {
/* Something weird happened, leak the thread and continue the shutdown
* process. */
*(stm->emergency_bailout) = true;
LOG("Destroy WaitForSingleObject on thread timed out,"
" leaking the thread: %d", GetLastError());
rv = false;
}
if (r == WAIT_FAILED) {
*(stm->emergency_bailout) = true;
LOG("Destroy WaitForSingleObject on thread failed: %d", GetLastError());
rv = false;
}
LOG("Closing thread.");
@ -1167,6 +1180,8 @@ void stop_and_join_render_thread(cubeb_stream * stm)
CloseHandle(stm->shutdown_event);
stm->shutdown_event = 0;
return rv;
}
void wasapi_destroy(cubeb * context)
@ -1395,7 +1410,7 @@ handle_channel_layout(cubeb_stream * stm, WAVEFORMATEX ** mix_format, const cub
template<typename T>
int setup_wasapi_stream_one_side(cubeb_stream * stm,
cubeb_stream_params * stream_params,
cubeb_devid devid,
wchar_t const * devid,
EDataFlow direction,
REFIID riid,
IAudioClient ** audio_client,
@ -1414,14 +1429,12 @@ int setup_wasapi_stream_one_side(cubeb_stream * stm,
// possibilities.
do {
if (devid) {
std::unique_ptr<const wchar_t[]> id(utf8_to_wstr(reinterpret_cast<char*>(devid)));
hr = get_endpoint(&device, id.get());
hr = get_endpoint(&device, devid);
if (FAILED(hr)) {
LOG("Could not get %s endpoint, error: %x\n", DIRECTION_NAME, hr);
return CUBEB_ERROR;
}
}
else {
} else {
hr = get_default_endpoint(&device, direction);
if (FAILED(hr)) {
LOG("Could not get default %s endpoint, error: %x\n", DIRECTION_NAME, hr);
@ -1534,10 +1547,10 @@ int setup_wasapi_stream(cubeb_stream * stm)
XASSERT((!stm->output_client || !stm->input_client) && "WASAPI stream already setup, close it first.");
if (has_input(stm)) {
LOG("Setup capture: device=%x", (int)stm->input_device);
LOG("(%p) Setup capture: device=%p", stm, stm->input_device.get());
rv = setup_wasapi_stream_one_side(stm,
&stm->input_stream_params,
stm->input_device,
stm->input_device.get(),
eCapture,
__uuidof(IAudioCaptureClient),
&stm->input_client,
@ -1552,10 +1565,10 @@ int setup_wasapi_stream(cubeb_stream * stm)
}
if (has_output(stm)) {
LOG("Setup render: device=%x", (int)stm->output_device);
LOG("(%p) Setup render: device=%p", stm, stm->output_device.get());
rv = setup_wasapi_stream_one_side(stm,
&stm->output_stream_params,
stm->output_device,
stm->output_device.get(),
eRender,
__uuidof(IAudioRenderClient),
&stm->output_client,
@ -1679,11 +1692,11 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
stm->draining = false;
if (input_stream_params) {
stm->input_stream_params = *input_stream_params;
stm->input_device = input_device;
stm->input_device = utf8_to_wstr(reinterpret_cast<char const *>(input_device));
}
if (output_stream_params) {
stm->output_stream_params = *output_stream_params;
stm->output_device = output_device;
stm->output_device = utf8_to_wstr(reinterpret_cast<char const *>(output_device));
}
stm->latency = latency_frames;
@ -1777,7 +1790,16 @@ void wasapi_stream_destroy(cubeb_stream * stm)
{
XASSERT(stm);
stop_and_join_render_thread(stm);
// Only free stm->emergency_bailout if we could not join the thread.
// If we could not join the thread, stm->emergency_bailout is true
// and is still alive until the thread wakes up and exits cleanly.
if (stop_and_join_render_thread(stm)) {
delete stm->emergency_bailout.load();
stm->emergency_bailout = nullptr;
} else {
// If we're leaking, it must be that this is true.
assert(*(stm->emergency_bailout));
}
unregister_notification_client(stm);
@ -1846,6 +1868,8 @@ int wasapi_stream_start(cubeb_stream * stm)
auto_lock lock(stm->stream_reset_lock);
stm->emergency_bailout = new std::atomic<bool>(false);
if (stm->output_client) {
int rv = stream_start_one_side(stm, OUTPUT);
if (rv != CUBEB_OK) {
@ -1905,7 +1929,12 @@ int wasapi_stream_stop(cubeb_stream * stm)
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
}
stop_and_join_render_thread(stm);
if (stop_and_join_render_thread(stm)) {
if (stm->emergency_bailout.load()) {
delete stm->emergency_bailout.load();
stm->emergency_bailout = nullptr;
}
}
return CUBEB_OK;
}
@ -1982,33 +2011,29 @@ int wasapi_stream_set_volume(cubeb_stream * stm, float volume)
return CUBEB_OK;
}
static char *
static char const *
wstr_to_utf8(LPCWSTR str)
{
char * ret = NULL;
int size;
size = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, 0, NULL, NULL);
if (size > 0) {
ret = static_cast<char *>(malloc(size));
::WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, size, NULL, NULL);
int size = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, NULL, NULL);
if (size <= 0) {
return nullptr;
}
char * ret = static_cast<char *>(malloc(size));
::WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, size, NULL, NULL);
return ret;
}
static std::unique_ptr<const wchar_t[]>
utf8_to_wstr(char* str)
static std::unique_ptr<wchar_t const []>
utf8_to_wstr(char const * str)
{
std::unique_ptr<wchar_t[]> ret;
int size;
size = ::MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0);
if (size > 0) {
ret.reset(new wchar_t[size]);
::MultiByteToWideChar(CP_UTF8, 0, str, -1, ret.get(), size);
int size = ::MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0);
if (size <= 0) {
return nullptr;
}
std::unique_ptr<wchar_t []> ret(new wchar_t[size]);
::MultiByteToWideChar(CP_UTF8, 0, str, -1, ret.get(), size);
return std::move(ret);
}
@ -2089,7 +2114,8 @@ wasapi_create_device(IMMDeviceEnumerator * enumerator, IMMDevice * dev)
ret = (cubeb_device_info *)calloc(1, sizeof(cubeb_device_info));
ret->devid = ret->device_id = wstr_to_utf8(device_id);
ret->device_id = wstr_to_utf8(device_id);
ret->devid = reinterpret_cast<cubeb_devid>(ret->device_id);
hr = propstore->GetValue(PKEY_Device_FriendlyName, &propvar);
if (SUCCEEDED(hr))
ret->friendly_name = wstr_to_utf8(propvar.pwszVal);

Просмотреть файл

@ -803,11 +803,11 @@ winmm_query_supported_formats(UINT devid, DWORD formats,
static char *
guid_to_cstr(LPGUID guid)
{
char * ret = malloc(sizeof(char) * 40);
char * ret = malloc(40);
if (!ret) {
return NULL;
}
_snprintf_s(ret, sizeof(char) * 40, _TRUNCATE,
_snprintf_s(ret, 40, _TRUNCATE,
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
@ -821,12 +821,12 @@ winmm_query_preferred_out_device(UINT devid)
DWORD mmpref = WAVE_MAPPER, compref = WAVE_MAPPER, status;
cubeb_device_pref ret = CUBEB_DEVICE_PREF_NONE;
if (waveOutMessage((HWAVEOUT)(size_t)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
if (waveOutMessage((HWAVEOUT) WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
(DWORD_PTR)&mmpref, (DWORD_PTR)&status) == MMSYSERR_NOERROR &&
devid == mmpref)
ret |= CUBEB_DEVICE_PREF_MULTIMEDIA | CUBEB_DEVICE_PREF_NOTIFICATION;
if (waveOutMessage((HWAVEOUT)(size_t)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET,
if (waveOutMessage((HWAVEOUT) WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET,
(DWORD_PTR)&compref, (DWORD_PTR)&status) == MMSYSERR_NOERROR &&
devid == compref)
ret |= CUBEB_DEVICE_PREF_VOICE;
@ -837,7 +837,7 @@ winmm_query_preferred_out_device(UINT devid)
static char *
device_id_idx(UINT devid)
{
char * ret = (char *)malloc(sizeof(char)*16);
char * ret = malloc(16);
if (!ret) {
return NULL;
}
@ -854,7 +854,7 @@ winmm_create_device_from_outcaps2(LPWAVEOUTCAPS2A caps, UINT devid)
if (!ret) {
return NULL;
}
ret->devid = (cubeb_devid)(size_t)devid;
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
ret->group_id = guid_to_cstr(&caps->ProductGuid);
@ -885,7 +885,7 @@ winmm_create_device_from_outcaps(LPWAVEOUTCAPSA caps, UINT devid)
if (!ret) {
return NULL;
}
ret->devid = (cubeb_devid)(size_t)devid;
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
ret->group_id = NULL;
@ -913,12 +913,12 @@ winmm_query_preferred_in_device(UINT devid)
DWORD mmpref = WAVE_MAPPER, compref = WAVE_MAPPER, status;
cubeb_device_pref ret = CUBEB_DEVICE_PREF_NONE;
if (waveInMessage((HWAVEIN)(size_t)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
if (waveInMessage((HWAVEIN) WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
(DWORD_PTR)&mmpref, (DWORD_PTR)&status) == MMSYSERR_NOERROR &&
devid == mmpref)
ret |= CUBEB_DEVICE_PREF_MULTIMEDIA | CUBEB_DEVICE_PREF_NOTIFICATION;
if (waveInMessage((HWAVEIN)(size_t)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET,
if (waveInMessage((HWAVEIN) WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET,
(DWORD_PTR)&compref, (DWORD_PTR)&status) == MMSYSERR_NOERROR &&
devid == compref)
ret |= CUBEB_DEVICE_PREF_VOICE;
@ -935,7 +935,7 @@ winmm_create_device_from_incaps2(LPWAVEINCAPS2A caps, UINT devid)
if (!ret) {
return NULL;
}
ret->devid = (cubeb_devid)(size_t)devid;
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
ret->group_id = guid_to_cstr(&caps->ProductGuid);
@ -966,7 +966,7 @@ winmm_create_device_from_incaps(LPWAVEINCAPSA caps, UINT devid)
if (!ret) {
return NULL;
}
ret->devid = (cubeb_devid)(size_t)devid;
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
ret->group_id = NULL;

Просмотреть файл

@ -1,60 +0,0 @@
#ifdef NDEBUG
#undef NDEBUG
#endif
#include <stdlib.h>
#include "cubeb/cubeb.h"
#include <assert.h>
#include <stdio.h>
#ifdef CUBEB_GECKO_BUILD
#include "TestHarness.h"
#endif
#define LOG(msg) fprintf(stderr, "%s\n", msg);
int main(int /*argc*/, char * /*argv*/[])
{
#ifdef CUBEB_GECKO_BUILD
ScopedXPCOM xpcom("test_latency");
#endif
cubeb * ctx = NULL;
int r;
uint32_t max_channels;
uint32_t preferred_rate;
uint32_t latency_frames;
LOG("latency_test start");
r = cubeb_init(&ctx, "Cubeb audio test");
assert(r == CUBEB_OK && "Cubeb init failed.");
LOG("cubeb_init ok");
r = cubeb_get_max_channel_count(ctx, &max_channels);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(max_channels > 0 && "Invalid max channel count.");
LOG("cubeb_get_max_channel_count ok");
}
r = cubeb_get_preferred_sample_rate(ctx, &preferred_rate);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(preferred_rate > 0 && "Invalid preferred sample rate.");
LOG("cubeb_get_preferred_sample_rate ok");
}
cubeb_stream_params params = {
CUBEB_SAMPLE_FLOAT32NE,
preferred_rate,
max_channels
};
r = cubeb_get_min_latency(ctx, params, &latency_frames);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(latency_frames > 0 && "Invalid minimal latency.");
LOG("cubeb_get_min_latency ok");
}
cubeb_destroy(ctx);
LOG("cubeb_destroy ok");
return EXIT_SUCCESS;
}

Просмотреть файл

@ -1,80 +0,0 @@
#include <cassert>
#include "cubeb_utils.h"
int test_auto_array()
{
auto_array<uint32_t> array;
auto_array<uint32_t> array2(10);
uint32_t a[10];
assert(array2.length() == 0);
assert(array2.capacity() == 10);
for (uint32_t i = 0; i < 10; i++) {
a[i] = i;
}
assert(array.capacity() == 0);
assert(array.length() == 0);
array.push(a, 10);
assert(!array.reserve(9));
for (uint32_t i = 0; i < 10; i++) {
assert(array.data()[i] == i);
}
assert(array.capacity() == 10);
assert(array.length() == 10);
uint32_t b[10];
array.pop(b, 5);
assert(array.capacity() == 10);
assert(array.length() == 5);
for (uint32_t i = 0; i < 5; i++) {
assert(b[i] == i);
assert(array.data()[i] == 5 + i);
}
uint32_t* bb = b + 5;
array.pop(bb, 5);
assert(array.capacity() == 10);
assert(array.length() == 0);
for (uint32_t i = 0; i < 5; i++) {
assert(bb[i] == 5 + i);
}
assert(!array.pop(nullptr, 1));
array.push(a, 10);
array.push(a, 10);
for (uint32_t j = 0; j < 2; j++) {
for (uint32_t i = 0; i < 10; i++) {
assert(array.data()[10 * j + i] == i);
}
}
assert(array.length() == 20);
assert(array.capacity() == 20);
array.pop(nullptr, 5);
for (uint32_t i = 0; i < 5; i++) {
assert(array.data()[i] == 5 + i);
}
assert(array.length() == 15);
assert(array.capacity() == 20);
return 0;
}
int main()
{
test_auto_array();
return 0;
}

Просмотреть файл

@ -30,16 +30,17 @@ cp $1/src/cubeb_utils_unix.h src
cp $1/src/cubeb_utils_win.h src
cp $1/src/cubeb_wasapi.cpp src
cp $1/src/cubeb_winmm.c src
cp $1/test/common.h tests/common.h
cp $1/test/test_audio.cpp tests/test_audio.cpp
#cp $1/test/test_devices.c tests/test_devices.cpp
cp $1/test/test_duplex.cpp tests/test_duplex.cpp
cp $1/test/test_latency.cpp tests/test_latency.cpp
cp $1/test/test_record.cpp tests/test_record.cpp
cp $1/test/test_resampler.cpp tests/test_resampler.cpp
cp $1/test/test_sanity.cpp tests/test_sanity.cpp
cp $1/test/test_tone.cpp tests/test_tone.cpp
cp $1/test/test_utils.cpp tests/test_utils.cpp
cp $1/test/common.h gtest
cp $1/test/test_audio.cpp gtest
cp $1/test/test_devices.cpp gtest
cp $1/test/test_duplex.cpp gtest
cp $1/test/test_latency.cpp gtest
cp $1/test/test_record.cpp gtest
cp $1/test/test_resampler.cpp gtest
cp $1/test/test_ring_array.cpp gtest
cp $1/test/test_sanity.cpp gtest
cp $1/test/test_tone.cpp gtest
cp $1/test/test_utils.cpp gtest
if [ -d $1/.git ]; then
rev=$(cd $1 && git rev-parse --verify HEAD)

Просмотреть файл

@ -85,17 +85,13 @@ skip-if = os == 'android' # Bug 1147631
[test_StatementCache]
[test_asyncStatementExecution_transaction]
[test_async_callbacks_with_spun_event_loops]
[test_audio]
[test_binding_params]
[test_deadlock_detector]
skip-if = os == 'b2g' || (os == 'android' && debug) # Bug 1054249
[test_file_perms]
[test_latency]
[test_mutex]
[test_sanity]
[test_service_init_background_thread]
[test_statement_scoper]
[test_tone]
[test_transaction_helper]
[test_true_async]
[test_unlock_notify]