mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 698328 - Add a new cubeb backend based on AudioTrack.cpp. r=kinetik
This commit is contained in:
parent
50b59f2b0b
commit
0994e31e10
@ -5657,10 +5657,7 @@ fi
|
||||
if test -n "$MOZ_CUBEB"; then
|
||||
case "$target" in
|
||||
*-android*|*-linuxandroid*)
|
||||
if test -n "$gonkdir"; then
|
||||
AC_DEFINE(MOZ_CUBEB)
|
||||
fi
|
||||
dnl No Android implementation of libcubeb yet.
|
||||
AC_DEFINE(MOZ_CUBEB)
|
||||
;;
|
||||
*-linux*)
|
||||
AC_DEFINE(MOZ_CUBEB)
|
||||
|
@ -1,3 +1,4 @@
|
||||
Matthew Gregan <kinetik@flim.org>
|
||||
Alexandre Ratchov <alex@caoua.org>
|
||||
Michael Wu <mwu@mozilla.com>
|
||||
Paul Adenot <paul@paul.cx>
|
||||
|
@ -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 f2d524c34b6f75d85053034c3075c2ff08383769.
|
||||
The git commit ID used was 0c7d97523096a7d4ae363974393d06f77c4592c9.
|
||||
|
@ -4,12 +4,12 @@
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#ifndef CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382
|
||||
#define CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382
|
||||
#if !defined(CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382)
|
||||
#define CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382
|
||||
|
||||
#include <cubeb/cubeb-stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@ -226,7 +226,7 @@ int cubeb_stream_stop(cubeb_stream * stream);
|
||||
@retval CUBEB_ERROR */
|
||||
int cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -28,14 +28,17 @@ DEFINES += -DUSE_WINMM
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Android)
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
CSRCS += \
|
||||
cubeb_audiotrack.c \
|
||||
$(NULL)
|
||||
DEFINES += -DUSE_AUDIOTRACK
|
||||
endif
|
||||
CSRCS += \
|
||||
cubeb_opensl.c \
|
||||
$(NULL)
|
||||
DEFINES += -DUSE_OPENSL
|
||||
endif
|
||||
# No Android implementation of libcubeb yet.
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Darwin)
|
||||
CSRCS += \
|
||||
|
81
media/libcubeb/src/android/audiotrack_definitions.h
Normal file
81
media/libcubeb/src/android/audiotrack_definitions.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cubeb/cubeb-stdint.h>
|
||||
|
||||
/*
|
||||
* The following definitions are copied from the android sources. Only the
|
||||
* relevant enum member and values needed are copied.
|
||||
*/
|
||||
|
||||
/*
|
||||
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/utils/Errors.h
|
||||
*/
|
||||
typedef int32_t status_t;
|
||||
|
||||
/*
|
||||
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/media/AudioTrack.h
|
||||
*/
|
||||
struct Buffer {
|
||||
uint32_t flags;
|
||||
int channelCount;
|
||||
int format;
|
||||
size_t frameCount;
|
||||
size_t size;
|
||||
union {
|
||||
void* raw;
|
||||
short* i16;
|
||||
int8_t* i8;
|
||||
};
|
||||
};
|
||||
|
||||
enum event_type {
|
||||
EVENT_MORE_DATA = 0,
|
||||
EVENT_UNDERRUN = 1,
|
||||
EVENT_LOOP_END = 2,
|
||||
EVENT_MARKER = 3,
|
||||
EVENT_NEW_POS = 4,
|
||||
EVENT_BUFFER_END = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/media/AudioSystem.h
|
||||
* and
|
||||
* https://android.googlesource.com/platform/system/core/+/android-4.2.2_r1/include/system/audio.h
|
||||
*/
|
||||
|
||||
#define AUDIO_STREAM_TYPE_MUSIC 3
|
||||
|
||||
enum {
|
||||
AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS = 0x1,
|
||||
AUDIO_CHANNEL_OUT_FRONT_RIGHT_ICS = 0x2,
|
||||
AUDIO_CHANNEL_OUT_MONO_ICS = AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS,
|
||||
AUDIO_CHANNEL_OUT_STEREO_ICS = (AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS | AUDIO_CHANNEL_OUT_FRONT_RIGHT_ICS)
|
||||
} AudioTrack_ChannelMapping_ICS;
|
||||
|
||||
enum {
|
||||
AUDIO_CHANNEL_OUT_FRONT_LEFT_Froyo = 0x4,
|
||||
AUDIO_CHANNEL_OUT_FRONT_RIGHT_Froyo = 0x8,
|
||||
AUDIO_CHANNEL_OUT_MONO_Froyo = AUDIO_CHANNEL_OUT_FRONT_LEFT_Froyo,
|
||||
AUDIO_CHANNEL_OUT_STEREO_Froyo = (AUDIO_CHANNEL_OUT_FRONT_LEFT_Froyo | AUDIO_CHANNEL_OUT_FRONT_RIGHT_Froyo)
|
||||
} AudioTrack_ChannelMapping_Froyo;
|
||||
|
||||
typedef enum {
|
||||
AUDIO_FORMAT_PCM = 0x00000000,
|
||||
AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1,
|
||||
AUDIO_FORMAT_PCM_16_BIT = (AUDIO_FORMAT_PCM | AUDIO_FORMAT_PCM_SUB_16_BIT),
|
||||
} AudioTrack_SampleType;
|
||||
|
67
media/libcubeb/src/android/sles_definitions.h
Normal file
67
media/libcubeb/src/android/sles_definitions.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is similar to the file "OpenSLES_AndroidConfiguration.h" found in
|
||||
* the Android NDK, but removes the #ifdef __cplusplus defines, so we can keep
|
||||
* using a C compiler in cubeb.
|
||||
*/
|
||||
|
||||
#ifndef OPENSL_ES_ANDROIDCONFIGURATION_H_
|
||||
#define OPENSL_ES_ANDROIDCONFIGURATION_H_
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Android AudioRecorder configuration */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** Audio recording preset */
|
||||
/** Audio recording preset key */
|
||||
#define SL_ANDROID_KEY_RECORDING_PRESET ((const SLchar*) "androidRecordingPreset")
|
||||
/** Audio recording preset values */
|
||||
/** preset "none" cannot be set, it is used to indicate the current settings
|
||||
* do not match any of the presets. */
|
||||
#define SL_ANDROID_RECORDING_PRESET_NONE ((SLuint32) 0x00000000)
|
||||
/** generic recording configuration on the platform */
|
||||
#define SL_ANDROID_RECORDING_PRESET_GENERIC ((SLuint32) 0x00000001)
|
||||
/** uses the microphone audio source with the same orientation as the camera
|
||||
* if available, the main device microphone otherwise */
|
||||
#define SL_ANDROID_RECORDING_PRESET_CAMCORDER ((SLuint32) 0x00000002)
|
||||
/** uses the main microphone tuned for voice recognition */
|
||||
#define SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION ((SLuint32) 0x00000003)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Android AudioPlayer configuration */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** Audio playback stream type */
|
||||
/** Audio playback stream type key */
|
||||
#define SL_ANDROID_KEY_STREAM_TYPE ((const SLchar*) "androidPlaybackStreamType")
|
||||
|
||||
/** Audio playback stream type values */
|
||||
/* same as android.media.AudioManager.STREAM_VOICE_CALL */
|
||||
#define SL_ANDROID_STREAM_VOICE ((SLint32) 0x00000000)
|
||||
/* same as android.media.AudioManager.STREAM_SYSTEM */
|
||||
#define SL_ANDROID_STREAM_SYSTEM ((SLint32) 0x00000001)
|
||||
/* same as android.media.AudioManager.STREAM_RING */
|
||||
#define SL_ANDROID_STREAM_RING ((SLint32) 0x00000002)
|
||||
/* same as android.media.AudioManager.STREAM_MUSIC */
|
||||
#define SL_ANDROID_STREAM_MEDIA ((SLint32) 0x00000003)
|
||||
/* same as android.media.AudioManager.STREAM_ALARM */
|
||||
#define SL_ANDROID_STREAM_ALARM ((SLint32) 0x00000004)
|
||||
/* same as android.media.AudioManager.STREAM_NOTIFICATION */
|
||||
#define SL_ANDROID_STREAM_NOTIFICATION ((SLint32) 0x00000005)
|
||||
|
||||
#endif /* OPENSL_ES_ANDROIDCONFIGURATION_H_ */
|
81
media/libcubeb/src/audiotrack_definitions.h
Normal file
81
media/libcubeb/src/audiotrack_definitions.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cubeb/cubeb-stdint.h>
|
||||
|
||||
/*
|
||||
* The following definitions are copied from the android sources. Only the
|
||||
* relevant enum member and values needed are copied.
|
||||
*/
|
||||
|
||||
/*
|
||||
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/utils/Errors.h
|
||||
*/
|
||||
typedef int32_t status_t;
|
||||
|
||||
/*
|
||||
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/media/AudioTrack.h
|
||||
*/
|
||||
struct Buffer {
|
||||
uint32_t flags;
|
||||
int channelCount;
|
||||
int format;
|
||||
size_t frameCount;
|
||||
size_t size;
|
||||
union {
|
||||
void* raw;
|
||||
short* i16;
|
||||
int8_t* i8;
|
||||
};
|
||||
};
|
||||
|
||||
enum event_type {
|
||||
EVENT_MORE_DATA = 0,
|
||||
EVENT_UNDERRUN = 1,
|
||||
EVENT_LOOP_END = 2,
|
||||
EVENT_MARKER = 3,
|
||||
EVENT_NEW_POS = 4,
|
||||
EVENT_BUFFER_END = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/media/AudioSystem.h
|
||||
* and
|
||||
* https://android.googlesource.com/platform/system/core/+/android-4.2.2_r1/include/system/audio.h
|
||||
*/
|
||||
|
||||
#define AUDIO_STREAM_TYPE_MUSIC 3
|
||||
|
||||
enum {
|
||||
AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS = 0x1,
|
||||
AUDIO_CHANNEL_OUT_FRONT_RIGHT_ICS = 0x2,
|
||||
AUDIO_CHANNEL_OUT_MONO_ICS = AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS,
|
||||
AUDIO_CHANNEL_OUT_STEREO_ICS = (AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS | AUDIO_CHANNEL_OUT_FRONT_RIGHT_ICS)
|
||||
} AudioTrack_ChannelMapping_ICS;
|
||||
|
||||
enum {
|
||||
AUDIO_CHANNEL_OUT_FRONT_LEFT_Froyo = 0x4,
|
||||
AUDIO_CHANNEL_OUT_FRONT_RIGHT_Froyo = 0x8,
|
||||
AUDIO_CHANNEL_OUT_MONO_Froyo = AUDIO_CHANNEL_OUT_FRONT_LEFT_Froyo,
|
||||
AUDIO_CHANNEL_OUT_STEREO_Froyo = (AUDIO_CHANNEL_OUT_FRONT_LEFT_Froyo | AUDIO_CHANNEL_OUT_FRONT_RIGHT_Froyo)
|
||||
} AudioTrack_ChannelMapping_Froyo;
|
||||
|
||||
typedef enum {
|
||||
AUDIO_FORMAT_PCM = 0x00000000,
|
||||
AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1,
|
||||
AUDIO_FORMAT_PCM_16_BIT = (AUDIO_FORMAT_PCM | AUDIO_FORMAT_PCM_SUB_16_BIT),
|
||||
} AudioTrack_SampleType;
|
||||
|
@ -4,8 +4,8 @@
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#ifndef CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5
|
||||
#define CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5
|
||||
#if !defined(CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5)
|
||||
#define CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5
|
||||
|
||||
#include "cubeb/cubeb.h"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "cubeb/cubeb.h"
|
||||
@ -21,30 +21,33 @@ struct cubeb_stream {
|
||||
struct cubeb * context;
|
||||
};
|
||||
|
||||
#ifdef USE_PULSE
|
||||
#if defined(USE_PULSE)
|
||||
int pulse_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#ifdef USE_ALSA
|
||||
#if defined(USE_ALSA)
|
||||
int alsa_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#ifdef USE_AUDIOQUEUE
|
||||
#if defined(USE_AUDIOQUEUE)
|
||||
int audioqueue_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#ifdef USE_AUDIOUNIT
|
||||
#if defined(USE_AUDIOUNIT)
|
||||
int audiounit_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#ifdef USE_DIRECTSOUND
|
||||
#if defined(USE_DIRECTSOUND)
|
||||
int directsound_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#ifdef USE_WINMM
|
||||
#if defined(USE_WINMM)
|
||||
int winmm_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#ifdef USE_SNDIO
|
||||
#if defined(USE_SNDIO)
|
||||
int sndio_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#ifdef USE_OPENSL
|
||||
#if defined(USE_OPENSL)
|
||||
int opensl_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_AUDIOTRACK)
|
||||
int audiotrack_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
|
||||
int
|
||||
validate_stream_params(cubeb_stream_params stream_params)
|
||||
@ -78,29 +81,32 @@ int
|
||||
cubeb_init(cubeb ** context, char const * context_name)
|
||||
{
|
||||
int (* init[])(cubeb **, char const *) = {
|
||||
#ifdef USE_PULSE
|
||||
#if defined(USE_PULSE)
|
||||
pulse_init,
|
||||
#endif
|
||||
#ifdef USE_ALSA
|
||||
#if defined(USE_ALSA)
|
||||
alsa_init,
|
||||
#endif
|
||||
#ifdef USE_AUDIOUNIT
|
||||
#if defined(USE_AUDIOUNIT)
|
||||
audiounit_init,
|
||||
#endif
|
||||
#ifdef USE_AUDIOQUEUE
|
||||
#if defined(USE_AUDIOQUEUE)
|
||||
audioqueue_init,
|
||||
#endif
|
||||
#ifdef USE_WINMM
|
||||
#if defined(USE_WINMM)
|
||||
winmm_init,
|
||||
#endif
|
||||
#ifdef USE_DIRECTSOUND
|
||||
#if defined(USE_DIRECTSOUND)
|
||||
directsound_init,
|
||||
#endif
|
||||
#ifdef USE_SNDIO
|
||||
#if defined(USE_SNDIO)
|
||||
sndio_init,
|
||||
#endif
|
||||
#ifdef USE_OPENSL
|
||||
#if defined(USE_OPENSL)
|
||||
opensl_init,
|
||||
#endif
|
||||
#if defined(USE_AUDIOTRACK)
|
||||
audiotrack_init,
|
||||
#endif
|
||||
};
|
||||
int i;
|
||||
|
402
media/libcubeb/src/cubeb_audiotrack.c
Normal file
402
media/libcubeb/src/cubeb_audiotrack.c
Normal file
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright © 2013 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <dlfcn.h>
|
||||
#include "android/log.h"
|
||||
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
#include "android/audiotrack_definitions.h"
|
||||
|
||||
#ifndef ALOG
|
||||
#if defined(DEBUG) || defined(FORCE_ALOG)
|
||||
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko - Cubeb" , ## args)
|
||||
#else
|
||||
#define ALOG(args...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A lot of bytes for safety. It should be possible to bring this down a bit. */
|
||||
#define SIZE_AUDIOTRACK_INSTANCE 256
|
||||
|
||||
/**
|
||||
* call dlsym to get the symbol |mangled_name|, handle the error and store the
|
||||
* pointer in |pointer|. Because depending on Android version, we want different
|
||||
* symbols, not finding a symbol is not an error. */
|
||||
#define DLSYM_DLERROR(mangled_name, pointer, lib) \
|
||||
do { \
|
||||
pointer = dlsym(lib, mangled_name); \
|
||||
if (!pointer) { \
|
||||
ALOG("error while loading %stm: %stm\n", mangled_name, dlerror()); \
|
||||
} else { \
|
||||
ALOG("%stm: OK", mangled_name); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
static struct cubeb_ops const audiotrack_ops;
|
||||
void audiotrack_destroy(cubeb * context);
|
||||
void audiotrack_stream_destroy(cubeb_stream * stream);
|
||||
|
||||
struct AudioTrack {
|
||||
/* only available on ICS and later. */
|
||||
/* static */ status_t (*get_min_frame_count)(int* frame_count, int stream_type, uint32_t rate);
|
||||
/* if this symbol is not availble, and the next one is, we know
|
||||
* we are on a Froyo (Android 2.2) device. */
|
||||
void* (*ctor)(void* instance, int, unsigned int, int, int, int, unsigned int, void (*)(int, void*, void*), void*, int, int);
|
||||
void* (*ctor_froyo)(void* instance, int, unsigned int, int, int, int, unsigned int, void (*)(int, void*, void*), void*, int);
|
||||
void* (*dtor)(void* instance);
|
||||
void (*start)(void* instance);
|
||||
void (*pause)(void* instance);
|
||||
uint32_t (*latency)(void* instance);
|
||||
status_t (*check)(void* instance);
|
||||
status_t (*get_position)(void* instance, uint32_t* position);
|
||||
/* only used on froyo. */
|
||||
/* static */ int (*get_output_frame_count)(int* frame_count, int stream);
|
||||
/* static */ int (*get_output_latency)(uint32_t* frame_count, int stream);
|
||||
/* static */ int (*get_output_samplingrate)(int* frame_count, int stream);
|
||||
status_t (*set_marker_position)(void* instance, unsigned int);
|
||||
|
||||
};
|
||||
|
||||
struct cubeb {
|
||||
struct cubeb_ops const * ops;
|
||||
void * library;
|
||||
struct AudioTrack klass;
|
||||
};
|
||||
|
||||
struct cubeb_stream {
|
||||
cubeb * context;
|
||||
cubeb_stream_params params;
|
||||
cubeb_data_callback data_callback;
|
||||
cubeb_state_callback state_callback;
|
||||
void * instance;
|
||||
void * user_ptr;
|
||||
/* Number of frames that have been passed to the AudioTrack callback */
|
||||
long unsigned written;
|
||||
int draining;
|
||||
};
|
||||
|
||||
static void
|
||||
audiotrack_refill(int event, void* user, void* info)
|
||||
{
|
||||
cubeb_stream * stream = user;
|
||||
switch (event) {
|
||||
case EVENT_MORE_DATA: {
|
||||
long got = 0;
|
||||
struct Buffer * b = (struct Buffer*)info;
|
||||
|
||||
if (stream->draining) {
|
||||
return;
|
||||
}
|
||||
|
||||
got = stream->data_callback(stream, stream->user_ptr, b->raw, b->frameCount);
|
||||
|
||||
stream->written += got;
|
||||
|
||||
if (got != (long)b->frameCount) {
|
||||
uint32_t p;
|
||||
stream->draining = 1;
|
||||
/* set a marker so we are notified when the are done draining, that is,
|
||||
* when every frame has been played by android. */
|
||||
stream->context->klass.set_marker_position(stream->instance, stream->written);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EVENT_UNDERRUN:
|
||||
ALOG("underrun in cubeb backend.");
|
||||
break;
|
||||
case EVENT_LOOP_END:
|
||||
assert(0 && "We don't support the loop feature of audiotrack.");
|
||||
break;
|
||||
case EVENT_MARKER:
|
||||
assert(stream->draining);
|
||||
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_DRAINED);
|
||||
break;
|
||||
case EVENT_NEW_POS:
|
||||
assert(0 && "We don't support the setPositionUpdatePeriod feature of audiotrack.");
|
||||
break;
|
||||
case EVENT_BUFFER_END:
|
||||
assert(0 && "Should not happen.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are running on froyo if we found the right AudioTrack constructor */
|
||||
static int
|
||||
audiotrack_version_is_froyo(cubeb * ctx)
|
||||
{
|
||||
return ctx->klass.ctor_froyo != NULL;
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_get_min_frame_count(cubeb * ctx, cubeb_stream_params * params, int * min_frame_count)
|
||||
{
|
||||
status_t status;
|
||||
/* Recent Android have a getMinFrameCount method. On Froyo, we have to compute it by hand. */
|
||||
if (audiotrack_version_is_froyo(ctx)) {
|
||||
int samplerate, frame_count, latency, min_buffer_count;
|
||||
status = ctx->klass.get_output_frame_count(&frame_count, AUDIO_STREAM_TYPE_MUSIC);
|
||||
if (status) {
|
||||
ALOG("error getting the output frame count.");
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
status = ctx->klass.get_output_latency((uint32_t*)&latency, AUDIO_STREAM_TYPE_MUSIC);
|
||||
if (status) {
|
||||
ALOG("error getting the output frame count.");
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
status = ctx->klass.get_output_samplingrate(&samplerate, AUDIO_STREAM_TYPE_MUSIC);
|
||||
if (status) {
|
||||
ALOG("error getting the output frame count.");
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
/* Those numbers were found reading the Android source. It is the minimum
|
||||
* numbers that will be accepted by the AudioTrack class, hence yielding the
|
||||
* best latency possible.
|
||||
* See https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/media/libmedia/AudioTrack.cpp
|
||||
* around line 181 for Android 2.2 */
|
||||
min_buffer_count = latency / ((1000 * frame_count) / samplerate);
|
||||
min_buffer_count = min_buffer_count < 2 ? min_buffer_count : 2;
|
||||
*min_frame_count = (frame_count * params->rate * min_buffer_count) / samplerate;
|
||||
return CUBEB_OK;
|
||||
}
|
||||
/* Recent Android have a getMinFrameCount method. */
|
||||
status = ctx->klass.get_min_frame_count(min_frame_count, AUDIO_STREAM_TYPE_MUSIC, params->rate);
|
||||
if (status != 0) {
|
||||
ALOG("error getting the min frame count");
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_init(cubeb ** context, char const * context_name)
|
||||
{
|
||||
cubeb * ctx;
|
||||
struct AudioTrack* c;
|
||||
|
||||
assert(context);
|
||||
*context = NULL;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
assert(ctx);
|
||||
|
||||
/* If we use an absolute path here ("/system/lib/libmedia.so"), and on Android
|
||||
* 2.2, the dlopen succeeds, all the dlsym succeed, but a segfault happens on
|
||||
* the first call to a dlsym'ed function. Somehow this does not happen when
|
||||
* using only the name of the library. */
|
||||
ctx->library = dlopen("libmedia.so", RTLD_LAZY);
|
||||
if (!ctx->library) {
|
||||
ALOG("dlopen error: %s.", dlerror());
|
||||
free(ctx);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
/* Recent Android first, then Froyo. */
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrackC1EijiiijPFviPvS1_ES1_ii", ctx->klass.ctor, ctx->library);
|
||||
if (!ctx->klass.ctor) {
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrackC1EijiiijPFviPvS1_ES1_i", ctx->klass.ctor_froyo, ctx->library);
|
||||
assert(ctx->klass.ctor_froyo);
|
||||
}
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrackD1Ev", ctx->klass.dtor, ctx->library);
|
||||
|
||||
DLSYM_DLERROR("_ZNK7android10AudioTrack7latencyEv", ctx->klass.latency, ctx->library);
|
||||
DLSYM_DLERROR("_ZNK7android10AudioTrack9initCheckEv", ctx->klass.check, ctx->library);
|
||||
|
||||
/* |getMinFrameCount| is not available on Froyo. */
|
||||
if (audiotrack_version_is_froyo(ctx)) {
|
||||
DLSYM_DLERROR("_ZN7android11AudioSystem19getOutputFrameCountEPii", ctx->klass.get_output_frame_count, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android11AudioSystem16getOutputLatencyEPji", ctx->klass.get_output_latency, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android11AudioSystem21getOutputSamplingRateEPii", ctx->klass.get_output_samplingrate, ctx->library);
|
||||
} else {
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack16getMinFrameCountEPi19audio_stream_type_tj", ctx->klass.get_min_frame_count, ctx->library);
|
||||
}
|
||||
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack5startEv", ctx->klass.start, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack5pauseEv", ctx->klass.pause, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack11getPositionEPj", ctx->klass.get_position, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack17setMarkerPositionEj", ctx->klass.set_marker_position, ctx->library);
|
||||
|
||||
/* check that we have a combination of symbol that makes sense */
|
||||
c = &ctx->klass;
|
||||
if(!((c->ctor || c->ctor_froyo) && /* at least on ctor. */
|
||||
c->dtor && c->latency && c->check &&
|
||||
/* at least one way to get the minimum frame count to request. */
|
||||
((c->get_output_frame_count && c->get_output_latency && c->get_output_samplingrate) ||
|
||||
c->get_min_frame_count) &&
|
||||
c->start && c->pause && c->get_position && c->set_marker_position)) {
|
||||
ALOG("Could not find all the symbols we need.");
|
||||
audiotrack_destroy(ctx);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
ctx->ops = &audiotrack_ops;
|
||||
|
||||
*context = ctx;
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
char const *
|
||||
audiotrack_get_backend_id(cubeb * context)
|
||||
{
|
||||
return "audiotrack";
|
||||
}
|
||||
|
||||
void
|
||||
audiotrack_destroy(cubeb * context)
|
||||
{
|
||||
assert(context);
|
||||
|
||||
dlclose(context->library);
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
|
||||
cubeb_stream_params stream_params, unsigned int latency,
|
||||
cubeb_data_callback data_callback,
|
||||
cubeb_state_callback state_callback,
|
||||
void * user_ptr)
|
||||
{
|
||||
struct cubeb_stream * stm;
|
||||
int32_t channels;
|
||||
int32_t min_frame_count;
|
||||
|
||||
assert(ctx && stream);
|
||||
|
||||
if (stream_params.format == CUBEB_SAMPLE_FLOAT32LE ||
|
||||
stream_params.format == CUBEB_SAMPLE_FLOAT32BE) {
|
||||
return CUBEB_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
if (audiotrack_get_min_frame_count(ctx, &stream_params, &min_frame_count)) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
stm = calloc(1, sizeof(*stm));
|
||||
assert(stm);
|
||||
|
||||
stm->context = ctx;
|
||||
stm->data_callback = data_callback;
|
||||
stm->state_callback = state_callback;
|
||||
stm->user_ptr = user_ptr;
|
||||
stm->params = stream_params;
|
||||
|
||||
stm->instance = calloc(SIZE_AUDIOTRACK_INSTANCE, 1);
|
||||
(*(uint32_t*)((intptr_t)stm->instance + SIZE_AUDIOTRACK_INSTANCE - 4)) = 0xbaadbaad;
|
||||
assert(stm->instance && "cubeb: EOM");
|
||||
|
||||
if (audiotrack_version_is_froyo(ctx)) {
|
||||
channels = stm->params.channels == 2 ? AUDIO_CHANNEL_OUT_STEREO_Froyo : AUDIO_CHANNEL_OUT_MONO_Froyo;
|
||||
} else {
|
||||
channels = stm->params.channels == 2 ? AUDIO_CHANNEL_OUT_STEREO_ICS : AUDIO_CHANNEL_OUT_MONO_ICS;
|
||||
}
|
||||
|
||||
if (audiotrack_version_is_froyo(ctx)) {
|
||||
ctx->klass.ctor_froyo(stm->instance,
|
||||
AUDIO_STREAM_TYPE_MUSIC,
|
||||
stm->params.rate,
|
||||
AUDIO_FORMAT_PCM_16_BIT,
|
||||
channels,
|
||||
min_frame_count,
|
||||
0,
|
||||
audiotrack_refill,
|
||||
stm,
|
||||
0);
|
||||
} else {
|
||||
ctx->klass.ctor(stm->instance,
|
||||
AUDIO_STREAM_TYPE_MUSIC,
|
||||
stm->params.rate,
|
||||
AUDIO_FORMAT_PCM_16_BIT,
|
||||
channels,
|
||||
min_frame_count,
|
||||
0,
|
||||
audiotrack_refill,
|
||||
stm,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
assert((*(uint32_t*)((intptr_t)stm->instance + SIZE_AUDIOTRACK_INSTANCE - 4)) == 0xbaadbaad);
|
||||
|
||||
if (ctx->klass.check(stm->instance)) {
|
||||
ALOG("stream not initialized properly.");
|
||||
audiotrack_stream_destroy(stm);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
*stream = stm;
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
void
|
||||
audiotrack_stream_destroy(cubeb_stream * stream)
|
||||
{
|
||||
assert(stream->context);
|
||||
|
||||
stream->context->klass.dtor(stream->instance);
|
||||
|
||||
free(stream->instance);
|
||||
stream->instance = NULL;
|
||||
free(stream);
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_stream_start(cubeb_stream * stream)
|
||||
{
|
||||
assert(stream->instance);
|
||||
|
||||
stream->context->klass.start(stream->instance);
|
||||
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_STARTED);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_stream_stop(cubeb_stream * stream)
|
||||
{
|
||||
assert(stream->instance);
|
||||
|
||||
stream->context->klass.pause(stream->instance);
|
||||
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_STOPPED);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_stream_get_position(cubeb_stream * stream, uint64_t * position)
|
||||
{
|
||||
uint32_t p;
|
||||
|
||||
assert(stream->instance && position);
|
||||
stream->context->klass.get_position(stream->instance, &p);
|
||||
*position = p;
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static struct cubeb_ops const audiotrack_ops = {
|
||||
.init = audiotrack_init,
|
||||
.get_backend_id = audiotrack_get_backend_id,
|
||||
.destroy = audiotrack_destroy,
|
||||
.stream_init = audiotrack_stream_init,
|
||||
.stream_destroy = audiotrack_stream_destroy,
|
||||
.stream_start = audiotrack_stream_start,
|
||||
.stream_stop = audiotrack_stream_stop,
|
||||
.stream_get_position = audiotrack_stream_get_position
|
||||
};
|
@ -10,6 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <SLES/OpenSLES.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include "android/sles_definitions.h"
|
||||
#include <SLES/OpenSLES_Android.h>
|
||||
#endif
|
||||
#include "cubeb/cubeb.h"
|
||||
@ -123,6 +124,8 @@ opensl_init(cubeb ** context, char const * context_name)
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
assert(ctx);
|
||||
|
||||
ctx->ops = &opensl_ops;
|
||||
|
||||
ctx->lib = dlopen("libOpenSLES.so", RTLD_LAZY);
|
||||
if (!ctx->lib) {
|
||||
free(ctx);
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
|
||||
#ifdef CUBEB_SNDIO_DEBUG
|
||||
#if defined(CUBEB_SNDIO_DEBUG)
|
||||
#define DPR(...) fprintf(stderr, __VA_ARGS__);
|
||||
#else
|
||||
#define DPR(...) do {} while(0)
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "cubeb-internal.h"
|
||||
|
||||
/* This is missing from the MinGW headers. Use a safe fallback. */
|
||||
#ifndef MEMORY_ALLOCATION_ALIGNMENT
|
||||
#if !defined(MEMORY_ALLOCATION_ALIGNMENT)
|
||||
#define MEMORY_ALLOCATION_ALIGNMENT 16
|
||||
#endif
|
||||
|
||||
|
@ -10,6 +10,9 @@ cp $1/src/cubeb_audiounit.c src
|
||||
cp $1/src/cubeb_pulse.c src
|
||||
cp $1/src/cubeb_sndio.c src
|
||||
cp $1/src/cubeb_opensl.c src
|
||||
cp $1/src/cubeb_audiotrack.c src
|
||||
cp $1/src/android/audiotrack_definitions.h src/android
|
||||
cp $1/src/android/sles_definitions.h src/android
|
||||
cp $1/LICENSE .
|
||||
cp $1/README .
|
||||
cp $1/AUTHORS .
|
||||
|
Loading…
Reference in New Issue
Block a user