#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
+int aout_get_native_sample_rate(void);
+
#define OPENSLES_BUFFERS 255 /* maximum number of buffers */
-#define OPENSLES_BUFLEN 4 /* ms */
+#define OPENSLES_BUFLEN 10 /* ms */
/*
- * 4ms of precision when mesasuring latency should be plenty enough,
- * with 255 buffers we can buffer ~1s of audio.
+ * 10ms of precision when mesasuring latency should be enough,
+ * with 255 buffers we can buffer 2.55s of audio.
*/
#define CHECK_OPENSL_ERROR(msg) \
sys->p_buffer_chain = NULL;
sys->pp_buffer_last = &sys->p_buffer_chain;
+ sys->samples = 0;
sys->started = false;
vlc_mutex_unlock(&sys->lock);
static int VolumeSet(audio_output_t *aout, float vol)
{
+ if (!aout->sys->volumeItf)
+ return -1;
+
/* Convert UI volume to linear factor (cube) */
vol = vol * vol * vol;
static int MuteSet(audio_output_t *aout, bool mute)
{
+ if (!aout->sys->volumeItf)
+ return -1;
+
SLresult r = SetMute(aout->sys->volumeItf, mute);
return (r == SL_RESULT_SUCCESS) ? 0 : -1;
}
/*****************************************************************************
*
*****************************************************************************/
-static void Clean(aout_sys_t *sys)
-{
- if (sys->playerObject)
- Destroy(sys->playerObject);
- if (sys->outputMixObject)
- Destroy(sys->outputMixObject);
- if (sys->engineObject)
- Destroy(sys->engineObject);
-}
-
static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
SLresult result;
//create audio player
const SLInterfaceID ids2[] = { sys->SL_IID_ANDROIDSIMPLEBUFFERQUEUE, sys->SL_IID_VOLUME };
static const SLboolean req2[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
- result = CreateAudioPlayer(sys->engineEngine, &sys->playerObject, &audioSrc,
+
+ if (aout_get_native_sample_rate() >= fmt->i_rate) {
+ result = CreateAudioPlayer(sys->engineEngine, &sys->playerObject, &audioSrc,
&audioSnk, sizeof(ids2) / sizeof(*ids2),
ids2, req2);
+ } else {
+ // Don't try to play back a sample rate higher than the native one,
+ // since OpenSL ES will try to use the fast path, which AudioFlinger
+ // will reject (fast path can't do resampling), and will end up with
+ // too small buffers for the resampling. See http://b.android.com/59453
+ // for details. This bug is still present in 4.4. If it is fixed later
+ // this workaround could be made conditional.
+ result = SL_RESULT_UNKNOWN_ERROR;
+ }
+ if (unlikely(result != SL_RESULT_SUCCESS)) {
+ /* Try again with a more sensible samplerate */
+ fmt->i_rate = 44100;
+ format_pcm.samplesPerSec = ((SLuint32) 44100 * 1000) ;
+ result = CreateAudioPlayer(sys->engineEngine, &sys->playerObject, &audioSrc,
+ &audioSnk, sizeof(ids2) / sizeof(*ids2),
+ ids2, req2);
+ }
CHECK_OPENSL_ERROR("Failed to create audio player");
result = Realize(sys->playerObject, SL_BOOLEAN_FALSE);
sys->p_buffer_chain = NULL;
sys->pp_buffer_last = &sys->p_buffer_chain;
+ sys->samples = 0;
// we want 16bit signed data native endian.
fmt->i_format = VLC_CODEC_S16N;
return VLC_SUCCESS;
error:
- Clean(sys);
+ if (sys->playerObject) {
+ Destroy(sys->playerObject);
+ sys->playerObject = NULL;
+ }
+
return VLC_EGENERIC;
}
free(sys->buf);
block_ChainRelease(sys->p_buffer_chain);
+
+ Destroy(sys->playerObject);
+ sys->playerObject = NULL;
}
/*****************************************************************************
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
- Clean(sys);
+ Destroy(sys->outputMixObject);
+ Destroy(sys->engineObject);
dlclose(sys->p_so_handle);
vlc_mutex_destroy(&sys->lock);
free(sys);
return VLC_SUCCESS;
error:
- Clean(sys);
+ if (sys->outputMixObject)
+ Destroy(sys->outputMixObject);
+ if (sys->engineObject)
+ Destroy(sys->engineObject);
if (sys->p_so_handle)
dlclose(sys->p_so_handle);
free(sys);