Bug 623444 - Import Windows libcubeb implementation. r=doublec, r=khuey

This commit is contained in:
Matthew Gregan 2012-01-13 14:38:39 +13:00
parent 8d881ee1d4
commit 576ad01988
21 changed files with 930 additions and 5 deletions

View File

@ -160,6 +160,7 @@ MOZ_ZIPWRITER = @MOZ_ZIPWRITER@
MOZ_OGG = @MOZ_OGG@
MOZ_RAW = @MOZ_RAW@
MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@
MOZ_CUBEB = @MOZ_CUBEB@
MOZ_WAVE = @MOZ_WAVE@
MOZ_MEDIA = @MOZ_MEDIA@
MOZ_VORBIS = @MOZ_VORBIS@

View File

@ -1050,4 +1050,5 @@ tremor/ivorbiscodec.h
ogg/ogg.h
ogg/os_types.h
nestegg/nestegg.h
cubeb/cubeb.h
#endif

View File

@ -4586,6 +4586,7 @@ MOZ_AUTH_EXTENSION=1
MOZ_OGG=1
MOZ_RAW=
MOZ_SYDNEYAUDIO=
MOZ_CUBEB=
MOZ_VORBIS=
MOZ_TREMOR=
MOZ_WAVE=1
@ -5596,6 +5597,7 @@ MOZ_ARG_DISABLE_BOOL(ogg,
if test -n "$MOZ_OGG"; then
AC_DEFINE(MOZ_OGG)
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
case "$target_cpu" in
arm*)
@ -5713,6 +5715,7 @@ AC_SUBST(MOZ_LIBVPX_LIBS)
if test -n "$MOZ_WEBM" -a -z "$MOZ_NATIVE_LIBVPX"; then
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
case "$target_cpu" in
arm*)
@ -5824,17 +5827,29 @@ MOZ_ARG_DISABLE_BOOL(wave,
if test -n "$MOZ_WAVE"; then
AC_DEFINE(MOZ_WAVE)
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
fi
dnl ========================================================
dnl = Handle dependent SYDNEYAUDIO and MEDIA defines
dnl = Handle dependent SYDNEYAUDIO, CUBEB, and MEDIA defines
dnl ========================================================
if test -n "$MOZ_SYDNEYAUDIO"; then
AC_DEFINE(MOZ_SYDNEYAUDIO)
fi
if test -n "$MOZ_CUBEB"; then
case "$target" in
*-mingw*)
AC_DEFINE(MOZ_CUBEB)
;;
*)
dnl Other targets will be enabled soon.
;;
esac
fi
if test -n "$MOZ_MEDIA"; then
AC_DEFINE(MOZ_MEDIA)
fi
@ -8696,6 +8711,7 @@ AC_SUBST(MOZ_APP_EXTRA_LIBS)
AC_SUBST(MOZ_MEDIA)
AC_SUBST(MOZ_SYDNEYAUDIO)
AC_SUBST(MOZ_CUBEB)
AC_SUBST(MOZ_WAVE)
AC_SUBST(MOZ_VORBIS)
AC_SUBST(MOZ_TREMOR)

View File

@ -1050,4 +1050,5 @@ tremor/ivorbiscodec.h
ogg/ogg.h
ogg/os_types.h
nestegg/nestegg.h
cubeb/cubeb.h
#endif

View File

@ -182,10 +182,6 @@ SHARED_LIBRARY_LIBS += \
$(NULL)
endif
ifdef MOZ_SYDNEYAUDIO
LOCAL_INCLUDES += -I$(DEPTH)/content/html/content/src
endif
ifdef NS_PRINTING
SHARED_LIBRARY_LIBS += \
../printing/$(LIB_PREFIX)gkprinting_s.$(LIB_SUFFIX) \

View File

@ -86,6 +86,12 @@ SHARED_LIBRARY_LIBS += \
$(NULL)
endif
ifdef MOZ_CUBEB
SHARED_LIBRARY_LIBS += \
$(DEPTH)/media/libcubeb/src/$(LIB_PREFIX)cubeb.$(LIB_SUFFIX) \
$(NULL)
endif
SHARED_LIBRARY_LIBS += \
$(DEPTH)/gfx/angle/$(LIB_PREFIX)angle.$(LIB_SUFFIX) \
$(NULL)
@ -100,6 +106,10 @@ else
EXTRA_DSO_LDOPTS += $(MOZ_ZLIB_LIBS)
endif
ifdef MOZ_CUBEB
EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, winmm ksguid)
endif
DEFFILE = symbols.def
endif

View File

@ -73,6 +73,15 @@ sa_stream_pause
sa_stream_resume
sa_stream_write
#endif
#ifdef MOZ_CUBEB
cubeb_destroy
cubeb_init
cubeb_stream_destroy
cubeb_stream_get_position
cubeb_stream_init
cubeb_stream_start
cubeb_stream_stop
#endif
#ifdef MOZ_OGG
th_comment_clear
th_comment_init

1
media/libcubeb/AUTHORS Normal file
View File

@ -0,0 +1 @@
Matthew Gregan <kinetik@flim.org>

13
media/libcubeb/LICENSE Normal file
View File

@ -0,0 +1,13 @@
Copyright © 2011 Mozilla Foundation
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -0,0 +1,52 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Matthew Gregan <kinetik@flim.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = cubeb
DIRS = \
include \
src \
$(NULL)
include $(topsrcdir)/config/rules.mk

3
media/libcubeb/README Normal file
View File

@ -0,0 +1,3 @@
See INSTALL for build instructions.
Licensed under an ISC-style license. See LICENSE for details.

View File

@ -0,0 +1,8 @@
The source from this directory was copied from the cubeb
git repository using the update.sh script. The only changes
made were those applied by update.sh and the addition of
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 ddfaaf39c1a15cfb1a04ce62d6bd253737fc764a-dirty.

View File

@ -0,0 +1,48 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Matthew Gregan <kinetik@flim.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
EXPORTS_NAMESPACES = cubeb
EXPORTS_cubeb = cubeb.h cubeb-stdint.h
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1 @@
#include "mozilla/StdInt.h"

View File

@ -0,0 +1,208 @@
/*
* Copyright © 2011 Mozilla Foundation
*
* 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
#include <cubeb/cubeb-stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @mainpage
@section intro Introduction
This is the documentation for the <tt>libcubeb</tt> C API.
<tt>libcubeb</tt> is a callback-based audio API library allowing the
authoring of portable multiplatform audio playback.
@section example Example code
@code
cubeb * app_ctx;
cubeb_init(&app_ctx, "Example Application");
cubeb_stream_params params;
params.format = CUBEB_SAMPLE_S16NE;
params.rate = 48000;
params.channels = 2;
unsigned int latency_ms = 250;
cubeb_stream * stm;
cubeb_stream_init(app_ctx, &stm, "Example Stream 1", params,
latency_ms, data_cb, state_cb, NULL);
cubeb_stream_start(stm);
for (;;) {
cubeb_get_time(stm, &ts);
printf("time=%lu\n", ts);
sleep(1);
}
cubeb_stream_stop(stm);
cubeb_stream_destroy(stm);
cubeb_destroy(app_ctx);
@endcode
@code
long data_cb(cubeb_stream * stm, void * user, void * buffer, long nframes)
{
short * buf = buffer;
for (i = 0; i < nframes; ++i) {
for (c = 0; c < params.channels; ++c) {
buf[i][c] = 0;
}
}
return nframes;
}
@endcode
@code
int state_cb(cubeb_stream * stm, void * user, cubeb_state state)
{
printf("state=%d\n", state);
return CUBEB_OK;
}
@endcode
*/
/** @file
The <tt>libcubeb</tt> C API. */
typedef struct cubeb cubeb; /**< Opaque handle referencing the application state. */
typedef struct cubeb_stream cubeb_stream; /**< Opaque handle referencing the stream state. */
/** Sample format enumeration. */
typedef enum {
/**< Little endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16LE,
/**< Big endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16BE,
/**< Little endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32LE,
/**< Big endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32BE,
#ifdef WORDS_BIGENDIAN
/**< Native endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16NE = CUBEB_SAMPLE_S16BE,
/**< Native endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32NE = CUBEB_SAMPLE_FLOAT32BE
#else
/**< Native endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16NE = CUBEB_SAMPLE_S16LE,
/**< Native endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32NE = CUBEB_SAMPLE_FLOAT32LE
#endif
} cubeb_sample_format;
/** Stream format initialization parameters. */
typedef struct {
cubeb_sample_format format; /**< Requested sample format. One of
#cubeb_sample_format. */
unsigned int rate; /**< Requested sample rate. Valid range is [1, 192000]. */
unsigned int channels; /**< Requested channel count. Valid range is [1, 32]. */
} cubeb_stream_params;
/** Stream states signaled via state_callback. */
typedef enum {
CUBEB_STATE_STARTED, /**< Stream started. */
CUBEB_STATE_STOPPED, /**< Stream stopped. */
CUBEB_STATE_DRAINED /**< Stream drained. */
} cubeb_state;
/** Result code enumeration. */
enum {
CUBEB_OK = 0, /**< Success. */
CUBEB_ERROR = -1, /**< Unclassified error. */
CUBEB_ERROR_INVALID_FORMAT /**< Unsupported #cubeb_stream_params requested. */
};
/** User supplied data callback.
@param stream
@param user_ptr
@param buffer
@param nframes
@retval Number of frames written to buffer, which must equal nframes except at end of stream.
@retval CUBEB_ERROR on error, in which case the data callback will stop
and the stream will enter a shutdown state. */
typedef long (* cubeb_data_callback)(cubeb_stream * stream,
void * user_ptr,
void * buffer,
long nframes);
/** User supplied state callback.
@param stream
@param user_ptr
@param state
@retval CUBEB_OK
@retval CUBEB_ERROR */
typedef int (* cubeb_state_callback)(cubeb_stream * stream,
void * user_ptr,
cubeb_state state);
/** Initialize an application context. This will perform any library or
application scoped initialization.
@param context
@param context_name
@retval CUBEB_OK
@retval CUBEB_ERROR */
int cubeb_init(cubeb ** context, char const * context_name);
/** Destroy an application context.
@param context */
void cubeb_destroy(cubeb * context);
/** Initialize a stream associated with the supplied application context.
@param context
@param stream
@param stream_name
@param stream_params
@param latency Approximate stream latency in milliseconds. Valid range is [1, 2000].
@param data_callback Will be called to preroll data before playback is
started by cubeb_stream_start.
@param state_callback
@param user_ptr
@retval CUBEB_OK
@retval CUBEB_ERROR
@retval CUBEB_ERROR_INVALID_FORMAT */
int cubeb_stream_init(cubeb * context, 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);
/** Destroy a stream.
@param stream */
void cubeb_stream_destroy(cubeb_stream * stream);
/** Start playback.
@param stream
@retval CUBEB_OK
@retval CUBEB_ERROR */
int cubeb_stream_start(cubeb_stream * stream);
/** Stop playback.
@param stream
@retval CUBEB_OK
@retval CUBEB_ERROR */
int cubeb_stream_stop(cubeb_stream * stream);
/** Get the current stream playback position.
@param stream
@param position Playback position in frames.
@retval CUBEB_OK
@retval CUBEB_ERROR */
int cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position);
#ifdef __cplusplus
}
#endif
#endif /* CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382 */

View File

@ -0,0 +1,58 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Matthew Gregan <kinetik@flim.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = cubeb
LIBRARY_NAME = cubeb
FORCE_STATIC_LIB= 1
ifeq (WINNT,$(OS_TARGET))
VISIBILITY_FLAGS =
endif
ifeq (WINNT,$(OS_TARGET))
CSRCS = \
cubeb_winmm.c \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,433 @@
/*
* Copyright <EFBFBD>Â<EFBFBD>© 2011 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#undef NDEBUG
#include <assert.h>
#include <windows.h>
#include <mmreg.h>
#include <mmsystem.h>
#include <process.h>
#include <stdlib.h>
#include "cubeb/cubeb.h"
#include <stdio.h>
#define NBUFS 4
struct cubeb_stream_item {
SLIST_ENTRY head;
cubeb_stream * stream;
};
struct cubeb {
HANDLE event;
HANDLE thread;
int shutdown;
PSLIST_HEADER work;
};
struct cubeb_stream {
cubeb * context;
cubeb_stream_params params;
cubeb_data_callback data_callback;
cubeb_state_callback state_callback;
void * user_ptr;
WAVEHDR buffers[NBUFS];
int next_buffer;
int free_buffers;
int shutdown;
int draining;
HANDLE event;
HWAVEOUT waveout;
CRITICAL_SECTION lock;
};
static size_t
bytes_per_frame(cubeb_stream_params params)
{
size_t bytes;
switch (params.format) {
case CUBEB_SAMPLE_S16LE:
bytes = sizeof(signed int);
break;
case CUBEB_SAMPLE_FLOAT32LE:
bytes = sizeof(float);
break;
default:
assert(0);
}
return bytes * params.channels;
}
static WAVEHDR *
cubeb_get_next_buffer(cubeb_stream * stm)
{
WAVEHDR * hdr = NULL;
assert(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
hdr = &stm->buffers[stm->next_buffer];
assert(hdr->dwFlags == 0 ||
(hdr->dwFlags & WHDR_DONE && !(hdr->dwFlags & WHDR_INQUEUE)));
stm->next_buffer = (stm->next_buffer + 1) % NBUFS;
stm->free_buffers -= 1;
return hdr;
}
static void
cubeb_submit_buffer(cubeb_stream * stm, WAVEHDR * hdr)
{
long got;
MMRESULT r;
got = stm->data_callback(stm, stm->user_ptr, hdr->lpData,
hdr->dwBufferLength / bytes_per_frame(stm->params));
if (got < 0) {
/* XXX handle this case */
assert(0);
return;
} else if ((DWORD) got < hdr->dwBufferLength / bytes_per_frame(stm->params)) {
r = waveOutUnprepareHeader(stm->waveout, hdr, sizeof(*hdr));
assert(r == MMSYSERR_NOERROR);
hdr->dwBufferLength = got * bytes_per_frame(stm->params);
r = waveOutPrepareHeader(stm->waveout, hdr, sizeof(*hdr));
assert(r == MMSYSERR_NOERROR);
stm->draining = 1;
}
assert(hdr->dwFlags & WHDR_PREPARED);
r = waveOutWrite(stm->waveout, hdr, sizeof(*hdr));
assert(r == MMSYSERR_NOERROR);
}
static unsigned __stdcall
cubeb_buffer_thread(void * user_ptr)
{
cubeb * ctx = (cubeb *) user_ptr;
assert(ctx);
for (;;) {
DWORD rv;
struct cubeb_stream_item * item;
rv = WaitForSingleObject(ctx->event, INFINITE);
assert(rv == WAIT_OBJECT_0);
item = (struct cubeb_stream_item *) InterlockedPopEntrySList(ctx->work);
while (item) {
cubeb_stream * stm = item->stream;
EnterCriticalSection(&stm->lock);
stm->free_buffers += 1;
assert(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
if (stm->draining || stm->shutdown) {
if (stm->free_buffers == NBUFS) {
if (stm->draining) {
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
}
SetEvent(stm->event);
}
} else {
cubeb_submit_buffer(stm, cubeb_get_next_buffer(stm));
}
LeaveCriticalSection(&stm->lock);
_aligned_free(item);
item = (struct cubeb_stream_item *) InterlockedPopEntrySList(ctx->work);
}
if (ctx->shutdown) {
break;
}
}
return 0;
}
static void CALLBACK
cubeb_buffer_callback(HWAVEOUT waveout, UINT msg, DWORD_PTR user_ptr, DWORD_PTR p1, DWORD_PTR p2)
{
cubeb_stream * stm = (cubeb_stream *) user_ptr;
struct cubeb_stream_item * item;
if (msg != WOM_DONE) {
return;
}
item = _aligned_malloc(sizeof(struct cubeb_stream_item), MEMORY_ALLOCATION_ALIGNMENT);
assert(item);
item->stream = stm;
InterlockedPushEntrySList(stm->context->work, &item->head);
SetEvent(stm->context->event);
}
int
cubeb_init(cubeb ** context, char const * context_name)
{
cubeb * ctx;
ctx = calloc(1, sizeof(*ctx));
assert(ctx);
ctx->work = _aligned_malloc(sizeof(*ctx->work), MEMORY_ALLOCATION_ALIGNMENT);
assert(ctx->work);
InitializeSListHead(ctx->work);
ctx->event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!ctx->event) {
cubeb_destroy(ctx);
return CUBEB_ERROR;
}
ctx->thread = (HANDLE) _beginthreadex(NULL, 64 * 1024, cubeb_buffer_thread, ctx, 0, NULL);
if (!ctx->thread) {
cubeb_destroy(ctx);
return CUBEB_ERROR;
}
*context = ctx;
return CUBEB_OK;
}
void
cubeb_destroy(cubeb * ctx)
{
DWORD rv;
assert(!InterlockedPopEntrySList(ctx->work));
if (ctx->thread) {
ctx->shutdown = 1;
SetEvent(ctx->event);
rv = WaitForSingleObject(ctx->thread, INFINITE);
assert(rv == WAIT_OBJECT_0);
CloseHandle(ctx->thread);
}
if (ctx->event) {
CloseHandle(ctx->event);
}
_aligned_free(ctx->work);
free(ctx);
}
int
cubeb_stream_init(cubeb * context, 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)
{
MMRESULT r;
WAVEFORMATEXTENSIBLE wfx;
cubeb_stream * stm;
int i;
size_t bufsz;
if (stream_params.rate < 1 || stream_params.rate > 192000 ||
stream_params.channels < 1 || stream_params.channels > 32 ||
latency < 1 || latency > 2000) {
return CUBEB_ERROR_INVALID_FORMAT;
}
memset(&wfx, 0, sizeof(wfx));
if (stream_params.channels > 2) {
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfx.Format.cbSize = sizeof(wfx) - sizeof(wfx.Format);
} else {
wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
if (stream_params.format == CUBEB_SAMPLE_FLOAT32LE) {
wfx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
}
wfx.Format.cbSize = 0;
}
wfx.Format.nChannels = stream_params.channels;
wfx.Format.nSamplesPerSec = stream_params.rate;
/* XXX fix channel mappings */
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
switch (stream_params.format) {
case CUBEB_SAMPLE_S16LE:
wfx.Format.wBitsPerSample = 16;
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
break;
case CUBEB_SAMPLE_FLOAT32LE:
wfx.Format.wBitsPerSample = 32;
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
break;
default:
return CUBEB_ERROR_INVALID_FORMAT;
}
wfx.Format.nBlockAlign = (wfx.Format.wBitsPerSample * wfx.Format.nChannels) / 8;
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
wfx.Samples.wValidBitsPerSample = 0;
wfx.Samples.wSamplesPerBlock = 0;
wfx.Samples.wReserved = 0;
stm = calloc(1, sizeof(*stm));
assert(stm);
stm->context = context;
stm->params = stream_params;
stm->data_callback = data_callback;
stm->state_callback = state_callback;
stm->user_ptr = user_ptr;
bufsz = (size_t) (stm->params.rate / 1000.0 * latency * bytes_per_frame(stm->params) / NBUFS);
if (bufsz % bytes_per_frame(stm->params) != 0) {
bufsz += bytes_per_frame(stm->params) - (bufsz % bytes_per_frame(stm->params));
}
assert(bufsz % bytes_per_frame(stm->params) == 0);
for (i = 0; i < NBUFS; ++i) {
stm->buffers[i].lpData = calloc(1, bufsz);
assert(stm->buffers[i].lpData);
stm->buffers[i].dwBufferLength = bufsz;
stm->buffers[i].dwFlags = 0;
}
InitializeCriticalSection(&stm->lock);
stm->event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!stm->event) {
cubeb_stream_destroy(stm);
return CUBEB_ERROR;
}
stm->free_buffers = NBUFS;
/* cubeb_buffer_callback will be called during waveOutOpen, so all
other initialization must be complete before calling it. */
r = waveOutOpen(&stm->waveout, WAVE_MAPPER, &wfx.Format,
(DWORD_PTR) cubeb_buffer_callback, (DWORD_PTR) stm,
CALLBACK_FUNCTION);
if (r != MMSYSERR_NOERROR) {
cubeb_stream_destroy(stm);
return CUBEB_ERROR;
}
assert(r == MMSYSERR_NOERROR);
r = waveOutPause(stm->waveout);
assert(r == MMSYSERR_NOERROR);
for (i = 0; i < NBUFS; ++i) {
WAVEHDR * hdr = cubeb_get_next_buffer(stm);
r = waveOutPrepareHeader(stm->waveout, hdr, sizeof(*hdr));
assert(r == MMSYSERR_NOERROR);
cubeb_submit_buffer(stm, hdr);
}
*stream = stm;
return CUBEB_OK;
}
void
cubeb_stream_destroy(cubeb_stream * stm)
{
MMRESULT r;
DWORD rv;
int i;
int enqueued;
if (stm->waveout) {
EnterCriticalSection(&stm->lock);
stm->shutdown = 1;
r = waveOutReset(stm->waveout);
assert(r == MMSYSERR_NOERROR);
enqueued = NBUFS - stm->free_buffers;
LeaveCriticalSection(&stm->lock);
/* wait for all blocks to complete */
if (enqueued > 0) {
rv = WaitForSingleObject(stm->event, INFINITE);
assert(rv == WAIT_OBJECT_0);
}
for (i = 0; i < NBUFS; ++i) {
r = waveOutUnprepareHeader(stm->waveout, &stm->buffers[i], sizeof(stm->buffers[i]));
assert(r == MMSYSERR_NOERROR);
}
r = waveOutClose(stm->waveout);
assert(r == MMSYSERR_NOERROR);
}
if (stm->event) {
CloseHandle(stm->event);
}
DeleteCriticalSection(&stm->lock);
for (i = 0; i < NBUFS; ++i) {
free(stm->buffers[i].lpData);
}
free(stm);
}
int
cubeb_stream_start(cubeb_stream * stm)
{
MMRESULT r;
r = waveOutRestart(stm->waveout);
assert(r == MMSYSERR_NOERROR);
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
return CUBEB_OK;
}
int
cubeb_stream_stop(cubeb_stream * stm)
{
MMRESULT r;
r = waveOutPause(stm->waveout);
assert(r == MMSYSERR_NOERROR);
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
return CUBEB_OK;
}
int
cubeb_stream_get_position(cubeb_stream * stm, uint64_t * position)
{
MMRESULT r;
MMTIME time;
time.wType = TIME_SAMPLES;
r = waveOutGetPosition(stm->waveout, &time, sizeof(time));
assert(r == MMSYSERR_NOERROR);
assert(time.wType == TIME_SAMPLES);
*position = time.u.sample;
return CUBEB_OK;
}

27
media/libcubeb/update.sh Normal file
View File

@ -0,0 +1,27 @@
# Usage: sh update.sh <upstream_src_directory>
set -e
cp $1/include/cubeb/cubeb.h include
cp $1/src/cubeb_alsa.c src
cp $1/src/cubeb_winmm.c src
cp $1/src/cubeb_audiounit.c src
cp $1/LICENSE .
cp $1/README .
cp $1/AUTHORS .
if [ -d $1/.git ]; then
rev=$(cd $1 && git rev-parse --verify HEAD)
dirty=$(cd $1 && git diff-index --name-only HEAD)
fi
if [ -n "$rev" ]; then
version=$rev
if [ -n "$dirty" ]; then
version=$version-dirty
echo "WARNING: updating from a dirty git repository."
fi
sed -i.bak -e "/The git commit ID used was/ s/[0-9a-f]\+\(-dirty\)\?\./$version./" README_MOZILLA
rm README_MOZILLA.bak
else
echo "Remember to update README_MOZILLA with the version details."
fi

View File

@ -132,6 +132,7 @@
<li><a href="about:license#jpnic">Japan Network Information Center License</a></li>
<li><a href="about:license#jemalloc">jemalloc License</a></li>
<li><a href="about:license#jquery">jQuery License</a></li>
<li><a href="about:license#libcubeb">libcubeb License</a></li>
<li><a href="about:license#libevent">libevent License</a></li>
<li><a href="about:license#libffi">libffi License</a></li>
<li><a href="about:license#libnestegg">libnestegg License</a></li>
@ -2936,6 +2937,30 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<hr>
<h1><a name="libcubeb"></a>libcubeb License</h1>
<p class="correctme">This license applies to files in the directory
<span class="path">media/libcubeb</span>.
</p>
<pre>
Copyright &copy; 2011 Mozilla Foundation
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</pre>
<hr>
<h1><a name="libevent"></a>libevent License</h1>
<p>This license applies to files in the directory

View File

@ -1584,6 +1584,14 @@ if [ "$MOZ_WAVE" ]; then
"
fi
if [ "$MOZ_CUBEB" ]; then
add_makefiles "
media/libcubeb/Makefile
media/libcubeb/include/Makefile
media/libcubeb/src/Makefile
"
fi
if [ "$MOZ_SYDNEYAUDIO" ]; then
add_makefiles "
media/libsydneyaudio/Makefile

View File

@ -154,6 +154,12 @@ tier_platform_dirs += \
$(NULL)
endif
ifdef MOZ_CUBEB
tier_platform_dirs += \
media/libcubeb \
$(NULL)
endif
ifndef MOZ_NATIVE_PNG
tier_platform_dirs += media/libpng
endif