0

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:

  1. If path is path to a directory, non-existent file, or empty regular file, I get a prefetch callback where GetPrefetchStatus returns SL_PREFETCHSTATUS_UNDERFLOW
  2. If path is path to an existent non-empty file, I never get a prefetch callback. I can call SetPlayState on the player to change it to SL_PLAYSTATE_PLAYING, but it gets stuck at GetPlayState() returning SL_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?

Simon Kissane
  • 4,373
  • 3
  • 34
  • 59

0 Answers0