Bug 1337805 - Update cubeb from upstream 21e96ac. r=padenot

MozReview-Commit-ID: 62VM613n915

--HG--
extra : rebase_source : 5a58866e8e3a0458eacabcdbb894bffcebe3467f
This commit is contained in:
Alex Chronopoulos 2017-02-10 13:20:15 +02:00
parent 448874c0f1
commit c0634dbb84
8 changed files with 339 additions and 120 deletions

View File

@ -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 927877c3204d6b8467b6dc782ca2aa740d240d41.
The git commit ID used was 21e96ac7fd456dc957cd9947a61da1366a1f862d.

View File

@ -27,7 +27,8 @@ TEST(cubeb, latency)
}
r = cubeb_get_preferred_channel_layout(ctx, &layout);
ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED ||
(r == CUBEB_ERROR && layout == CUBEB_LAYOUT_UNDEFINED));
cubeb_stream_params params = {
CUBEB_SAMPLE_FLOAT32NE,

View File

@ -316,12 +316,12 @@ alsa_process_stream(cubeb_stream * stm)
/* Capture: Pass read frames to callback function */
if (stm->stream_type == SND_PCM_STREAM_CAPTURE && stm->bufframes > 0 &&
(!stm->other_stream || stm->other_stream->bufframes < stm->other_stream->buffer_size)) {
long wrote = stm->bufframes;
snd_pcm_sframes_t wrote = stm->bufframes;
struct cubeb_stream * mainstm = stm->other_stream ? stm->other_stream : stm;
void * other_buffer = stm->other_stream ? stm->other_stream->buffer + stm->other_stream->bufframes : NULL;
/* Correct write size to the other stream available space */
if (stm->other_stream && wrote > stm->other_stream->buffer_size - stm->other_stream->bufframes) {
if (stm->other_stream && wrote > (snd_pcm_sframes_t) (stm->other_stream->buffer_size - stm->other_stream->bufframes)) {
wrote = stm->other_stream->buffer_size - stm->other_stream->bufframes;
}
@ -341,14 +341,14 @@ alsa_process_stream(cubeb_stream * stm)
}
/* Playback: Don't have enough data? Let's ask for more. */
if (stm->stream_type == SND_PCM_STREAM_PLAYBACK && avail > stm->bufframes &&
if (stm->stream_type == SND_PCM_STREAM_PLAYBACK && avail > (snd_pcm_sframes_t) stm->bufframes &&
(!stm->other_stream || stm->other_stream->bufframes > 0)) {
long got = avail - stm->bufframes;
void * other_buffer = stm->other_stream ? stm->other_stream->buffer : NULL;
char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes);
/* Correct read size to the other stream available frames */
if (stm->other_stream && got > stm->other_stream->bufframes) {
if (stm->other_stream && got > (snd_pcm_sframes_t) stm->other_stream->bufframes) {
got = stm->other_stream->bufframes;
}
@ -368,7 +368,7 @@ alsa_process_stream(cubeb_stream * stm)
}
/* Playback: Still don't have enough data? Add some silence. */
if (stm->stream_type == SND_PCM_STREAM_PLAYBACK && avail > stm->bufframes) {
if (stm->stream_type == SND_PCM_STREAM_PLAYBACK && avail > (snd_pcm_sframes_t) stm->bufframes) {
long drain_frames = avail - stm->bufframes;
double drain_time = (double) drain_frames / stm->params.rate;
@ -933,6 +933,9 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream
r = pthread_mutex_init(&stm->mutex, NULL);
assert(r == 0);
r = pthread_cond_init(&stm->cond, NULL);
assert(r == 0);
r = alsa_locked_pcm_open(&stm->pcm, pcm_name, stm->stream_type, ctx->local_config);
if (r < 0) {
alsa_stream_destroy(stm);
@ -976,9 +979,6 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream
r = snd_pcm_poll_descriptors(stm->pcm, stm->saved_fds, stm->nfds);
assert((nfds_t) r == stm->nfds);
r = pthread_cond_init(&stm->cond, NULL);
assert(r == 0);
if (alsa_register_stream(ctx, stm) != 0) {
alsa_stream_destroy(stm);
return CUBEB_ERROR;

View File

@ -22,6 +22,7 @@
#include <AudioToolbox/AudioToolbox.h>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
#include "cubeb_mixer.h"
#include "cubeb_panner.h"
#if !TARGET_OS_IPHONE
#include "cubeb_osx_run_loop.h"
@ -40,6 +41,8 @@ typedef UInt32 AudioFormatFlags;
#define AU_OUT_BUS 0
#define AU_IN_BUS 1
#define fieldOffset(type, field) ((size_t) &((type *) 0)->field)
#define PRINT_ERROR_CODE(str, r) do { \
LOG("System call failed: %s (rv: %d)", str, (int) r); \
} while(0)
@ -56,6 +59,10 @@ void audiounit_stream_stop_internal(cubeb_stream * stm);
void audiounit_stream_start_internal(cubeb_stream * stm);
static void audiounit_close_stream(cubeb_stream *stm);
static int audiounit_setup_stream(cubeb_stream *stm);
static int audiounit_create_unit(AudioUnit * unit, bool is_input,
const cubeb_stream_params * /* stream_params */,
AudioDeviceID device);
static cubeb_channel_layout audiounit_get_channel_layout(bool preferred);
extern cubeb_ops const audiounit_ops;
@ -83,6 +90,54 @@ struct auto_array_wrapper {
virtual ~auto_array_wrapper() {}
};
class auto_channel_layout
{
public:
auto_channel_layout()
: layout(nullptr)
{
}
auto_channel_layout(size_t size)
: layout(reinterpret_cast<AudioChannelLayout*>(malloc(size)))
{
memset(layout, 0, size);
}
~auto_channel_layout()
{
release();
}
void reset(size_t size)
{
release();
layout = reinterpret_cast<AudioChannelLayout*>(malloc(size));
memset(layout, 0, size);
}
AudioChannelLayout* get()
{
return layout;
}
size_t size()
{
return sizeof(*layout);
}
private:
void release()
{
if (layout) {
free(layout);
layout = NULL;
}
}
AudioChannelLayout * layout;
};
template <typename T>
struct auto_array_wrapper_impl : public auto_array_wrapper {
explicit auto_array_wrapper_impl(uint32_t size)
@ -130,6 +185,11 @@ private:
auto_array<T> ar;
};
enum io_side {
INPUT,
OUTPUT,
};
struct cubeb_stream {
explicit cubeb_stream(cubeb * context);
@ -195,6 +255,42 @@ bool has_output(cubeb_stream * stm)
return stm->output_stream_params.rate != 0;
}
cubeb_channel
channel_label_to_cubeb_channel(UInt32 label)
{
switch (label) {
case kAudioChannelLabel_Mono: return CHANNEL_MONO;
case kAudioChannelLabel_Left: return CHANNEL_LEFT;
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;
default: return CHANNEL_INVALID;
}
}
AudioChannelLabel
cubeb_channel_to_channel_label(cubeb_channel channel)
{
switch (channel) {
case CHANNEL_MONO: return kAudioChannelLabel_Mono;
case CHANNEL_LEFT: return kAudioChannelLabel_Left;
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;
default: return kAudioChannelLabel_Unknown;
}
}
#if TARGET_OS_IPHONE
typedef UInt32 AudioDeviceID;
typedef UInt32 AudioObjectID;
@ -958,6 +1054,26 @@ audiounit_get_preferred_sample_rate(cubeb * /* ctx */, uint32_t * rate)
return CUBEB_OK;
}
static int
audiounit_get_preferred_channel_layout(cubeb * /* ctx */, cubeb_channel_layout * layout)
{
// The preferred layout is only returned when the connected sound device
// (e.g. ASUS Xonar U7), has preferred layout setting.
// For default output on Mac, there is no preferred channel layout,
// so it might return UNDEFINED.
// In that case, we should get the channel configuration directly.
*layout = audiounit_get_channel_layout(true);
if (*layout == CUBEB_LAYOUT_UNDEFINED) {
*layout = audiounit_get_channel_layout(false);
}
if (*layout == CUBEB_LAYOUT_UNDEFINED) {
return CUBEB_ERROR;
}
return CUBEB_OK;
}
static OSStatus audiounit_remove_device_listener(cubeb * context);
static void
@ -1021,6 +1137,80 @@ audio_stream_desc_init(AudioStreamBasicDescription * ss,
return CUBEB_OK;
}
static int
audiounit_layout_init(AudioUnit * unit,
io_side side,
const cubeb_stream_params * stream_params)
{
assert(stream_params->layout != CUBEB_LAYOUT_UNDEFINED);
assert(stream_params->channels == CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels);
OSStatus r;
auto_channel_layout layout(sizeof(AudioChannelLayout));
switch (stream_params->layout) {
case CUBEB_LAYOUT_DUAL_MONO:
case CUBEB_LAYOUT_STEREO:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
break;
case CUBEB_LAYOUT_MONO:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
break;
case CUBEB_LAYOUT_3F:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_0;
break;
case CUBEB_LAYOUT_2F1:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_2_1;
break;
case CUBEB_LAYOUT_3F1:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_1;
break;
case CUBEB_LAYOUT_2F2:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_2_2;
break;
case CUBEB_LAYOUT_3F2:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_2;
break;
case CUBEB_LAYOUT_3F2_LFE:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_5_1;
break;
default:
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_Unknown;
break;
}
// For those layouts that can't be matched to coreaudio's predefined layout,
// we use customized layout.
if (layout.get()->mChannelLayoutTag == kAudioChannelLayoutTag_Unknown) {
size_t size = fieldOffset(AudioChannelLayout, mChannelDescriptions[stream_params->channels]);
layout.reset(size);
layout.get()->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
layout.get()->mNumberChannelDescriptions = stream_params->channels;
for (UInt32 i = 0 ; i < stream_params->channels ; ++i) {
layout.get()->mChannelDescriptions[i].mChannelLabel =
cubeb_channel_to_channel_label(CHANNEL_INDEX_TO_ORDER[stream_params->layout][i]);
layout.get()->mChannelDescriptions[i].mChannelFlags = kAudioChannelFlags_AllOff;
}
}
r = AudioUnitSetProperty(*unit,
kAudioUnitProperty_AudioChannelLayout,
side == INPUT ? kAudioUnitScope_Output : kAudioUnitScope_Input,
side == INPUT ? AU_IN_BUS : AU_OUT_BUS,
layout.get(),
layout.size());
if (r != noErr) {
if (side == INPUT) {
PRINT_ERROR_CODE("AudioUnitSetProperty/input/kAudioUnitProperty_AudioChannelLayout", r);
} else {
PRINT_ERROR_CODE("AudioUnitSetProperty/output/kAudioUnitProperty_AudioChannelLayout", r);
}
return CUBEB_ERROR;
}
return CUBEB_OK;
}
static int
audiounit_create_unit(AudioUnit * unit,
bool is_input,
@ -1243,20 +1433,15 @@ buffer_size_changed_callback(void * inClientData,
}
}
enum set_buffer_size_side {
INPUT,
OUTPUT,
};
static int
audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, set_buffer_size_side set_side)
audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, io_side side)
{
AudioUnit au = stm->output_unit;
AudioUnitScope au_scope = kAudioUnitScope_Input;
AudioUnitElement au_element = AU_OUT_BUS;
const char * au_type = "output";
if (set_side == INPUT) {
if (side == INPUT) {
au = stm->input_unit;
au_scope = kAudioUnitScope_Output;
au_element = AU_IN_BUS;
@ -1272,7 +1457,7 @@ audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, set_buff
&buffer_frames,
&size);
if (r != noErr) {
if (set_side == INPUT) {
if (side == INPUT) {
PRINT_ERROR_CODE("AudioUnitGetProperty/input/kAudioDevicePropertyBufferFrameSize", r);
} else {
PRINT_ERROR_CODE("AudioUnitGetProperty/output/kAudioDevicePropertyBufferFrameSize", r);
@ -1290,7 +1475,7 @@ audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, set_buff
buffer_size_changed_callback,
stm);
if (r != noErr) {
if (set_side == INPUT) {
if (side == INPUT) {
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/input/kAudioDevicePropertyBufferFrameSize", r);
} else {
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/output/kAudioDevicePropertyBufferFrameSize", r);
@ -1307,7 +1492,7 @@ audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, set_buff
&new_size_frames,
sizeof(new_size_frames));
if (r != noErr) {
if (set_side == INPUT) {
if (side == INPUT) {
PRINT_ERROR_CODE("AudioUnitSetProperty/input/kAudioDevicePropertyBufferFrameSize", r);
} else {
PRINT_ERROR_CODE("AudioUnitSetProperty/output/kAudioDevicePropertyBufferFrameSize", r);
@ -1318,7 +1503,7 @@ audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, set_buff
buffer_size_changed_callback,
stm);
if (r != noErr) {
if (set_side == INPUT) {
if (side == INPUT) {
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/input/kAudioDevicePropertyBufferFrameSize", r);
} else {
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/output/kAudioDevicePropertyBufferFrameSize", r);
@ -1344,7 +1529,7 @@ audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, set_buff
buffer_size_changed_callback,
stm);
if (r != noErr) {
if (set_side == INPUT) {
if (side == INPUT) {
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/input/kAudioDevicePropertyBufferFrameSize", r);
} else {
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/output/kAudioDevicePropertyBufferFrameSize", r);
@ -1489,7 +1674,7 @@ audiounit_configure_output(cubeb_stream * stm)
&output_hw_desc,
&size);
if (r != noErr) {
PRINT_ERROR_CODE("AudioUnitGetProperty/output/tkAudioUnitProperty_StreamFormat", r);
PRINT_ERROR_CODE("AudioUnitGetProperty/output/kAudioUnitProperty_StreamFormat", r);
return CUBEB_ERROR;
}
stm->output_hw_rate = output_hw_desc.mSampleRate;
@ -1538,6 +1723,8 @@ audiounit_configure_output(cubeb_stream * stm)
return CUBEB_ERROR;
}
audiounit_layout_init(&stm->output_unit, OUTPUT, &stm->output_stream_params);
LOG("(%p) Output audiounit init successfully.", stm);
return CUBEB_OK;
}
@ -2528,13 +2715,76 @@ int audiounit_register_device_collection_changed(cubeb * context,
return (ret == noErr) ? CUBEB_OK : CUBEB_ERROR;
}
static cubeb_channel_layout
audiounit_get_channel_layout(bool preferred)
{
OSStatus rv = noErr;
// Get the default ouput unit
AudioUnit output_unit;
audiounit_create_unit(&output_unit, false, nullptr, 0);
// Get the channel layout
UInt32 size = 0;
rv = AudioUnitGetPropertyInfo(output_unit,
preferred ? kAudioDevicePropertyPreferredChannelLayout :
kAudioUnitProperty_AudioChannelLayout,
kAudioUnitScope_Output,
AU_OUT_BUS,
&size,
nullptr);
if (rv != noErr) {
if (preferred) {
PRINT_ERROR_CODE("AudioUnitGetPropertyInfo/kAudioDevicePropertyPreferredChannelLayout", rv);
} else {
PRINT_ERROR_CODE("AudioUnitGetPropertyInfo/kAudioUnitProperty_AudioChannelLayout", rv);
}
return CUBEB_LAYOUT_UNDEFINED;
}
assert(size > 0);
auto_channel_layout layout(size);
rv = AudioUnitGetProperty(output_unit,
preferred ? kAudioDevicePropertyPreferredChannelLayout :
kAudioUnitProperty_AudioChannelLayout,
kAudioUnitScope_Output,
AU_OUT_BUS,
layout.get(),
&size);
if (rv != noErr) {
if (preferred) {
PRINT_ERROR_CODE("AudioUnitGetProperty/kAudioDevicePropertyPreferredChannelLayout", rv);
} else {
PRINT_ERROR_CODE("AudioUnitGetProperty/kAudioUnitProperty_AudioChannelLayout", rv);
}
return CUBEB_LAYOUT_UNDEFINED;
}
if (layout.get()->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions) {
// kAudioChannelLayoutTag_UseChannelBitmap
// kAudioChannelLayoutTag_Mono
// kAudioChannelLayoutTag_Stereo
// ....
LOG("Only handle UseChannelDescriptions for now.\n");
return CUBEB_LAYOUT_UNDEFINED;
}
cubeb_channel_map cm;
cm.channels = layout.get()->mNumberChannelDescriptions;
for (UInt32 i = 0; i < layout.get()->mNumberChannelDescriptions; ++i) {
cm.map[i] = channel_label_to_cubeb_channel(layout.get()->mChannelDescriptions[i].mChannelLabel);
}
return cubeb_channel_map_to_layout(&cm);
}
cubeb_ops const audiounit_ops = {
/*.init =*/ audiounit_init,
/*.get_backend_id =*/ audiounit_get_backend_id,
/*.get_max_channel_count =*/ audiounit_get_max_channel_count,
/*.get_min_latency =*/ audiounit_get_min_latency,
/*.get_preferred_sample_rate =*/ audiounit_get_preferred_sample_rate,
/*.get_preferred_channel_layout =*/ nullptr,
/*.get_preferred_channel_layout =*/ audiounit_get_preferred_channel_layout,
/*.enumerate_devices =*/ audiounit_enumerate_devices,
/*.destroy =*/ audiounit_destroy,
/*.stream_init =*/ audiounit_stream_init,

View File

@ -9,6 +9,55 @@
#include "cubeb-internal.h"
#include "cubeb_mixer.h"
// DUAL_MONO(_LFE) is same as STEREO(_LFE).
#define MASK_MONO (1 << CHANNEL_MONO)
#define MASK_MONO_LFE (MASK_MONO | (1 << CHANNEL_LFE))
#define MASK_STEREO ((1 << CHANNEL_LEFT) | (1 << CHANNEL_RIGHT))
#define MASK_STEREO_LFE (MASK_STEREO | (1 << CHANNEL_LFE))
#define MASK_3F (MASK_STEREO | (1 << CHANNEL_CENTER))
#define MASK_3F_LFE (MASK_3F | (1 << CHANNEL_LFE))
#define MASK_2F1 (MASK_STEREO | (1 << CHANNEL_RCENTER))
#define MASK_2F1_LFE (MASK_2F1 | (1 << CHANNEL_LFE))
#define MASK_3F1 (MASK_3F | (1 << CHANNEL_RCENTER))
#define MASK_3F1_LFE (MASK_3F1 | (1 << CHANNEL_LFE))
#define MASK_2F2 (MASK_STEREO | (1 << CHANNEL_LS) | (1 << CHANNEL_RS))
#define MASK_2F2_LFE (MASK_2F2 | (1 << CHANNEL_LFE))
#define MASK_3F2 (MASK_2F2 | (1 << CHANNEL_CENTER))
#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) {
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;
case MASK_STEREO: return CUBEB_LAYOUT_STEREO;
case MASK_STEREO_LFE: return CUBEB_LAYOUT_STEREO_LFE;
case MASK_3F: return CUBEB_LAYOUT_3F;
case MASK_3F_LFE: return CUBEB_LAYOUT_3F_LFE;
case MASK_2F1: return CUBEB_LAYOUT_2F1;
case MASK_2F1_LFE: return CUBEB_LAYOUT_2F1_LFE;
case MASK_3F1: return CUBEB_LAYOUT_3F1;
case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE;
case MASK_2F2: return CUBEB_LAYOUT_2F2;
case MASK_2F2_LFE: return CUBEB_LAYOUT_2F2_LFE;
case MASK_3F2: return CUBEB_LAYOUT_3F2;
case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE;
case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE;
case MASK_3F4_LFE: return CUBEB_LAYOUT_3F4_LFE;
default: return CUBEB_LAYOUT_UNDEFINED;
}
}
cubeb_layout_map const CUBEB_CHANNEL_LAYOUT_MAPS[CUBEB_LAYOUT_MAX] = {
{ "undefined", 0, CUBEB_LAYOUT_UNDEFINED },
{ "dual mono", 2, CUBEB_LAYOUT_DUAL_MONO },

View File

@ -52,6 +52,13 @@ static cubeb_channel const CHANNEL_INDEX_TO_ORDER[CUBEB_LAYOUT_MAX][CHANNEL_MAX]
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RLS, CHANNEL_RRS, CHANNEL_LS, CHANNEL_RS } // 3F4_LFE
};
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);
bool cubeb_should_upmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer);
bool cubeb_should_downmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer);

View File

@ -525,55 +525,15 @@ layout_to_channel_map(cubeb_channel_layout layout, pa_channel_map * cm)
}
}
// DUAL_MONO(_LFE) is same as STEREO(_LFE).
#define MASK_MONO (1 << CHANNEL_MONO)
#define MASK_MONO_LFE (MASK_MONO | (1 << CHANNEL_LFE))
#define MASK_STEREO ((1 << CHANNEL_LEFT) | (1 << CHANNEL_RIGHT))
#define MASK_STEREO_LFE (MASK_STEREO | (1 << CHANNEL_LFE))
#define MASK_3F (MASK_STEREO | (1 << CHANNEL_CENTER))
#define MASK_3F_LFE (MASK_3F | (1 << CHANNEL_LFE))
#define MASK_2F1 (MASK_STEREO | (1 << CHANNEL_RCENTER))
#define MASK_2F1_LFE (MASK_2F1 | (1 << CHANNEL_LFE))
#define MASK_3F1 (MASK_3F | (1 << CHANNEL_RCENTER))
#define MASK_3F1_LFE (MASK_3F1 | (1 << CHANNEL_LFE))
#define MASK_2F2 (MASK_STEREO | (1 << CHANNEL_LS) | (1 << CHANNEL_RS))
#define MASK_2F2_LFE (MASK_2F2 | (1 << CHANNEL_LFE))
#define MASK_3F2 (MASK_2F2 | (1 << CHANNEL_CENTER))
#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))
static cubeb_channel_layout
channel_map_to_layout(pa_channel_map * cm)
{
uint32_t channel_mask = 0;
for (uint8_t i = 0 ; i < cm->channels ; ++i) {
cubeb_channel channel = pa_channel_to_cubeb_channel(cm->map[i]);
if (channel == CHANNEL_INVALID) {
return CUBEB_LAYOUT_UNDEFINED;
}
channel_mask |= 1 << channel;
}
switch(channel_mask) {
case MASK_MONO: return CUBEB_LAYOUT_MONO;
case MASK_MONO_LFE: return CUBEB_LAYOUT_MONO_LFE;
case MASK_STEREO: return CUBEB_LAYOUT_STEREO;
case MASK_STEREO_LFE: return CUBEB_LAYOUT_STEREO_LFE;
case MASK_3F: return CUBEB_LAYOUT_3F;
case MASK_3F_LFE: return CUBEB_LAYOUT_3F_LFE;
case MASK_2F1: return CUBEB_LAYOUT_2F1;
case MASK_2F1_LFE: return CUBEB_LAYOUT_2F1_LFE;
case MASK_3F1: return CUBEB_LAYOUT_3F1;
case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE;
case MASK_2F2: return CUBEB_LAYOUT_2F2;
case MASK_2F2_LFE: return CUBEB_LAYOUT_2F2_LFE;
case MASK_3F2: return CUBEB_LAYOUT_3F2;
case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE;
case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE;
case MASK_3F4_LFE: return CUBEB_LAYOUT_3F4_LFE;
default: return CUBEB_LAYOUT_UNDEFINED;
cubeb_channel_map cubeb_map;
cubeb_map.channels = cm->channels;
for (uint32_t i = 0 ; i < cm->channels ; ++i) {
cubeb_map.map[i] = pa_channel_to_cubeb_channel(cm->map[i]);
}
return cubeb_channel_map_to_layout(&cubeb_map);
}
static void pulse_context_destroy(cubeb * ctx);

View File

@ -4,11 +4,7 @@
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
// Explicitly define NTDDI_VERSION rather than letting the value be derived
// from _WIN32_WINNT because we depend on values defined for XP SP2 and WS03
// SP1.
#define _WIN32_WINNT 0x0502
#define NTDDI_VERSION 0x05020100
#define _WIN32_WINNT 0x0600
#define NOMINMAX
#include <initguid.h>
@ -164,10 +160,6 @@ private:
HRESULT result;
};
typedef HANDLE (WINAPI *set_mm_thread_characteristics_function)(
const char * TaskName, LPDWORD TaskIndex);
typedef BOOL (WINAPI *revert_mm_thread_characteristics_function)(HANDLE handle);
extern cubeb_ops const wasapi_ops;
int wasapi_stream_stop(cubeb_stream * stm);
@ -181,11 +173,6 @@ static std::unique_ptr<wchar_t const []> utf8_to_wstr(char const * str);
struct cubeb {
cubeb_ops const * ops = &wasapi_ops;
/* Library dynamically opened to increase the render thread priority, and
the two function pointers we need. */
HMODULE mmcss_module = nullptr;
set_mm_thread_characteristics_function set_mm_thread_characteristics = nullptr;
revert_mm_thread_characteristics_function revert_mm_thread_characteristics = nullptr;
};
class wasapi_endpoint_notification_client;
@ -864,8 +851,7 @@ wasapi_stream_render_loop(LPVOID stream)
/* We could consider using "Pro Audio" here for WebAudio and
maybe WebRTC. */
mmcss_handle =
stm->context->set_mm_thread_characteristics("Audio", &mmcss_task_index);
mmcss_handle = AvSetMmThreadCharacteristicsA("Audio", &mmcss_task_index);
if (!mmcss_handle) {
/* This is not fatal, but we might glitch under heavy load. */
LOG("Unable to use mmcss to bump the render thread priority: %lx", GetLastError());
@ -967,7 +953,7 @@ wasapi_stream_render_loop(LPVOID stream)
}
if (mmcss_handle) {
stm->context->revert_mm_thread_characteristics(mmcss_handle);
AvRevertMmThreadCharacteristics(mmcss_handle);
}
return 0;
@ -975,16 +961,6 @@ wasapi_stream_render_loop(LPVOID stream)
void wasapi_destroy(cubeb * context);
HANDLE WINAPI set_mm_thread_characteristics_noop(const char *, LPDWORD mmcss_task_index)
{
return (HANDLE)1;
}
BOOL WINAPI revert_mm_thread_characteristics_noop(HANDLE mmcss_handle)
{
return true;
}
HRESULT register_notification_client(cubeb_stream * stm)
{
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
@ -1162,27 +1138,6 @@ int wasapi_init(cubeb ** context, char const * context_name)
ctx->ops = &wasapi_ops;
ctx->mmcss_module = LoadLibraryA("Avrt.dll");
if (ctx->mmcss_module) {
ctx->set_mm_thread_characteristics =
(set_mm_thread_characteristics_function) GetProcAddress(
ctx->mmcss_module, "AvSetMmThreadCharacteristicsA");
ctx->revert_mm_thread_characteristics =
(revert_mm_thread_characteristics_function) GetProcAddress(
ctx->mmcss_module, "AvRevertMmThreadCharacteristics");
if (!(ctx->set_mm_thread_characteristics && ctx->revert_mm_thread_characteristics)) {
LOG("Could not load AvSetMmThreadCharacteristics or AvRevertMmThreadCharacteristics: %lx", GetLastError());
FreeLibrary(ctx->mmcss_module);
}
} else {
// This is not a fatal error, but we might end up glitching when
// the system is under high load.
LOG("Could not load Avrt.dll");
ctx->set_mm_thread_characteristics = &set_mm_thread_characteristics_noop;
ctx->revert_mm_thread_characteristics = &revert_mm_thread_characteristics_noop;
}
*context = ctx;
return CUBEB_OK;
@ -1239,9 +1194,6 @@ bool stop_and_join_render_thread(cubeb_stream * stm)
void wasapi_destroy(cubeb * context)
{
if (context->mmcss_module) {
FreeLibrary(context->mmcss_module);
}
delete context;
}