1page.title=OpenSL ES Programming Notes 2@jd:body 3 4<div id="qv-wrapper"> 5 <div id="qv"> 6 <h2>On this page</h2> 7 8 <ol> 9 <li><a href="#init">Objects and Interface Initialization</a></li> 10 <li><a href="#prefetch">Audio Player Prefetch</a></li> 11 <li><a href="#destroy">Destroy</a></li> 12 <li><a href="#panning">Stereo Panning</a></li> 13 <li><a href="#callbacks">Callbacks and Threads</a></li> 14 <li><a href="#perform">Performance</a></li> 15 <li><a href="#sandp">Security and Permissions</a></li> 16 </ol> 17 </div> 18</div> 19 20<p> 21The notes in this section supplement the 22<a class="external-link" href="https://www.khronos.org/registry/sles/">OpenSL ES 1.0.1 23specification</a>. 24</p> 25 26<h2 id="init">Objects and Interface Initialization</h2> 27 28<p> 29Two aspects of the OpenSL ES programming model that may be unfamiliar to new developers are the 30distinction between objects and interfaces, and the initialization sequence. 31</p> 32 33<p> 34Briefly, an OpenSL ES object is similar to the object concept in 35 programming languages such as Java 36and C++, except an OpenSL ES object is only visible via its associated interfaces. 37 This includes 38the initial interface for all objects, called {@code SLObjectItf}. 39 There is no handle for an object 40itself, only a handle to the {@code SLObjectItf} interface of the object. 41</p> 42 43<p> 44An OpenSL ES object is first <em>created</em>, which returns an {@code SLObjectItf}, then 45<em>realized</em>. This is similar to the common programming pattern of first constructing an 46object (which should never fail other than for lack of memory or invalid parameters), and then 47completing initialization (which may fail due to lack of resources). The realize step gives the 48implementation a logical place to allocate additional resources if needed. 49</p> 50 51<p> 52As part of the API to create an object, an application specifies an array of desired interfaces 53that it plans to acquire later. Note that this array does not automatically 54 acquire the interfaces; 55it merely indicates a future intention to acquire them. Interfaces are distinguished as 56<em>implicit</em> or <em>explicit</em>. An explicit interface must be listed in the array if it 57will be acquired later. An implicit interface need not be listed in the 58 object create array, but 59there is no harm in listing it there. OpenSL ES has one more kind of interface called 60<em>dynamic</em>, which does not need to be specified in the object 61 create array and can be added 62later after the object is created. The Android implementation provides 63 a convenience feature to 64avoid this complexity, which is described in 65 <a href="{@docRoot}ndk/guides/audio/opensl-for-android.html#dynamic-interfaces">Dynamic interfaces at object creation</a>. 66</p> 67 68<p> 69After the object is created and realized, the application should acquire interfaces for each 70feature it needs, using {@code GetInterface} on the initial {@code SLObjectItf}. 71</p> 72 73<p> 74Finally, the object is available for use via its interfaces, though note that 75 some objects require 76further setup. In particular, an audio player with URI data source needs a bit 77 more preparation in 78order to detect connection errors. See the 79 <a href="#prefetch">Audio player prefetch</a> section for details. 80</p> 81 82<p> 83After your application is done with the object, you should explicitly destroy it; see the 84<a href="#destroy">Destroy</a> section below. 85</p> 86 87<h2 id="prefetch">Audio Player Prefetch</h2> 88 89<p> 90For an audio player with URI data source, {@code Object::Realize} allocates 91 resources but does not 92connect to the data source (<em>prepare</em>) or begin pre-fetching data. These occur once the 93player state is set to either {@code SL_PLAYSTATE_PAUSED} or {@code SL_PLAYSTATE_PLAYING}. 94</p> 95 96<p> 97Some information may still be unknown until relatively late in this sequence. In 98particular, initially {@code Player::GetDuration} returns {@code SL_TIME_UNKNOWN} and 99{@code MuteSolo::GetChannelCount} either returns successfully with channel count zero or the 100error result {@code SL_RESULT_PRECONDITIONS_VIOLATED}. These APIs return the proper values 101once they are known. 102</p> 103 104<p> 105Other properties that are initially unknown include the sample rate and 106 actual media content type 107based on examining the content's header (as opposed to the 108 application-specified MIME type and 109container type). These are also determined later during 110 prepare/prefetch, but there are no APIs to 111retrieve them. 112</p> 113 114<p> 115The prefetch status interface is useful for detecting when all information 116 is available, or your 117application can poll periodically. Note that some information, such as the 118 duration of a streaming 119MP3, may <em>never</em> be known. 120</p> 121 122<p> 123The prefetch status interface is also useful for detecting errors. Register a callback 124 and enable 125at least the {@code SL_PREFETCHEVENT_FILLLEVELCHANGE} and {@code SL_PREFETCHEVENT_STATUSCHANGE} 126events. If both of these events are delivered simultaneously, and 127{@code PrefetchStatus::GetFillLevel} reports a zero level, and 128{@code PrefetchStatus::GetPrefetchStatus} reports {@code SL_PREFETCHSTATUS_UNDERFLOW}, 129 then this 130indicates a non-recoverable error in the data source. This includes the inability to 131 connect to the 132data source because the local filename does not exist or the network URI is invalid. 133</p> 134 135<p> 136The next version of OpenSL ES is expected to add more explicit support for 137 handling errors in the 138data source. However, for future binary compatibility, we intend to continue 139 to support the current 140method for reporting a non-recoverable error. 141</p> 142 143<p> 144In summary, a recommended code sequence is: 145</p> 146 147<ol> 148 <li>{@code Engine::CreateAudioPlayer}</li> 149 <li>{@code Object:Realize}</li> 150 <li>{@code Object::GetInterface} for {@code SL_IID_PREFETCHSTATUS}</li> 151 <li>{@code PrefetchStatus::SetCallbackEventsMask}</li> 152 <li>{@code PrefetchStatus::SetFillUpdatePeriod}</li> 153 <li>{@code PrefetchStatus::RegisterCallback}</li> 154 <li>{@code Object::GetInterface} for {@code SL_IID_PLAY}</li> 155 <li>{@code Play::SetPlayState} to {@code SL_PLAYSTATE_PAUSED}, or 156 {@code SL_PLAYSTATE_PLAYING}</li> 157</ol> 158 159<p class="note"><strong>Note: </strong> 160Preparation and prefetching occur here; during this time your callback is called with 161periodic status updates. 162</p> 163 164<h2 id="destroy">Destroy</h2> 165 166<p> 167Be sure to destroy all objects when exiting from your application. 168 Objects should be destroyed in 169reverse order of their creation, as it is not safe to destroy an object that has any dependent 170objects. For example, destroy in this order: audio players and recorders, output mix, and then 171finally the engine. 172</p> 173 174<p> 175OpenSL ES does not support automatic garbage collection or 176<a class="external-link" href="http://en.wikipedia.org/wiki/Reference_counting">reference 177counting</a> of interfaces. After you call {@code Object::Destroy}, all extant 178 interfaces that are 179derived from the associated object become undefined. 180</p> 181 182<p> 183The Android OpenSL ES implementation does not detect the incorrect use of such interfaces. 184Continuing to use such interfaces after the object is destroyed can cause your application to 185crash or behave in unpredictable ways. 186</p> 187 188<p> 189We recommend that you explicitly set both the primary object interface and all associated 190interfaces to NULL as part of your object destruction sequence, which prevents the accidental 191misuse of a stale interface handle. 192</p> 193 194<h2 id="panning">Stereo Panning</h2> 195 196<p> 197When {@code Volume::EnableStereoPosition} is used to enable stereo panning of a mono source, 198 there is a 3-dB reduction in total 199<a class="external-link" href="http://en.wikipedia.org/wiki/Sound_power_level">sound power 200level</a>. This is needed to permit the total sound power level to remain constant as 201 the source is 202panned from one channel to the other. Therefore, only enable stereo positioning if you need 203it. See the Wikipedia article on 204<a class="external-link" href="http://en.wikipedia.org/wiki/Panning_(audio)">audio panning</a> 205 for more information. 206</p> 207 208<h2 id="callbacks">Callbacks and Threads</h2> 209 210<p> 211Callback handlers are generally called synchronously with respect to the event. That is, at the 212moment and location that the event is detected by the implementation. This point is 213asynchronous with respect to the application, so you should use a non-blocking synchronization 214mechanism to control access to any variables shared between the application and the callback 215handler. In the example code, such as for buffer queues, we have either omitted this 216synchronization or used blocking synchronization in the interest of simplicity. However, proper 217non-blocking synchronization is critical for any production code. 218</p> 219 220<p> 221Callback handlers are called from internal non-application threads that are not attached to the 222Android runtime, so they are ineligible to use JNI. Because these internal threads are 223critical to 224the integrity of the OpenSL ES implementation, a callback handler should also not block 225 or perform 226excessive work. 227</p> 228 229<p> 230If your callback handler needs to use JNI or execute work that is not proportional to the 231callback, the handler should instead post an event for another thread to process. Examples of 232acceptable callback workload include rendering and enqueuing the next output buffer 233(for an AudioPlayer), processing the just-filled input buffer and enqueueing the next 234 empty buffer 235(for an AudioRecorder), or simple APIs such as most of the <em>Get</em> family. See the 236<a href="#perform">Performance</a> section below regarding the workload. 237</p> 238 239<p> 240Note that the converse is safe: an Android application thread that has entered JNI 241 is allowed to 242directly call OpenSL ES APIs, including those that block. However, blocking calls are not 243recommended from the main thread, as they may result in 244 <em>Application Not Responding</em> (ANR). 245</p> 246 247<p> 248The determination regarding the thread that calls a callback handler is largely left up to the 249implementation. The reason for this flexibility is to permit future optimizations, 250 especially on 251multi-core devices. 252</p> 253 254<p> 255The thread on which the callback handler runs is not guaranteed to have the same 256 identity across 257different calls. Therefore, do not rely on the {@code pthread_t returned by pthread_self()} 258 or the 259{@code pid_t returned by gettid()} to be consistent across calls. For the same reason, 260 do not use 261the thread local storage (TLS) APIs such as {@code pthread_setspecific()} and 262{@code pthread_getspecific()} from a callback. 263</p> 264 265<p> 266The implementation guarantees that concurrent callbacks of the same kind, for the 267 same object, does 268not occur. However, concurrent callbacks of different kinds for the same object are possible on 269different threads. 270</p> 271 272<h2 id="perform">Performance</h2> 273 274<p> 275As OpenSL ES is a native C API, non-runtime application threads that call OpenSL ES have no 276runtime-related overhead such as garbage collection pauses. With one exception described below, 277there is no additional performance benefit to the use of OpenSL ES other than this. 278 In particular, 279the use of OpenSL ES does not guarantee enhancements such as lower audio latency and higher 280scheduling priority over that which the platform generally provides. On the other hand, as the 281Android platform and specific device implementations continue to evolve, an OpenSL ES application 282can expect to benefit from any future system performance improvements. 283</p> 284 285<p> 286One such evolution is support for reduced 287<a href="{@docRoot}ndk/guides/audio/output-latency.html">audio output latency</a>. 288The underpinnings for reduced 289output latency were first included in Android 4.1 (API level 16), and then 290continued progress occurred in Android 4.2 (API level 17). These improvements are available via 291OpenSL ES for device implementations that 292 claim feature {@code android.hardware.audio.low_latency}. 293If the device doesn't claim this feature but supports Android 2.3 (API level 9) 294or later, then you can still use the OpenSL ES APIs but the output latency may be higher. 295 The lower 296output latency path is used only if the application requests a buffer size and sample rate 297 that are 298compatible with the device's native output configuration. These parameters are 299 device-specific and 300should be obtained as described below. 301</p> 302 303<p> 304Beginning with Android 4.2 (API level 17), an application can query for the 305platform native or optimal output sample rate and buffer size for the device's primary output 306stream. When combined with the feature test just mentioned, an app can now configure itself 307appropriately for lower latency output on devices that claim support. 308</p> 309 310<p> 311For Android 4.2 (API level 17) and earlier, a buffer count of two or more is 312required for lower latency. Beginning with Android 4.3 (API level 18), a buffer 313count of one is sufficient for lower latency. 314</p> 315 316<p> 317All OpenSL ES interfaces for output effects preclude the lower latency path. 318</p> 319 320<p> 321The recommended sequence is as follows: 322</p> 323 324<ol> 325 <li>Check for API level 9 or higher to confirm the use of OpenSL ES.</li> 326 <li>Check for the {@code android.hardware.audio.low_latency} feature using code such as this: 327 <pre>import android.content.pm.PackageManager; 328... 329PackageManager pm = getContext().getPackageManager(); 330boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY); 331 </pre></li> 332 <li>Check for API level 17 or higher to confirm the use of 333 {@code android.media.AudioManager.getProperty()}.</li> 334 <li>Get the native or optimal output sample rate and buffer size for this device's 335 primary output 336 stream using code such as this: 337 <pre>import android.media.AudioManager; 338... 339AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 340String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); 341String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); 342 </pre> 343 Note that {@code sampleRate} and {@code framesPerBuffer} are <em>strings</em>. First check for 344 null and then convert to int using {@code Integer.parseInt()}.</li> 345 <li>Now use OpenSL ES to create an AudioPlayer with PCM buffer queue data locator.</li> 346</ol> 347 348<p class="note"><strong>Note: </strong> 349You can use the 350<a class="external-link" 351 href="https://play.google.com/store/apps/details?id=com.levien.audiobuffersize"> 352 Audio Buffer Size</a> 353test app to determine the native buffer size and sample rate for OpenSL ES audio 354applications on your audio device. You can also visit GitHub to view <a class="external-link" 355href="https://github.com/gkasten/high-performance-audio/tree/master/audio-buffer-size"> 356audio-buffer-size</a> samples. 357 358<p> 359The number of lower latency audio players is limited. If your application requires more 360than a few 361audio sources, consider mixing your audio at the application level. Be sure to destroy your audio 362players when your activity is paused, as they are a global resource shared with other apps. 363</p> 364 365<p> 366To avoid audible glitches, the buffer queue callback handler must execute within a small and 367predictable time window. This typically implies no unbounded blocking on mutexes, conditions, 368or I/O operations. Instead consider <em>try locks</em>, locks and waits with timeouts, and 369<a class="external-link" 370 href="https://source.android.com/devices/audio/avoiding_pi.html#nonBlockingAlgorithms"> 371 non-blocking algorithms</a>. 372</p> 373 374<p> 375The computation required to render the next buffer (for AudioPlayer) or consume the previous 376buffer (for AudioRecord) should take approximately the same amount of time for each callback. 377Avoid algorithms that execute in a non-deterministic amount of time or are <em>bursty</em> in 378their computations. A callback computation is bursty if the CPU time spent in any given callback 379is significantly larger than the average. In summary, the ideal is for the CPU execution time of 380the handler to have variance near zero, and for the handler to not block for unbounded times. 381</p> 382 383<p> 384Lower latency audio is possible for these outputs only: 385</p> 386 387<ul> 388 <li>On-device speakers.</li> 389 <li>Wired headphones.</li> 390 <li>Wired headsets.</li> 391 <li>Line out.</li> 392 <li><a class="external-link" href="https://source.android.com/devices/audio/usb.html"> 393 USB digital 394 audio</a>.</li> 395</ul> 396 397<p> 398On some devices, speaker latency is higher than other paths due to digital signal processing for 399speaker correction and protection. 400</p> 401 402<p> 403As of API level 21, 404<a href="{@docRoot}ndk/guides/audio/input-latency.html">lower latency audio input</a> 405 is supported 406on select devices. To take advantage of 407this feature, first confirm that lower latency output is available as described above. The 408capability for lower latency output is a prerequisite for the lower latency input feature. Then, 409create an AudioRecorder with the same sample rate and buffer size as would be used for output. 410OpenSL ES interfaces for input effects preclude the lower latency path. The record preset 411{@code SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION} must be used for lower latency; this preset 412disables device-specific digital signal processing that may add latency to the input path. For 413more information on record presets, see the <a href="#configuration-interface">Android 414configuration interface</a> section above. 415</p> 416 417<p> 418For simultaneous input and output, separate buffer queue completion handlers are used for each 419side. There is no guarantee of the relative order of these callbacks, or the synchronization of 420the audio clocks, even when both sides use the same sample rate. Your application 421 should buffer the 422data with proper buffer synchronization. 423</p> 424 425<p> 426One consequence of potentially independent audio clocks is the need for asynchronous sample rate 427conversion. A simple (though not ideal for audio quality) technique for asynchronous sample rate 428conversion is to duplicate or drop samples as needed near a zero-crossing point. 429 More sophisticated 430conversions are possible. 431</p> 432 433<h2 id="sandp">Security and Permissions</h2> 434 435<p> 436As far as who can do what, security in Android is done at the process level. Java programming 437language code cannot do anything more than native code, nor can native code do anything more than 438Java programming language code. The only differences between them are the available APIs. 439</p> 440 441<p> 442Applications using OpenSL ES must request the permissions that they would need for similar 443non-native APIs. For example, if your application records audio, then it needs the 444{@code android.permission.RECORD_AUDIO} permission. Applications that use audio effects need 445{@code android.permission.MODIFY_AUDIO_SETTINGS}. Applications that play network URI resources 446need {@code android.permission.NETWORK}. See 447<a href="https://developer.android.com/training/permissions/index.html">Working with System 448Permissions</a> for more information. 449</p> 450 451<p> 452Depending on the platform version and implementation, media content parsers and 453 software codecs may 454run within the context of the Android application that calls OpenSL ES (hardware codecs are 455abstracted but are device-dependent). Malformed content designed to exploit parser and codec 456vulnerabilities is a known attack vector. We recommend that you play media only from trustworthy 457sources or that you partition your application such that code that handles media from 458untrustworthy sources runs in a relatively <em>sandboxed</em> environment. For example, you could 459process media from untrustworthy sources in a separate process. Though both processes would still 460run under the same UID, this separation does make an attack more difficult. 461</p> 462