mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added xaudio2-WMA_support patchset
This commit is contained in:
parent
74b35082b3
commit
19db07f062
@ -419,6 +419,7 @@ patch_enable_all ()
|
||||
enable_wuauserv_Dummy_Service="$1"
|
||||
enable_wusa_MSU_Package_Installer="$1"
|
||||
enable_xaudio2_7_OnVoiceProcessingPassStart="$1"
|
||||
enable_xaudio2_7_WMA_support="$1"
|
||||
enable_xaudio2_CommitChanges="$1"
|
||||
}
|
||||
|
||||
@ -1434,6 +1435,9 @@ patch_enable ()
|
||||
xaudio2_7-OnVoiceProcessingPassStart)
|
||||
enable_xaudio2_7_OnVoiceProcessingPassStart="$2"
|
||||
;;
|
||||
xaudio2_7-WMA_support)
|
||||
enable_xaudio2_7_WMA_support="$2"
|
||||
;;
|
||||
xaudio2_CommitChanges)
|
||||
enable_xaudio2_CommitChanges="$2"
|
||||
;;
|
||||
@ -8412,6 +8416,24 @@ if test "$enable_xaudio2_7_OnVoiceProcessingPassStart" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset xaudio2_7-WMA_support
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#39402] Use ffmpeg 4.x to convert WMA format
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * configure.ac, dlls/xaudio2_0/Makefile.in, dlls/xaudio2_1/Makefile.in, dlls/xaudio2_2/Makefile.in,
|
||||
# | dlls/xaudio2_3/Makefile.in, dlls/xaudio2_4/Makefile.in, dlls/xaudio2_5/Makefile.in, dlls/xaudio2_6/Makefile.in,
|
||||
# | dlls/xaudio2_7/Makefile.in, dlls/xaudio2_7/xaudio_dll.c, dlls/xaudio2_7/xaudio_private.h, dlls/xaudio2_8/Makefile.in,
|
||||
# | dlls/xaudio2_9/Makefile.in, include/config.h.in, include/mmreg.h
|
||||
# |
|
||||
if test "$enable_xaudio2_7_WMA_support" -eq 1; then
|
||||
patch_apply xaudio2_7-WMA_support/0001-xaudio2-Use-ffmpeg-to-convert-WMA-formats.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Andrew Eikum", "xaudio2: Use ffmpeg to convert WMA formats.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset xaudio2_CommitChanges
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
@ -0,0 +1,721 @@
|
||||
From 86489505fd9cdf61f90ba31a045f1412833517cc Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Eikum <aeikum@codeweavers.com>
|
||||
Date: Thu, 31 May 2018 10:58:48 -0500
|
||||
Subject: [PATCH] xaudio2: Use ffmpeg to convert WMA formats
|
||||
|
||||
---
|
||||
configure.ac | 33 ++++
|
||||
dlls/xaudio2_0/Makefile.in | 2 +-
|
||||
dlls/xaudio2_1/Makefile.in | 2 +-
|
||||
dlls/xaudio2_2/Makefile.in | 2 +-
|
||||
dlls/xaudio2_3/Makefile.in | 2 +-
|
||||
dlls/xaudio2_4/Makefile.in | 2 +-
|
||||
dlls/xaudio2_5/Makefile.in | 2 +-
|
||||
dlls/xaudio2_6/Makefile.in | 2 +-
|
||||
dlls/xaudio2_7/Makefile.in | 2 +-
|
||||
dlls/xaudio2_7/xaudio_dll.c | 370 ++++++++++++++++++++++++++++++++++++++--
|
||||
dlls/xaudio2_7/xaudio_private.h | 9 +
|
||||
dlls/xaudio2_8/Makefile.in | 2 +-
|
||||
dlls/xaudio2_9/Makefile.in | 2 +-
|
||||
include/config.h.in | 9 +
|
||||
include/mmreg.h | 5 +
|
||||
15 files changed, 426 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index e8dc9f2..ca0ad72 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -43,6 +43,7 @@ AC_ARG_WITH(cups, AS_HELP_STRING([--without-cups],[do not use CUPS]))
|
||||
AC_ARG_WITH(curses, AS_HELP_STRING([--without-curses],[do not use (n)curses]),
|
||||
[if test "x$withval" = "xno"; then ac_cv_header_ncurses_h=no; ac_cv_header_curses_h=no; fi])
|
||||
AC_ARG_WITH(dbus, AS_HELP_STRING([--without-dbus],[do not use DBus (dynamic device support)]))
|
||||
+AC_ARG_WITH(ffmpeg, AS_HELP_STRING([--without-ffmpeg],[do not use the FFmpeg library]))
|
||||
AC_ARG_WITH(float-abi, AS_HELP_STRING([--with-float-abi=abi],[specify the ABI (soft|softfp|hard) for ARM platforms]))
|
||||
AC_ARG_WITH(fontconfig,AS_HELP_STRING([--without-fontconfig],[do not use fontconfig]))
|
||||
AC_ARG_WITH(freetype, AS_HELP_STRING([--without-freetype],[do not use the FreeType library]))
|
||||
@@ -1836,6 +1837,38 @@ WINE_NOTICE_WITH(mpg123,[test "x$ac_cv_lib_mpg123_mpg123_feed" != xyes -a x"$ac_
|
||||
[enable_l3codeca_acm])
|
||||
test "x$ac_cv_lib_mpg123_mpg123_feed" = xyes || enable_mp3dmod=${enable_mp3dmod:-no}
|
||||
|
||||
+dnl **** Check for FFmpeg's libavutil ****
|
||||
+if test "x$with_ffmpeg" != "xno"
|
||||
+then
|
||||
+ WINE_PACKAGE_FLAGS(LIBAVUTIL,[libavutil],[-llibavutil],,,
|
||||
+ [AC_CHECK_HEADERS([libavutil/avutil.h])
|
||||
+ if test "$ac_cv_header_libavutil_avutil_h" = "yes"
|
||||
+ then
|
||||
+ AC_CHECK_LIB(avutil,av_frame_alloc,[:],[LIBAVUTIL_LIBS=""],[$LIBAVUTIL_LIBS])
|
||||
+ else
|
||||
+ LIBAVUTIL_CFLAGS=""
|
||||
+ LIBAVUTIL_LIBS=""
|
||||
+ fi])
|
||||
+fi
|
||||
+
|
||||
+dnl **** Check for FFmpeg's libavcodec ****
|
||||
+if test "x$with_ffmpeg" != "xno" -a "x$ac_cv_lib_avutil_av_frame_alloc" = "xyes"
|
||||
+then
|
||||
+ WINE_PACKAGE_FLAGS(LIBAVCODEC,[libavcodec],[-llibavcodec],,,
|
||||
+ [AC_CHECK_HEADERS([libavcodec/avcodec.h])
|
||||
+ if test "$ac_cv_header_libavcodec_avcodec_h" = "yes"
|
||||
+ then
|
||||
+ AC_CHECK_LIB(avcodec,avcodec_send_packet,
|
||||
+ [AC_DEFINE(HAVE_FFMPEG, 1, [Define to 1 if you have libavutil and libavcodec from ffmpeg.])],
|
||||
+ [LIBAVCODEC_LIBS=""], [$LIBAVUTIL_LIBS $LIBAVCODEC_LIBS])
|
||||
+ else
|
||||
+ LIBAVCODEC_CFLAGS=""
|
||||
+ LIBAVCODEC_LIBS=""
|
||||
+ fi])
|
||||
+fi
|
||||
+WINE_NOTICE_WITH(libavcodec,[test "x$ac_cv_lib_avcodec_avcodec_send_packet" != xyes],
|
||||
+ [libavcodec ${notice_platform}development files not found (or too old), XAudio2 WMA conversion won't be supported.])
|
||||
+
|
||||
dnl **** Check for OpenAL 1.1 ****
|
||||
if test "$ac_cv_header_AL_al_h" = "yes"
|
||||
then
|
||||
diff --git a/dlls/xaudio2_0/Makefile.in b/dlls/xaudio2_0/Makefile.in
|
||||
index cf15c7b..d1127e5 100644
|
||||
--- a/dlls/xaudio2_0/Makefile.in
|
||||
+++ b/dlls/xaudio2_0/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=0
|
||||
MODULE = xaudio2_0.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_1/Makefile.in b/dlls/xaudio2_1/Makefile.in
|
||||
index 32a5a62..53d9c10 100644
|
||||
--- a/dlls/xaudio2_1/Makefile.in
|
||||
+++ b/dlls/xaudio2_1/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=1
|
||||
MODULE = xaudio2_1.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_2/Makefile.in b/dlls/xaudio2_2/Makefile.in
|
||||
index f20de2d..d1b4384 100644
|
||||
--- a/dlls/xaudio2_2/Makefile.in
|
||||
+++ b/dlls/xaudio2_2/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=2
|
||||
MODULE = xaudio2_2.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_3/Makefile.in b/dlls/xaudio2_3/Makefile.in
|
||||
index ca749f2..c431146 100644
|
||||
--- a/dlls/xaudio2_3/Makefile.in
|
||||
+++ b/dlls/xaudio2_3/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=3
|
||||
MODULE = xaudio2_3.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_4/Makefile.in b/dlls/xaudio2_4/Makefile.in
|
||||
index 0b74f68..69ffc69 100644
|
||||
--- a/dlls/xaudio2_4/Makefile.in
|
||||
+++ b/dlls/xaudio2_4/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=4
|
||||
MODULE = xaudio2_4.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_5/Makefile.in b/dlls/xaudio2_5/Makefile.in
|
||||
index 09356c9..011cc7a 100644
|
||||
--- a/dlls/xaudio2_5/Makefile.in
|
||||
+++ b/dlls/xaudio2_5/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=5
|
||||
MODULE = xaudio2_5.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_6/Makefile.in b/dlls/xaudio2_6/Makefile.in
|
||||
index e0ef588..455c6d7 100644
|
||||
--- a/dlls/xaudio2_6/Makefile.in
|
||||
+++ b/dlls/xaudio2_6/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=6
|
||||
MODULE = xaudio2_6.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_7/Makefile.in b/dlls/xaudio2_7/Makefile.in
|
||||
index 2f2e232..3e6d595 100644
|
||||
--- a/dlls/xaudio2_7/Makefile.in
|
||||
+++ b/dlls/xaudio2_7/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=7
|
||||
MODULE = xaudio2_7.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
|
||||
C_SRCS = \
|
||||
compat.c \
|
||||
diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c
|
||||
index e52d962..319c239 100644
|
||||
--- a/dlls/xaudio2_7/xaudio_dll.c
|
||||
+++ b/dlls/xaudio2_7/xaudio_dll.c
|
||||
@@ -82,6 +82,11 @@ __ASM_GLOBAL_FUNC( call_on_voice_processing_pass_start,
|
||||
"ret" )
|
||||
#endif
|
||||
|
||||
+#define IS_WMA(tag) (tag == WAVE_FORMAT_MSAUDIO1 || \
|
||||
+ tag == WAVE_FORMAT_WMAUDIO2 || \
|
||||
+ tag == WAVE_FORMAT_WMAUDIO3 || \
|
||||
+ tag == WAVE_FORMAT_WMAUDIO_LOSSLESS)
|
||||
+
|
||||
static void dump_fmt(const WAVEFORMATEX *fmt)
|
||||
{
|
||||
TRACE("wFormatTag: 0x%x (", fmt->wFormatTag);
|
||||
@@ -90,6 +95,11 @@ static void dump_fmt(const WAVEFORMATEX *fmt)
|
||||
DOCASE(WAVE_FORMAT_PCM)
|
||||
DOCASE(WAVE_FORMAT_IEEE_FLOAT)
|
||||
DOCASE(WAVE_FORMAT_EXTENSIBLE)
|
||||
+ DOCASE(WAVE_FORMAT_ADPCM)
|
||||
+ DOCASE(WAVE_FORMAT_MSAUDIO1)
|
||||
+ DOCASE(WAVE_FORMAT_WMAUDIO2)
|
||||
+ DOCASE(WAVE_FORMAT_WMAUDIO3)
|
||||
+ DOCASE(WAVE_FORMAT_WMAUDIO_LOSSLESS)
|
||||
#undef DOCASE
|
||||
default:
|
||||
TRACE("Unknown");
|
||||
@@ -462,6 +472,10 @@ static void WINAPI XA2SRC_DestroyVoice(IXAudio2SourceVoice *iface)
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This->fmt);
|
||||
+ HeapFree(GetProcessHeap(), 0, This->scratch_buf);
|
||||
+ This->scratch_buf = NULL;
|
||||
+ HeapFree(GetProcessHeap(), 0, This->convert_buf);
|
||||
+ This->convert_buf = NULL;
|
||||
|
||||
alDeleteBuffers(XAUDIO2_MAX_QUEUED_BUFFERS, This->al_bufs);
|
||||
alDeleteSources(1, &This->al_src);
|
||||
@@ -474,6 +488,17 @@ static void WINAPI XA2SRC_DestroyVoice(IXAudio2SourceVoice *iface)
|
||||
This->cur_buf = 0;
|
||||
This->abandoned_albufs = 0;
|
||||
|
||||
+#if HAVE_FFMPEG
|
||||
+ if(This->conv_ctx){
|
||||
+ HeapFree(GetProcessHeap(), 0, This->conv_ctx->extradata);
|
||||
+ av_frame_free(&This->conv_frame);
|
||||
+ This->conv_frame = NULL;
|
||||
+ avcodec_close(This->conv_ctx);
|
||||
+ av_free(This->conv_ctx);
|
||||
+ This->conv_ctx = NULL;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
LeaveCriticalSection(&This->lock);
|
||||
}
|
||||
|
||||
@@ -579,6 +604,97 @@ static ALenum get_al_format(const WAVEFORMATEX *fmt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#if HAVE_FFMPEG
|
||||
+static enum AVCodecID get_ffmpeg_format(const WAVEFORMATEX *pSourceFormat)
|
||||
+{
|
||||
+ switch(pSourceFormat->wFormatTag){
|
||||
+ case WAVE_FORMAT_MSAUDIO1:
|
||||
+ return AV_CODEC_ID_WMAV1;
|
||||
+ case WAVE_FORMAT_WMAUDIO2:
|
||||
+ return AV_CODEC_ID_WMAV2;
|
||||
+ case WAVE_FORMAT_WMAUDIO3:
|
||||
+ return AV_CODEC_ID_WMAPRO;
|
||||
+ case WAVE_FORMAT_WMAUDIO_LOSSLESS:
|
||||
+ return AV_CODEC_ID_WMALOSSLESS;
|
||||
+ case WAVE_FORMAT_ADPCM:
|
||||
+ return AV_CODEC_ID_ADPCM_MS;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static ALenum ffmpeg_to_al_fmt(enum AVSampleFormat fmt, int channels)
|
||||
+{
|
||||
+ switch(fmt){
|
||||
+ case AV_SAMPLE_FMT_U8:
|
||||
+ case AV_SAMPLE_FMT_U8P:
|
||||
+ switch(channels){
|
||||
+ case 1:
|
||||
+ return AL_FORMAT_MONO8;
|
||||
+ case 2:
|
||||
+ return AL_FORMAT_STEREO8;
|
||||
+ case 4:
|
||||
+ return AL_FORMAT_QUAD8;
|
||||
+ case 6:
|
||||
+ return AL_FORMAT_51CHN8;
|
||||
+ case 7:
|
||||
+ return AL_FORMAT_61CHN8;
|
||||
+ case 8:
|
||||
+ return AL_FORMAT_71CHN8;
|
||||
+ }
|
||||
+ break;
|
||||
+ case AV_SAMPLE_FMT_S16:
|
||||
+ case AV_SAMPLE_FMT_S16P:
|
||||
+ switch(channels){
|
||||
+ case 1:
|
||||
+ return AL_FORMAT_MONO16;
|
||||
+ case 2:
|
||||
+ return AL_FORMAT_STEREO16;
|
||||
+ case 4:
|
||||
+ return AL_FORMAT_QUAD16;
|
||||
+ case 6:
|
||||
+ return AL_FORMAT_51CHN16;
|
||||
+ case 7:
|
||||
+ return AL_FORMAT_61CHN16;
|
||||
+ case 8:
|
||||
+ return AL_FORMAT_71CHN16;
|
||||
+ }
|
||||
+ break;
|
||||
+ case AV_SAMPLE_FMT_S32:
|
||||
+ case AV_SAMPLE_FMT_S32P:
|
||||
+ switch(channels){
|
||||
+ /* TODO: mono/stereo? */
|
||||
+ case 4:
|
||||
+ return AL_FORMAT_QUAD32;
|
||||
+ case 6:
|
||||
+ return AL_FORMAT_51CHN32;
|
||||
+ case 7:
|
||||
+ return AL_FORMAT_61CHN32;
|
||||
+ case 8:
|
||||
+ return AL_FORMAT_71CHN32;
|
||||
+ }
|
||||
+ case AV_SAMPLE_FMT_FLT:
|
||||
+ case AV_SAMPLE_FMT_FLTP:
|
||||
+ switch(channels){
|
||||
+ case 1:
|
||||
+ return AL_FORMAT_MONO_FLOAT32;
|
||||
+ case 2:
|
||||
+ return AL_FORMAT_STEREO_FLOAT32;
|
||||
+ }
|
||||
+ case AV_SAMPLE_FMT_DBL:
|
||||
+ case AV_SAMPLE_FMT_DBLP:
|
||||
+ switch(channels){
|
||||
+ case 1:
|
||||
+ return AL_FORMAT_MONO_DOUBLE_EXT;
|
||||
+ case 2:
|
||||
+ return AL_FORMAT_STEREO_DOUBLE_EXT;
|
||||
+ }
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
|
||||
const XAUDIO2_BUFFER *pBuffer, const XAUDIO2_BUFFER_WMA *pBufferWMA)
|
||||
{
|
||||
@@ -622,7 +738,10 @@ static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
|
||||
#endif
|
||||
|
||||
/* convert samples offsets to bytes */
|
||||
- if(This->fmt->wFormatTag == WAVE_FORMAT_ADPCM){
|
||||
+ if(IS_WMA(This->fmt->wFormatTag)){
|
||||
+ /* Offsets for WMA appear to just be byte offsets, since it doesn't
|
||||
+ * have the concept of "samples". */
|
||||
+ }else if(This->fmt->wFormatTag == WAVE_FORMAT_ADPCM){
|
||||
/* ADPCM gives us a number of samples per block, so round down to
|
||||
* nearest block and convert to bytes */
|
||||
buf->xa2buffer.PlayBegin = buf->xa2buffer.PlayBegin / ((ADPCMWAVEFORMAT*)This->fmt)->wSamplesPerBlock * This->fmt->nBlockAlign;
|
||||
@@ -1513,19 +1632,119 @@ static HRESULT WINAPI IXAudio2Impl_CreateSourceVoice(IXAudio2 *iface,
|
||||
|
||||
src->al_fmt = get_al_format(pSourceFormat);
|
||||
if(!src->al_fmt){
|
||||
- src->in_use = FALSE;
|
||||
- LeaveCriticalSection(&src->lock);
|
||||
- WARN("OpenAL can't convert this format!\n");
|
||||
- return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
- }
|
||||
+#if HAVE_FFMPEG
|
||||
+ enum AVCodecID cid;
|
||||
+ AVCodec *codec;
|
||||
+
|
||||
+ TRACE("OpenAL can't use this format, so using FFmpeg\n");
|
||||
+
|
||||
+ cid = get_ffmpeg_format(pSourceFormat);
|
||||
+ if(!cid){
|
||||
+ WARN("Don't know how to convert this format to an FFmpeg codec\n");
|
||||
+ src->in_use = FALSE;
|
||||
+ LeaveCriticalSection(&src->lock);
|
||||
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
+ }
|
||||
+
|
||||
+ codec = avcodec_find_decoder(cid);
|
||||
+ if(!codec){
|
||||
+ WARN("FFmpeg can't convert this format (0x%x), so failing\n", cid);
|
||||
+ src->in_use = FALSE;
|
||||
+ LeaveCriticalSection(&src->lock);
|
||||
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
+ }
|
||||
+
|
||||
+ src->conv_ctx = avcodec_alloc_context3(codec);
|
||||
+ if(!src->conv_ctx){
|
||||
+ WARN("avcodec_alloc_context3 failed\n");
|
||||
+ src->in_use = FALSE;
|
||||
+ LeaveCriticalSection(&src->lock);
|
||||
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
+ }
|
||||
+
|
||||
+ src->conv_ctx->bit_rate = pSourceFormat->nAvgBytesPerSec * 8;
|
||||
+ src->conv_ctx->channels = pSourceFormat->nChannels;
|
||||
+ src->conv_ctx->sample_rate = pSourceFormat->nSamplesPerSec;
|
||||
+ src->conv_ctx->block_align = pSourceFormat->nBlockAlign;
|
||||
+ src->conv_ctx->bits_per_coded_sample = pSourceFormat->wBitsPerSample;
|
||||
+ src->conv_ctx->extradata_size = pSourceFormat->cbSize;
|
||||
+ if(pSourceFormat->cbSize){
|
||||
+ src->conv_ctx->extradata = HeapAlloc(GetProcessHeap(), 0, pSourceFormat->cbSize + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
+ memcpy(src->conv_ctx->extradata, (&pSourceFormat->cbSize) + 1, pSourceFormat->cbSize);
|
||||
+ }else if(IS_WMA(pSourceFormat->wFormatTag)){
|
||||
+ /* xWMA doesn't provide the extradata info that FFmpeg needs to
|
||||
+ * decode WMA data, so we create some fake extradata. This is taken
|
||||
+ * from <ffmpeg/libavformat/xwma.c>. */
|
||||
+ TRACE("synthesizing extradata for xWMA\n");
|
||||
+ src->conv_ctx->extradata_size = 6;
|
||||
+ src->conv_ctx->extradata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
+ src->conv_ctx->extradata[4] = 31;
|
||||
+ }
|
||||
|
||||
- src->submit_blocksize = pSourceFormat->nBlockAlign;
|
||||
+ if(avcodec_open2(src->conv_ctx, codec, NULL) < 0){
|
||||
+ WARN("avcodec_open2 failed\n");
|
||||
+ HeapFree(GetProcessHeap(), 0, src->conv_ctx->extradata);
|
||||
+ av_free(src->conv_ctx);
|
||||
+ src->conv_ctx = NULL;
|
||||
+ src->in_use = FALSE;
|
||||
+ LeaveCriticalSection(&src->lock);
|
||||
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
+ }
|
||||
+
|
||||
+ src->conv_frame = av_frame_alloc();
|
||||
+ if(!src->conv_ctx){
|
||||
+ WARN("av_frame_alloc failed\n");
|
||||
+ avcodec_close(src->conv_ctx);
|
||||
+ HeapFree(GetProcessHeap(), 0, src->conv_ctx->extradata);
|
||||
+ av_free(src->conv_ctx);
|
||||
+ src->conv_ctx = NULL;
|
||||
+ src->in_use = FALSE;
|
||||
+ LeaveCriticalSection(&src->lock);
|
||||
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
+ }
|
||||
+
|
||||
+ src->al_fmt = ffmpeg_to_al_fmt(src->conv_ctx->sample_fmt, pSourceFormat->nChannels);
|
||||
+ if(!src->al_fmt){
|
||||
+ WARN("OpenAL can't use FFmpeg output format\n");
|
||||
+ av_frame_free(&src->conv_frame);
|
||||
+ src->conv_frame = NULL;
|
||||
+ avcodec_close(src->conv_ctx);
|
||||
+ HeapFree(GetProcessHeap(), 0, src->conv_ctx->extradata);
|
||||
+ av_free(src->conv_ctx);
|
||||
+ src->conv_ctx = NULL;
|
||||
+ src->in_use = FALSE;
|
||||
+ LeaveCriticalSection(&src->lock);
|
||||
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
+ }
|
||||
+
|
||||
+ src->submit_blocksize = av_get_bytes_per_sample(src->conv_ctx->sample_fmt);
|
||||
+
|
||||
+ src->scratch_bytes = This->period_frames * 1.5 * src->submit_blocksize;
|
||||
+ src->scratch_buf = HeapAlloc(GetProcessHeap(), 0, src->scratch_bytes);
|
||||
+
|
||||
+ src->convert_bytes = pSourceFormat->nBlockAlign + AV_INPUT_BUFFER_PADDING_SIZE;
|
||||
+ src->convert_buf = HeapAlloc(GetProcessHeap(), 0, src->convert_bytes);
|
||||
+#else
|
||||
+ WARN("OpenAL can't use this format and no FFmpeg, so giving up\n");
|
||||
+#endif
|
||||
+ }else
|
||||
+ src->submit_blocksize = pSourceFormat->nBlockAlign;
|
||||
|
||||
src->fmt = copy_waveformat(pSourceFormat);
|
||||
|
||||
hr = XA2SRC_SetOutputVoices(&src->IXAudio2SourceVoice_iface, pSendList);
|
||||
if(FAILED(hr)){
|
||||
HeapFree(GetProcessHeap(), 0, src->fmt);
|
||||
+#if HAVE_FFMPEG
|
||||
+ if(src->conv_ctx){
|
||||
+ av_frame_free(&src->conv_frame);
|
||||
+ src->conv_frame = NULL;
|
||||
+ avcodec_close(src->conv_ctx);
|
||||
+ HeapFree(GetProcessHeap(), 0, src->conv_ctx->extradata);
|
||||
+ av_free(src->conv_ctx);
|
||||
+ src->conv_ctx = NULL;
|
||||
+ }
|
||||
+#endif
|
||||
src->in_use = FALSE;
|
||||
LeaveCriticalSection(&src->lock);
|
||||
return hr;
|
||||
@@ -2255,6 +2474,9 @@ HRESULT WINAPI XAudio2Create(IXAudio2 **ppxa2, UINT32 flags, XAUDIO2_PROCESSOR p
|
||||
* buffer's data has all been queued */
|
||||
static BOOL xa2buffer_queue_period(XA2SourceImpl *src, XA2Buffer *buf, ALuint al_buf)
|
||||
{
|
||||
+#if HAVE_FFMPEG
|
||||
+ int averr;
|
||||
+#endif
|
||||
UINT32 submit_bytes;
|
||||
const BYTE *submit_buf = NULL;
|
||||
|
||||
@@ -2263,9 +2485,133 @@ static BOOL xa2buffer_queue_period(XA2SourceImpl *src, XA2Buffer *buf, ALuint al
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
- submit_bytes = min(src->xa2->period_frames * src->submit_blocksize, buf->cur_end_bytes - buf->offs_bytes);
|
||||
- submit_buf = buf->xa2buffer.pAudioData + buf->offs_bytes;
|
||||
- buf->offs_bytes += submit_bytes;
|
||||
+#if HAVE_FFMPEG
|
||||
+ if(src->conv_ctx){
|
||||
+ DWORD scratch_offs_bytes = 0;
|
||||
+ AVPacket avpkt = {0};
|
||||
+
|
||||
+ avpkt.size = src->fmt->nBlockAlign;
|
||||
+ avpkt.data = (unsigned char*)buf->xa2buffer.pAudioData + buf->offs_bytes;
|
||||
+
|
||||
+ /* convert at least a period into scratch_buf */
|
||||
+ while(scratch_offs_bytes < src->xa2->period_frames * src->submit_blocksize){
|
||||
+ DWORD to_copy_bytes;
|
||||
+
|
||||
+ averr = avcodec_receive_frame(src->conv_ctx, src->conv_frame);
|
||||
+ if(averr == AVERROR(EAGAIN)){
|
||||
+ /* ffmpeg needs more data to decode */
|
||||
+ avpkt.pts = avpkt.dts = AV_NOPTS_VALUE;
|
||||
+
|
||||
+ if(buf->offs_bytes >= buf->cur_end_bytes)
|
||||
+ /* no more data in this buffer */
|
||||
+ break;
|
||||
+
|
||||
+ if(buf->offs_bytes + avpkt.size + AV_INPUT_BUFFER_PADDING_SIZE > buf->cur_end_bytes){
|
||||
+ UINT32 remain = buf->cur_end_bytes - buf->offs_bytes;
|
||||
+ /* Unfortunately, the FFmpeg API requires that a number of
|
||||
+ * extra bytes must be available past the end of the buffer.
|
||||
+ * The xaudio2 client probably hasn't done this, so we have to
|
||||
+ * perform a copy near the end of the buffer. */
|
||||
+ TRACE("hitting end of buffer. copying %u + %u bytes into %u buffer\n",
|
||||
+ remain, AV_INPUT_BUFFER_PADDING_SIZE, src->convert_bytes);
|
||||
+ if(src->convert_bytes < remain + AV_INPUT_BUFFER_PADDING_SIZE){
|
||||
+ src->convert_bytes = remain + AV_INPUT_BUFFER_PADDING_SIZE;
|
||||
+ TRACE("buffer too small, expanding to %u\n", src->convert_bytes);
|
||||
+ src->convert_buf = HeapReAlloc(GetProcessHeap(), 0, src->convert_buf, src->convert_bytes);
|
||||
+ }
|
||||
+ memcpy(src->convert_buf, buf->xa2buffer.pAudioData + buf->offs_bytes, remain);
|
||||
+ memset(src->convert_buf + remain, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
+ avpkt.data = src->convert_buf;
|
||||
+ }
|
||||
+
|
||||
+ averr = avcodec_send_packet(src->conv_ctx, &avpkt);
|
||||
+ if(averr){
|
||||
+ WARN("avcodec_send_packet failed: %s\n", av_err2str(averr));
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ buf->offs_bytes += avpkt.size;
|
||||
+ avpkt.data += avpkt.size;
|
||||
+
|
||||
+ /* data sent, try receive again */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if(averr){
|
||||
+ WARN("avcodec_receive_frame failed: %s\n", av_err2str(averr));
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
+ to_copy_bytes = src->conv_frame->nb_samples * src->conv_ctx->channels * src->submit_blocksize;
|
||||
+
|
||||
+ while(scratch_offs_bytes + to_copy_bytes >= src->scratch_bytes){
|
||||
+ src->scratch_bytes *= 2;
|
||||
+ src->scratch_buf = HeapReAlloc(GetProcessHeap(), 0, src->scratch_buf, src->scratch_bytes);
|
||||
+ }
|
||||
+
|
||||
+ if(av_sample_fmt_is_planar(src->conv_ctx->sample_fmt)){
|
||||
+ int s, c;
|
||||
+ uint8_t **source, *dst;
|
||||
+ uint16_t *dst16;
|
||||
+ uint32_t *dst32;
|
||||
+ uint64_t *dst64;
|
||||
+
|
||||
+ /* one buffer per channel, but openal needs interleaved, so
|
||||
+ * interleave samples into scratch buf */
|
||||
+ dst = src->scratch_buf + scratch_offs_bytes;
|
||||
+ source = src->conv_frame->data;
|
||||
+
|
||||
+ switch(src->submit_blocksize){
|
||||
+ case 1:
|
||||
+ for(s = 0; s < src->conv_frame->nb_samples; ++s)
|
||||
+ for(c = 0; c < src->conv_ctx->channels; ++c)
|
||||
+ *(dst++) = source[c][s];
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ dst16 = (uint16_t*)dst;
|
||||
+ for(s = 0; s < src->conv_frame->nb_samples; ++s)
|
||||
+ for(c = 0; c < src->conv_ctx->channels; ++c)
|
||||
+ *(dst16++) = ((uint16_t*)(source[c]))[s];
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ dst32 = (uint32_t*)dst;
|
||||
+ for(s = 0; s < src->conv_frame->nb_samples; ++s)
|
||||
+ for(c = 0; c < src->conv_ctx->channels; ++c)
|
||||
+ *(dst32++) = ((uint32_t*)(source[c]))[s];
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ dst64 = (uint64_t*)dst;
|
||||
+ for(s = 0; s < src->conv_frame->nb_samples; ++s)
|
||||
+ for(c = 0; c < src->conv_ctx->channels; ++c)
|
||||
+ *(dst64++) = ((uint64_t*)(source[c]))[s];
|
||||
+ break;
|
||||
+ default:
|
||||
+ for(s = 0; s < src->conv_frame->nb_samples; ++s)
|
||||
+ for(c = 0; c < src->conv_ctx->channels; ++c){
|
||||
+ memcpy(dst, &source[c][src->submit_blocksize * s], src->submit_blocksize);
|
||||
+ dst += src->submit_blocksize;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ scratch_offs_bytes += to_copy_bytes;
|
||||
+ }else{
|
||||
+ /* copy into scratch buf */
|
||||
+ memcpy(src->scratch_buf + scratch_offs_bytes, src->conv_frame->data[0], to_copy_bytes);
|
||||
+ scratch_offs_bytes += to_copy_bytes;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ submit_bytes = scratch_offs_bytes;
|
||||
+ submit_buf = src->scratch_buf;
|
||||
+ }else{
|
||||
+#endif
|
||||
+ submit_bytes = min(src->xa2->period_frames * src->submit_blocksize, buf->cur_end_bytes - buf->offs_bytes);
|
||||
+ submit_buf = buf->xa2buffer.pAudioData + buf->offs_bytes;
|
||||
+ buf->offs_bytes += submit_bytes;
|
||||
+#if HAVE_FFMPEG
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
alBufferData(al_buf, src->al_fmt, submit_buf, submit_bytes,
|
||||
src->fmt->nSamplesPerSec);
|
||||
@@ -2288,6 +2634,10 @@ static UINT32 get_underrun_warning(XA2SourceImpl *src)
|
||||
UINT32 period_bytes = src->xa2->period_frames * src->submit_blocksize;
|
||||
UINT32 total = 0, i;
|
||||
|
||||
+ if(IS_WMA(src->fmt->wFormatTag))
|
||||
+ /* PCM only */
|
||||
+ return 0;
|
||||
+
|
||||
for(i = 0; i < src->nbufs && total < IN_AL_PERIODS * period_bytes; ++i){
|
||||
XA2Buffer *buf = &src->buffers[(src->first_buf + i) % XAUDIO2_MAX_QUEUED_BUFFERS];
|
||||
total += buf->cur_end_bytes - buf->offs_bytes;
|
||||
diff --git a/dlls/xaudio2_7/xaudio_private.h b/dlls/xaudio2_7/xaudio_private.h
|
||||
index 5d3814f..9cf7f00 100644
|
||||
--- a/dlls/xaudio2_7/xaudio_private.h
|
||||
+++ b/dlls/xaudio2_7/xaudio_private.h
|
||||
@@ -29,6 +29,10 @@
|
||||
#include "mmdeviceapi.h"
|
||||
#include "audioclient.h"
|
||||
|
||||
+#if HAVE_FFMPEG
|
||||
+#include <libavcodec/avcodec.h>
|
||||
+#endif
|
||||
+
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <AL/alext.h>
|
||||
@@ -83,6 +87,11 @@ typedef struct _XA2SourceImpl {
|
||||
ALuint al_bufs[XAUDIO2_MAX_QUEUED_BUFFERS];
|
||||
DWORD first_al_buf, al_bufs_used, abandoned_albufs;
|
||||
|
||||
+#if HAVE_FFMPEG
|
||||
+ AVCodecContext *conv_ctx;
|
||||
+ AVFrame *conv_frame;
|
||||
+#endif
|
||||
+
|
||||
struct list entry;
|
||||
} XA2SourceImpl;
|
||||
|
||||
diff --git a/dlls/xaudio2_8/Makefile.in b/dlls/xaudio2_8/Makefile.in
|
||||
index d4efc41..017bff8 100644
|
||||
--- a/dlls/xaudio2_8/Makefile.in
|
||||
+++ b/dlls/xaudio2_8/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=8
|
||||
MODULE = xaudio2_8.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/dlls/xaudio2_9/Makefile.in b/dlls/xaudio2_9/Makefile.in
|
||||
index ceb2216..cf68947 100644
|
||||
--- a/dlls/xaudio2_9/Makefile.in
|
||||
+++ b/dlls/xaudio2_9/Makefile.in
|
||||
@@ -1,7 +1,7 @@
|
||||
EXTRADEFS = -DXAUDIO2_VER=9
|
||||
MODULE = xaudio2_9.dll
|
||||
IMPORTS = advapi32 ole32 user32 uuid
|
||||
-EXTRALIBS = $(OPENAL_LIBS)
|
||||
+EXTRALIBS = $(OPENAL_LIBS) $(LIBAVCODEC_LIBS) $(LIBAVUTIL_LIBS)
|
||||
PARENTSRC = ../xaudio2_7
|
||||
|
||||
C_SRCS = \
|
||||
diff --git a/include/config.h.in b/include/config.h.in
|
||||
index c3247cb..7067a10 100644
|
||||
--- a/include/config.h.in
|
||||
+++ b/include/config.h.in
|
||||
@@ -408,6 +408,15 @@
|
||||
/* Define to 1 if you have the `lgammaf' function. */
|
||||
#undef HAVE_LGAMMAF
|
||||
|
||||
+/* Define to 1 if you have the <libavcodec/avcodec.h> header file. */
|
||||
+#undef HAVE_LIBAVCODEC_AVCODEC_H
|
||||
+
|
||||
+/* Define to 1 if you have the <libavutil/avutil.h> header file. */
|
||||
+#undef HAVE_LIBAVUTIL_AVUTIL_H
|
||||
+
|
||||
+/* Define to 1 if you have libavutil and libavcodec from ffmpeg. */
|
||||
+#undef HAVE_FFMPEG
|
||||
+
|
||||
/* Define to 1 if you have the `gettextpo' library (-lgettextpo). */
|
||||
#undef HAVE_LIBGETTEXTPO
|
||||
|
||||
diff --git a/include/mmreg.h b/include/mmreg.h
|
||||
index 8bb581d..1214dfa 100644
|
||||
--- a/include/mmreg.h
|
||||
+++ b/include/mmreg.h
|
||||
@@ -110,6 +110,11 @@ typedef struct _WAVEFORMATEX {
|
||||
#define WAVE_FORMAT_MPEG 0x0050 /* Microsoft Corporation */
|
||||
#define WAVE_FORMAT_MPEGLAYER3 0x0055
|
||||
#define WAVE_FORMAT_MSRT24 0x0082 /* Microsoft Corporation */
|
||||
+#define WAVE_FORMAT_MSAUDIO1 0x0160
|
||||
+#define WAVE_FORMAT_WMAUDIO2 0x0161
|
||||
+#define WAVE_FORMAT_WMAUDIO3 0x0162
|
||||
+#define WAVE_FORMAT_WMAUDIO_LOSSLESS 0x0163
|
||||
+
|
||||
#define WAVE_FORMAT_CREATIVE_ADPCM 0x0200 /* Creative Labs, Inc */
|
||||
#define WAVE_FORMAT_CREATIVE_FASTSPEECH8 0x0202 /* Creative Labs, Inc */
|
||||
#define WAVE_FORMAT_CREATIVE_FASTSPEECH10 0x0203 /* Creative Labs, Inc */
|
||||
--
|
||||
1.9.1
|
||||
|
1
patches/xaudio2_7-WMA_support/definition
Normal file
1
patches/xaudio2_7-WMA_support/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: [39402] Use ffmpeg 4.x to convert WMA format
|
Loading…
x
Reference in New Issue
Block a user