qt: playlist: use item title if available
[vlc.git] / modules / audio_output / audiotrack.c
blob605d76ce365b36885e90d7d03c516b720fb92d45
1 /*****************************************************************************
2 * audiotrack.c: Android Java AudioTrack audio output module
3 *****************************************************************************
4 * Copyright © 2012-2015 VLC authors and VideoLAN, VideoLabs
6 * Authors: Thomas Guillem <thomas@gllm.fr>
7 * Ming Hu <tewilove@gmail.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <assert.h>
29 #include <jni.h>
30 #include <dlfcn.h>
31 #include <stdbool.h>
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_aout.h>
36 #include "../video_output/android/utils.h"
38 #define SMOOTHPOS_SAMPLE_COUNT 10
39 #define SMOOTHPOS_INTERVAL_US VLC_TICK_FROM_MS(30) // 30ms
41 #define AUDIOTIMESTAMP_INTERVAL_US VLC_TICK_FROM_MS(500) // 500ms
43 #define AUDIOTRACK_MAX_BUFFER_US VLC_TICK_FROM_MS(750) // 750ms
45 static int Open( vlc_object_t * );
46 static void Close( vlc_object_t * );
47 static void Stop( audio_output_t * );
48 static int Start( audio_output_t *, audio_sample_format_t * );
49 static void *AudioTrack_Thread( void * );
51 /* There is an undefined behavior when configuring AudioTrack with SPDIF or
52 * more than 2 channels when there is no HDMI out. It may succeed and the
53 * Android ressampler will be used to downmix to stereo. It may fails cleanly,
54 * and this module will be able to recover and fallback to stereo. Finally, in
55 * some rare cases, it may crash during init or while ressampling. Because of
56 * the last case we don't try up to 8 channels and we use AT_DEV_STEREO device
57 * per default */
58 enum at_dev {
59 AT_DEV_STEREO = 0,
60 AT_DEV_PCM,
61 AT_DEV_ENCODED,
63 #define AT_DEV_DEFAULT AT_DEV_STEREO
64 #define AT_DEV_MAX_CHANNELS 8
66 static const struct {
67 const char *id;
68 const char *name;
69 enum at_dev at_dev;
70 } at_devs[] = {
71 { "stereo", "Up to 2 channels (compat mode).", AT_DEV_STEREO },
72 { "pcm", "Up to 8 channels.", AT_DEV_PCM },
74 /* With "encoded", the module will try to play every audio codecs via
75 * passthrough.
77 * With "encoded:ENCODING_FLAGS_MASK", the module will try to play only
78 * codecs specified by ENCODING_FLAGS_MASK. This extra value is a long long
79 * that contains binary-shifted AudioFormat.ENCODING_* values. */
80 { "encoded", "Up to 8 channels, passthrough if available.", AT_DEV_ENCODED },
81 { NULL, NULL, AT_DEV_DEFAULT },
84 typedef struct
86 enum at_dev at_dev;
88 jobject p_audiotrack; /* AudioTrack ref */
89 float volume;
90 bool mute;
92 audio_sample_format_t fmt; /* fmt setup by Start */
94 struct {
95 unsigned int i_rate;
96 int i_channel_config;
97 int i_format;
98 int i_size;
99 } audiotrack_args;
101 /* Used by AudioTrack_getPlaybackHeadPosition */
102 struct {
103 uint64_t i_wrap_count;
104 uint32_t i_last;
105 } headpos;
107 /* Used by AudioTrack_GetTimestampPositionUs */
108 struct {
109 jobject p_obj; /* AudioTimestamp ref */
110 vlc_tick_t i_frame_us;
112 jlong i_frame_post_last;
113 uint64_t i_frame_wrap_count;
114 uint64_t i_frame_pos;
116 vlc_tick_t i_last_time;
117 } timestamp;
119 /* Used by AudioTrack_GetSmoothPositionUs */
120 struct {
121 uint32_t i_idx;
122 uint32_t i_count;
123 vlc_tick_t p_us[SMOOTHPOS_SAMPLE_COUNT];
124 vlc_tick_t i_us;
125 vlc_tick_t i_last_time;
126 } smoothpos;
128 uint32_t i_max_audiotrack_samples;
129 long long i_encoding_flags;
130 bool b_passthrough;
131 uint8_t i_chans_to_reorder; /* do we need channel reordering */
132 uint8_t p_chan_table[AOUT_CHAN_MAX];
134 enum {
135 WRITE_BYTEARRAY,
136 WRITE_BYTEARRAYV23,
137 WRITE_SHORTARRAYV23,
138 WRITE_BYTEBUFFER,
139 WRITE_FLOATARRAY
140 } i_write_type;
142 vlc_thread_t thread; /* AudioTrack_Thread */
143 vlc_mutex_t lock;
144 vlc_cond_t aout_cond; /* cond owned by aout */
145 vlc_cond_t thread_cond; /* cond owned by AudioTrack_Thread */
147 /* These variables need locking on read and write */
148 bool b_thread_running; /* Set to false by aout to stop the thread */
149 bool b_thread_paused; /* If true, the thread won't process any data, see
150 * Pause() */
152 uint64_t i_samples_written; /* Number of samples written since last flush */
153 bool b_audiotrack_exception; /* True if audiotrack threw an exception */
154 bool b_error; /* generic error */
156 struct {
157 uint64_t i_read; /* Number of bytes read */
158 uint64_t i_write; /* Number of bytes written */
159 size_t i_size; /* Size of the circular buffer in bytes */
160 union {
161 jbyteArray p_bytearray;
162 jfloatArray p_floatarray;
163 jshortArray p_shortarray;
164 struct {
165 uint8_t *p_data;
166 jobject p_obj;
167 } bytebuffer;
168 } u;
169 } circular;
170 } aout_sys_t;
173 // Don't use Float for now since 5.1/7.1 Float is down sampled to Stereo Float
174 //#define AUDIOTRACK_USE_FLOAT
175 //#define AUDIOTRACK_HW_LATENCY
177 /* Get AudioTrack native sample rate: if activated, most of the resampling
178 * will be done by VLC */
179 #define AUDIOTRACK_NATIVE_SAMPLERATE
181 #define AUDIOTRACK_SESSION_ID_TEXT " Id of audio session the AudioTrack must be attached to"
183 vlc_module_begin ()
184 set_shortname( "AudioTrack" )
185 set_description( "Android AudioTrack audio output" )
186 set_capability( "audio output", 180 )
187 set_category( CAT_AUDIO )
188 set_subcategory( SUBCAT_AUDIO_AOUT )
189 add_integer( "audiotrack-session-id", 0,
190 AUDIOTRACK_SESSION_ID_TEXT, NULL, true )
191 change_private()
192 add_shortcut( "audiotrack" )
193 set_callbacks( Open, Close )
194 vlc_module_end ()
196 #define THREAD_NAME "android_audiotrack"
197 #define GET_ENV() android_getEnv( VLC_OBJECT(p_aout), THREAD_NAME )
199 static struct
201 struct {
202 jclass clazz;
203 jmethodID ctor;
204 bool has_ctor_21;
205 jmethodID release;
206 jmethodID getState;
207 jmethodID play;
208 jmethodID stop;
209 jmethodID flush;
210 jmethodID pause;
211 jmethodID write;
212 jmethodID writeV23;
213 jmethodID writeShortV23;
214 jmethodID writeBufferV21;
215 jmethodID writeFloat;
216 jmethodID getBufferSizeInFrames;
217 jmethodID getLatency;
218 jmethodID getPlaybackHeadPosition;
219 jmethodID getTimestamp;
220 jmethodID getMinBufferSize;
221 jmethodID getNativeOutputSampleRate;
222 jmethodID setVolume;
223 jmethodID setStereoVolume;
224 jint STATE_INITIALIZED;
225 jint MODE_STREAM;
226 jint ERROR;
227 jint ERROR_BAD_VALUE;
228 jint ERROR_INVALID_OPERATION;
229 jint WRITE_NON_BLOCKING;
230 } AudioTrack;
231 struct {
232 jclass clazz;
233 jmethodID ctor;
234 jmethodID build;
235 jmethodID setLegacyStreamType;
236 } AudioAttributes_Builder;
237 struct {
238 jint ENCODING_PCM_8BIT;
239 jint ENCODING_PCM_16BIT;
240 jint ENCODING_PCM_FLOAT;
241 bool has_ENCODING_PCM_FLOAT;
242 jint ENCODING_AC3;
243 bool has_ENCODING_AC3;
244 jint ENCODING_E_AC3;
245 bool has_ENCODING_E_AC3;
246 jint ENCODING_DOLBY_TRUEHD;
247 bool has_ENCODING_DOLBY_TRUEHD;
248 jint ENCODING_DTS;
249 bool has_ENCODING_DTS;
250 jint ENCODING_DTS_HD;
251 bool has_ENCODING_DTS_HD;
252 jint ENCODING_IEC61937;
253 bool has_ENCODING_IEC61937;
254 jint CHANNEL_OUT_MONO;
255 jint CHANNEL_OUT_STEREO;
256 jint CHANNEL_OUT_FRONT_LEFT;
257 jint CHANNEL_OUT_FRONT_RIGHT;
258 jint CHANNEL_OUT_BACK_LEFT;
259 jint CHANNEL_OUT_BACK_RIGHT;
260 jint CHANNEL_OUT_FRONT_CENTER;
261 jint CHANNEL_OUT_LOW_FREQUENCY;
262 jint CHANNEL_OUT_BACK_CENTER;
263 jint CHANNEL_OUT_5POINT1;
264 jint CHANNEL_OUT_SIDE_LEFT;
265 jint CHANNEL_OUT_SIDE_RIGHT;
266 bool has_CHANNEL_OUT_SIDE;
267 } AudioFormat;
268 struct {
269 jclass clazz;
270 jmethodID ctor;
271 jmethodID build;
272 jmethodID setChannelMask;
273 jmethodID setEncoding;
274 jmethodID setSampleRate;
275 } AudioFormat_Builder;
276 struct {
277 jint ERROR_DEAD_OBJECT;
278 bool has_ERROR_DEAD_OBJECT;
279 jint STREAM_MUSIC;
280 } AudioManager;
281 struct {
282 jclass clazz;
283 jmethodID ctor;
284 jfieldID framePosition;
285 jfieldID nanoTime;
286 } AudioTimestamp;
287 } jfields;
289 /* init all jni fields.
290 * Done only one time during the first initialisation */
291 static bool
292 InitJNIFields( audio_output_t *p_aout, JNIEnv* env )
294 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
295 static int i_init_state = -1;
296 bool ret;
297 jclass clazz;
298 jfieldID field;
300 vlc_mutex_lock( &lock );
302 if( i_init_state != -1 )
303 goto end;
305 #define CHECK_EXCEPTION( what, critical ) do { \
306 if( (*env)->ExceptionCheck( env ) ) \
308 msg_Err( p_aout, "%s failed", what ); \
309 (*env)->ExceptionClear( env ); \
310 if( (critical) ) \
312 i_init_state = 0; \
313 goto end; \
316 } while( 0 )
317 #define GET_CLASS( str, critical ) do { \
318 clazz = (*env)->FindClass( env, (str) ); \
319 CHECK_EXCEPTION( "FindClass(" str ")", critical ); \
320 } while( 0 )
321 #define GET_ID( get, id, str, args, critical ) do { \
322 jfields.id = (*env)->get( env, clazz, (str), (args) ); \
323 CHECK_EXCEPTION( #get "(" #id ")", critical ); \
324 } while( 0 )
325 #define GET_CONST_INT( id, str, critical ) do { \
326 field = NULL; \
327 field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
328 CHECK_EXCEPTION( "GetStaticFieldID(" #id ")", critical ); \
329 if( field ) \
331 jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
332 CHECK_EXCEPTION( #id, critical ); \
334 } while( 0 )
336 /* AudioTrack class init */
337 GET_CLASS( "android/media/AudioTrack", true );
338 jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
339 CHECK_EXCEPTION( "NewGlobalRef", true );
341 GET_ID( GetMethodID, AudioTrack.ctor, "<init>",
342 "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;III)V", false );
343 jfields.AudioTrack.has_ctor_21 = jfields.AudioTrack.ctor != NULL;
344 if( !jfields.AudioTrack.has_ctor_21 )
345 GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIIII)V", true );
346 GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true );
347 GET_ID( GetMethodID, AudioTrack.getState, "getState", "()I", true );
348 GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true );
349 GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true );
350 GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true );
351 GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true );
353 GET_ID( GetMethodID, AudioTrack.writeV23, "write", "([BIII)I", false );
354 GET_ID( GetMethodID, AudioTrack.writeShortV23, "write", "([SIII)I", false );
355 if( !jfields.AudioTrack.writeV23 )
356 GET_ID( GetMethodID, AudioTrack.writeBufferV21, "write", "(Ljava/nio/ByteBuffer;II)I", false );
358 if( jfields.AudioTrack.writeV23 || jfields.AudioTrack.writeBufferV21 )
360 GET_CONST_INT( AudioTrack.WRITE_NON_BLOCKING, "WRITE_NON_BLOCKING", true );
361 #ifdef AUDIOTRACK_USE_FLOAT
362 GET_ID( GetMethodID, AudioTrack.writeFloat, "write", "([FIII)I", true );
363 #endif
364 } else
365 GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
367 GET_ID( GetMethodID, AudioTrack.getBufferSizeInFrames,
368 "getBufferSizeInFrames", "()I", false );
370 #ifdef AUDIOTRACK_HW_LATENCY
371 GET_ID( GetMethodID, AudioTrack.getLatency, "getLatency", "()I", false );
372 #endif
374 GET_ID( GetMethodID, AudioTrack.getTimestamp,
375 "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
376 GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
377 "getPlaybackHeadPosition", "()I", true );
379 GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize",
380 "(III)I", true );
381 #ifdef AUDIOTRACK_NATIVE_SAMPLERATE
382 GET_ID( GetStaticMethodID, AudioTrack.getNativeOutputSampleRate,
383 "getNativeOutputSampleRate", "(I)I", true );
384 #endif
385 GET_ID( GetMethodID, AudioTrack.setVolume,
386 "setVolume", "(F)I", false );
387 if( !jfields.AudioTrack.setVolume )
388 GET_ID( GetMethodID, AudioTrack.setStereoVolume,
389 "setStereoVolume", "(FF)I", true );
390 GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true );
391 GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
392 GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
393 GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true );
394 GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION,
395 "ERROR_INVALID_OPERATION", true );
397 if( jfields.AudioTrack.has_ctor_21 )
399 /* AudioAttributes_Builder class init */
400 GET_CLASS( "android/media/AudioAttributes$Builder", true );
401 jfields.AudioAttributes_Builder.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
402 CHECK_EXCEPTION( "NewGlobalRef", true );
403 GET_ID( GetMethodID, AudioAttributes_Builder.ctor, "<init>",
404 "()V", true );
405 GET_ID( GetMethodID, AudioAttributes_Builder.build, "build",
406 "()Landroid/media/AudioAttributes;", true );
407 GET_ID( GetMethodID, AudioAttributes_Builder.setLegacyStreamType, "setLegacyStreamType",
408 "(I)Landroid/media/AudioAttributes$Builder;", true );
410 /* AudioFormat_Builder class init */
411 GET_CLASS( "android/media/AudioFormat$Builder", true );
412 jfields.AudioFormat_Builder.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
413 CHECK_EXCEPTION( "NewGlobalRef", true );
414 GET_ID( GetMethodID, AudioFormat_Builder.ctor, "<init>",
415 "()V", true );
416 GET_ID( GetMethodID, AudioFormat_Builder.build, "build",
417 "()Landroid/media/AudioFormat;", true );
418 GET_ID( GetMethodID, AudioFormat_Builder.setChannelMask, "setChannelMask",
419 "(I)Landroid/media/AudioFormat$Builder;", true );
420 GET_ID( GetMethodID, AudioFormat_Builder.setEncoding, "setEncoding",
421 "(I)Landroid/media/AudioFormat$Builder;", true );
422 GET_ID( GetMethodID, AudioFormat_Builder.setSampleRate, "setSampleRate",
423 "(I)Landroid/media/AudioFormat$Builder;", true );
426 /* AudioTimestamp class init (if any) */
427 if( jfields.AudioTrack.getTimestamp )
429 GET_CLASS( "android/media/AudioTimestamp", true );
430 jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env,
431 clazz );
432 CHECK_EXCEPTION( "NewGlobalRef", true );
434 GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true );
435 GET_ID( GetFieldID, AudioTimestamp.framePosition,
436 "framePosition", "J", true );
437 GET_ID( GetFieldID, AudioTimestamp.nanoTime,
438 "nanoTime", "J", true );
441 /* AudioFormat class init */
442 GET_CLASS( "android/media/AudioFormat", true );
443 GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
444 GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
445 #ifdef AUDIOTRACK_USE_FLOAT
446 GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
447 false );
448 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL &&
449 jfields.AudioTrack.writeFloat;
450 #else
451 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
452 #endif
454 if( jfields.AudioTrack.writeShortV23 )
456 GET_CONST_INT( AudioFormat.ENCODING_IEC61937, "ENCODING_IEC61937", false );
457 jfields.AudioFormat.has_ENCODING_IEC61937 = field != NULL;
459 else
460 jfields.AudioFormat.has_ENCODING_IEC61937 = false;
462 GET_CONST_INT( AudioFormat.ENCODING_AC3, "ENCODING_AC3", false );
463 jfields.AudioFormat.has_ENCODING_AC3 = field != NULL;
464 GET_CONST_INT( AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3", false );
465 jfields.AudioFormat.has_ENCODING_E_AC3 = field != NULL;
467 GET_CONST_INT( AudioFormat.ENCODING_DTS, "ENCODING_DTS", false );
468 jfields.AudioFormat.has_ENCODING_DTS = field != NULL;
469 GET_CONST_INT( AudioFormat.ENCODING_DTS_HD, "ENCODING_DTS_HD", false );
470 jfields.AudioFormat.has_ENCODING_DTS_HD = field != NULL;
472 GET_CONST_INT( AudioFormat.ENCODING_DOLBY_TRUEHD, "ENCODING_DOLBY_TRUEHD",
473 false );
474 jfields.AudioFormat.has_ENCODING_DOLBY_TRUEHD = field != NULL;
476 GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
477 GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
478 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_LEFT, "CHANNEL_OUT_FRONT_LEFT", true );
479 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_RIGHT, "CHANNEL_OUT_FRONT_RIGHT", true );
480 GET_CONST_INT( AudioFormat.CHANNEL_OUT_5POINT1, "CHANNEL_OUT_5POINT1", true );
481 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_LEFT, "CHANNEL_OUT_BACK_LEFT", true );
482 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_RIGHT, "CHANNEL_OUT_BACK_RIGHT", true );
483 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_CENTER, "CHANNEL_OUT_FRONT_CENTER", true );
484 GET_CONST_INT( AudioFormat.CHANNEL_OUT_LOW_FREQUENCY, "CHANNEL_OUT_LOW_FREQUENCY", true );
485 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_CENTER, "CHANNEL_OUT_BACK_CENTER", true );
486 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_LEFT, "CHANNEL_OUT_SIDE_LEFT", false );
487 if( field != NULL )
489 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_RIGHT, "CHANNEL_OUT_SIDE_RIGHT", true );
490 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = true;
491 } else
492 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = false;
494 /* AudioManager class init */
495 GET_CLASS( "android/media/AudioManager", true );
496 GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false );
497 jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
498 GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
500 #undef CHECK_EXCEPTION
501 #undef GET_CLASS
502 #undef GET_ID
503 #undef GET_CONST_INT
505 i_init_state = 1;
506 end:
507 ret = i_init_state == 1;
508 if( !ret )
509 msg_Err( p_aout, "AudioTrack jni init failed" );
510 vlc_mutex_unlock( &lock );
511 return ret;
514 static inline bool
515 check_exception( JNIEnv *env, audio_output_t *p_aout,
516 const char *class, const char *method )
518 if( (*env)->ExceptionCheck( env ) )
520 aout_sys_t *p_sys = p_aout->sys;
522 p_sys->b_audiotrack_exception = true;
523 p_sys->b_error = true;
524 (*env)->ExceptionDescribe( env );
525 (*env)->ExceptionClear( env );
526 msg_Err( p_aout, "%s.%s triggered an exception !", class, method );
527 return true;
528 } else
529 return false;
532 #define CHECK_EXCEPTION( class, method ) check_exception( env, p_aout, class, method )
533 #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, "AudioTrack", method )
535 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
537 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
538 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
539 #define JNI_CALL_OBJECT( obj, method, ... ) JNI_CALL( CallObjectMethod, obj, method, ##__VA_ARGS__ )
540 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
541 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
543 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
544 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
545 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
546 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
547 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
549 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->timestamp.p_obj, jfields.AudioTimestamp.field )
551 static inline vlc_tick_t
552 frames_to_us( aout_sys_t *p_sys, uint64_t i_nb_frames )
554 return vlc_tick_from_samples(i_nb_frames, p_sys->fmt.i_rate);
556 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
558 static inline uint64_t
559 bytes_to_frames( aout_sys_t *p_sys, size_t i_bytes )
561 return i_bytes * p_sys->fmt.i_frame_length / p_sys->fmt.i_bytes_per_frame;
563 #define BYTES_TO_FRAMES(x) bytes_to_frames( p_sys, (x) )
564 #define BYTES_TO_US(x) frames_to_us( p_sys, bytes_to_frames( p_sys, (x) ) )
566 static inline size_t
567 frames_to_bytes( aout_sys_t *p_sys, uint64_t i_frames )
569 return i_frames * p_sys->fmt.i_bytes_per_frame / p_sys->fmt.i_frame_length;
571 #define FRAMES_TO_BYTES(x) frames_to_bytes( p_sys, (x) )
573 static inline uint64_t
574 us_to_frames( aout_sys_t *p_sys, vlc_tick_t i_us )
576 return samples_from_vlc_tick( i_us, p_sys->fmt.i_rate );
578 #define US_TO_FRAMES(x) us_to_frames( p_sys, x)
579 #define US_TO_BYTES(x) frames_to_bytes( p_sys, us_to_frames( p_sys, x ) )
582 * Get the AudioTrack position
584 * The doc says that the position is reset to zero after flush but it's not
585 * true for all devices or Android versions.
587 static uint64_t
588 AudioTrack_getPlaybackHeadPosition( JNIEnv *env, audio_output_t *p_aout )
590 /* Android doc:
591 * getPlaybackHeadPosition: Returns the playback head position expressed in
592 * frames. Though the "int" type is signed 32-bits, the value should be
593 * reinterpreted as if it is unsigned 32-bits. That is, the next position
594 * after 0x7FFFFFFF is (int) 0x80000000. This is a continuously advancing
595 * counter. It will wrap (overflow) periodically, for example approximately
596 * once every 27:03:11 hours:minutes:seconds at 44.1 kHz. It is reset to
597 * zero by flush(), reload(), and stop().
600 aout_sys_t *p_sys = p_aout->sys;
601 uint32_t i_pos;
603 /* int32_t to uint32_t */
604 i_pos = 0xFFFFFFFFL & JNI_AT_CALL_INT( getPlaybackHeadPosition );
606 /* uint32_t to uint64_t */
607 if( p_sys->headpos.i_last > i_pos )
608 p_sys->headpos.i_wrap_count++;
609 p_sys->headpos.i_last = i_pos;
610 return p_sys->headpos.i_last + (p_sys->headpos.i_wrap_count << 32);
614 * Reset AudioTrack position
616 * Called after flush, or start
618 static void
619 AudioTrack_ResetWrapCount( JNIEnv *env, audio_output_t *p_aout )
621 (void) env;
622 aout_sys_t *p_sys = p_aout->sys;
624 p_sys->headpos.i_last = 0;
625 p_sys->headpos.i_wrap_count = 0;
627 p_sys->timestamp.i_frame_post_last = 0;
628 p_sys->timestamp.i_frame_wrap_count = 0;
632 * Reset AudioTrack SmoothPosition and TimestampPosition
634 static void
635 AudioTrack_ResetPositions( JNIEnv *env, audio_output_t *p_aout )
637 aout_sys_t *p_sys = p_aout->sys;
638 VLC_UNUSED( env );
640 p_sys->timestamp.i_last_time = 0;
641 p_sys->timestamp.i_frame_us = 0;
642 p_sys->timestamp.i_frame_pos = 0;
644 p_sys->smoothpos.i_count = 0;
645 p_sys->smoothpos.i_idx = 0;
646 p_sys->smoothpos.i_last_time = 0;
647 p_sys->smoothpos.i_us = 0;
651 * Reset all AudioTrack positions and internal state
653 static void
654 AudioTrack_Reset( JNIEnv *env, audio_output_t *p_aout )
656 aout_sys_t *p_sys = p_aout->sys;
658 AudioTrack_ResetPositions( env, p_aout );
659 AudioTrack_ResetWrapCount( env, p_aout );
660 p_sys->i_samples_written = 0;
663 static vlc_tick_t
664 AudioTrack_GetLatencyUs( JNIEnv *env, audio_output_t *p_aout )
666 aout_sys_t *p_sys = p_aout->sys;
668 if( jfields.AudioTrack.getLatency )
670 int i_latency_ms = JNI_AT_CALL_INT( getLatency );
672 /* getLatency() includes the latency due to AudioTrack buffer size,
673 * AudioMixer (if any) and audio hardware driver. We only need the
674 * audio hardware latency */
675 if( i_latency_ms > 0 )
677 vlc_tick_t i_latency_us = VLC_TICK_FROM_MS( i_latency_ms )
678 - FRAMES_TO_US( p_sys->i_max_audiotrack_samples );
679 return i_latency_us >= 0 ? i_latency_us : 0;
683 return 0;
687 * Get a smooth AudioTrack position
689 * This function smooth out the AudioTrack position since it has a very bad
690 * precision (+/- 20ms on old devices).
692 static vlc_tick_t
693 AudioTrack_GetSmoothPositionUs( JNIEnv *env, audio_output_t *p_aout )
695 aout_sys_t *p_sys = p_aout->sys;
696 uint64_t i_audiotrack_us;
697 vlc_tick_t i_now = vlc_tick_now();
699 /* Fetch an AudioTrack position every SMOOTHPOS_INTERVAL_US (30ms) */
700 if( i_now - p_sys->smoothpos.i_last_time >= SMOOTHPOS_INTERVAL_US )
702 i_audiotrack_us = FRAMES_TO_US( AudioTrack_getPlaybackHeadPosition( env, p_aout ) );
703 if( i_audiotrack_us == 0 )
704 goto bailout;
706 p_sys->smoothpos.i_last_time = i_now;
708 /* Base the position off the current time */
709 p_sys->smoothpos.p_us[p_sys->smoothpos.i_idx] = i_audiotrack_us - i_now;
710 p_sys->smoothpos.i_idx = (p_sys->smoothpos.i_idx + 1)
711 % SMOOTHPOS_SAMPLE_COUNT;
712 if( p_sys->smoothpos.i_count < SMOOTHPOS_SAMPLE_COUNT )
713 p_sys->smoothpos.i_count++;
715 /* Calculate the average position based off the current time */
716 p_sys->smoothpos.i_us = 0;
717 for( uint32_t i = 0; i < p_sys->smoothpos.i_count; ++i )
718 p_sys->smoothpos.i_us += p_sys->smoothpos.p_us[i];
719 p_sys->smoothpos.i_us /= p_sys->smoothpos.i_count;
722 if( p_sys->smoothpos.i_us != 0 )
723 return p_sys->smoothpos.i_us + i_now - AudioTrack_GetLatencyUs( env, p_aout );
725 bailout:
726 return 0;
729 static vlc_tick_t
730 AudioTrack_GetTimestampPositionUs( JNIEnv *env, audio_output_t *p_aout )
732 aout_sys_t *p_sys = p_aout->sys;
733 vlc_tick_t i_now;
735 if( !p_sys->timestamp.p_obj )
736 return 0;
738 i_now = vlc_tick_now();
740 /* Android doc:
741 * getTimestamp: Poll for a timestamp on demand.
743 * If you need to track timestamps during initial warmup or after a
744 * routing or mode change, you should request a new timestamp once per
745 * second until the reported timestamps show that the audio clock is
746 * stable. Thereafter, query for a new timestamp approximately once
747 * every 10 seconds to once per minute. Calling this method more often
748 * is inefficient. It is also counter-productive to call this method
749 * more often than recommended, because the short-term differences
750 * between successive timestamp reports are not meaningful. If you need
751 * a high-resolution mapping between frame position and presentation
752 * time, consider implementing that at application level, based on
753 * low-resolution timestamps.
756 /* Fetch an AudioTrack timestamp every AUDIOTIMESTAMP_INTERVAL_US (500ms) */
757 if( i_now - p_sys->timestamp.i_last_time >= AUDIOTIMESTAMP_INTERVAL_US )
759 if( JNI_AT_CALL_BOOL( getTimestamp, p_sys->timestamp.p_obj ) )
761 p_sys->timestamp.i_frame_us = VLC_TICK_FROM_NS(JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime ));
763 /* the low-order 32 bits of position is in wrapping frame units
764 * similar to AudioTrack#getPlaybackHeadPosition. */
765 jlong i_frame_post_last = JNI_AUDIOTIMESTAMP_GET_LONG( framePosition );
766 if( p_sys->timestamp.i_frame_post_last > i_frame_post_last )
767 p_sys->timestamp.i_frame_wrap_count++;
768 p_sys->timestamp.i_frame_post_last = i_frame_post_last;
769 p_sys->timestamp.i_frame_pos = i_frame_post_last
770 + (p_sys->timestamp.i_frame_wrap_count << 32);
772 /* frame time should be after last play time
773 * frame time shouldn't be in the future
774 * frame time should be less than 10 seconds old */
775 if( p_sys->timestamp.i_frame_us != 0 && p_sys->timestamp.i_frame_pos != 0
776 && i_now > p_sys->timestamp.i_frame_us
777 && ( i_now - p_sys->timestamp.i_frame_us ) <= VLC_TICK_FROM_SEC(10) )
778 p_sys->timestamp.i_last_time = i_now;
779 else
781 p_sys->timestamp.i_last_time = 0;
782 p_sys->timestamp.i_frame_us = 0;
785 else
786 p_sys->timestamp.i_frame_us = 0;
789 if( p_sys->timestamp.i_frame_us != 0 )
791 vlc_tick_t i_time_diff = i_now - p_sys->timestamp.i_frame_us;
792 jlong i_frames_diff = samples_from_vlc_tick(i_time_diff, p_sys->fmt.i_rate);
793 return FRAMES_TO_US( p_sys->timestamp.i_frame_pos + i_frames_diff );
794 } else
795 return 0;
798 static int
799 TimeGet( audio_output_t *p_aout, vlc_tick_t *restrict p_delay )
801 aout_sys_t *p_sys = p_aout->sys;
802 vlc_tick_t i_audiotrack_us;
803 JNIEnv *env;
805 if( p_sys->b_passthrough )
806 return -1;
808 vlc_mutex_lock( &p_sys->lock );
810 if( p_sys->b_error || !p_sys->i_samples_written || !( env = GET_ENV() ) )
811 goto bailout;
813 i_audiotrack_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
815 if( i_audiotrack_us <= 0 )
816 i_audiotrack_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
818 /* Debug log for both delays */
819 #if 0
821 vlc_tick_t i_ts_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
822 vlc_tick_t i_smooth_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
823 vlc_tick_t i_latency_us = AudioTrack_GetLatencyUs( env, p_aout );
825 msg_Err( p_aout, "TimeGet: TimeStamp: %"PRId64", Smooth: %"PRId64" (latency: %"PRId64")",
826 i_ts_us, i_smooth_us, i_latency_us );
828 #endif
830 if( i_audiotrack_us > 0 )
832 /* AudioTrack delay */
833 vlc_tick_t i_delay = FRAMES_TO_US( p_sys->i_samples_written )
834 - i_audiotrack_us;
835 if( i_delay >= 0 )
837 /* Circular buffer delay */
838 i_delay += BYTES_TO_US( p_sys->circular.i_write
839 - p_sys->circular.i_read );
840 *p_delay = i_delay;
841 vlc_mutex_unlock( &p_sys->lock );
842 return 0;
844 else
846 msg_Warn( p_aout, "timing screwed, reset positions" );
847 AudioTrack_ResetPositions( env, p_aout );
851 bailout:
852 vlc_mutex_unlock( &p_sys->lock );
853 return -1;
856 static void
857 AudioTrack_GetChanOrder( uint16_t i_physical_channels, uint32_t p_chans_out[] )
859 #define HAS_CHAN( x ) ( ( i_physical_channels & (x) ) == (x) )
860 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
861 int i = 0;
863 if( HAS_CHAN( AOUT_CHAN_LEFT ) )
864 p_chans_out[i++] = AOUT_CHAN_LEFT;
865 if( HAS_CHAN( AOUT_CHAN_RIGHT ) )
866 p_chans_out[i++] = AOUT_CHAN_RIGHT;
868 if( HAS_CHAN( AOUT_CHAN_CENTER ) )
869 p_chans_out[i++] = AOUT_CHAN_CENTER;
871 if( HAS_CHAN( AOUT_CHAN_LFE ) )
872 p_chans_out[i++] = AOUT_CHAN_LFE;
874 if( HAS_CHAN( AOUT_CHAN_REARLEFT ) )
875 p_chans_out[i++] = AOUT_CHAN_REARLEFT;
876 if( HAS_CHAN( AOUT_CHAN_REARRIGHT ) )
877 p_chans_out[i++] = AOUT_CHAN_REARRIGHT;
879 if( HAS_CHAN( AOUT_CHAN_REARCENTER ) )
880 p_chans_out[i++] = AOUT_CHAN_REARCENTER;
882 if( HAS_CHAN( AOUT_CHAN_MIDDLELEFT ) )
883 p_chans_out[i++] = AOUT_CHAN_MIDDLELEFT;
884 if( HAS_CHAN( AOUT_CHAN_MIDDLERIGHT ) )
885 p_chans_out[i++] = AOUT_CHAN_MIDDLERIGHT;
887 assert( i <= AOUT_CHAN_MAX );
888 #undef HAS_CHAN
891 static jobject
892 AudioTrack_New21( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
893 int i_channel_config, int i_format, int i_size,
894 jint session_id )
896 jobject p_audiotrack = NULL;
897 jobject p_aattr_builder = NULL;
898 jobject p_audio_attributes = NULL;
899 jobject p_afmt_builder = NULL;
900 jobject p_audio_format = NULL;
901 jobject ref;
903 p_aattr_builder =
904 JNI_CALL( NewObject,
905 jfields.AudioAttributes_Builder.clazz,
906 jfields.AudioAttributes_Builder.ctor );
907 if( !p_aattr_builder )
908 return NULL;
910 ref = JNI_CALL_OBJECT( p_aattr_builder,
911 jfields.AudioAttributes_Builder.setLegacyStreamType,
912 jfields.AudioManager.STREAM_MUSIC );
913 (*env)->DeleteLocalRef( env, ref );
915 p_audio_attributes =
916 JNI_CALL_OBJECT( p_aattr_builder,
917 jfields.AudioAttributes_Builder.build );
918 if( !p_audio_attributes )
919 goto del_local_refs;
921 p_afmt_builder = JNI_CALL( NewObject,
922 jfields.AudioFormat_Builder.clazz,
923 jfields.AudioFormat_Builder.ctor );
924 if( !p_afmt_builder )
925 goto del_local_refs;
927 ref = JNI_CALL_OBJECT( p_afmt_builder,
928 jfields.AudioFormat_Builder.setChannelMask,
929 i_channel_config );
930 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setChannelMask" ) )
932 (*env)->DeleteLocalRef( env, ref );
933 goto del_local_refs;
935 (*env)->DeleteLocalRef( env, ref );
937 ref = JNI_CALL_OBJECT( p_afmt_builder,
938 jfields.AudioFormat_Builder.setEncoding,
939 i_format );
940 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setEncoding" ) )
942 (*env)->DeleteLocalRef( env, ref );
943 goto del_local_refs;
945 (*env)->DeleteLocalRef( env, ref );
947 ref = JNI_CALL_OBJECT( p_afmt_builder,
948 jfields.AudioFormat_Builder.setSampleRate,
949 i_rate );
950 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setSampleRate" ) )
952 (*env)->DeleteLocalRef( env, ref );
953 goto del_local_refs;
955 (*env)->DeleteLocalRef( env, ref );
957 p_audio_format = JNI_CALL_OBJECT( p_afmt_builder,
958 jfields.AudioFormat_Builder.build );
959 if(!p_audio_format)
960 goto del_local_refs;
962 p_audiotrack = JNI_AT_NEW( p_audio_attributes, p_audio_format, i_size,
963 jfields.AudioTrack.MODE_STREAM, session_id );
965 del_local_refs:
966 (*env)->DeleteLocalRef( env, p_aattr_builder );
967 (*env)->DeleteLocalRef( env, p_audio_attributes );
968 (*env)->DeleteLocalRef( env, p_afmt_builder );
969 (*env)->DeleteLocalRef( env, p_audio_format );
970 return p_audiotrack;
973 static jobject
974 AudioTrack_NewLegacy( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
975 int i_channel_config, int i_format, int i_size,
976 jint session_id )
978 VLC_UNUSED( p_aout );
979 return JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate,
980 i_channel_config, i_format, i_size,
981 jfields.AudioTrack.MODE_STREAM, session_id );
985 * Create an Android AudioTrack.
986 * returns -1 on error, 0 on success.
988 static int
989 AudioTrack_New( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
990 int i_channel_config, int i_format, int i_size )
992 aout_sys_t *p_sys = p_aout->sys;
993 jint session_id = var_InheritInteger( p_aout, "audiotrack-session-id" );
995 jobject p_audiotrack;
996 if( jfields.AudioTrack.has_ctor_21 )
997 p_audiotrack = AudioTrack_New21( env, p_aout, i_rate, i_channel_config,
998 i_format, i_size, session_id );
999 else
1000 p_audiotrack = AudioTrack_NewLegacy( env, p_aout, i_rate,
1001 i_channel_config, i_format, i_size,
1002 session_id );
1003 if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
1005 msg_Warn( p_aout, "AudioTrack Init failed" );
1006 return -1;
1008 if( JNI_CALL_INT( p_audiotrack, jfields.AudioTrack.getState )
1009 != jfields.AudioTrack.STATE_INITIALIZED )
1011 JNI_CALL_VOID( p_audiotrack, jfields.AudioTrack.release );
1012 (*env)->DeleteLocalRef( env, p_audiotrack );
1013 msg_Err( p_aout, "AudioTrack getState failed" );
1014 return -1;
1017 p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
1018 (*env)->DeleteLocalRef( env, p_audiotrack );
1019 if( !p_sys->p_audiotrack )
1020 return -1;
1022 return 0;
1026 * Destroy and recreate an Android AudioTrack using the same arguments.
1027 * returns -1 on error, 0 on success.
1029 static int
1030 AudioTrack_Recreate( JNIEnv *env, audio_output_t *p_aout )
1032 aout_sys_t *p_sys = p_aout->sys;
1034 JNI_AT_CALL_VOID( release );
1035 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
1036 p_sys->p_audiotrack = NULL;
1037 return AudioTrack_New( env, p_aout, p_sys->audiotrack_args.i_rate,
1038 p_sys->audiotrack_args.i_channel_config,
1039 p_sys->audiotrack_args.i_format,
1040 p_sys->audiotrack_args.i_size );
1044 * Configure and create an Android AudioTrack.
1045 * returns -1 on configuration error, 0 on success.
1047 static int
1048 AudioTrack_Create( JNIEnv *env, audio_output_t *p_aout,
1049 unsigned int i_rate,
1050 int i_format,
1051 uint16_t i_physical_channels )
1053 aout_sys_t *p_sys = p_aout->sys;
1054 int i_size, i_min_buffer_size, i_channel_config;
1056 switch( i_physical_channels )
1058 case AOUT_CHANS_7_1:
1059 /* bitmask of CHANNEL_OUT_7POINT1 doesn't correspond to 5POINT1 and
1060 * SIDES */
1061 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1 |
1062 jfields.AudioFormat.CHANNEL_OUT_SIDE_LEFT |
1063 jfields.AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
1064 break;
1065 case AOUT_CHANS_5_1:
1066 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1;
1067 break;
1068 case AOUT_CHAN_LEFT:
1069 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_MONO;
1070 break;
1071 case AOUT_CHANS_STEREO:
1072 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_STEREO;
1073 break;
1074 default:
1075 vlc_assert_unreachable();
1078 i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize, i_rate,
1079 i_channel_config, i_format );
1080 if( i_min_buffer_size <= 0 )
1082 msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
1083 return -1;
1085 i_size = i_min_buffer_size * 2;
1087 /* Clip the buffer size to a maximum safe size since audiotrack init will
1088 * fail of the requested size is too big. */
1089 const int i_max_size = US_TO_BYTES( AUDIOTRACK_MAX_BUFFER_US );
1090 if( i_size > i_max_size )
1091 i_size = i_max_size;
1093 /* create AudioTrack object */
1094 if( AudioTrack_New( env, p_aout, i_rate, i_channel_config,
1095 i_format , i_size ) != 0 )
1096 return -1;
1098 p_sys->audiotrack_args.i_rate = i_rate;
1099 p_sys->audiotrack_args.i_channel_config = i_channel_config;
1100 p_sys->audiotrack_args.i_format = i_format;
1101 p_sys->audiotrack_args.i_size = i_size;
1103 return 0;
1106 static bool
1107 AudioTrack_HasEncoding( audio_output_t *p_aout, vlc_fourcc_t i_format )
1109 aout_sys_t *p_sys = p_aout->sys;
1111 #define MATCH_ENCODING_FLAG(x) jfields.AudioFormat.has_##x && \
1112 ( p_sys->i_encoding_flags == 0 || p_sys->i_encoding_flags & (1 << jfields.AudioFormat.x) )
1114 switch( i_format )
1116 case VLC_CODEC_DTSHD:
1117 return MATCH_ENCODING_FLAG( ENCODING_DTS_HD );
1118 case VLC_CODEC_DTS:
1119 return MATCH_ENCODING_FLAG( ENCODING_DTS );
1120 case VLC_CODEC_A52:
1121 return MATCH_ENCODING_FLAG( ENCODING_AC3 );
1122 case VLC_CODEC_EAC3:
1123 return MATCH_ENCODING_FLAG( ENCODING_E_AC3 );
1124 case VLC_CODEC_TRUEHD:
1125 case VLC_CODEC_MLP:
1126 return MATCH_ENCODING_FLAG( ENCODING_DOLBY_TRUEHD );
1127 default:
1128 return false;
1132 static int
1133 StartPassthrough( JNIEnv *env, audio_output_t *p_aout )
1135 aout_sys_t *p_sys = p_aout->sys;
1136 int i_at_format;
1138 if( !AudioTrack_HasEncoding( p_aout, p_sys->fmt.i_format ) )
1139 return VLC_EGENERIC;
1141 if( jfields.AudioFormat.has_ENCODING_IEC61937 )
1143 i_at_format = jfields.AudioFormat.ENCODING_IEC61937;
1144 switch( p_sys->fmt.i_format )
1146 case VLC_CODEC_TRUEHD:
1147 case VLC_CODEC_MLP:
1148 p_sys->fmt.i_rate = 192000;
1149 p_sys->fmt.i_bytes_per_frame = 16;
1151 /* AudioFormat.ENCODING_IEC61937 documentation says that the
1152 * channel layout must be stereo. Well, not for TrueHD
1153 * apparently */
1154 p_sys->fmt.i_physical_channels = AOUT_CHANS_7_1;
1155 break;
1156 case VLC_CODEC_DTS:
1157 p_sys->fmt.i_bytes_per_frame = 4;
1158 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1159 break;
1160 case VLC_CODEC_DTSHD:
1161 p_sys->fmt.i_bytes_per_frame = 4;
1162 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1163 p_sys->fmt.i_rate = 192000;
1164 p_sys->fmt.i_bytes_per_frame = 16;
1165 break;
1166 case VLC_CODEC_EAC3:
1167 p_sys->fmt.i_rate = 192000;
1168 case VLC_CODEC_A52:
1169 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1170 p_sys->fmt.i_bytes_per_frame = 4;
1171 break;
1172 default:
1173 return VLC_EGENERIC;
1175 p_sys->fmt.i_frame_length = 1;
1176 p_sys->fmt.i_channels = aout_FormatNbChannels( &p_sys->fmt );
1177 p_sys->fmt.i_format = VLC_CODEC_SPDIFL;
1179 else
1181 switch( p_sys->fmt.i_format )
1183 case VLC_CODEC_A52:
1184 if( !jfields.AudioFormat.has_ENCODING_AC3 )
1185 return VLC_EGENERIC;
1186 i_at_format = jfields.AudioFormat.ENCODING_AC3;
1187 break;
1188 case VLC_CODEC_EAC3:
1189 if( !jfields.AudioFormat.has_ENCODING_E_AC3 )
1190 return VLC_EGENERIC;
1191 i_at_format = jfields.AudioFormat.ENCODING_E_AC3;
1192 break;
1193 case VLC_CODEC_DTS:
1194 if( !jfields.AudioFormat.has_ENCODING_DTS )
1195 return VLC_EGENERIC;
1196 i_at_format = jfields.AudioFormat.ENCODING_DTS;
1197 break;
1198 default:
1199 return VLC_EGENERIC;
1201 p_sys->fmt.i_bytes_per_frame = 4;
1202 p_sys->fmt.i_frame_length = 1;
1203 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1204 p_sys->fmt.i_channels = 2;
1205 p_sys->fmt.i_format = VLC_CODEC_SPDIFB;
1208 int i_ret = AudioTrack_Create( env, p_aout, p_sys->fmt.i_rate, i_at_format,
1209 p_sys->fmt.i_physical_channels );
1210 if( i_ret != VLC_SUCCESS )
1211 msg_Warn( p_aout, "SPDIF configuration failed" );
1212 else
1214 p_sys->b_passthrough = true;
1215 p_sys->i_chans_to_reorder = 0;
1218 return i_ret;
1221 static int
1222 StartPCM( JNIEnv *env, audio_output_t *p_aout, unsigned i_max_channels )
1224 aout_sys_t *p_sys = p_aout->sys;
1225 unsigned i_nb_channels;
1226 int i_at_format, i_ret;
1228 if (jfields.AudioTrack.getNativeOutputSampleRate)
1229 p_sys->fmt.i_rate =
1230 JNI_AT_CALL_STATIC_INT( getNativeOutputSampleRate,
1231 jfields.AudioManager.STREAM_MUSIC );
1232 else
1233 p_sys->fmt.i_rate = VLC_CLIP( p_sys->fmt.i_rate, 4000, 48000 );
1237 /* We can only accept U8, S16N, FL32, and AC3 */
1238 switch( p_sys->fmt.i_format )
1240 case VLC_CODEC_U8:
1241 i_at_format = jfields.AudioFormat.ENCODING_PCM_8BIT;
1242 break;
1243 case VLC_CODEC_S16N:
1244 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1245 break;
1246 case VLC_CODEC_FL32:
1247 if( jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
1248 i_at_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
1249 else
1251 p_sys->fmt.i_format = VLC_CODEC_S16N;
1252 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1254 break;
1255 default:
1256 p_sys->fmt.i_format = VLC_CODEC_S16N;
1257 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1258 break;
1261 /* Android AudioTrack supports only mono, stereo, 5.1 and 7.1.
1262 * Android will downmix to stereo if audio output doesn't handle 5.1 or 7.1
1265 i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
1266 if( i_nb_channels == 0 )
1267 return VLC_EGENERIC;
1268 if( AOUT_FMT_LINEAR( &p_sys->fmt ) )
1269 i_nb_channels = __MIN( i_max_channels, i_nb_channels );
1270 if( i_nb_channels > 5 )
1272 if( i_nb_channels > 7 && jfields.AudioFormat.has_CHANNEL_OUT_SIDE )
1273 p_sys->fmt.i_physical_channels = AOUT_CHANS_7_1;
1274 else
1275 p_sys->fmt.i_physical_channels = AOUT_CHANS_5_1;
1276 } else
1278 if( i_nb_channels == 1 )
1279 p_sys->fmt.i_physical_channels = AOUT_CHAN_LEFT;
1280 else
1281 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1284 /* Try to create an AudioTrack with the most advanced channel and
1285 * format configuration. If AudioTrack_Create fails, try again with a
1286 * less advanced format (PCM S16N). If it fails again, try again with
1287 * Stereo channels. */
1288 i_ret = AudioTrack_Create( env, p_aout, p_sys->fmt.i_rate, i_at_format,
1289 p_sys->fmt.i_physical_channels );
1290 if( i_ret != 0 )
1292 if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
1294 msg_Warn( p_aout, "FL32 configuration failed, "
1295 "fallback to S16N PCM" );
1296 p_sys->fmt.i_format = VLC_CODEC_S16N;
1298 else if( p_sys->fmt.i_physical_channels & AOUT_CHANS_5_1 )
1300 msg_Warn( p_aout, "5.1 or 7.1 configuration failed, "
1301 "fallback to Stereo" );
1302 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1304 else
1305 break;
1307 } while( i_ret != 0 );
1309 if( i_ret != VLC_SUCCESS )
1310 return i_ret;
1312 uint32_t p_chans_out[AOUT_CHAN_MAX];
1313 memset( p_chans_out, 0, sizeof(p_chans_out) );
1314 AudioTrack_GetChanOrder( p_sys->fmt.i_physical_channels, p_chans_out );
1315 p_sys->i_chans_to_reorder =
1316 aout_CheckChannelReorder( NULL, p_chans_out,
1317 p_sys->fmt.i_physical_channels,
1318 p_sys->p_chan_table );
1319 aout_FormatPrepare( &p_sys->fmt );
1320 return VLC_SUCCESS;
1323 static int
1324 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
1326 aout_sys_t *p_sys = p_aout->sys;
1327 JNIEnv *env;
1328 int i_ret;
1329 bool b_try_passthrough;
1330 unsigned i_max_channels;
1332 if( p_sys->at_dev == AT_DEV_ENCODED )
1334 b_try_passthrough = true;
1335 i_max_channels = AT_DEV_MAX_CHANNELS;
1337 else
1339 b_try_passthrough = var_InheritBool( p_aout, "spdif" );
1340 i_max_channels = p_sys->at_dev == AT_DEV_STEREO ? 2 : AT_DEV_MAX_CHANNELS;
1343 if( !( env = GET_ENV() ) )
1344 return VLC_EGENERIC;
1346 p_sys->fmt = *p_fmt;
1348 aout_FormatPrint( p_aout, "VLC is looking for:", &p_sys->fmt );
1350 bool low_latency = false;
1351 if (p_sys->fmt.channel_type == AUDIO_CHANNEL_TYPE_AMBISONICS)
1353 p_sys->fmt.channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
1355 /* TODO: detect sink channel layout */
1356 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1357 aout_FormatPrepare(&p_sys->fmt);
1358 low_latency = true;
1361 if( AOUT_FMT_LINEAR( &p_sys->fmt ) )
1362 i_ret = StartPCM( env, p_aout, i_max_channels );
1363 else if( b_try_passthrough )
1364 i_ret = StartPassthrough( env, p_aout );
1365 else
1366 return VLC_EGENERIC;
1368 if( i_ret != 0 )
1369 return VLC_EGENERIC;
1371 if( jfields.AudioTrack.getBufferSizeInFrames )
1372 p_sys->i_max_audiotrack_samples = JNI_AT_CALL_INT( getBufferSizeInFrames );
1373 else
1374 p_sys->i_max_audiotrack_samples = BYTES_TO_FRAMES( p_sys->audiotrack_args.i_size );
1376 #ifdef AUDIOTRACK_HW_LATENCY
1377 if( jfields.AudioTimestamp.clazz )
1379 /* create AudioTimestamp object */
1380 jobject p_obj = JNI_CALL( NewObject, jfields.AudioTimestamp.clazz,
1381 jfields.AudioTimestamp.ctor );
1382 if( p_obj )
1384 p_sys->timestamp.p_obj = (*env)->NewGlobalRef( env, p_obj );
1385 (*env)->DeleteLocalRef( env, p_obj );
1387 if( !p_sys->timestamp.p_obj )
1388 goto error;
1390 #endif
1392 AudioTrack_Reset( env, p_aout );
1394 if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
1396 msg_Dbg( p_aout, "using WRITE_FLOATARRAY");
1397 p_sys->i_write_type = WRITE_FLOATARRAY;
1399 else if( p_sys->fmt.i_format == VLC_CODEC_SPDIFL )
1401 assert( jfields.AudioFormat.has_ENCODING_IEC61937 );
1402 msg_Dbg( p_aout, "using WRITE_SHORTARRAYV23");
1403 p_sys->i_write_type = WRITE_SHORTARRAYV23;
1405 else if( jfields.AudioTrack.writeV23 )
1407 msg_Dbg( p_aout, "using WRITE_BYTEARRAYV23");
1408 p_sys->i_write_type = WRITE_BYTEARRAYV23;
1410 else if( jfields.AudioTrack.writeBufferV21 )
1412 msg_Dbg( p_aout, "using WRITE_BYTEBUFFER");
1413 p_sys->i_write_type = WRITE_BYTEBUFFER;
1415 else
1417 msg_Dbg( p_aout, "using WRITE_BYTEARRAY");
1418 p_sys->i_write_type = WRITE_BYTEARRAY;
1421 p_sys->circular.i_read = p_sys->circular.i_write = 0;
1422 p_sys->circular.i_size = (int)p_sys->fmt.i_rate
1423 * p_sys->fmt.i_bytes_per_frame
1424 / p_sys->fmt.i_frame_length;
1425 if (low_latency)
1427 /* 40 ms of buffering */
1428 p_sys->circular.i_size = p_sys->circular.i_size / 25;
1430 else
1432 /* 2 seconds of buffering */
1433 p_sys->circular.i_size = samples_from_vlc_tick(AOUT_MAX_PREPARE_TIME, p_sys->circular.i_size);
1436 /* Allocate circular buffer */
1437 switch( p_sys->i_write_type )
1439 case WRITE_BYTEARRAY:
1440 case WRITE_BYTEARRAYV23:
1442 jbyteArray p_bytearray;
1444 p_bytearray = (*env)->NewByteArray( env, p_sys->circular.i_size );
1445 if( p_bytearray )
1447 p_sys->circular.u.p_bytearray = (*env)->NewGlobalRef( env, p_bytearray );
1448 (*env)->DeleteLocalRef( env, p_bytearray );
1451 if( !p_sys->circular.u.p_bytearray )
1453 msg_Err(p_aout, "byte array allocation failed");
1454 goto error;
1456 break;
1458 case WRITE_SHORTARRAYV23:
1460 jshortArray p_shortarray;
1462 p_shortarray = (*env)->NewShortArray( env,
1463 p_sys->circular.i_size / 2 );
1464 if( p_shortarray )
1466 p_sys->circular.u.p_shortarray = (*env)->NewGlobalRef( env, p_shortarray );
1467 (*env)->DeleteLocalRef( env, p_shortarray );
1469 if( !p_sys->circular.u.p_shortarray )
1471 msg_Err(p_aout, "short array allocation failed");
1472 goto error;
1474 break;
1476 case WRITE_FLOATARRAY:
1478 jfloatArray p_floatarray;
1480 p_floatarray = (*env)->NewFloatArray( env,
1481 p_sys->circular.i_size / 4 );
1482 if( p_floatarray )
1484 p_sys->circular.u.p_floatarray = (*env)->NewGlobalRef( env, p_floatarray );
1485 (*env)->DeleteLocalRef( env, p_floatarray );
1487 if( !p_sys->circular.u.p_floatarray )
1489 msg_Err(p_aout, "float array allocation failed");
1490 goto error;
1492 break;
1494 case WRITE_BYTEBUFFER:
1495 p_sys->circular.u.bytebuffer.p_data = malloc( p_sys->circular.i_size );
1496 if( !p_sys->circular.u.bytebuffer.p_data )
1498 msg_Err(p_aout, "bytebuffer allocation failed");
1499 goto error;
1501 break;
1504 /* Run AudioTrack_Thread */
1505 p_sys->b_thread_running = true;
1506 p_sys->b_thread_paused = false;
1507 if ( vlc_clone( &p_sys->thread, AudioTrack_Thread, p_aout,
1508 VLC_THREAD_PRIORITY_LOW ) )
1510 msg_Err(p_aout, "vlc clone failed");
1511 goto error;
1514 JNI_AT_CALL_VOID( play );
1515 CHECK_AT_EXCEPTION( "play" );
1517 *p_fmt = p_sys->fmt;
1519 p_aout->volume_set(p_aout, p_sys->volume);
1520 if (p_sys->mute)
1521 p_aout->mute_set(p_aout, true);
1522 aout_FormatPrint( p_aout, "VLC will output:", &p_sys->fmt );
1524 return VLC_SUCCESS;
1526 error:
1527 Stop( p_aout );
1528 return VLC_EGENERIC;
1531 static void
1532 Stop( audio_output_t *p_aout )
1534 aout_sys_t *p_sys = p_aout->sys;
1535 JNIEnv *env;
1537 if( !( env = GET_ENV() ) )
1538 return;
1540 /* Stop the AudioTrack thread */
1541 vlc_mutex_lock( &p_sys->lock );
1542 if( p_sys->b_thread_running )
1544 p_sys->b_thread_running = false;
1545 vlc_cond_signal( &p_sys->thread_cond );
1546 vlc_mutex_unlock( &p_sys->lock );
1547 vlc_join( p_sys->thread, NULL );
1549 else
1550 vlc_mutex_unlock( &p_sys->lock );
1552 /* Release the AudioTrack object */
1553 if( p_sys->p_audiotrack )
1555 if( !p_sys->b_audiotrack_exception )
1557 JNI_AT_CALL_VOID( stop );
1558 if( !CHECK_AT_EXCEPTION( "stop" ) )
1559 JNI_AT_CALL_VOID( release );
1561 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
1562 p_sys->p_audiotrack = NULL;
1565 /* Release the timestamp object */
1566 if( p_sys->timestamp.p_obj )
1568 (*env)->DeleteGlobalRef( env, p_sys->timestamp.p_obj );
1569 p_sys->timestamp.p_obj = NULL;
1572 /* Release the Circular buffer data */
1573 switch( p_sys->i_write_type )
1575 case WRITE_BYTEARRAY:
1576 case WRITE_BYTEARRAYV23:
1577 if( p_sys->circular.u.p_bytearray )
1579 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_bytearray );
1580 p_sys->circular.u.p_bytearray = NULL;
1582 break;
1583 case WRITE_SHORTARRAYV23:
1584 if( p_sys->circular.u.p_shortarray )
1586 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_shortarray );
1587 p_sys->circular.u.p_shortarray = NULL;
1589 break;
1590 case WRITE_FLOATARRAY:
1591 if( p_sys->circular.u.p_floatarray )
1593 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_floatarray );
1594 p_sys->circular.u.p_floatarray = NULL;
1596 break;
1597 case WRITE_BYTEBUFFER:
1598 free( p_sys->circular.u.bytebuffer.p_data );
1599 p_sys->circular.u.bytebuffer.p_data = NULL;
1600 break;
1603 p_sys->b_audiotrack_exception = false;
1604 p_sys->b_error = false;
1605 p_sys->b_passthrough = false;
1609 * Non blocking write function, run from AudioTrack_Thread.
1610 * Do a calculation between current position and audiotrack position and assure
1611 * that we won't wait in AudioTrack.write() method.
1613 static int
1614 AudioTrack_WriteByteArray( JNIEnv *env, audio_output_t *p_aout,
1615 size_t i_data_size, size_t i_data_offset,
1616 bool b_force )
1618 aout_sys_t *p_sys = p_aout->sys;
1619 uint64_t i_samples;
1620 uint64_t i_audiotrack_pos;
1621 uint64_t i_samples_pending;
1623 i_audiotrack_pos = AudioTrack_getPlaybackHeadPosition( env, p_aout );
1625 assert( i_audiotrack_pos <= p_sys->i_samples_written );
1626 if( i_audiotrack_pos > p_sys->i_samples_written )
1628 msg_Err( p_aout, "audiotrack position is ahead. Should NOT happen" );
1629 p_sys->i_samples_written = 0;
1630 p_sys->b_error = true;
1631 return 0;
1633 i_samples_pending = p_sys->i_samples_written - i_audiotrack_pos;
1635 /* check if audiotrack buffer is not full before writing on it. */
1636 if( b_force )
1638 msg_Warn( p_aout, "Force write. It may block..." );
1639 i_samples_pending = 0;
1640 } else if( i_samples_pending >= p_sys->i_max_audiotrack_samples )
1641 return 0;
1643 i_samples = __MIN( p_sys->i_max_audiotrack_samples - i_samples_pending,
1644 BYTES_TO_FRAMES( i_data_size ) );
1646 i_data_size = FRAMES_TO_BYTES( i_samples );
1648 return JNI_AT_CALL_INT( write, p_sys->circular.u.p_bytearray,
1649 i_data_offset, i_data_size );
1653 * Non blocking write function for Android M and after, run from
1654 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1655 * flags.
1657 static int
1658 AudioTrack_WriteByteArrayV23( JNIEnv *env, audio_output_t *p_aout,
1659 size_t i_data_size, size_t i_data_offset )
1661 aout_sys_t *p_sys = p_aout->sys;
1663 return JNI_AT_CALL_INT( writeV23, p_sys->circular.u.p_bytearray,
1664 i_data_offset, i_data_size,
1665 jfields.AudioTrack.WRITE_NON_BLOCKING );
1669 * Non blocking play function for Lollipop and after, run from
1670 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1671 * flags.
1673 static int
1674 AudioTrack_WriteByteBuffer( JNIEnv *env, audio_output_t *p_aout,
1675 size_t i_data_size, size_t i_data_offset )
1677 aout_sys_t *p_sys = p_aout->sys;
1679 /* The same DirectByteBuffer will be used until the data_offset reaches 0.
1680 * The internal position of this buffer is moved by the writeBufferV21
1681 * wall. */
1682 if( i_data_offset == 0 )
1684 /* No need to get a global ref, this object will be only used from the
1685 * same Thread */
1686 if( p_sys->circular.u.bytebuffer.p_obj )
1687 (*env)->DeleteLocalRef( env, p_sys->circular.u.bytebuffer.p_obj );
1689 p_sys->circular.u.bytebuffer.p_obj = (*env)->NewDirectByteBuffer( env,
1690 p_sys->circular.u.bytebuffer.p_data,
1691 p_sys->circular.i_size );
1692 if( !p_sys->circular.u.bytebuffer.p_obj )
1694 if( (*env)->ExceptionCheck( env ) )
1695 (*env)->ExceptionClear( env );
1696 return jfields.AudioTrack.ERROR;
1700 return JNI_AT_CALL_INT( writeBufferV21, p_sys->circular.u.bytebuffer.p_obj,
1701 i_data_size,
1702 jfields.AudioTrack.WRITE_NON_BLOCKING );
1706 * Non blocking short write function for Android M and after, run from
1707 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1708 * flags.
1710 static int
1711 AudioTrack_WriteShortArrayV23( JNIEnv *env, audio_output_t *p_aout,
1712 size_t i_data_size, size_t i_data_offset )
1714 aout_sys_t *p_sys = p_aout->sys;
1715 int i_ret;
1717 i_ret = JNI_AT_CALL_INT( writeShortV23, p_sys->circular.u.p_shortarray,
1718 i_data_offset / 2, i_data_size / 2,
1719 jfields.AudioTrack.WRITE_NON_BLOCKING );
1720 if( i_ret < 0 )
1721 return i_ret;
1722 else
1723 return i_ret * 2;
1727 * Non blocking play float function for Lollipop and after, run from
1728 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1729 * flags.
1731 static int
1732 AudioTrack_WriteFloatArray( JNIEnv *env, audio_output_t *p_aout,
1733 size_t i_data_size, size_t i_data_offset )
1735 aout_sys_t *p_sys = p_aout->sys;
1736 int i_ret;
1738 i_ret = JNI_AT_CALL_INT( writeFloat, p_sys->circular.u.p_floatarray,
1739 i_data_offset / 4, i_data_size / 4,
1740 jfields.AudioTrack.WRITE_NON_BLOCKING );
1741 if( i_ret < 0 )
1742 return i_ret;
1743 else
1744 return i_ret * 4;
1747 static int
1748 AudioTrack_Write( JNIEnv *env, audio_output_t *p_aout, size_t i_data_size,
1749 size_t i_data_offset, bool b_force )
1751 aout_sys_t *p_sys = p_aout->sys;
1752 int i_ret;
1754 switch( p_sys->i_write_type )
1756 case WRITE_BYTEARRAYV23:
1757 i_ret = AudioTrack_WriteByteArrayV23( env, p_aout, i_data_size,
1758 i_data_offset );
1759 break;
1760 case WRITE_BYTEBUFFER:
1761 i_ret = AudioTrack_WriteByteBuffer( env, p_aout, i_data_size,
1762 i_data_offset );
1763 break;
1764 case WRITE_SHORTARRAYV23:
1765 i_ret = AudioTrack_WriteShortArrayV23( env, p_aout, i_data_size,
1766 i_data_offset );
1767 break;
1768 case WRITE_BYTEARRAY:
1769 i_ret = AudioTrack_WriteByteArray( env, p_aout, i_data_size,
1770 i_data_offset, b_force );
1771 break;
1772 case WRITE_FLOATARRAY:
1773 i_ret = AudioTrack_WriteFloatArray( env, p_aout, i_data_size,
1774 i_data_offset );
1775 break;
1776 default:
1777 vlc_assert_unreachable();
1780 if( i_ret < 0 ) {
1781 if( jfields.AudioManager.has_ERROR_DEAD_OBJECT
1782 && i_ret == jfields.AudioManager.ERROR_DEAD_OBJECT )
1784 msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
1785 "try recreating AudioTrack" );
1786 if( ( i_ret = AudioTrack_Recreate( env, p_aout ) ) == 0 )
1788 AudioTrack_Reset( env, p_aout );
1789 JNI_AT_CALL_VOID( play );
1790 CHECK_AT_EXCEPTION( "play" );
1792 } else
1794 const char *str;
1795 if( i_ret == jfields.AudioTrack.ERROR_INVALID_OPERATION )
1796 str = "ERROR_INVALID_OPERATION";
1797 else if( i_ret == jfields.AudioTrack.ERROR_BAD_VALUE )
1798 str = "ERROR_BAD_VALUE";
1799 else
1800 str = "ERROR";
1801 msg_Err( p_aout, "Write failed: %s", str );
1802 p_sys->b_error = true;
1804 } else
1805 p_sys->i_samples_written += BYTES_TO_FRAMES( i_ret );
1806 return i_ret;
1810 * This thread will play the data coming from the circular buffer.
1812 static void *
1813 AudioTrack_Thread( void *p_data )
1815 audio_output_t *p_aout = p_data;
1816 aout_sys_t *p_sys = p_aout->sys;
1817 JNIEnv *env = GET_ENV();
1818 vlc_tick_t i_last_time_blocked = 0;
1820 if( !env )
1821 return NULL;
1823 for( ;; )
1825 int i_ret = 0;
1826 bool b_forced;
1827 size_t i_data_offset;
1828 size_t i_data_size;
1830 vlc_mutex_lock( &p_sys->lock );
1832 /* Wait for not paused state */
1833 while( p_sys->b_thread_running && p_sys->b_thread_paused )
1835 i_last_time_blocked = 0;
1836 vlc_cond_wait( &p_sys->thread_cond, &p_sys->lock );
1839 /* Wait for more data in the circular buffer */
1840 while( p_sys->b_thread_running
1841 && p_sys->circular.i_read >= p_sys->circular.i_write )
1842 vlc_cond_wait( &p_sys->thread_cond, &p_sys->lock );
1844 if( !p_sys->b_thread_running || p_sys->b_error )
1846 vlc_mutex_unlock( &p_sys->lock );
1847 break;
1850 /* HACK: AudioFlinger can drop frames without notifying us and there is
1851 * no way to know it. If it happens, i_audiotrack_pos won't move and
1852 * the current code will be stuck because it'll assume that audiotrack
1853 * internal buffer is full when it's not. It may happen only after
1854 * Android 4.4.2 if we send frames too quickly. To fix this issue,
1855 * force the writing of the buffer after a certain delay. */
1856 if( i_last_time_blocked != 0 )
1857 b_forced = vlc_tick_now() - i_last_time_blocked >
1858 FRAMES_TO_US( p_sys->i_max_audiotrack_samples ) * 2;
1859 else
1860 b_forced = false;
1862 i_data_offset = p_sys->circular.i_read % p_sys->circular.i_size;
1863 i_data_size = __MIN( p_sys->circular.i_size - i_data_offset,
1864 p_sys->circular.i_write - p_sys->circular.i_read );
1866 i_ret = AudioTrack_Write( env, p_aout, i_data_size, i_data_offset,
1867 b_forced );
1868 if( i_ret >= 0 )
1870 if( i_ret == 0 )
1872 vlc_tick_t i_now = vlc_tick_now();
1874 /* cf. b_forced HACK comment */
1875 if( p_sys->i_write_type == WRITE_BYTEARRAY && i_last_time_blocked == 0 )
1876 i_last_time_blocked = i_now;
1878 /* Wait for free space in Audiotrack internal buffer */
1879 vlc_tick_t i_play_deadline = i_now + __MAX( 10000,
1880 FRAMES_TO_US( p_sys->i_max_audiotrack_samples / 5 ) );
1882 while( p_sys->b_thread_running && i_ret == 0 )
1883 i_ret = vlc_cond_timedwait( &p_sys->thread_cond, &p_sys->lock,
1884 i_play_deadline );
1887 else
1889 i_last_time_blocked = 0;
1890 p_sys->circular.i_read += i_ret;
1891 vlc_cond_signal( &p_sys->aout_cond );
1895 vlc_mutex_unlock( &p_sys->lock );
1898 if( p_sys->circular.u.bytebuffer.p_obj )
1900 (*env)->DeleteLocalRef( env, p_sys->circular.u.bytebuffer.p_obj );
1901 p_sys->circular.u.bytebuffer.p_obj = NULL;
1904 return NULL;
1907 static int
1908 ConvertFromIEC61937( audio_output_t *p_aout, block_t *p_buffer )
1910 /* This function is only used for Android API 23 when AudioTrack is
1911 * configured with ENCODING_ AC3/E_AC3/DTS. In that case, only the codec
1912 * data is needed (without the IEC61937 encapsulation). This function
1913 * recovers the codec data from an EC61937 frame. It is the opposite of the
1914 * code found in converter/tospdif.c. We could also request VLC core to
1915 * send us the codec data directly, but in that case, we wouldn't benefit
1916 * from the eac3 block merger of tospdif.c. */
1918 VLC_UNUSED( p_aout );
1919 uint8_t i_length_mul;
1921 if( p_buffer->i_buffer < 6 )
1922 return -1;
1924 switch( GetWBE( &p_buffer->p_buffer[4] ) & 0xFF )
1926 case 0x01: /* IEC61937_AC3 */
1927 i_length_mul = 8;
1928 break;
1929 case 0x15: /* IEC61937_EAC3 */
1930 i_length_mul = 1;
1931 break;
1932 case 0x0B: /* IEC61937_DTS1 */
1933 case 0x0C: /* IEC61937_DTS2 */
1934 case 0x0D: /* IEC61937_DTS3 */
1935 i_length_mul = 8;
1936 break;
1937 case 0x11: /* IEC61937_DTSHD */
1938 i_length_mul = 1;
1939 break;
1940 default:
1941 vlc_assert_unreachable();
1943 uint16_t i_length = GetWBE( &p_buffer->p_buffer[6] );
1944 if( i_length == 0 )
1945 return -1;
1947 i_length /= i_length_mul;
1948 if( i_length > p_buffer->i_buffer - 8 )
1949 return -1;
1951 p_buffer->p_buffer += 8; /* SPDIF_HEADER_SIZE */
1952 p_buffer->i_buffer = i_length;
1954 return 0;
1957 static void
1958 Play( audio_output_t *p_aout, block_t *p_buffer, vlc_tick_t i_date )
1960 JNIEnv *env = NULL;
1961 size_t i_buffer_offset = 0;
1962 aout_sys_t *p_sys = p_aout->sys;
1964 if( p_sys->b_passthrough && p_sys->fmt.i_format == VLC_CODEC_SPDIFB
1965 && ConvertFromIEC61937( p_aout, p_buffer ) != 0 )
1967 block_Release(p_buffer);
1968 return;
1971 vlc_mutex_lock( &p_sys->lock );
1973 if( p_sys->b_error || !( env = GET_ENV() ) )
1974 goto bailout;
1976 if( p_sys->i_chans_to_reorder )
1977 aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
1978 p_sys->i_chans_to_reorder, p_sys->p_chan_table,
1979 p_sys->fmt.i_format );
1981 while( i_buffer_offset < p_buffer->i_buffer && !p_sys->b_error )
1983 size_t i_circular_free;
1984 size_t i_data_offset;
1985 size_t i_data_size;
1987 /* Wait for enough room in circular buffer */
1988 while( !p_sys->b_error && ( i_circular_free = p_sys->circular.i_size -
1989 ( p_sys->circular.i_write - p_sys->circular.i_read ) ) == 0 )
1990 vlc_cond_wait( &p_sys->aout_cond, &p_sys->lock );
1991 if( p_sys->b_error )
1992 goto bailout;
1994 i_data_offset = p_sys->circular.i_write % p_sys->circular.i_size;
1995 i_data_size = __MIN( p_buffer->i_buffer - i_buffer_offset,
1996 p_sys->circular.i_size - i_data_offset );
1997 i_data_size = __MIN( i_data_size, i_circular_free );
1999 switch( p_sys->i_write_type )
2001 case WRITE_BYTEARRAY:
2002 case WRITE_BYTEARRAYV23:
2003 (*env)->SetByteArrayRegion( env, p_sys->circular.u.p_bytearray,
2004 i_data_offset, i_data_size,
2005 (jbyte *)p_buffer->p_buffer
2006 + i_buffer_offset);
2007 break;
2008 case WRITE_SHORTARRAYV23:
2009 i_data_offset &= ~1;
2010 i_data_size &= ~1;
2011 (*env)->SetShortArrayRegion( env, p_sys->circular.u.p_shortarray,
2012 i_data_offset / 2, i_data_size / 2,
2013 (jshort *)p_buffer->p_buffer
2014 + i_buffer_offset / 2);
2015 break;
2016 case WRITE_FLOATARRAY:
2017 i_data_offset &= ~3;
2018 i_data_size &= ~3;
2019 (*env)->SetFloatArrayRegion( env, p_sys->circular.u.p_floatarray,
2020 i_data_offset / 4, i_data_size / 4,
2021 (jfloat *)p_buffer->p_buffer
2022 + i_buffer_offset / 4);
2024 break;
2025 case WRITE_BYTEBUFFER:
2026 memcpy( p_sys->circular.u.bytebuffer.p_data + i_data_offset,
2027 p_buffer->p_buffer + i_buffer_offset, i_data_size );
2028 break;
2031 i_buffer_offset += i_data_size;
2032 p_sys->circular.i_write += i_data_size;
2034 vlc_cond_signal( &p_sys->thread_cond );
2037 bailout:
2038 vlc_mutex_unlock( &p_sys->lock );
2039 block_Release( p_buffer );
2040 (void) i_date;
2043 static void
2044 Pause( audio_output_t *p_aout, bool b_pause, vlc_tick_t i_date )
2046 aout_sys_t *p_sys = p_aout->sys;
2047 JNIEnv *env;
2048 VLC_UNUSED( i_date );
2050 vlc_mutex_lock( &p_sys->lock );
2052 if( p_sys->b_error || !( env = GET_ENV() ) )
2053 goto bailout;
2055 if( b_pause )
2057 p_sys->b_thread_paused = true;
2058 JNI_AT_CALL_VOID( pause );
2059 CHECK_AT_EXCEPTION( "pause" );
2060 } else
2062 p_sys->b_thread_paused = false;
2063 AudioTrack_ResetPositions( env, p_aout );
2064 JNI_AT_CALL_VOID( play );
2065 CHECK_AT_EXCEPTION( "play" );
2068 bailout:
2069 vlc_mutex_unlock( &p_sys->lock );
2072 static void
2073 Flush( audio_output_t *p_aout )
2075 aout_sys_t *p_sys = p_aout->sys;
2076 JNIEnv *env;
2078 vlc_mutex_lock( &p_sys->lock );
2080 if( p_sys->b_error || !( env = GET_ENV() ) )
2081 goto bailout;
2083 /* Android doc:
2084 * stop(): Stops playing the audio data. When used on an instance created
2085 * in MODE_STREAM mode, audio will stop playing after the last buffer that
2086 * was written has been played. For an immediate stop, use pause(),
2087 * followed by flush() to discard audio data that hasn't been played back
2088 * yet.
2090 * flush(): Flushes the audio data currently queued for playback. Any data
2091 * that has not been played back will be discarded. No-op if not stopped
2092 * or paused, or if the track's creation mode is not MODE_STREAM.
2094 JNI_AT_CALL_VOID( pause );
2095 if( CHECK_AT_EXCEPTION( "pause" ) )
2096 goto bailout;
2097 JNI_AT_CALL_VOID( flush );
2098 p_sys->circular.i_read = p_sys->circular.i_write = 0;
2100 /* HACK: Before Android 4.4, the head position is not reset to zero and is
2101 * still moving after a flush or a stop. This prevents to get a precise
2102 * head position and there is no way to know when it stabilizes. Therefore
2103 * recreate an AudioTrack object in that case. The AudioTimestamp class was
2104 * added in API Level 19, so if this class is not found, the Android
2105 * Version is 4.3 or before */
2106 if( !jfields.AudioTimestamp.clazz && p_sys->i_samples_written > 0 )
2108 if( AudioTrack_Recreate( env, p_aout ) != 0 )
2110 p_sys->b_error = true;
2111 goto bailout;
2114 AudioTrack_Reset( env, p_aout );
2115 JNI_AT_CALL_VOID( play );
2116 CHECK_AT_EXCEPTION( "play" );
2118 bailout:
2119 vlc_mutex_unlock( &p_sys->lock );
2122 static int
2123 VolumeSet( audio_output_t *p_aout, float volume )
2125 aout_sys_t *p_sys = p_aout->sys;
2126 JNIEnv *env;
2127 float gain = 1.0f;
2129 if (volume > 1.f)
2131 p_sys->volume = 1.f;
2132 gain = volume;
2134 else
2135 p_sys->volume = volume;
2137 if( !p_sys->b_error && p_sys->p_audiotrack != NULL && ( env = GET_ENV() ) )
2139 if( jfields.AudioTrack.setVolume )
2141 JNI_AT_CALL_INT( setVolume, volume );
2142 CHECK_AT_EXCEPTION( "setVolume" );
2143 } else
2145 JNI_AT_CALL_INT( setStereoVolume, volume, volume );
2146 CHECK_AT_EXCEPTION( "setStereoVolume" );
2149 aout_VolumeReport(p_aout, volume);
2150 aout_GainRequest(p_aout, gain * gain * gain);
2151 return 0;
2154 static int
2155 MuteSet( audio_output_t *p_aout, bool mute )
2157 aout_sys_t *p_sys = p_aout->sys;
2158 JNIEnv *env;
2159 p_sys->mute = mute;
2161 if( !p_sys->b_error && p_sys->p_audiotrack != NULL && ( env = GET_ENV() ) )
2163 if( jfields.AudioTrack.setVolume )
2165 JNI_AT_CALL_INT( setVolume, mute ? 0.0f : p_sys->volume );
2166 CHECK_AT_EXCEPTION( "setVolume" );
2167 } else
2169 JNI_AT_CALL_INT( setStereoVolume, mute ? 0.0f : p_sys->volume, mute ? 0.0f : p_sys->volume );
2170 CHECK_AT_EXCEPTION( "setStereoVolume" );
2173 aout_MuteReport(p_aout, mute);
2174 return 0;
2177 static int DeviceSelect(audio_output_t *p_aout, const char *p_id)
2179 aout_sys_t *p_sys = p_aout->sys;
2180 enum at_dev at_dev = AT_DEV_DEFAULT;
2182 if( p_id )
2184 for( unsigned int i = 0; at_devs[i].id; ++i )
2186 if( strncmp( p_id, at_devs[i].id, strlen( at_devs[i].id ) ) == 0 )
2188 at_dev = at_devs[i].at_dev;
2189 break;
2194 long long i_encoding_flags = 0;
2195 if( at_dev == AT_DEV_ENCODED )
2197 const size_t i_prefix_size = strlen( "encoded:" );
2198 if( strncmp( p_id, "encoded:", i_prefix_size ) == 0 )
2199 i_encoding_flags = atoll( p_id + i_prefix_size );
2202 if( at_dev != p_sys->at_dev || i_encoding_flags != p_sys->i_encoding_flags )
2204 p_sys->at_dev = at_dev;
2205 p_sys->i_encoding_flags = i_encoding_flags;
2206 aout_RestartRequest( p_aout, AOUT_RESTART_OUTPUT );
2207 msg_Dbg( p_aout, "selected device: %s", p_id );
2209 if( at_dev == AT_DEV_ENCODED )
2211 static const vlc_fourcc_t enc_fourccs[] = {
2212 VLC_CODEC_DTS, VLC_CODEC_DTSHD, VLC_CODEC_A52, VLC_CODEC_EAC3,
2213 VLC_CODEC_TRUEHD,
2215 for( size_t i = 0;
2216 i < sizeof( enc_fourccs ) / sizeof( enc_fourccs[0] ); ++i )
2218 if( AudioTrack_HasEncoding( p_aout, enc_fourccs[i] ) )
2219 msg_Dbg( p_aout, "device has %4.4s passthrough support",
2220 (const char *)&enc_fourccs[i] );
2224 aout_DeviceReport( p_aout, p_id );
2225 return VLC_SUCCESS;
2228 static int
2229 Open( vlc_object_t *obj )
2231 audio_output_t *p_aout = (audio_output_t *) obj;
2232 aout_sys_t *p_sys;
2233 JNIEnv *env = GET_ENV();
2235 if( !env || !InitJNIFields( p_aout, env ) )
2236 return VLC_EGENERIC;
2238 p_sys = calloc( 1, sizeof (aout_sys_t) );
2240 if( unlikely( p_sys == NULL ) )
2241 return VLC_ENOMEM;
2243 p_sys->at_dev = AT_DEV_DEFAULT;
2244 vlc_mutex_init(&p_sys->lock);
2245 vlc_cond_init(&p_sys->aout_cond);
2246 vlc_cond_init(&p_sys->thread_cond);
2248 p_aout->sys = p_sys;
2249 p_aout->start = Start;
2250 p_aout->stop = Stop;
2251 p_aout->play = Play;
2252 p_aout->pause = Pause;
2253 p_aout->flush = Flush;
2254 p_aout->time_get = TimeGet;
2255 p_aout->device_select = DeviceSelect;
2257 for( unsigned int i = 0; at_devs[i].id; ++i )
2258 aout_HotplugReport(p_aout, at_devs[i].id, at_devs[i].name);
2260 p_aout->volume_set = VolumeSet;
2261 p_aout->mute_set = MuteSet;
2262 p_sys->volume = 1.0f;
2263 p_sys->mute = false;
2265 return VLC_SUCCESS;
2268 static void
2269 Close( vlc_object_t *obj )
2271 audio_output_t *p_aout = (audio_output_t *) obj;
2272 aout_sys_t *p_sys = p_aout->sys;
2274 free( p_sys );