0

I'm currently trying to change the uri of the audioplayer without destroying the realized SLPlayItf object.

I've got something like this in the code :

static SLDataSource audioSrcOne;
static SLDataLocator_URI locUriOne;

void initialize_player_with_streamOne()
{
  ...

  locUriOne.locatorType         = SL_DATALOCATOR_URI;
  locUriOne.URI                 = (SLchar *) streamOne->utf8;

  SLDataFormat_MIME format_mime = { SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED };
  audioSrcOne.pLocator          = (void *)&locUriOne;
  audioSrcOne.pFormat           = (void *)&format_mime;

  ...

  result = ( *engine->engineEngine )->CreateAudioPlayer( engine->engineEngine, &( streamOne->playerObject ), &audioSrcOne, &audioSnkOne, 3, idm, reqm );
  assert( SL_RESULT_SUCCESS == result );

  ...
}

I thought that SLDataSource and SLDataLocator_URI were sent to OpenSL as pointers. And if I simply changed it, the new url would be set.

LOGV("STREAM ONE RESET - Configuring audio source %s", streamOne->utf8 );
locUriOne.URI = (SLchar *) streamOne->utf8;
LOGV("STREAM ONE RESET - %s", locUriOne.URI );

Even though I can see that the URI is pointing to the new char array, audio player is still playing the old one.

Does anyone have any idea about how to replace the current url of an audioplayer without destroying it?

PS: Before changing the URL, I'm sending SL_PLAYER_STOPPED to both buffer and player objects. Also clearing the buffers. But this did not solve the problem.

PSS: You'll ask me why not destroy the old audioplayer and create a new one. Well the answer to that is, the boilerplate is too big for both destroying and creating. Plus destroy/create takes too much time for my taste. I prefer re-using the current created objects. And also, when I'm creating a second audioplayer, I'm not able to destroy the first. Native Destroy() command hangs the thread and code does not respond anymore.

emrahgunduz
  • 1,404
  • 1
  • 13
  • 26

1 Answers1

0

I've been digging the source of opensl and in IEngine.c file, I found this code:

    // Check the source and sink parameters against generic constraints,
    // and make a local copy of all parameters in case other application threads
    // change memory concurrently.

    result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource,
            DATALOCATOR_MASK_URI | DATALOCATOR_MASK_ADDRESS |
            DATALOCATOR_MASK_BUFFERQUEUE
#ifdef ANDROID
            | DATALOCATOR_MASK_ANDROIDFD | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE
            | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE
#endif
            , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM);

    if (SL_RESULT_SUCCESS != result) {
        break;
    }


   ... ...


   // It would be unsafe to ever refer to the application pointers again
   pAudioSrc = NULL;
   pAudioSnk = NULL;

As the code says, the audio source is copied and then incoming pointer is set to null for the sake of thread safety. So, it seems that changing the audio source of SLPlayItf on the fly is not possible.

emrahgunduz
  • 1,404
  • 1
  • 13
  • 26