I am using OpenSL ES on Android NDK. I am creating an audio player, like this:
SLDataLocator_URI uriLocator = {SL_DATALOCATOR_URI, (SLchar *) path};
SLDataFormat_MIME formatMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
SLDataSource audioSource = {&uriLocator, &formatMIME};
// Configure the audio sink
SLDataLocator_OutputMix locatorOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMix};
SLDataSink audioSink = {&locatorOutputMix, NULL};
const SLInterfaceID ids[] = {SL_IID_SEEK, SL_IID_MUTESOLO, SL_IID_PREFETCHSTATUS, SL_IID_PLAY};
const SLboolean req[] = {SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_TRUE , SL_BOOLEAN_TRUE };
(*engine)->CreateAudioPlayer(engine, &audioPlayer, &audioSource, &audioSink, 4, ids, req);
Note the above is a simplified version of my actual code, I defined some macros to automate logging and error checking of the OpenSL API calls. Here is my actual code: https://github.com/skissane/adbplay/blob/master/adbplay.c#L195
Here is what I find:
- If
path
is path to a directory, non-existent file, or empty regular file, I get a prefetch callback whereGetPrefetchStatus
returnsSL_PREFETCHSTATUS_UNDERFLOW
- If
path
is path to an existent non-empty file, I never get a prefetch callback. I can callSetPlayState
on the player to change it to SL_PLAYSTATE_PLAYING, but it gets stuck atGetPlayState()
returningSL_PLAYSTATE_PLAYING
forever. I never get any callback or failed API call.
The bizarre thing about (2), is it behaves the same no matter what the file is, so long as it is a non-empty regular file. I get the same behaviour if I pass the path to a valid .wav
file or if I pass the path to the executable. A zero byte regular file behaves like (1) but a one byte regular file behaves like (2).
My test audio file is a 65,402 byte WAV file:
$ file ./test.wav
./test.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 22050 Hz
$ ffprobe ./test.wav
...
Input #0, wav, from './test.wav':
Duration: 00:00:01.48, bitrate: 353 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, s16, 352 kb/s
The test file is under 2 seconds long, but it is stuck in SL_PLAYSTATE_PLAYING
indefinitely, a lot longer than 2 seconds.
My test device is an Android TV (Sony BRAVIA 4K GB, BRAVIA_ATV2_PA) running Android 8.0, armeabi-v7a.
I also tried changing my SLDataFormat_MIME
to:
SLDataFormat_MIME formatMIME = {SL_DATAFORMAT_MIME, (SLchar*)"audio/x-wav", SL_CONTAINERTYPE_WAV};
But still it makes no difference–it still makes no progress playing a valid WAV file, and still behaves the same (without error) even for a completely invalid file such as an ELF executable. Why don't I at least get some error reported?
Is this some kind of strange permissions/security issue because I am running this from adb shell
instead of a normal Android app? Still, shouldn't I at least get some error in that case?