audiotrack: use an up to date buffer size
[vlc.git] / modules / audio_output / audiotrack.c
blob0c09f35d4e65cc67e0611c4091d706fec2159f61
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 static int Open( vlc_object_t * );
44 static void Close( vlc_object_t * );
45 static void Stop( audio_output_t * );
46 static int Start( audio_output_t *, audio_sample_format_t * );
47 static void *AudioTrack_Thread( void * );
49 /* There is an undefined behavior when configuring AudioTrack with SPDIF or
50 * more than 2 channels when there is no HDMI out. It may succeed and the
51 * Android ressampler will be used to downmix to stereo. It may fails cleanly,
52 * and this module will be able to recover and fallback to stereo. Finally, in
53 * some rare cases, it may crash during init or while ressampling. Because of
54 * the last case we don't try up to 8 channels and we use AT_DEV_STEREO device
55 * per default */
56 enum at_dev {
57 AT_DEV_STEREO = 0,
58 AT_DEV_PCM,
59 AT_DEV_ENCODED,
61 #define AT_DEV_DEFAULT AT_DEV_STEREO
62 #define AT_DEV_MAX_CHANNELS 8
64 static const struct {
65 const char *id;
66 const char *name;
67 enum at_dev at_dev;
68 } at_devs[] = {
69 { "stereo", "Up to 2 channels (compat mode).", AT_DEV_STEREO },
70 { "pcm", "Up to 8 channels.", AT_DEV_PCM },
72 /* With "encoded", the module will try to play every audio codecs via
73 * passthrough.
75 * With "encoded:ENCODING_FLAGS_MASK", the module will try to play only
76 * codecs specified by ENCODING_FLAGS_MASK. This extra value is a long long
77 * that contains binary-shifted AudioFormat.ENCODING_* values. */
78 { "encoded", "Up to 8 channels, passthrough if available.", AT_DEV_ENCODED },
79 { NULL, NULL, AT_DEV_DEFAULT },
82 typedef struct
84 enum at_dev at_dev;
86 jobject p_audiotrack; /* AudioTrack ref */
87 float volume;
88 bool mute;
90 audio_sample_format_t fmt; /* fmt setup by Start */
92 struct {
93 unsigned int i_rate;
94 int i_channel_config;
95 int i_format;
96 int i_size;
97 } audiotrack_args;
99 /* Used by AudioTrack_getPlaybackHeadPosition */
100 struct {
101 uint32_t i_wrap_count;
102 uint32_t i_last;
103 } headpos;
105 /* Used by AudioTrack_GetTimestampPositionUs */
106 struct {
107 jobject p_obj; /* AudioTimestamp ref */
108 vlc_tick_t i_frame_us;
109 jlong i_frame_pos;
110 vlc_tick_t i_play_time; /* time when play was called */
111 vlc_tick_t i_last_time;
112 } timestamp;
114 /* Used by AudioTrack_GetSmoothPositionUs */
115 struct {
116 uint32_t i_idx;
117 uint32_t i_count;
118 vlc_tick_t p_us[SMOOTHPOS_SAMPLE_COUNT];
119 vlc_tick_t i_us;
120 vlc_tick_t i_last_time;
121 } smoothpos;
123 uint32_t i_max_audiotrack_samples;
124 long long i_encoding_flags;
125 bool b_passthrough;
126 uint8_t i_chans_to_reorder; /* do we need channel reordering */
127 uint8_t p_chan_table[AOUT_CHAN_MAX];
129 enum {
130 WRITE_BYTEARRAY,
131 WRITE_BYTEARRAYV23,
132 WRITE_SHORTARRAYV23,
133 WRITE_BYTEBUFFER,
134 WRITE_FLOATARRAY
135 } i_write_type;
137 vlc_thread_t thread; /* AudioTrack_Thread */
138 vlc_mutex_t lock;
139 vlc_cond_t aout_cond; /* cond owned by aout */
140 vlc_cond_t thread_cond; /* cond owned by AudioTrack_Thread */
142 /* These variables need locking on read and write */
143 bool b_thread_running; /* Set to false by aout to stop the thread */
144 bool b_thread_paused; /* If true, the thread won't process any data, see
145 * Pause() */
146 bool b_thread_waiting; /* If true, the thread is waiting for enough spaces
147 * in AudioTrack internal buffers */
149 uint64_t i_samples_written; /* Number of samples written since last flush */
150 bool b_audiotrack_exception; /* True if audiotrack threw an exception */
151 bool b_error; /* generic error */
153 struct {
154 uint64_t i_read; /* Number of bytes read */
155 uint64_t i_write; /* Number of bytes written */
156 size_t i_size; /* Size of the circular buffer in bytes */
157 union {
158 jbyteArray p_bytearray;
159 jfloatArray p_floatarray;
160 jshortArray p_shortarray;
161 struct {
162 uint8_t *p_data;
163 jobject p_obj;
164 } bytebuffer;
165 } u;
166 } circular;
167 } aout_sys_t;
170 // Don't use Float for now since 5.1/7.1 Float is down sampled to Stereo Float
171 //#define AUDIOTRACK_USE_FLOAT
172 //#define AUDIOTRACK_HW_LATENCY
174 /* Get AudioTrack native sample rate: if activated, most of the resampling
175 * will be done by VLC */
176 #define AUDIOTRACK_NATIVE_SAMPLERATE
178 #define AUDIOTRACK_SESSION_ID_TEXT " Id of audio session the AudioTrack must be attached to"
180 vlc_module_begin ()
181 set_shortname( "AudioTrack" )
182 set_description( "Android AudioTrack audio output" )
183 set_capability( "audio output", 180 )
184 set_category( CAT_AUDIO )
185 set_subcategory( SUBCAT_AUDIO_AOUT )
186 add_integer( "audiotrack-session-id", 0,
187 AUDIOTRACK_SESSION_ID_TEXT, NULL, true )
188 change_private()
189 add_shortcut( "audiotrack" )
190 set_callbacks( Open, Close )
191 vlc_module_end ()
193 #define THREAD_NAME "android_audiotrack"
194 #define GET_ENV() android_getEnv( VLC_OBJECT(p_aout), THREAD_NAME )
196 static struct
198 struct {
199 jclass clazz;
200 jmethodID ctor;
201 bool has_ctor_21;
202 jmethodID release;
203 jmethodID getState;
204 jmethodID play;
205 jmethodID stop;
206 jmethodID flush;
207 jmethodID pause;
208 jmethodID write;
209 jmethodID writeV23;
210 jmethodID writeShortV23;
211 jmethodID writeBufferV21;
212 jmethodID writeFloat;
213 jmethodID getBufferSizeInFrames;
214 jmethodID getLatency;
215 jmethodID getPlaybackHeadPosition;
216 jmethodID getTimestamp;
217 jmethodID getMinBufferSize;
218 jmethodID getNativeOutputSampleRate;
219 jmethodID setVolume;
220 jmethodID setStereoVolume;
221 jint STATE_INITIALIZED;
222 jint MODE_STREAM;
223 jint ERROR;
224 jint ERROR_BAD_VALUE;
225 jint ERROR_INVALID_OPERATION;
226 jint WRITE_NON_BLOCKING;
227 } AudioTrack;
228 struct {
229 jclass clazz;
230 jmethodID ctor;
231 jmethodID build;
232 jmethodID setLegacyStreamType;
233 } AudioAttributes_Builder;
234 struct {
235 jint ENCODING_PCM_8BIT;
236 jint ENCODING_PCM_16BIT;
237 jint ENCODING_PCM_FLOAT;
238 bool has_ENCODING_PCM_FLOAT;
239 jint ENCODING_AC3;
240 bool has_ENCODING_AC3;
241 jint ENCODING_E_AC3;
242 bool has_ENCODING_E_AC3;
243 jint ENCODING_DOLBY_TRUEHD;
244 bool has_ENCODING_DOLBY_TRUEHD;
245 jint ENCODING_DTS;
246 bool has_ENCODING_DTS;
247 jint ENCODING_DTS_HD;
248 bool has_ENCODING_DTS_HD;
249 jint ENCODING_IEC61937;
250 bool has_ENCODING_IEC61937;
251 jint CHANNEL_OUT_MONO;
252 jint CHANNEL_OUT_STEREO;
253 jint CHANNEL_OUT_FRONT_LEFT;
254 jint CHANNEL_OUT_FRONT_RIGHT;
255 jint CHANNEL_OUT_BACK_LEFT;
256 jint CHANNEL_OUT_BACK_RIGHT;
257 jint CHANNEL_OUT_FRONT_CENTER;
258 jint CHANNEL_OUT_LOW_FREQUENCY;
259 jint CHANNEL_OUT_BACK_CENTER;
260 jint CHANNEL_OUT_5POINT1;
261 jint CHANNEL_OUT_SIDE_LEFT;
262 jint CHANNEL_OUT_SIDE_RIGHT;
263 bool has_CHANNEL_OUT_SIDE;
264 } AudioFormat;
265 struct {
266 jclass clazz;
267 jmethodID ctor;
268 jmethodID build;
269 jmethodID setChannelMask;
270 jmethodID setEncoding;
271 jmethodID setSampleRate;
272 } AudioFormat_Builder;
273 struct {
274 jint ERROR_DEAD_OBJECT;
275 bool has_ERROR_DEAD_OBJECT;
276 jint STREAM_MUSIC;
277 } AudioManager;
278 struct {
279 jclass clazz;
280 jmethodID ctor;
281 jfieldID framePosition;
282 jfieldID nanoTime;
283 } AudioTimestamp;
284 } jfields;
286 /* init all jni fields.
287 * Done only one time during the first initialisation */
288 static bool
289 InitJNIFields( audio_output_t *p_aout, JNIEnv* env )
291 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
292 static int i_init_state = -1;
293 bool ret;
294 jclass clazz;
295 jfieldID field;
297 vlc_mutex_lock( &lock );
299 if( i_init_state != -1 )
300 goto end;
302 #define CHECK_EXCEPTION( what, critical ) do { \
303 if( (*env)->ExceptionCheck( env ) ) \
305 msg_Err( p_aout, "%s failed", what ); \
306 (*env)->ExceptionClear( env ); \
307 if( (critical) ) \
309 i_init_state = 0; \
310 goto end; \
313 } while( 0 )
314 #define GET_CLASS( str, critical ) do { \
315 clazz = (*env)->FindClass( env, (str) ); \
316 CHECK_EXCEPTION( "FindClass(" str ")", critical ); \
317 } while( 0 )
318 #define GET_ID( get, id, str, args, critical ) do { \
319 jfields.id = (*env)->get( env, clazz, (str), (args) ); \
320 CHECK_EXCEPTION( #get "(" #id ")", critical ); \
321 } while( 0 )
322 #define GET_CONST_INT( id, str, critical ) do { \
323 field = NULL; \
324 field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
325 CHECK_EXCEPTION( "GetStaticFieldID(" #id ")", critical ); \
326 if( field ) \
328 jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
329 CHECK_EXCEPTION( #id, critical ); \
331 } while( 0 )
333 /* AudioTrack class init */
334 GET_CLASS( "android/media/AudioTrack", true );
335 jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
336 CHECK_EXCEPTION( "NewGlobalRef", true );
338 GET_ID( GetMethodID, AudioTrack.ctor, "<init>",
339 "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;III)V", false );
340 jfields.AudioTrack.has_ctor_21 = jfields.AudioTrack.ctor != NULL;
341 if( !jfields.AudioTrack.has_ctor_21 )
342 GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIIII)V", true );
343 GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true );
344 GET_ID( GetMethodID, AudioTrack.getState, "getState", "()I", true );
345 GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true );
346 GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true );
347 GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true );
348 GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true );
350 GET_ID( GetMethodID, AudioTrack.writeV23, "write", "([BIII)I", false );
351 GET_ID( GetMethodID, AudioTrack.writeShortV23, "write", "([SIII)I", false );
352 if( !jfields.AudioTrack.writeV23 )
353 GET_ID( GetMethodID, AudioTrack.writeBufferV21, "write", "(Ljava/nio/ByteBuffer;II)I", false );
355 if( jfields.AudioTrack.writeV23 || jfields.AudioTrack.writeBufferV21 )
357 GET_CONST_INT( AudioTrack.WRITE_NON_BLOCKING, "WRITE_NON_BLOCKING", true );
358 #ifdef AUDIOTRACK_USE_FLOAT
359 GET_ID( GetMethodID, AudioTrack.writeFloat, "write", "([FIII)I", true );
360 #endif
361 } else
362 GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
364 GET_ID( GetMethodID, AudioTrack.getBufferSizeInFrames,
365 "getBufferSizeInFrames", "()I", false );
367 #ifdef AUDIOTRACK_HW_LATENCY
368 GET_ID( GetMethodID, AudioTrack.getLatency, "getLatency", "()I", false );
369 #endif
371 GET_ID( GetMethodID, AudioTrack.getTimestamp,
372 "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
373 GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
374 "getPlaybackHeadPosition", "()I", true );
376 GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize",
377 "(III)I", true );
378 #ifdef AUDIOTRACK_NATIVE_SAMPLERATE
379 GET_ID( GetStaticMethodID, AudioTrack.getNativeOutputSampleRate,
380 "getNativeOutputSampleRate", "(I)I", true );
381 #endif
382 GET_ID( GetMethodID, AudioTrack.setVolume,
383 "setVolume", "(F)I", false );
384 if( !jfields.AudioTrack.setVolume )
385 GET_ID( GetMethodID, AudioTrack.setStereoVolume,
386 "setStereoVolume", "(FF)I", true );
387 GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true );
388 GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
389 GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
390 GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true );
391 GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION,
392 "ERROR_INVALID_OPERATION", true );
394 if( jfields.AudioTrack.has_ctor_21 )
396 /* AudioAttributes_Builder class init */
397 GET_CLASS( "android/media/AudioAttributes$Builder", true );
398 jfields.AudioAttributes_Builder.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
399 CHECK_EXCEPTION( "NewGlobalRef", true );
400 GET_ID( GetMethodID, AudioAttributes_Builder.ctor, "<init>",
401 "()V", true );
402 GET_ID( GetMethodID, AudioAttributes_Builder.build, "build",
403 "()Landroid/media/AudioAttributes;", true );
404 GET_ID( GetMethodID, AudioAttributes_Builder.setLegacyStreamType, "setLegacyStreamType",
405 "(I)Landroid/media/AudioAttributes$Builder;", true );
407 /* AudioFormat_Builder class init */
408 GET_CLASS( "android/media/AudioFormat$Builder", true );
409 jfields.AudioFormat_Builder.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
410 CHECK_EXCEPTION( "NewGlobalRef", true );
411 GET_ID( GetMethodID, AudioFormat_Builder.ctor, "<init>",
412 "()V", true );
413 GET_ID( GetMethodID, AudioFormat_Builder.build, "build",
414 "()Landroid/media/AudioFormat;", true );
415 GET_ID( GetMethodID, AudioFormat_Builder.setChannelMask, "setChannelMask",
416 "(I)Landroid/media/AudioFormat$Builder;", true );
417 GET_ID( GetMethodID, AudioFormat_Builder.setEncoding, "setEncoding",
418 "(I)Landroid/media/AudioFormat$Builder;", true );
419 GET_ID( GetMethodID, AudioFormat_Builder.setSampleRate, "setSampleRate",
420 "(I)Landroid/media/AudioFormat$Builder;", true );
423 /* AudioTimestamp class init (if any) */
424 if( jfields.AudioTrack.getTimestamp )
426 GET_CLASS( "android/media/AudioTimestamp", true );
427 jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env,
428 clazz );
429 CHECK_EXCEPTION( "NewGlobalRef", true );
431 GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true );
432 GET_ID( GetFieldID, AudioTimestamp.framePosition,
433 "framePosition", "J", true );
434 GET_ID( GetFieldID, AudioTimestamp.nanoTime,
435 "nanoTime", "J", true );
438 /* AudioFormat class init */
439 GET_CLASS( "android/media/AudioFormat", true );
440 GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
441 GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
442 #ifdef AUDIOTRACK_USE_FLOAT
443 GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
444 false );
445 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL &&
446 jfields.AudioTrack.writeFloat;
447 #else
448 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
449 #endif
451 if( jfields.AudioTrack.writeShortV23 )
453 GET_CONST_INT( AudioFormat.ENCODING_IEC61937, "ENCODING_IEC61937", false );
454 jfields.AudioFormat.has_ENCODING_IEC61937 = field != NULL;
456 else
457 jfields.AudioFormat.has_ENCODING_IEC61937 = false;
459 GET_CONST_INT( AudioFormat.ENCODING_AC3, "ENCODING_AC3", false );
460 jfields.AudioFormat.has_ENCODING_AC3 = field != NULL;
461 GET_CONST_INT( AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3", false );
462 jfields.AudioFormat.has_ENCODING_E_AC3 = field != NULL;
464 GET_CONST_INT( AudioFormat.ENCODING_DTS, "ENCODING_DTS", false );
465 jfields.AudioFormat.has_ENCODING_DTS = field != NULL;
466 GET_CONST_INT( AudioFormat.ENCODING_DTS_HD, "ENCODING_DTS_HD", false );
467 jfields.AudioFormat.has_ENCODING_DTS_HD = field != NULL;
469 GET_CONST_INT( AudioFormat.ENCODING_DOLBY_TRUEHD, "ENCODING_DOLBY_TRUEHD",
470 false );
471 jfields.AudioFormat.has_ENCODING_DOLBY_TRUEHD = field != NULL;
473 GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
474 GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
475 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_LEFT, "CHANNEL_OUT_FRONT_LEFT", true );
476 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_RIGHT, "CHANNEL_OUT_FRONT_RIGHT", true );
477 GET_CONST_INT( AudioFormat.CHANNEL_OUT_5POINT1, "CHANNEL_OUT_5POINT1", true );
478 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_LEFT, "CHANNEL_OUT_BACK_LEFT", true );
479 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_RIGHT, "CHANNEL_OUT_BACK_RIGHT", true );
480 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_CENTER, "CHANNEL_OUT_FRONT_CENTER", true );
481 GET_CONST_INT( AudioFormat.CHANNEL_OUT_LOW_FREQUENCY, "CHANNEL_OUT_LOW_FREQUENCY", true );
482 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_CENTER, "CHANNEL_OUT_BACK_CENTER", true );
483 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_LEFT, "CHANNEL_OUT_SIDE_LEFT", false );
484 if( field != NULL )
486 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_RIGHT, "CHANNEL_OUT_SIDE_RIGHT", true );
487 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = true;
488 } else
489 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = false;
491 /* AudioManager class init */
492 GET_CLASS( "android/media/AudioManager", true );
493 GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false );
494 jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
495 GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
497 #undef CHECK_EXCEPTION
498 #undef GET_CLASS
499 #undef GET_ID
500 #undef GET_CONST_INT
502 i_init_state = 1;
503 end:
504 ret = i_init_state == 1;
505 if( !ret )
506 msg_Err( p_aout, "AudioTrack jni init failed" );
507 vlc_mutex_unlock( &lock );
508 return ret;
511 static inline bool
512 check_exception( JNIEnv *env, audio_output_t *p_aout,
513 const char *class, const char *method )
515 if( (*env)->ExceptionCheck( env ) )
517 aout_sys_t *p_sys = p_aout->sys;
519 p_sys->b_audiotrack_exception = true;
520 p_sys->b_error = true;
521 (*env)->ExceptionDescribe( env );
522 (*env)->ExceptionClear( env );
523 msg_Err( p_aout, "%s.%s triggered an exception !", class, method );
524 return true;
525 } else
526 return false;
529 #define CHECK_EXCEPTION( class, method ) check_exception( env, p_aout, class, method )
530 #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, "AudioTrack", method )
532 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
534 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
535 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
536 #define JNI_CALL_OBJECT( obj, method, ... ) JNI_CALL( CallObjectMethod, obj, method, ##__VA_ARGS__ )
537 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
538 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
540 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
541 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
542 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
543 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
544 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
546 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->timestamp.p_obj, jfields.AudioTimestamp.field )
548 static inline vlc_tick_t
549 frames_to_us( aout_sys_t *p_sys, uint64_t i_nb_frames )
551 return vlc_tick_from_samples(i_nb_frames, p_sys->fmt.i_rate);
553 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
555 static inline uint64_t
556 bytes_to_frames( aout_sys_t *p_sys, size_t i_bytes )
558 return i_bytes * p_sys->fmt.i_frame_length / p_sys->fmt.i_bytes_per_frame;
560 #define BYTES_TO_FRAMES(x) bytes_to_frames( p_sys, (x) )
561 #define BYTES_TO_US(x) frames_to_us( p_sys, bytes_to_frames( p_sys, (x) ) )
563 static inline size_t
564 frames_to_bytes( aout_sys_t *p_sys, uint64_t i_frames )
566 return i_frames * p_sys->fmt.i_bytes_per_frame / p_sys->fmt.i_frame_length;
568 #define FRAMES_TO_BYTES(x) frames_to_bytes( p_sys, (x) )
571 * Get the AudioTrack position
573 * The doc says that the position is reset to zero after flush but it's not
574 * true for all devices or Android versions.
576 static uint64_t
577 AudioTrack_getPlaybackHeadPosition( JNIEnv *env, audio_output_t *p_aout )
579 /* Android doc:
580 * getPlaybackHeadPosition: Returns the playback head position expressed in
581 * frames. Though the "int" type is signed 32-bits, the value should be
582 * reinterpreted as if it is unsigned 32-bits. That is, the next position
583 * after 0x7FFFFFFF is (int) 0x80000000. This is a continuously advancing
584 * counter. It will wrap (overflow) periodically, for example approximately
585 * once every 27:03:11 hours:minutes:seconds at 44.1 kHz. It is reset to
586 * zero by flush(), reload(), and stop().
589 aout_sys_t *p_sys = p_aout->sys;
590 uint32_t i_pos;
592 /* int32_t to uint32_t */
593 i_pos = 0xFFFFFFFFL & JNI_AT_CALL_INT( getPlaybackHeadPosition );
595 /* uint32_t to uint64_t */
596 if( p_sys->headpos.i_last > i_pos )
597 p_sys->headpos.i_wrap_count++;
598 p_sys->headpos.i_last = i_pos;
599 return p_sys->headpos.i_last + ((uint64_t)p_sys->headpos.i_wrap_count << 32);
603 * Reset AudioTrack position
605 * Called after flush, or start
607 static void
608 AudioTrack_ResetPlaybackHeadPosition( JNIEnv *env, audio_output_t *p_aout )
610 (void) env;
611 aout_sys_t *p_sys = p_aout->sys;
613 p_sys->headpos.i_last = 0;
614 p_sys->headpos.i_wrap_count = 0;
618 * Reset AudioTrack SmoothPosition and TimestampPosition
620 static void
621 AudioTrack_ResetPositions( JNIEnv *env, audio_output_t *p_aout )
623 aout_sys_t *p_sys = p_aout->sys;
624 VLC_UNUSED( env );
626 p_sys->timestamp.i_play_time = vlc_tick_now();
627 p_sys->timestamp.i_last_time = 0;
628 p_sys->timestamp.i_frame_us = 0;
629 p_sys->timestamp.i_frame_pos = 0;
631 p_sys->smoothpos.i_count = 0;
632 p_sys->smoothpos.i_idx = 0;
633 p_sys->smoothpos.i_last_time = 0;
634 p_sys->smoothpos.i_us = 0;
638 * Reset all AudioTrack positions and internal state
640 static void
641 AudioTrack_Reset( JNIEnv *env, audio_output_t *p_aout )
643 aout_sys_t *p_sys = p_aout->sys;
645 AudioTrack_ResetPositions( env, p_aout );
646 AudioTrack_ResetPlaybackHeadPosition( env, p_aout );
647 p_sys->i_samples_written = 0;
650 static vlc_tick_t
651 AudioTrack_GetLatencyUs( JNIEnv *env, audio_output_t *p_aout )
653 aout_sys_t *p_sys = p_aout->sys;
655 if( jfields.AudioTrack.getLatency )
657 int i_latency_ms = JNI_AT_CALL_INT( getLatency );
659 /* getLatency() includes the latency due to AudioTrack buffer size,
660 * AudioMixer (if any) and audio hardware driver. We only need the
661 * audio hardware latency */
662 if( i_latency_ms > 0 )
664 vlc_tick_t i_latency_us = VLC_TICK_FROM_MS( i_latency_ms )
665 - FRAMES_TO_US( p_sys->i_max_audiotrack_samples );
666 return i_latency_us >= 0 ? i_latency_us : 0;
670 return 0;
674 * Get a smooth AudioTrack position
676 * This function smooth out the AudioTrack position since it has a very bad
677 * precision (+/- 20ms on old devices).
679 static vlc_tick_t
680 AudioTrack_GetSmoothPositionUs( JNIEnv *env, audio_output_t *p_aout )
682 aout_sys_t *p_sys = p_aout->sys;
683 uint64_t i_audiotrack_us;
684 vlc_tick_t i_now = vlc_tick_now();
686 /* Fetch an AudioTrack position every SMOOTHPOS_INTERVAL_US (30ms) */
687 if( i_now - p_sys->smoothpos.i_last_time >= SMOOTHPOS_INTERVAL_US )
689 i_audiotrack_us = FRAMES_TO_US( AudioTrack_getPlaybackHeadPosition( env, p_aout ) );
690 if( i_audiotrack_us == 0 )
691 goto bailout;
693 p_sys->smoothpos.i_last_time = i_now;
695 /* Base the position off the current time */
696 p_sys->smoothpos.p_us[p_sys->smoothpos.i_idx] = i_audiotrack_us - i_now;
697 p_sys->smoothpos.i_idx = (p_sys->smoothpos.i_idx + 1)
698 % SMOOTHPOS_SAMPLE_COUNT;
699 if( p_sys->smoothpos.i_count < SMOOTHPOS_SAMPLE_COUNT )
700 p_sys->smoothpos.i_count++;
702 /* Calculate the average position based off the current time */
703 p_sys->smoothpos.i_us = 0;
704 for( uint32_t i = 0; i < p_sys->smoothpos.i_count; ++i )
705 p_sys->smoothpos.i_us += p_sys->smoothpos.p_us[i];
706 p_sys->smoothpos.i_us /= p_sys->smoothpos.i_count;
709 if( p_sys->smoothpos.i_us != 0 )
710 return p_sys->smoothpos.i_us + i_now - AudioTrack_GetLatencyUs( env, p_aout );
712 bailout:
713 return 0;
716 static vlc_tick_t
717 AudioTrack_GetTimestampPositionUs( JNIEnv *env, audio_output_t *p_aout )
719 aout_sys_t *p_sys = p_aout->sys;
720 vlc_tick_t i_now;
722 if( !p_sys->timestamp.p_obj )
723 return 0;
725 i_now = vlc_tick_now();
727 /* Android doc:
728 * getTimestamp: Poll for a timestamp on demand.
730 * If you need to track timestamps during initial warmup or after a
731 * routing or mode change, you should request a new timestamp once per
732 * second until the reported timestamps show that the audio clock is
733 * stable. Thereafter, query for a new timestamp approximately once
734 * every 10 seconds to once per minute. Calling this method more often
735 * is inefficient. It is also counter-productive to call this method
736 * more often than recommended, because the short-term differences
737 * between successive timestamp reports are not meaningful. If you need
738 * a high-resolution mapping between frame position and presentation
739 * time, consider implementing that at application level, based on
740 * low-resolution timestamps.
743 /* Fetch an AudioTrack timestamp every AUDIOTIMESTAMP_INTERVAL_US (500ms) */
744 if( i_now - p_sys->timestamp.i_last_time >= AUDIOTIMESTAMP_INTERVAL_US )
746 p_sys->timestamp.i_last_time = i_now;
748 if( JNI_AT_CALL_BOOL( getTimestamp, p_sys->timestamp.p_obj ) )
750 p_sys->timestamp.i_frame_us = VLC_TICK_FROM_NS(JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime ));
751 p_sys->timestamp.i_frame_pos = JNI_AUDIOTIMESTAMP_GET_LONG( framePosition );
753 else
755 p_sys->timestamp.i_frame_us = 0;
756 p_sys->timestamp.i_frame_pos = 0;
760 /* frame time should be after last play time
761 * frame time shouldn't be in the future
762 * frame time should be less than 10 seconds old */
763 if( p_sys->timestamp.i_frame_us != 0 && p_sys->timestamp.i_frame_pos != 0
764 && p_sys->timestamp.i_frame_us > p_sys->timestamp.i_play_time
765 && i_now > p_sys->timestamp.i_frame_us
766 && ( i_now - p_sys->timestamp.i_frame_us ) <= VLC_TICK_FROM_SEC(10) )
768 vlc_tick_t i_time_diff = i_now - p_sys->timestamp.i_frame_us;
769 jlong i_frames_diff = samples_from_vlc_tick(i_time_diff, p_sys->fmt.i_rate);
770 return FRAMES_TO_US( p_sys->timestamp.i_frame_pos + i_frames_diff );
771 } else
772 return 0;
775 static int
776 TimeGet( audio_output_t *p_aout, vlc_tick_t *restrict p_delay )
778 aout_sys_t *p_sys = p_aout->sys;
779 vlc_tick_t i_audiotrack_us;
780 JNIEnv *env;
782 if( p_sys->b_passthrough )
783 return -1;
785 vlc_mutex_lock( &p_sys->lock );
787 if( p_sys->b_error || !p_sys->i_samples_written || !( env = GET_ENV() ) )
788 goto bailout;
790 i_audiotrack_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
792 if( i_audiotrack_us <= 0 )
793 i_audiotrack_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
795 /* Debug log for both delays */
796 #if 0
798 vlc_tick_t i_ts_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
799 vlc_tick_t i_smooth_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
800 vlc_tick_t i_latency_us = AudioTrack_GetLatencyUs( env, p_aout );
802 msg_Err( p_aout, "TimeGet: TimeStamp: %"PRId64", Smooth: %"PRId64" (latency: %"PRId64")",
803 i_ts_us, i_smooth_us, i_latency_us );
805 #endif
807 if( i_audiotrack_us > 0 )
809 /* AudioTrack delay */
810 vlc_tick_t i_delay = FRAMES_TO_US( p_sys->i_samples_written )
811 - i_audiotrack_us;
812 if( i_delay >= 0 )
814 /* Circular buffer delay */
815 i_delay += BYTES_TO_US( p_sys->circular.i_write
816 - p_sys->circular.i_read );
817 *p_delay = i_delay;
818 vlc_mutex_unlock( &p_sys->lock );
819 return 0;
821 else
823 msg_Warn( p_aout, "timing screwed, reset positions" );
824 AudioTrack_ResetPositions( env, p_aout );
828 bailout:
829 vlc_mutex_unlock( &p_sys->lock );
830 return -1;
833 static void
834 AudioTrack_GetChanOrder( uint16_t i_physical_channels, uint32_t p_chans_out[] )
836 #define HAS_CHAN( x ) ( ( i_physical_channels & (x) ) == (x) )
837 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
838 int i = 0;
840 if( HAS_CHAN( AOUT_CHAN_LEFT ) )
841 p_chans_out[i++] = AOUT_CHAN_LEFT;
842 if( HAS_CHAN( AOUT_CHAN_RIGHT ) )
843 p_chans_out[i++] = AOUT_CHAN_RIGHT;
845 if( HAS_CHAN( AOUT_CHAN_CENTER ) )
846 p_chans_out[i++] = AOUT_CHAN_CENTER;
848 if( HAS_CHAN( AOUT_CHAN_LFE ) )
849 p_chans_out[i++] = AOUT_CHAN_LFE;
851 if( HAS_CHAN( AOUT_CHAN_REARLEFT ) )
852 p_chans_out[i++] = AOUT_CHAN_REARLEFT;
853 if( HAS_CHAN( AOUT_CHAN_REARRIGHT ) )
854 p_chans_out[i++] = AOUT_CHAN_REARRIGHT;
856 if( HAS_CHAN( AOUT_CHAN_REARCENTER ) )
857 p_chans_out[i++] = AOUT_CHAN_REARCENTER;
859 if( HAS_CHAN( AOUT_CHAN_MIDDLELEFT ) )
860 p_chans_out[i++] = AOUT_CHAN_MIDDLELEFT;
861 if( HAS_CHAN( AOUT_CHAN_MIDDLERIGHT ) )
862 p_chans_out[i++] = AOUT_CHAN_MIDDLERIGHT;
864 assert( i <= AOUT_CHAN_MAX );
865 #undef HAS_CHAN
868 static jobject
869 AudioTrack_New21( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
870 int i_channel_config, int i_format, int i_size,
871 jint session_id )
873 jobject p_audiotrack = NULL;
874 jobject p_aattr_builder = NULL;
875 jobject p_audio_attributes = NULL;
876 jobject p_afmt_builder = NULL;
877 jobject p_audio_format = NULL;
878 jobject ref;
880 p_aattr_builder =
881 JNI_CALL( NewObject,
882 jfields.AudioAttributes_Builder.clazz,
883 jfields.AudioAttributes_Builder.ctor );
884 if( !p_aattr_builder )
885 return NULL;
887 ref = JNI_CALL_OBJECT( p_aattr_builder,
888 jfields.AudioAttributes_Builder.setLegacyStreamType,
889 jfields.AudioManager.STREAM_MUSIC );
890 (*env)->DeleteLocalRef( env, ref );
892 p_audio_attributes =
893 JNI_CALL_OBJECT( p_aattr_builder,
894 jfields.AudioAttributes_Builder.build );
895 if( !p_audio_attributes )
896 goto del_local_refs;
898 p_afmt_builder = JNI_CALL( NewObject,
899 jfields.AudioFormat_Builder.clazz,
900 jfields.AudioFormat_Builder.ctor );
901 if( !p_afmt_builder )
902 goto del_local_refs;
904 ref = JNI_CALL_OBJECT( p_afmt_builder,
905 jfields.AudioFormat_Builder.setChannelMask,
906 i_channel_config );
907 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setChannelMask" ) )
909 (*env)->DeleteLocalRef( env, ref );
910 goto del_local_refs;
912 (*env)->DeleteLocalRef( env, ref );
914 ref = JNI_CALL_OBJECT( p_afmt_builder,
915 jfields.AudioFormat_Builder.setEncoding,
916 i_format );
917 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setEncoding" ) )
919 (*env)->DeleteLocalRef( env, ref );
920 goto del_local_refs;
922 (*env)->DeleteLocalRef( env, ref );
924 ref = JNI_CALL_OBJECT( p_afmt_builder,
925 jfields.AudioFormat_Builder.setSampleRate,
926 i_rate );
927 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setSampleRate" ) )
929 (*env)->DeleteLocalRef( env, ref );
930 goto del_local_refs;
932 (*env)->DeleteLocalRef( env, ref );
934 p_audio_format = JNI_CALL_OBJECT( p_afmt_builder,
935 jfields.AudioFormat_Builder.build );
936 if(!p_audio_format)
937 goto del_local_refs;
939 p_audiotrack = JNI_AT_NEW( p_audio_attributes, p_audio_format, i_size,
940 jfields.AudioTrack.MODE_STREAM, session_id );
942 del_local_refs:
943 (*env)->DeleteLocalRef( env, p_aattr_builder );
944 (*env)->DeleteLocalRef( env, p_audio_attributes );
945 (*env)->DeleteLocalRef( env, p_afmt_builder );
946 (*env)->DeleteLocalRef( env, p_audio_format );
947 return p_audiotrack;
950 static jobject
951 AudioTrack_NewLegacy( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
952 int i_channel_config, int i_format, int i_size,
953 jint session_id )
955 VLC_UNUSED( p_aout );
956 return JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate,
957 i_channel_config, i_format, i_size,
958 jfields.AudioTrack.MODE_STREAM, session_id );
962 * Create an Android AudioTrack.
963 * returns -1 on error, 0 on success.
965 static int
966 AudioTrack_New( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
967 int i_channel_config, int i_format, int i_size )
969 aout_sys_t *p_sys = p_aout->sys;
970 jint session_id = var_InheritInteger( p_aout, "audiotrack-session-id" );
972 jobject p_audiotrack;
973 if( jfields.AudioTrack.has_ctor_21 )
974 p_audiotrack = AudioTrack_New21( env, p_aout, i_rate, i_channel_config,
975 i_format, i_size, session_id );
976 else
977 p_audiotrack = AudioTrack_NewLegacy( env, p_aout, i_rate,
978 i_channel_config, i_format, i_size,
979 session_id );
980 if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
982 msg_Warn( p_aout, "AudioTrack Init failed" );
983 return -1;
985 if( JNI_CALL_INT( p_audiotrack, jfields.AudioTrack.getState )
986 != jfields.AudioTrack.STATE_INITIALIZED )
988 JNI_CALL_VOID( p_audiotrack, jfields.AudioTrack.release );
989 (*env)->DeleteLocalRef( env, p_audiotrack );
990 msg_Err( p_aout, "AudioTrack getState failed" );
991 return -1;
994 p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
995 (*env)->DeleteLocalRef( env, p_audiotrack );
996 if( !p_sys->p_audiotrack )
997 return -1;
999 return 0;
1003 * Destroy and recreate an Android AudioTrack using the same arguments.
1004 * returns -1 on error, 0 on success.
1006 static int
1007 AudioTrack_Recreate( JNIEnv *env, audio_output_t *p_aout )
1009 aout_sys_t *p_sys = p_aout->sys;
1011 JNI_AT_CALL_VOID( release );
1012 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
1013 p_sys->p_audiotrack = NULL;
1014 return AudioTrack_New( env, p_aout, p_sys->audiotrack_args.i_rate,
1015 p_sys->audiotrack_args.i_channel_config,
1016 p_sys->audiotrack_args.i_format,
1017 p_sys->audiotrack_args.i_size );
1021 * Configure and create an Android AudioTrack.
1022 * returns -1 on configuration error, 0 on success.
1024 static int
1025 AudioTrack_Create( JNIEnv *env, audio_output_t *p_aout,
1026 unsigned int i_rate,
1027 int i_format,
1028 uint16_t i_physical_channels )
1030 aout_sys_t *p_sys = p_aout->sys;
1031 int i_size, i_min_buffer_size, i_channel_config;
1033 switch( i_physical_channels )
1035 case AOUT_CHANS_7_1:
1036 /* bitmask of CHANNEL_OUT_7POINT1 doesn't correspond to 5POINT1 and
1037 * SIDES */
1038 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1 |
1039 jfields.AudioFormat.CHANNEL_OUT_SIDE_LEFT |
1040 jfields.AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
1041 break;
1042 case AOUT_CHANS_5_1:
1043 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1;
1044 break;
1045 case AOUT_CHAN_LEFT:
1046 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_MONO;
1047 break;
1048 case AOUT_CHANS_STEREO:
1049 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_STEREO;
1050 break;
1051 default:
1052 vlc_assert_unreachable();
1055 i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize, i_rate,
1056 i_channel_config, i_format );
1057 if( i_min_buffer_size <= 0 )
1059 msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
1060 return -1;
1062 i_size = i_min_buffer_size * 2;
1064 /* create AudioTrack object */
1065 if( AudioTrack_New( env, p_aout, i_rate, i_channel_config,
1066 i_format , i_size ) != 0 )
1067 return -1;
1069 p_sys->audiotrack_args.i_rate = i_rate;
1070 p_sys->audiotrack_args.i_channel_config = i_channel_config;
1071 p_sys->audiotrack_args.i_format = i_format;
1072 p_sys->audiotrack_args.i_size = i_size;
1074 return 0;
1077 static bool
1078 AudioTrack_HasEncoding( audio_output_t *p_aout, vlc_fourcc_t i_format )
1080 aout_sys_t *p_sys = p_aout->sys;
1082 #define MATCH_ENCODING_FLAG(x) jfields.AudioFormat.has_##x && \
1083 ( p_sys->i_encoding_flags == 0 || p_sys->i_encoding_flags & (1 << jfields.AudioFormat.x) )
1085 switch( i_format )
1087 case VLC_CODEC_DTSHD:
1088 return MATCH_ENCODING_FLAG( ENCODING_DTS_HD );
1089 case VLC_CODEC_DTS:
1090 return MATCH_ENCODING_FLAG( ENCODING_DTS );
1091 case VLC_CODEC_A52:
1092 return MATCH_ENCODING_FLAG( ENCODING_AC3 );
1093 case VLC_CODEC_EAC3:
1094 return MATCH_ENCODING_FLAG( ENCODING_E_AC3 );
1095 case VLC_CODEC_TRUEHD:
1096 case VLC_CODEC_MLP:
1097 return MATCH_ENCODING_FLAG( ENCODING_DOLBY_TRUEHD );
1098 default:
1099 return false;
1103 static int
1104 StartPassthrough( JNIEnv *env, audio_output_t *p_aout )
1106 aout_sys_t *p_sys = p_aout->sys;
1107 int i_at_format;
1109 if( !AudioTrack_HasEncoding( p_aout, p_sys->fmt.i_format ) )
1110 return VLC_EGENERIC;
1112 if( jfields.AudioFormat.has_ENCODING_IEC61937 )
1114 i_at_format = jfields.AudioFormat.ENCODING_IEC61937;
1115 switch( p_sys->fmt.i_format )
1117 case VLC_CODEC_TRUEHD:
1118 case VLC_CODEC_MLP:
1119 p_sys->fmt.i_rate = 192000;
1120 p_sys->fmt.i_bytes_per_frame = 16;
1122 /* AudioFormat.ENCODING_IEC61937 documentation says that the
1123 * channel layout must be stereo. Well, not for TrueHD
1124 * apparently */
1125 p_sys->fmt.i_physical_channels = AOUT_CHANS_7_1;
1126 break;
1127 case VLC_CODEC_DTS:
1128 p_sys->fmt.i_bytes_per_frame = 4;
1129 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1130 break;
1131 case VLC_CODEC_DTSHD:
1132 p_sys->fmt.i_bytes_per_frame = 4;
1133 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1134 p_sys->fmt.i_rate = 192000;
1135 p_sys->fmt.i_bytes_per_frame = 16;
1136 break;
1137 case VLC_CODEC_EAC3:
1138 p_sys->fmt.i_rate = 192000;
1139 case VLC_CODEC_A52:
1140 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1141 p_sys->fmt.i_bytes_per_frame = 4;
1142 break;
1143 default:
1144 return VLC_EGENERIC;
1146 p_sys->fmt.i_frame_length = 1;
1147 p_sys->fmt.i_channels = aout_FormatNbChannels( &p_sys->fmt );
1148 p_sys->fmt.i_format = VLC_CODEC_SPDIFL;
1150 else
1152 switch( p_sys->fmt.i_format )
1154 case VLC_CODEC_A52:
1155 if( !jfields.AudioFormat.has_ENCODING_AC3 )
1156 return VLC_EGENERIC;
1157 i_at_format = jfields.AudioFormat.ENCODING_AC3;
1158 break;
1159 case VLC_CODEC_EAC3:
1160 if( !jfields.AudioFormat.has_ENCODING_E_AC3 )
1161 return VLC_EGENERIC;
1162 i_at_format = jfields.AudioFormat.ENCODING_E_AC3;
1163 break;
1164 case VLC_CODEC_DTS:
1165 if( !jfields.AudioFormat.has_ENCODING_DTS )
1166 return VLC_EGENERIC;
1167 i_at_format = jfields.AudioFormat.ENCODING_DTS;
1168 break;
1169 default:
1170 return VLC_EGENERIC;
1172 p_sys->fmt.i_bytes_per_frame = 4;
1173 p_sys->fmt.i_frame_length = 1;
1174 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1175 p_sys->fmt.i_channels = 2;
1176 p_sys->fmt.i_format = VLC_CODEC_SPDIFB;
1179 int i_ret = AudioTrack_Create( env, p_aout, p_sys->fmt.i_rate, i_at_format,
1180 p_sys->fmt.i_physical_channels );
1181 if( i_ret != VLC_SUCCESS )
1182 msg_Warn( p_aout, "SPDIF configuration failed" );
1183 else
1185 p_sys->b_passthrough = true;
1186 p_sys->i_chans_to_reorder = 0;
1189 return i_ret;
1192 static int
1193 StartPCM( JNIEnv *env, audio_output_t *p_aout, unsigned i_max_channels )
1195 aout_sys_t *p_sys = p_aout->sys;
1196 unsigned i_nb_channels;
1197 int i_at_format, i_ret;
1199 if (jfields.AudioTrack.getNativeOutputSampleRate)
1200 p_sys->fmt.i_rate =
1201 JNI_AT_CALL_STATIC_INT( getNativeOutputSampleRate,
1202 jfields.AudioManager.STREAM_MUSIC );
1203 else
1204 p_sys->fmt.i_rate = VLC_CLIP( p_sys->fmt.i_rate, 4000, 48000 );
1208 /* We can only accept U8, S16N, FL32, and AC3 */
1209 switch( p_sys->fmt.i_format )
1211 case VLC_CODEC_U8:
1212 i_at_format = jfields.AudioFormat.ENCODING_PCM_8BIT;
1213 break;
1214 case VLC_CODEC_S16N:
1215 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1216 break;
1217 case VLC_CODEC_FL32:
1218 if( jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
1219 i_at_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
1220 else
1222 p_sys->fmt.i_format = VLC_CODEC_S16N;
1223 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1225 break;
1226 default:
1227 p_sys->fmt.i_format = VLC_CODEC_S16N;
1228 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1229 break;
1232 /* Android AudioTrack supports only mono, stereo, 5.1 and 7.1.
1233 * Android will downmix to stereo if audio output doesn't handle 5.1 or 7.1
1236 i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
1237 if( i_nb_channels == 0 )
1238 return VLC_EGENERIC;
1239 if( AOUT_FMT_LINEAR( &p_sys->fmt ) )
1240 i_nb_channels = __MIN( i_max_channels, i_nb_channels );
1241 if( i_nb_channels > 5 )
1243 if( i_nb_channels > 7 && jfields.AudioFormat.has_CHANNEL_OUT_SIDE )
1244 p_sys->fmt.i_physical_channels = AOUT_CHANS_7_1;
1245 else
1246 p_sys->fmt.i_physical_channels = AOUT_CHANS_5_1;
1247 } else
1249 if( i_nb_channels == 1 )
1250 p_sys->fmt.i_physical_channels = AOUT_CHAN_LEFT;
1251 else
1252 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1255 /* Try to create an AudioTrack with the most advanced channel and
1256 * format configuration. If AudioTrack_Create fails, try again with a
1257 * less advanced format (PCM S16N). If it fails again, try again with
1258 * Stereo channels. */
1259 i_ret = AudioTrack_Create( env, p_aout, p_sys->fmt.i_rate, i_at_format,
1260 p_sys->fmt.i_physical_channels );
1261 if( i_ret != 0 )
1263 if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
1265 msg_Warn( p_aout, "FL32 configuration failed, "
1266 "fallback to S16N PCM" );
1267 p_sys->fmt.i_format = VLC_CODEC_S16N;
1269 else if( p_sys->fmt.i_physical_channels & AOUT_CHANS_5_1 )
1271 msg_Warn( p_aout, "5.1 or 7.1 configuration failed, "
1272 "fallback to Stereo" );
1273 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1275 else
1276 break;
1278 } while( i_ret != 0 );
1280 if( i_ret != VLC_SUCCESS )
1281 return i_ret;
1283 uint32_t p_chans_out[AOUT_CHAN_MAX];
1284 memset( p_chans_out, 0, sizeof(p_chans_out) );
1285 AudioTrack_GetChanOrder( p_sys->fmt.i_physical_channels, p_chans_out );
1286 p_sys->i_chans_to_reorder =
1287 aout_CheckChannelReorder( NULL, p_chans_out,
1288 p_sys->fmt.i_physical_channels,
1289 p_sys->p_chan_table );
1290 aout_FormatPrepare( &p_sys->fmt );
1291 return VLC_SUCCESS;
1294 static int
1295 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
1297 aout_sys_t *p_sys = p_aout->sys;
1298 JNIEnv *env;
1299 int i_ret;
1300 bool b_try_passthrough;
1301 unsigned i_max_channels;
1303 if( p_sys->at_dev == AT_DEV_ENCODED )
1305 b_try_passthrough = true;
1306 i_max_channels = AT_DEV_MAX_CHANNELS;
1308 else
1310 b_try_passthrough = var_InheritBool( p_aout, "spdif" );
1311 i_max_channels = p_sys->at_dev == AT_DEV_STEREO ? 2 : AT_DEV_MAX_CHANNELS;
1314 if( !( env = GET_ENV() ) )
1315 return VLC_EGENERIC;
1317 p_sys->fmt = *p_fmt;
1319 aout_FormatPrint( p_aout, "VLC is looking for:", &p_sys->fmt );
1321 bool low_latency = false;
1322 if (p_sys->fmt.channel_type == AUDIO_CHANNEL_TYPE_AMBISONICS)
1324 p_sys->fmt.channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
1326 /* TODO: detect sink channel layout */
1327 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1328 aout_FormatPrepare(&p_sys->fmt);
1329 low_latency = true;
1332 if( AOUT_FMT_LINEAR( &p_sys->fmt ) )
1333 i_ret = StartPCM( env, p_aout, i_max_channels );
1334 else if( b_try_passthrough )
1335 i_ret = StartPassthrough( env, p_aout );
1336 else
1337 return VLC_EGENERIC;
1339 if( i_ret != 0 )
1340 return VLC_EGENERIC;
1342 if( jfields.AudioTrack.getBufferSizeInFrames )
1343 p_sys->i_max_audiotrack_samples = JNI_AT_CALL_INT( getBufferSizeInFrames );
1344 else
1345 p_sys->i_max_audiotrack_samples = BYTES_TO_FRAMES( p_sys->audiotrack_args.i_size );
1347 #ifdef AUDIOTRACK_HW_LATENCY
1348 if( jfields.AudioTimestamp.clazz )
1350 /* create AudioTimestamp object */
1351 jobject p_obj = JNI_CALL( NewObject, jfields.AudioTimestamp.clazz,
1352 jfields.AudioTimestamp.ctor );
1353 if( p_obj )
1355 p_sys->timestamp.p_obj = (*env)->NewGlobalRef( env, p_obj );
1356 (*env)->DeleteLocalRef( env, p_obj );
1358 if( !p_sys->timestamp.p_obj )
1359 goto error;
1361 #endif
1363 AudioTrack_Reset( env, p_aout );
1365 if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
1367 msg_Dbg( p_aout, "using WRITE_FLOATARRAY");
1368 p_sys->i_write_type = WRITE_FLOATARRAY;
1370 else if( p_sys->fmt.i_format == VLC_CODEC_SPDIFL )
1372 assert( jfields.AudioFormat.has_ENCODING_IEC61937 );
1373 msg_Dbg( p_aout, "using WRITE_SHORTARRAYV23");
1374 p_sys->i_write_type = WRITE_SHORTARRAYV23;
1376 else if( jfields.AudioTrack.writeV23 )
1378 msg_Dbg( p_aout, "using WRITE_BYTEARRAYV23");
1379 p_sys->i_write_type = WRITE_BYTEARRAYV23;
1381 else if( jfields.AudioTrack.writeBufferV21 )
1383 msg_Dbg( p_aout, "using WRITE_BYTEBUFFER");
1384 p_sys->i_write_type = WRITE_BYTEBUFFER;
1386 else
1388 msg_Dbg( p_aout, "using WRITE_BYTEARRAY");
1389 p_sys->i_write_type = WRITE_BYTEARRAY;
1392 p_sys->circular.i_read = p_sys->circular.i_write = 0;
1393 p_sys->circular.i_size = (int)p_sys->fmt.i_rate
1394 * p_sys->fmt.i_bytes_per_frame
1395 / p_sys->fmt.i_frame_length;
1396 if (low_latency)
1398 /* 40 ms of buffering */
1399 p_sys->circular.i_size = p_sys->circular.i_size / 25;
1401 else
1403 /* 2 seconds of buffering */
1404 p_sys->circular.i_size = samples_from_vlc_tick(AOUT_MAX_PREPARE_TIME, p_sys->circular.i_size);
1407 /* Allocate circular buffer */
1408 switch( p_sys->i_write_type )
1410 case WRITE_BYTEARRAY:
1411 case WRITE_BYTEARRAYV23:
1413 jbyteArray p_bytearray;
1415 p_bytearray = (*env)->NewByteArray( env, p_sys->circular.i_size );
1416 if( p_bytearray )
1418 p_sys->circular.u.p_bytearray = (*env)->NewGlobalRef( env, p_bytearray );
1419 (*env)->DeleteLocalRef( env, p_bytearray );
1422 if( !p_sys->circular.u.p_bytearray )
1424 msg_Err(p_aout, "byte array allocation failed");
1425 goto error;
1427 break;
1429 case WRITE_SHORTARRAYV23:
1431 jshortArray p_shortarray;
1433 p_shortarray = (*env)->NewShortArray( env,
1434 p_sys->circular.i_size / 2 );
1435 if( p_shortarray )
1437 p_sys->circular.u.p_shortarray = (*env)->NewGlobalRef( env, p_shortarray );
1438 (*env)->DeleteLocalRef( env, p_shortarray );
1440 if( !p_sys->circular.u.p_shortarray )
1442 msg_Err(p_aout, "short array allocation failed");
1443 goto error;
1445 break;
1447 case WRITE_FLOATARRAY:
1449 jfloatArray p_floatarray;
1451 p_floatarray = (*env)->NewFloatArray( env,
1452 p_sys->circular.i_size / 4 );
1453 if( p_floatarray )
1455 p_sys->circular.u.p_floatarray = (*env)->NewGlobalRef( env, p_floatarray );
1456 (*env)->DeleteLocalRef( env, p_floatarray );
1458 if( !p_sys->circular.u.p_floatarray )
1460 msg_Err(p_aout, "float array allocation failed");
1461 goto error;
1463 break;
1465 case WRITE_BYTEBUFFER:
1466 p_sys->circular.u.bytebuffer.p_data = malloc( p_sys->circular.i_size );
1467 if( !p_sys->circular.u.bytebuffer.p_data )
1469 msg_Err(p_aout, "bytebuffer allocation failed");
1470 goto error;
1472 break;
1475 /* Run AudioTrack_Thread */
1476 p_sys->b_thread_running = true;
1477 p_sys->b_thread_paused = false;
1478 if ( vlc_clone( &p_sys->thread, AudioTrack_Thread, p_aout,
1479 VLC_THREAD_PRIORITY_LOW ) )
1481 msg_Err(p_aout, "vlc clone failed");
1482 goto error;
1485 JNI_AT_CALL_VOID( play );
1486 CHECK_AT_EXCEPTION( "play" );
1488 *p_fmt = p_sys->fmt;
1490 p_aout->volume_set(p_aout, p_sys->volume);
1491 if (p_sys->mute)
1492 p_aout->mute_set(p_aout, true);
1493 aout_FormatPrint( p_aout, "VLC will output:", &p_sys->fmt );
1495 return VLC_SUCCESS;
1497 error:
1498 Stop( p_aout );
1499 return VLC_EGENERIC;
1502 static void
1503 Stop( audio_output_t *p_aout )
1505 aout_sys_t *p_sys = p_aout->sys;
1506 JNIEnv *env;
1508 if( !( env = GET_ENV() ) )
1509 return;
1511 /* Stop the AudioTrack thread */
1512 vlc_mutex_lock( &p_sys->lock );
1513 if( p_sys->b_thread_running )
1515 p_sys->b_thread_running = false;
1516 vlc_cond_signal( &p_sys->thread_cond );
1517 vlc_mutex_unlock( &p_sys->lock );
1518 vlc_join( p_sys->thread, NULL );
1520 else
1521 vlc_mutex_unlock( &p_sys->lock );
1523 /* Release the AudioTrack object */
1524 if( p_sys->p_audiotrack )
1526 if( !p_sys->b_audiotrack_exception )
1528 JNI_AT_CALL_VOID( stop );
1529 if( !CHECK_AT_EXCEPTION( "stop" ) )
1530 JNI_AT_CALL_VOID( release );
1532 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
1533 p_sys->p_audiotrack = NULL;
1536 /* Release the timestamp object */
1537 if( p_sys->timestamp.p_obj )
1539 (*env)->DeleteGlobalRef( env, p_sys->timestamp.p_obj );
1540 p_sys->timestamp.p_obj = NULL;
1543 /* Release the Circular buffer data */
1544 switch( p_sys->i_write_type )
1546 case WRITE_BYTEARRAY:
1547 case WRITE_BYTEARRAYV23:
1548 if( p_sys->circular.u.p_bytearray )
1550 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_bytearray );
1551 p_sys->circular.u.p_bytearray = NULL;
1553 break;
1554 case WRITE_SHORTARRAYV23:
1555 if( p_sys->circular.u.p_shortarray )
1557 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_shortarray );
1558 p_sys->circular.u.p_shortarray = NULL;
1560 break;
1561 case WRITE_FLOATARRAY:
1562 if( p_sys->circular.u.p_floatarray )
1564 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_floatarray );
1565 p_sys->circular.u.p_floatarray = NULL;
1567 break;
1568 case WRITE_BYTEBUFFER:
1569 free( p_sys->circular.u.bytebuffer.p_data );
1570 p_sys->circular.u.bytebuffer.p_data = NULL;
1571 break;
1574 p_sys->b_audiotrack_exception = false;
1575 p_sys->b_error = false;
1576 p_sys->b_passthrough = false;
1580 * Non blocking write function, run from AudioTrack_Thread.
1581 * Do a calculation between current position and audiotrack position and assure
1582 * that we won't wait in AudioTrack.write() method.
1584 static int
1585 AudioTrack_PlayByteArray( JNIEnv *env, audio_output_t *p_aout,
1586 size_t i_data_size, size_t i_data_offset,
1587 bool b_force )
1589 aout_sys_t *p_sys = p_aout->sys;
1590 uint64_t i_samples;
1591 uint64_t i_audiotrack_pos;
1592 uint64_t i_samples_pending;
1594 i_audiotrack_pos = AudioTrack_getPlaybackHeadPosition( env, p_aout );
1596 assert( i_audiotrack_pos <= p_sys->i_samples_written );
1597 if( i_audiotrack_pos > p_sys->i_samples_written )
1599 msg_Err( p_aout, "audiotrack position is ahead. Should NOT happen" );
1600 p_sys->i_samples_written = 0;
1601 p_sys->b_error = true;
1602 return 0;
1604 i_samples_pending = p_sys->i_samples_written - i_audiotrack_pos;
1606 /* check if audiotrack buffer is not full before writing on it. */
1607 if( b_force )
1609 msg_Warn( p_aout, "Force write. It may block..." );
1610 i_samples_pending = 0;
1611 } else if( i_samples_pending >= p_sys->i_max_audiotrack_samples )
1612 return 0;
1614 i_samples = __MIN( p_sys->i_max_audiotrack_samples - i_samples_pending,
1615 BYTES_TO_FRAMES( i_data_size ) );
1617 i_data_size = FRAMES_TO_BYTES( i_samples );
1619 return JNI_AT_CALL_INT( write, p_sys->circular.u.p_bytearray,
1620 i_data_offset, i_data_size );
1624 * Non blocking write function for Android M and after, run from
1625 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1626 * flags.
1628 static int
1629 AudioTrack_PlayByteArrayV23( JNIEnv *env, audio_output_t *p_aout,
1630 size_t i_data_size, size_t i_data_offset )
1632 aout_sys_t *p_sys = p_aout->sys;
1634 return JNI_AT_CALL_INT( writeV23, p_sys->circular.u.p_bytearray,
1635 i_data_offset, i_data_size,
1636 jfields.AudioTrack.WRITE_NON_BLOCKING );
1640 * Non blocking play function for Lollipop and after, run from
1641 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1642 * flags.
1644 static int
1645 AudioTrack_PlayByteBuffer( JNIEnv *env, audio_output_t *p_aout,
1646 size_t i_data_size, size_t i_data_offset )
1648 aout_sys_t *p_sys = p_aout->sys;
1650 /* The same DirectByteBuffer will be used until the data_offset reaches 0.
1651 * The internal position of this buffer is moved by the writeBufferV21
1652 * wall. */
1653 if( i_data_offset == 0 )
1655 /* No need to get a global ref, this object will be only used from the
1656 * same Thread */
1657 if( p_sys->circular.u.bytebuffer.p_obj )
1658 (*env)->DeleteLocalRef( env, p_sys->circular.u.bytebuffer.p_obj );
1660 p_sys->circular.u.bytebuffer.p_obj = (*env)->NewDirectByteBuffer( env,
1661 p_sys->circular.u.bytebuffer.p_data,
1662 p_sys->circular.i_size );
1663 if( !p_sys->circular.u.bytebuffer.p_obj )
1665 if( (*env)->ExceptionCheck( env ) )
1666 (*env)->ExceptionClear( env );
1667 return jfields.AudioTrack.ERROR;
1671 return JNI_AT_CALL_INT( writeBufferV21, p_sys->circular.u.bytebuffer.p_obj,
1672 i_data_size,
1673 jfields.AudioTrack.WRITE_NON_BLOCKING );
1677 * Non blocking short write function for Android M and after, run from
1678 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1679 * flags.
1681 static int
1682 AudioTrack_PlayShortArrayV23( JNIEnv *env, audio_output_t *p_aout,
1683 size_t i_data_size, size_t i_data_offset )
1685 aout_sys_t *p_sys = p_aout->sys;
1686 int i_ret;
1688 i_ret = JNI_AT_CALL_INT( writeShortV23, p_sys->circular.u.p_shortarray,
1689 i_data_offset / 2, i_data_size / 2,
1690 jfields.AudioTrack.WRITE_NON_BLOCKING );
1691 if( i_ret < 0 )
1692 return i_ret;
1693 else
1694 return i_ret * 2;
1698 * Non blocking play float function for Lollipop and after, run from
1699 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1700 * flags.
1702 static int
1703 AudioTrack_PlayFloatArray( JNIEnv *env, audio_output_t *p_aout,
1704 size_t i_data_size, size_t i_data_offset )
1706 aout_sys_t *p_sys = p_aout->sys;
1707 int i_ret;
1709 i_ret = JNI_AT_CALL_INT( writeFloat, p_sys->circular.u.p_floatarray,
1710 i_data_offset / 4, i_data_size / 4,
1711 jfields.AudioTrack.WRITE_NON_BLOCKING );
1712 if( i_ret < 0 )
1713 return i_ret;
1714 else
1715 return i_ret * 4;
1718 static int
1719 AudioTrack_Play( JNIEnv *env, audio_output_t *p_aout, size_t i_data_size,
1720 size_t i_data_offset, bool b_force )
1722 aout_sys_t *p_sys = p_aout->sys;
1723 int i_ret;
1725 switch( p_sys->i_write_type )
1727 case WRITE_BYTEARRAYV23:
1728 i_ret = AudioTrack_PlayByteArrayV23( env, p_aout, i_data_size,
1729 i_data_offset );
1730 break;
1731 case WRITE_BYTEBUFFER:
1732 i_ret = AudioTrack_PlayByteBuffer( env, p_aout, i_data_size,
1733 i_data_offset );
1734 break;
1735 case WRITE_SHORTARRAYV23:
1736 i_ret = AudioTrack_PlayShortArrayV23( env, p_aout, i_data_size,
1737 i_data_offset );
1738 break;
1739 case WRITE_BYTEARRAY:
1740 i_ret = AudioTrack_PlayByteArray( env, p_aout, i_data_size,
1741 i_data_offset, b_force );
1742 break;
1743 case WRITE_FLOATARRAY:
1744 i_ret = AudioTrack_PlayFloatArray( env, p_aout, i_data_size,
1745 i_data_offset );
1746 break;
1747 default:
1748 vlc_assert_unreachable();
1751 if( i_ret < 0 ) {
1752 if( jfields.AudioManager.has_ERROR_DEAD_OBJECT
1753 && i_ret == jfields.AudioManager.ERROR_DEAD_OBJECT )
1755 msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
1756 "try recreating AudioTrack" );
1757 if( ( i_ret = AudioTrack_Recreate( env, p_aout ) ) == 0 )
1759 AudioTrack_Reset( env, p_aout );
1760 JNI_AT_CALL_VOID( play );
1761 CHECK_AT_EXCEPTION( "play" );
1763 } else
1765 const char *str;
1766 if( i_ret == jfields.AudioTrack.ERROR_INVALID_OPERATION )
1767 str = "ERROR_INVALID_OPERATION";
1768 else if( i_ret == jfields.AudioTrack.ERROR_BAD_VALUE )
1769 str = "ERROR_BAD_VALUE";
1770 else
1771 str = "ERROR";
1772 msg_Err( p_aout, "Write failed: %s", str );
1773 p_sys->b_error = true;
1775 } else
1776 p_sys->i_samples_written += BYTES_TO_FRAMES( i_ret );
1777 return i_ret;
1781 * This thread will play the data coming from the circular buffer.
1783 static void *
1784 AudioTrack_Thread( void *p_data )
1786 audio_output_t *p_aout = p_data;
1787 aout_sys_t *p_sys = p_aout->sys;
1788 JNIEnv *env = GET_ENV();
1789 vlc_tick_t i_play_deadline = 0;
1790 vlc_tick_t i_last_time_blocked = 0;
1792 if( !env )
1793 return NULL;
1795 for( ;; )
1797 int i_ret = 0;
1798 bool b_forced;
1799 size_t i_data_offset;
1800 size_t i_data_size;
1802 vlc_mutex_lock( &p_sys->lock );
1804 /* Wait for free space in Audiotrack internal buffer */
1805 if( i_play_deadline != 0 && vlc_tick_now() < i_play_deadline )
1807 /* Don't wake up the thread when there is new data since we are
1808 * waiting for more space */
1809 p_sys->b_thread_waiting = true;
1810 while( p_sys->b_thread_running && i_ret == 0 )
1811 i_ret = vlc_cond_timedwait( &p_sys->thread_cond,
1812 &p_sys->lock,
1813 i_play_deadline );
1814 i_play_deadline = 0;
1815 p_sys->b_thread_waiting = false;
1818 /* Wait for not paused state */
1819 while( p_sys->b_thread_running && p_sys->b_thread_paused )
1821 i_last_time_blocked = 0;
1822 vlc_cond_wait( &p_sys->thread_cond, &p_sys->lock );
1825 /* Wait for more data in the circular buffer */
1826 while( p_sys->b_thread_running
1827 && p_sys->circular.i_read >= p_sys->circular.i_write )
1828 vlc_cond_wait( &p_sys->thread_cond, &p_sys->lock );
1830 if( !p_sys->b_thread_running || p_sys->b_error )
1832 vlc_mutex_unlock( &p_sys->lock );
1833 break;
1836 /* HACK: AudioFlinger can drop frames without notifying us and there is
1837 * no way to know it. If it happens, i_audiotrack_pos won't move and
1838 * the current code will be stuck because it'll assume that audiotrack
1839 * internal buffer is full when it's not. It may happen only after
1840 * Android 4.4.2 if we send frames too quickly. To fix this issue,
1841 * force the writing of the buffer after a certain delay. */
1842 if( i_last_time_blocked != 0 )
1843 b_forced = vlc_tick_now() - i_last_time_blocked >
1844 FRAMES_TO_US( p_sys->i_max_audiotrack_samples ) * 2;
1845 else
1846 b_forced = false;
1848 i_data_offset = p_sys->circular.i_read % p_sys->circular.i_size;
1849 i_data_size = __MIN( p_sys->circular.i_size - i_data_offset,
1850 p_sys->circular.i_write - p_sys->circular.i_read );
1852 i_ret = AudioTrack_Play( env, p_aout, i_data_size, i_data_offset,
1853 b_forced );
1854 if( i_ret >= 0 )
1856 if( p_sys->i_write_type == WRITE_BYTEARRAY )
1858 if( i_ret != 0 )
1859 i_last_time_blocked = 0;
1860 else if( i_last_time_blocked == 0 )
1861 i_last_time_blocked = vlc_tick_now();
1864 if( i_ret == 0 )
1865 i_play_deadline = vlc_tick_now() + __MAX( 10000, FRAMES_TO_US(
1866 p_sys->i_max_audiotrack_samples / 5 ) );
1867 else
1868 p_sys->circular.i_read += i_ret;
1871 vlc_cond_signal( &p_sys->aout_cond );
1872 vlc_mutex_unlock( &p_sys->lock );
1875 if( p_sys->circular.u.bytebuffer.p_obj )
1877 (*env)->DeleteLocalRef( env, p_sys->circular.u.bytebuffer.p_obj );
1878 p_sys->circular.u.bytebuffer.p_obj = NULL;
1881 return NULL;
1884 static int
1885 ConvertFromIEC61937( audio_output_t *p_aout, block_t *p_buffer )
1887 /* This function is only used for Android API 23 when AudioTrack is
1888 * configured with ENCODING_ AC3/E_AC3/DTS. In that case, only the codec
1889 * data is needed (without the IEC61937 encapsulation). This function
1890 * recovers the codec data from an EC61937 frame. It is the opposite of the
1891 * code found in converter/tospdif.c. We could also request VLC core to
1892 * send us the codec data directly, but in that case, we wouldn't benefit
1893 * from the eac3 block merger of tospdif.c. */
1895 VLC_UNUSED( p_aout );
1896 uint8_t i_length_mul;
1898 if( p_buffer->i_buffer < 6 )
1899 return -1;
1901 switch( GetWBE( &p_buffer->p_buffer[4] ) & 0xFF )
1903 case 0x01: /* IEC61937_AC3 */
1904 i_length_mul = 8;
1905 break;
1906 case 0x15: /* IEC61937_EAC3 */
1907 i_length_mul = 1;
1908 break;
1909 case 0x0B: /* IEC61937_DTS1 */
1910 case 0x0C: /* IEC61937_DTS2 */
1911 case 0x0D: /* IEC61937_DTS3 */
1912 i_length_mul = 8;
1913 break;
1914 case 0x11: /* IEC61937_DTSHD */
1915 i_length_mul = 1;
1916 break;
1917 default:
1918 vlc_assert_unreachable();
1920 uint16_t i_length = GetWBE( &p_buffer->p_buffer[6] );
1921 if( i_length == 0 )
1922 return -1;
1924 i_length /= i_length_mul;
1925 if( i_length > p_buffer->i_buffer - 8 )
1926 return -1;
1928 p_buffer->p_buffer += 8; /* SPDIF_HEADER_SIZE */
1929 p_buffer->i_buffer = i_length;
1931 return 0;
1934 static void
1935 Play( audio_output_t *p_aout, block_t *p_buffer, vlc_tick_t i_date )
1937 JNIEnv *env = NULL;
1938 size_t i_buffer_offset = 0;
1939 aout_sys_t *p_sys = p_aout->sys;
1941 if( p_sys->b_passthrough && p_sys->fmt.i_format == VLC_CODEC_SPDIFB
1942 && ConvertFromIEC61937( p_aout, p_buffer ) != 0 )
1944 block_Release(p_buffer);
1945 return;
1948 vlc_mutex_lock( &p_sys->lock );
1950 if( p_sys->b_error || !( env = GET_ENV() ) )
1951 goto bailout;
1953 if( p_sys->i_chans_to_reorder )
1954 aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
1955 p_sys->i_chans_to_reorder, p_sys->p_chan_table,
1956 p_sys->fmt.i_format );
1958 while( i_buffer_offset < p_buffer->i_buffer && !p_sys->b_error )
1960 size_t i_circular_free;
1961 size_t i_data_offset;
1962 size_t i_data_size;
1964 /* Wait for enough room in circular buffer */
1965 while( !p_sys->b_error && ( i_circular_free = p_sys->circular.i_size -
1966 ( p_sys->circular.i_write - p_sys->circular.i_read ) ) == 0 )
1967 vlc_cond_wait( &p_sys->aout_cond, &p_sys->lock );
1968 if( p_sys->b_error )
1969 goto bailout;
1971 i_data_offset = p_sys->circular.i_write % p_sys->circular.i_size;
1972 i_data_size = __MIN( p_buffer->i_buffer - i_buffer_offset,
1973 p_sys->circular.i_size - i_data_offset );
1974 i_data_size = __MIN( i_data_size, i_circular_free );
1976 switch( p_sys->i_write_type )
1978 case WRITE_BYTEARRAY:
1979 case WRITE_BYTEARRAYV23:
1980 (*env)->SetByteArrayRegion( env, p_sys->circular.u.p_bytearray,
1981 i_data_offset, i_data_size,
1982 (jbyte *)p_buffer->p_buffer
1983 + i_buffer_offset);
1984 break;
1985 case WRITE_SHORTARRAYV23:
1986 i_data_offset &= ~1;
1987 i_data_size &= ~1;
1988 (*env)->SetShortArrayRegion( env, p_sys->circular.u.p_shortarray,
1989 i_data_offset / 2, i_data_size / 2,
1990 (jshort *)p_buffer->p_buffer
1991 + i_buffer_offset / 2);
1992 break;
1993 case WRITE_FLOATARRAY:
1994 i_data_offset &= ~3;
1995 i_data_size &= ~3;
1996 (*env)->SetFloatArrayRegion( env, p_sys->circular.u.p_floatarray,
1997 i_data_offset / 4, i_data_size / 4,
1998 (jfloat *)p_buffer->p_buffer
1999 + i_buffer_offset / 4);
2001 break;
2002 case WRITE_BYTEBUFFER:
2003 memcpy( p_sys->circular.u.bytebuffer.p_data + i_data_offset,
2004 p_buffer->p_buffer + i_buffer_offset, i_data_size );
2005 break;
2008 i_buffer_offset += i_data_size;
2009 p_sys->circular.i_write += i_data_size;
2011 if( !p_sys->b_thread_waiting )
2012 vlc_cond_signal( &p_sys->thread_cond );
2015 bailout:
2016 vlc_mutex_unlock( &p_sys->lock );
2017 block_Release( p_buffer );
2018 (void) i_date;
2021 static void
2022 Pause( audio_output_t *p_aout, bool b_pause, vlc_tick_t i_date )
2024 aout_sys_t *p_sys = p_aout->sys;
2025 JNIEnv *env;
2026 VLC_UNUSED( i_date );
2028 vlc_mutex_lock( &p_sys->lock );
2030 if( p_sys->b_error || !( env = GET_ENV() ) )
2031 goto bailout;
2033 if( b_pause )
2035 p_sys->b_thread_paused = true;
2036 JNI_AT_CALL_VOID( pause );
2037 CHECK_AT_EXCEPTION( "pause" );
2038 } else
2040 p_sys->b_thread_paused = false;
2041 AudioTrack_ResetPositions( env, p_aout );
2042 JNI_AT_CALL_VOID( play );
2043 CHECK_AT_EXCEPTION( "play" );
2046 bailout:
2047 vlc_mutex_unlock( &p_sys->lock );
2050 static void
2051 Flush( audio_output_t *p_aout )
2053 aout_sys_t *p_sys = p_aout->sys;
2054 JNIEnv *env;
2056 vlc_mutex_lock( &p_sys->lock );
2058 if( p_sys->b_error || !( env = GET_ENV() ) )
2059 goto bailout;
2061 /* Android doc:
2062 * stop(): Stops playing the audio data. When used on an instance created
2063 * in MODE_STREAM mode, audio will stop playing after the last buffer that
2064 * was written has been played. For an immediate stop, use pause(),
2065 * followed by flush() to discard audio data that hasn't been played back
2066 * yet.
2068 * flush(): Flushes the audio data currently queued for playback. Any data
2069 * that has not been played back will be discarded. No-op if not stopped
2070 * or paused, or if the track's creation mode is not MODE_STREAM.
2072 JNI_AT_CALL_VOID( pause );
2073 if( CHECK_AT_EXCEPTION( "pause" ) )
2074 goto bailout;
2075 JNI_AT_CALL_VOID( flush );
2076 p_sys->circular.i_read = p_sys->circular.i_write = 0;
2078 /* HACK: Before Android 4.4, the head position is not reset to zero and is
2079 * still moving after a flush or a stop. This prevents to get a precise
2080 * head position and there is no way to know when it stabilizes. Therefore
2081 * recreate an AudioTrack object in that case. The AudioTimestamp class was
2082 * added in API Level 19, so if this class is not found, the Android
2083 * Version is 4.3 or before */
2084 if( !jfields.AudioTimestamp.clazz && p_sys->i_samples_written > 0 )
2086 if( AudioTrack_Recreate( env, p_aout ) != 0 )
2088 p_sys->b_error = true;
2089 goto bailout;
2092 AudioTrack_Reset( env, p_aout );
2093 JNI_AT_CALL_VOID( play );
2094 CHECK_AT_EXCEPTION( "play" );
2096 bailout:
2097 vlc_mutex_unlock( &p_sys->lock );
2100 static int
2101 VolumeSet( audio_output_t *p_aout, float volume )
2103 aout_sys_t *p_sys = p_aout->sys;
2104 JNIEnv *env;
2105 float gain = 1.0f;
2107 if (volume > 1.f)
2109 p_sys->volume = 1.f;
2110 gain = volume;
2112 else
2113 p_sys->volume = volume;
2115 if( !p_sys->b_error && p_sys->p_audiotrack != NULL && ( env = GET_ENV() ) )
2117 if( jfields.AudioTrack.setVolume )
2119 JNI_AT_CALL_INT( setVolume, volume );
2120 CHECK_AT_EXCEPTION( "setVolume" );
2121 } else
2123 JNI_AT_CALL_INT( setStereoVolume, volume, volume );
2124 CHECK_AT_EXCEPTION( "setStereoVolume" );
2127 aout_VolumeReport(p_aout, volume);
2128 aout_GainRequest(p_aout, gain * gain * gain);
2129 return 0;
2132 static int
2133 MuteSet( audio_output_t *p_aout, bool mute )
2135 aout_sys_t *p_sys = p_aout->sys;
2136 JNIEnv *env;
2137 p_sys->mute = mute;
2139 if( !p_sys->b_error && p_sys->p_audiotrack != NULL && ( env = GET_ENV() ) )
2141 if( jfields.AudioTrack.setVolume )
2143 JNI_AT_CALL_INT( setVolume, mute ? 0.0f : p_sys->volume );
2144 CHECK_AT_EXCEPTION( "setVolume" );
2145 } else
2147 JNI_AT_CALL_INT( setStereoVolume, mute ? 0.0f : p_sys->volume, mute ? 0.0f : p_sys->volume );
2148 CHECK_AT_EXCEPTION( "setStereoVolume" );
2151 aout_MuteReport(p_aout, mute);
2152 return 0;
2155 static int DeviceSelect(audio_output_t *p_aout, const char *p_id)
2157 aout_sys_t *p_sys = p_aout->sys;
2158 enum at_dev at_dev = AT_DEV_DEFAULT;
2160 if( p_id )
2162 for( unsigned int i = 0; at_devs[i].id; ++i )
2164 if( strncmp( p_id, at_devs[i].id, strlen( at_devs[i].id ) ) == 0 )
2166 at_dev = at_devs[i].at_dev;
2167 break;
2172 long long i_encoding_flags = 0;
2173 if( at_dev == AT_DEV_ENCODED )
2175 const size_t i_prefix_size = strlen( "encoded:" );
2176 if( strncmp( p_id, "encoded:", i_prefix_size ) == 0 )
2177 i_encoding_flags = atoll( p_id + i_prefix_size );
2180 if( at_dev != p_sys->at_dev || i_encoding_flags != p_sys->i_encoding_flags )
2182 p_sys->at_dev = at_dev;
2183 p_sys->i_encoding_flags = i_encoding_flags;
2184 aout_RestartRequest( p_aout, AOUT_RESTART_OUTPUT );
2185 msg_Dbg( p_aout, "selected device: %s", p_id );
2187 if( at_dev == AT_DEV_ENCODED )
2189 static const vlc_fourcc_t enc_fourccs[] = {
2190 VLC_CODEC_DTS, VLC_CODEC_DTSHD, VLC_CODEC_A52, VLC_CODEC_EAC3,
2191 VLC_CODEC_TRUEHD,
2193 for( size_t i = 0;
2194 i < sizeof( enc_fourccs ) / sizeof( enc_fourccs[0] ); ++i )
2196 if( AudioTrack_HasEncoding( p_aout, enc_fourccs[i] ) )
2197 msg_Dbg( p_aout, "device has %4.4s passthrough support",
2198 (const char *)&enc_fourccs[i] );
2202 aout_DeviceReport( p_aout, p_id );
2203 return VLC_SUCCESS;
2206 static int
2207 Open( vlc_object_t *obj )
2209 audio_output_t *p_aout = (audio_output_t *) obj;
2210 aout_sys_t *p_sys;
2211 JNIEnv *env = GET_ENV();
2213 if( !env || !InitJNIFields( p_aout, env ) )
2214 return VLC_EGENERIC;
2216 p_sys = calloc( 1, sizeof (aout_sys_t) );
2218 if( unlikely( p_sys == NULL ) )
2219 return VLC_ENOMEM;
2221 p_sys->at_dev = AT_DEV_DEFAULT;
2222 vlc_mutex_init(&p_sys->lock);
2223 vlc_cond_init(&p_sys->aout_cond);
2224 vlc_cond_init(&p_sys->thread_cond);
2226 p_aout->sys = p_sys;
2227 p_aout->start = Start;
2228 p_aout->stop = Stop;
2229 p_aout->play = Play;
2230 p_aout->pause = Pause;
2231 p_aout->flush = Flush;
2232 p_aout->time_get = TimeGet;
2233 p_aout->device_select = DeviceSelect;
2235 for( unsigned int i = 0; at_devs[i].id; ++i )
2236 aout_HotplugReport(p_aout, at_devs[i].id, at_devs[i].name);
2238 p_aout->volume_set = VolumeSet;
2239 p_aout->mute_set = MuteSet;
2240 p_sys->volume = 1.0f;
2241 p_sys->mute = false;
2243 return VLC_SUCCESS;
2246 static void
2247 Close( vlc_object_t *obj )
2249 audio_output_t *p_aout = (audio_output_t *) obj;
2250 aout_sys_t *p_sys = p_aout->sys;
2252 free( p_sys );