# HG changeset patch # User komh # Date 1265033393 0 # Node ID 2118e8876a2b0bf2210be13d3a3330dd7c953ec9 # Parent 82a05ac8860683ae2c4882e553f9ba21e413511a Add OS/2 KAI audio driver support diff -r 82a05ac88606 -r 2118e8876a2b Changelog --- a/Changelog Mon Feb 01 09:24:32 2010 +0000 +++ b/Changelog Mon Feb 01 14:09:53 2010 +0000 @@ -28,6 +28,7 @@ * Selectable YUV to RGB conversion standard for -vo gl (-vo gl:colorspace=...:levelconv=...) * -vo matrixview finally added + * add OS/2 KAI audio driver (-ao kai) Other: * -nosub option for disabling auto-selected subtitles diff -r 82a05ac88606 -r 2118e8876a2b DOCS/man/en/mplayer.1 --- a/DOCS/man/en/mplayer.1 Mon Feb 01 09:24:32 2010 +0000 +++ b/DOCS/man/en/mplayer.1 Mon Feb 01 14:09:53 2010 +0000 @@ -2858,6 +2858,22 @@ .PD 1 . .TP +.B kai (OS/2 only) +OS/2 KAI audio output driver +.PD 0 +.RSs +.IPs uniaud +Force UNIAUD mode +.IPs dart +Force DART mode +.IPs (no)share +Open audio in shareable or exclusive mode. +.IPs bufsize= +Set buffer size to in samples (default: 2048). +.RE +.PD 1 +. +.TP .B dart (OS/2 only) OS/2 DART audio output driver .PD 0 diff -r 82a05ac88606 -r 2118e8876a2b Makefile --- a/Makefile Mon Feb 01 09:24:32 2010 +0000 +++ b/Makefile Mon Feb 01 14:09:53 2010 +0000 @@ -590,6 +590,7 @@ SRCS_MPLAYER-$(JACK) += libao2/ao_jack.c SRCS_MPLAYER-$(JOYSTICK) += input/joystick.c SRCS_MPLAYER-$(JPEG) += libvo/vo_jpeg.c +SRCS_MPLAYER-$(KAI) += libao2/ao_kai.c SRCS_MPLAYER-$(KVA) += libvo/vo_kva.c SRCS_MPLAYER-$(LIBAVCODEC) += libvo/vo_png.c SRCS_MPLAYER-$(LIBMENU) += libmenu/menu.c \ diff -r 82a05ac88606 -r 2118e8876a2b configure --- a/configure Mon Feb 01 09:24:32 2010 +0000 +++ b/configure Mon Feb 01 14:09:53 2010 +0000 @@ -424,6 +424,7 @@ --disable-nas disable NAS audio output [autodetect] --disable-sgiaudio disable SGI audio output [autodetect] --disable-sunaudio disable Sun audio output [autodetect] + --disable-kai disable KAI audio output [autodetect] --disable-dart disable DART audio output [autodetect] --disable-win32waveout disable Windows waveout audio output [autodetect] --disable-coreaudio disable CoreAudio audio output [autodetect] @@ -617,6 +618,7 @@ _esd=auto _pulse=auto _jack=auto +_kai=auto _dart=auto _openal=auto _libcdio=auto @@ -1010,6 +1012,8 @@ --disable-jack) _jack=no ;; --enable-openal) _openal=yes ;; --disable-openal) _openal=no ;; + --enable-kai) _kai=yes ;; + --disable-kai) _kai=no ;; --enable-dart) _dart=yes ;; --disable-dart) _dart=no ;; --enable-mad) _mad=yes ;; @@ -6021,6 +6025,26 @@ if os2 ; then +echocheck "KAI (UNIAUD/DART)" +if test "$_kai" = auto; then + cat > $TMPC << EOF +#include +#include +int main(void) { return 0; } +EOF + _kai=no; + cc_check -lkai && _kai=yes +fi +if test "$_kai" = yes ; then + def_kai='#define CONFIG_KAI 1' + libs_mplayer="$libs_mplayer -lkai" + _aomodules="kai $_aomodules" +else + def_kai='#undef CONFIG_KAI' + _noaomodules="kai $_noaomodules" +fi +echores "$_kai" + echocheck "DART" if test "$_dart" = auto; then cat > $TMPC << EOF @@ -8533,6 +8557,7 @@ JACK = $_jack JOYSTICK = $_joystick JPEG = $_jpeg +KAI = $_kai KVA = $_kva LADSPA = $_ladspa LIBA52 = $_liba52 @@ -8972,6 +8997,7 @@ $def_esd $def_esd_latency $def_jack +$def_kai $def_nas $def_openal $def_openal_h diff -r 82a05ac88606 -r 2118e8876a2b libao2/ao_kai.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libao2/ao_kai.c Mon Feb 01 14:09:53 2010 +0000 @@ -0,0 +1,331 @@ +/* + * OS/2 KAI audio output driver + * + * Copyright (c) 2010 by KO Myung-Hun (komh@chollian.net) + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define INCL_DOS +#define INCL_DOSERRORS +#include + +#include +#include +#include +#include + +#include + +#include "config.h" +#include "libaf/af_format.h" +#include "audio_out.h" +#include "audio_out_internal.h" +#include "mp_msg.h" +#include "libvo/fastmemcpy.h" +#include "subopt-helper.h" +#include "libavutil/fifo.h" + +static const ao_info_t info = { + "KAI audio output", + "kai", + "KO Myung-Hun ", + "" +}; + +LIBAO_EXTERN(kai) + +#define OUTBURST_SAMPLES 512 +#define DEFAULT_SAMPLES (OUTBURST_SAMPLES << 2) + +#define CHUNK_SIZE ao_data.outburst + +static AVFifoBuffer *m_audioBuf; + +static int m_nBufSize = 0; + +static volatile int m_fQuit = FALSE; + +static KAISPEC m_kaiSpec; + +static HKAI m_hkai; + +static int write_buffer(unsigned char *data, int len) +{ + int nFree = av_fifo_space(m_audioBuf); + + len = FFMIN(len, nFree); + + return av_fifo_generic_write(m_audioBuf, data, len, NULL); +} + +static int read_buffer(unsigned char *data, int len) +{ + int nBuffered = av_fifo_size(m_audioBuf); + + len = FFMIN(len, nBuffered); + + av_fifo_generic_read(m_audioBuf, data, len, NULL); + return len; +} + +// end ring buffer stuff + +static ULONG APIENTRY kai_audio_callback(PVOID pCBData, PVOID pBuffer, + ULONG ulSize) +{ + int nReadLen; + + nReadLen = read_buffer(pBuffer, ulSize); + if (nReadLen < ulSize && !m_fQuit) { + memset((uint8_t *)pBuffer + nReadLen, m_kaiSpec.bSilence, ulSize - nReadLen); + nReadLen = ulSize; + } + + return nReadLen; +} + +// to set/get/query special features/parameters +static int control(int cmd, void *arg) +{ + switch (cmd) { + case AOCONTROL_GET_VOLUME: + { + ao_control_vol_t *vol = arg; + + vol->left = vol->right = kaiGetVolume(m_hkai, MCI_STATUS_AUDIO_ALL); + + return CONTROL_OK; + } + + case AOCONTROL_SET_VOLUME: + { + int mid; + ao_control_vol_t *vol = arg; + + mid = (vol->left + vol->right) / 2; + kaiSetVolume(m_hkai, MCI_SET_AUDIO_ALL, mid); + + return CONTROL_OK; + } + } + + return CONTROL_UNKNOWN; +} + +static void print_help(void) +{ + mp_msg(MSGT_AO, MSGL_FATAL, + "\n-ao kai commandline help:\n" + "Example: mplayer -ao kai:noshare\n" + " open audio in exclusive mode\n" + "\nOptions:\n" + " uniaud\n" + " Use UNIAUD audio driver\n" + " dart\n" + " Use DART audio driver\n" + " (no)share\n" + " Open audio in shareable or exclusive mode\n" + " bufsize=\n" + " Set buffer size to in samples(default: 2048)\n"); +} + +// open & set up audio device +// return: 1=success 0=fail +static int init(int rate, int channels, int format, int flags) +{ + int fUseUniaud = 0; + int fUseDart = 0; + int fShare = 1; + ULONG kaiMode; + KAICAPS kc; + int nSamples = DEFAULT_SAMPLES; + int nBytesPerSample; + KAISPEC ksWanted; + + const opt_t subopts[] = { + {"uniaud", OPT_ARG_BOOL, &fUseUniaud, NULL}, + {"dart", OPT_ARG_BOOL, &fUseDart, NULL}, + {"share", OPT_ARG_BOOL, &fShare, NULL}, + {"bufsize", OPT_ARG_INT, &nSamples, int_non_neg}, + {NULL} + }; + + const char *audioDriver[] = {"DART", "UNIAUD",}; + + if (subopt_parse(ao_subdevice, subopts) != 0) { + print_help(); + return 0; + } + + if (fUseUniaud && fUseDart) + mp_msg(MSGT_VO, MSGL_WARN,"KAI: Multiple mode specified!!!\n"); + + if (fUseUniaud) + kaiMode = KAIM_UNIAUD; + else if (fUseDart) + kaiMode = KAIM_DART; + else + kaiMode = KAIM_AUTO; + + if (kaiInit(kaiMode)) { + mp_msg(MSGT_VO, MSGL_ERR, "KAI: Init failed!!!\n"); + return 0; + } + + kaiCaps(&kc); + mp_msg(MSGT_AO, MSGL_V, "KAI: selected audio driver = %s\n", + audioDriver[kc.ulMode - 1]); + mp_msg(MSGT_AO, MSGL_V, "KAI: PDD name = %s, maximum channels = %lu\n", + kc.szPDDName, kc.ulMaxChannels); + + if (!nSamples) + nSamples = DEFAULT_SAMPLES; + + mp_msg(MSGT_AO, MSGL_V, "KAI: open in %s mode, buffer size = %d sample(s)\n", + fShare ? "shareable" : "exclusive", nSamples); + + switch (format) { + case AF_FORMAT_S16_LE: + case AF_FORMAT_S8: + break; + + default: + format = AF_FORMAT_S16_LE; + mp_msg(MSGT_AO, MSGL_V, "KAI: format %s not supported defaulting to Signed 16-bit Little-Endian\n", + af_fmt2str_short(format)); + break; + } + + nBytesPerSample = (af_fmt2bits(format) >> 3) * channels; + + ksWanted.usDeviceIndex = 0; + ksWanted.ulType = KAIT_PLAY; + ksWanted.ulBitsPerSample = af_fmt2bits(format); + ksWanted.ulSamplingRate = rate; + ksWanted.ulDataFormat = MCI_WAVE_FORMAT_PCM; + ksWanted.ulChannels = channels; + ksWanted.ulNumBuffers = 2; + ksWanted.ulBufferSize = nBytesPerSample * nSamples; + ksWanted.fShareable = fShare; + ksWanted.pfnCallBack = kai_audio_callback; + ksWanted.pCallBackData = NULL; + + if (kaiOpen(&ksWanted, &m_kaiSpec, &m_hkai)) { + mp_msg(MSGT_VO, MSGL_ERR, "KAI: Open failed!!!\n"); + return 0; + } + + mp_msg(MSGT_AO, MSGL_V, "KAI: obtained buffer count = %lu, size = %lu bytes\n", + m_kaiSpec.ulNumBuffers, m_kaiSpec.ulBufferSize); + + m_fQuit = FALSE; + + ao_data.channels = channels; + ao_data.samplerate = rate; + ao_data.format = format; + ao_data.bps = nBytesPerSample * rate; + ao_data.outburst = nBytesPerSample * OUTBURST_SAMPLES; + ao_data.buffersize = m_kaiSpec.ulBufferSize; + + m_nBufSize = (m_kaiSpec.ulBufferSize * m_kaiSpec.ulNumBuffers) << 3; + + // multiple of CHUNK_SIZE + m_nBufSize = (m_nBufSize / CHUNK_SIZE) * CHUNK_SIZE; + + // and one more chunk plus round up + m_nBufSize += 2 * CHUNK_SIZE; + + mp_msg(MSGT_AO, MSGL_V, "KAI: internal audio buffer size = %d bytes\n", + m_nBufSize); + + m_audioBuf = av_fifo_alloc(m_nBufSize); + + kaiPlay(m_hkai); + + // might cause PM DLLs to be loaded which incorrectly enable SIG_FPE, + // which AAC decoding might trigger. + // so, mask off all floating-point exceptions. + _control87(MCW_EM, MCW_EM); + + return 1; +} + +// close audio device +static void uninit(int immed) +{ + m_fQuit = TRUE; + + if (!immed) + while (kaiStatus(m_hkai) & KAIS_PLAYING) + DosSleep(1); + + kaiClose(m_hkai); + + kaiDone(); + + av_fifo_free(m_audioBuf); +} + +// stop playing and empty buffers (for seeking/pause) +static void reset(void) +{ + kaiPause(m_hkai); + + // Reset ring-buffer state + av_fifo_reset(m_audioBuf); + + kaiResume(m_hkai); +} + +// stop playing, keep buffers (for pause) +static void audio_pause(void) +{ + kaiPause(m_hkai); +} + +// resume playing, after audio_pause() +static void audio_resume(void) +{ + kaiResume(m_hkai); +} + +// return: how many bytes can be played without blocking +static int get_space(void) +{ + return av_fifo_space(m_audioBuf); +} + +// plays 'len' bytes of 'data' +// it should round it down to outburst*n +// return: number of bytes played +static int play(void *data, int len, int flags) +{ + + if (!(flags & AOPLAY_FINAL_CHUNK)) + len = (len / ao_data.outburst) * ao_data.outburst; + + return write_buffer(data, len); +} + +// return: delay in seconds between first and last sample in buffer +static float get_delay(void) +{ + int nBuffered = av_fifo_size(m_audioBuf); // could be less + + return (float)nBuffered / (float)ao_data.bps; +} diff -r 82a05ac88606 -r 2118e8876a2b libao2/audio_out.c --- a/libao2/audio_out.c Mon Feb 01 09:24:32 2010 +0000 +++ b/libao2/audio_out.c Mon Feb 01 14:09:53 2010 +0000 @@ -47,6 +47,7 @@ extern const ao_functions_t audio_out_sgi; extern const ao_functions_t audio_out_win32; extern const ao_functions_t audio_out_dsound; +extern const ao_functions_t audio_out_kai; extern const ao_functions_t audio_out_dart; extern const ao_functions_t audio_out_dxr2; extern const ao_functions_t audio_out_ivtv; @@ -64,6 +65,9 @@ #ifdef CONFIG_WIN32WAVEOUT &audio_out_win32, #endif +#ifdef CONFIG_KAI + &audio_out_kai, +#endif #ifdef CONFIG_DART &audio_out_dart, #endif