input: add an input_item_t arg to input_CreateFilename()
[vlc.git] / modules / audio_output / audiotrack.c
blob58c08b8e7b5e758d321da8d235118d11f6c2b9fb
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 /* sw gain */
85 float soft_gain;
86 bool soft_mute;
88 enum at_dev at_dev;
90 jobject p_audiotrack; /* AudioTrack ref */
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 uint32_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;
111 jlong i_frame_pos;
112 vlc_tick_t i_play_time; /* time when play was called */
113 vlc_tick_t i_last_time;
114 } timestamp;
116 /* Used by AudioTrack_GetSmoothPositionUs */
117 struct {
118 uint32_t i_idx;
119 uint32_t i_count;
120 vlc_tick_t p_us[SMOOTHPOS_SAMPLE_COUNT];
121 vlc_tick_t i_us;
122 vlc_tick_t i_last_time;
123 vlc_tick_t i_latency_us;
124 } smoothpos;
126 uint32_t i_max_audiotrack_samples;
127 long long i_encoding_flags;
128 bool b_passthrough;
129 uint8_t i_chans_to_reorder; /* do we need channel reordering */
130 uint8_t p_chan_table[AOUT_CHAN_MAX];
132 enum {
133 WRITE_BYTEARRAY,
134 WRITE_BYTEARRAYV23,
135 WRITE_SHORTARRAYV23,
136 WRITE_BYTEBUFFER,
137 WRITE_FLOATARRAY
138 } i_write_type;
140 vlc_thread_t thread; /* AudioTrack_Thread */
141 vlc_mutex_t lock;
142 vlc_cond_t aout_cond; /* cond owned by aout */
143 vlc_cond_t thread_cond; /* cond owned by AudioTrack_Thread */
145 /* These variables need locking on read and write */
146 bool b_thread_running; /* Set to false by aout to stop the thread */
147 bool b_thread_paused; /* If true, the thread won't process any data, see
148 * Pause() */
149 bool b_thread_waiting; /* If true, the thread is waiting for enough spaces
150 * in AudioTrack internal buffers */
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;
172 /* Soft volume helper */
173 #include "audio_output/volume.h"
175 // Don't use Float for now since 5.1/7.1 Float is down sampled to Stereo Float
176 //#define AUDIOTRACK_USE_FLOAT
177 //#define AUDIOTRACK_HW_LATENCY
179 /* Get AudioTrack native sample rate: if activated, most of the resampling
180 * will be done by VLC */
181 #define AUDIOTRACK_NATIVE_SAMPLERATE
183 #define AUDIOTRACK_SESSION_ID_TEXT " Id of audio session the AudioTrack must be attached to"
185 vlc_module_begin ()
186 set_shortname( "AudioTrack" )
187 set_description( "Android AudioTrack audio output" )
188 set_capability( "audio output", 180 )
189 set_category( CAT_AUDIO )
190 set_subcategory( SUBCAT_AUDIO_AOUT )
191 add_integer( "audiotrack-session-id", 0,
192 AUDIOTRACK_SESSION_ID_TEXT, NULL, true )
193 change_private()
194 add_sw_gain()
195 add_shortcut( "audiotrack" )
196 set_callbacks( Open, Close )
197 vlc_module_end ()
199 #define THREAD_NAME "android_audiotrack"
200 #define GET_ENV() android_getEnv( VLC_OBJECT(p_aout), THREAD_NAME )
202 static struct
204 struct {
205 jclass clazz;
206 jmethodID ctor;
207 jmethodID release;
208 jmethodID getState;
209 jmethodID play;
210 jmethodID stop;
211 jmethodID flush;
212 jmethodID pause;
213 jmethodID write;
214 jmethodID writeV23;
215 jmethodID writeShortV23;
216 jmethodID writeBufferV21;
217 jmethodID writeFloat;
218 jmethodID getPlaybackHeadPosition;
219 jmethodID getTimestamp;
220 jmethodID getMinBufferSize;
221 jmethodID getNativeOutputSampleRate;
222 jint STATE_INITIALIZED;
223 jint MODE_STREAM;
224 jint ERROR;
225 jint ERROR_BAD_VALUE;
226 jint ERROR_INVALID_OPERATION;
227 jint WRITE_NON_BLOCKING;
228 } AudioTrack;
229 struct {
230 jint ENCODING_PCM_8BIT;
231 jint ENCODING_PCM_16BIT;
232 jint ENCODING_PCM_FLOAT;
233 bool has_ENCODING_PCM_FLOAT;
234 jint ENCODING_AC3;
235 bool has_ENCODING_AC3;
236 jint ENCODING_E_AC3;
237 bool has_ENCODING_E_AC3;
238 jint ENCODING_DOLBY_TRUEHD;
239 bool has_ENCODING_DOLBY_TRUEHD;
240 jint ENCODING_DTS;
241 bool has_ENCODING_DTS;
242 jint ENCODING_DTS_HD;
243 bool has_ENCODING_DTS_HD;
244 jint ENCODING_IEC61937;
245 bool has_ENCODING_IEC61937;
246 jint CHANNEL_OUT_MONO;
247 jint CHANNEL_OUT_STEREO;
248 jint CHANNEL_OUT_FRONT_LEFT;
249 jint CHANNEL_OUT_FRONT_RIGHT;
250 jint CHANNEL_OUT_BACK_LEFT;
251 jint CHANNEL_OUT_BACK_RIGHT;
252 jint CHANNEL_OUT_FRONT_CENTER;
253 jint CHANNEL_OUT_LOW_FREQUENCY;
254 jint CHANNEL_OUT_BACK_CENTER;
255 jint CHANNEL_OUT_5POINT1;
256 jint CHANNEL_OUT_SIDE_LEFT;
257 jint CHANNEL_OUT_SIDE_RIGHT;
258 bool has_CHANNEL_OUT_SIDE;
259 } AudioFormat;
260 struct {
261 jint ERROR_DEAD_OBJECT;
262 bool has_ERROR_DEAD_OBJECT;
263 jint STREAM_MUSIC;
264 } AudioManager;
265 struct {
266 jclass clazz;
267 jmethodID getOutputLatency;
268 } AudioSystem;
269 struct {
270 jclass clazz;
271 jmethodID ctor;
272 jfieldID framePosition;
273 jfieldID nanoTime;
274 } AudioTimestamp;
275 } jfields;
277 /* init all jni fields.
278 * Done only one time during the first initialisation */
279 static bool
280 InitJNIFields( audio_output_t *p_aout, JNIEnv* env )
282 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
283 static int i_init_state = -1;
284 bool ret;
285 jclass clazz;
286 jfieldID field;
288 vlc_mutex_lock( &lock );
290 if( i_init_state != -1 )
291 goto end;
293 #define CHECK_EXCEPTION( what, critical ) do { \
294 if( (*env)->ExceptionCheck( env ) ) \
296 msg_Err( p_aout, "%s failed", what ); \
297 (*env)->ExceptionClear( env ); \
298 if( (critical) ) \
300 i_init_state = 0; \
301 goto end; \
304 } while( 0 )
305 #define GET_CLASS( str, critical ) do { \
306 clazz = (*env)->FindClass( env, (str) ); \
307 CHECK_EXCEPTION( "FindClass(" str ")", critical ); \
308 } while( 0 )
309 #define GET_ID( get, id, str, args, critical ) do { \
310 jfields.id = (*env)->get( env, clazz, (str), (args) ); \
311 CHECK_EXCEPTION( #get "(" #id ")", critical ); \
312 } while( 0 )
313 #define GET_CONST_INT( id, str, critical ) do { \
314 field = NULL; \
315 field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
316 CHECK_EXCEPTION( "GetStaticFieldID(" #id ")", critical ); \
317 if( field ) \
319 jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
320 CHECK_EXCEPTION( #id, critical ); \
322 } while( 0 )
324 /* AudioTrack class init */
325 GET_CLASS( "android/media/AudioTrack", true );
326 jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
327 CHECK_EXCEPTION( "NewGlobalRef", true );
329 GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIIII)V", true );
330 GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true );
331 GET_ID( GetMethodID, AudioTrack.getState, "getState", "()I", true );
332 GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true );
333 GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true );
334 GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true );
335 GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true );
337 GET_ID( GetMethodID, AudioTrack.writeV23, "write", "([BIII)I", false );
338 GET_ID( GetMethodID, AudioTrack.writeShortV23, "write", "([SIII)I", false );
339 if( !jfields.AudioTrack.writeV23 )
340 GET_ID( GetMethodID, AudioTrack.writeBufferV21, "write", "(Ljava/nio/ByteBuffer;II)I", false );
342 if( jfields.AudioTrack.writeV23 || jfields.AudioTrack.writeBufferV21 )
344 GET_CONST_INT( AudioTrack.WRITE_NON_BLOCKING, "WRITE_NON_BLOCKING", true );
345 #ifdef AUDIOTRACK_USE_FLOAT
346 GET_ID( GetMethodID, AudioTrack.writeFloat, "write", "([FIII)I", true );
347 #endif
348 } else
349 GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
351 GET_ID( GetMethodID, AudioTrack.getTimestamp,
352 "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
353 GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
354 "getPlaybackHeadPosition", "()I", true );
356 GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize",
357 "(III)I", true );
358 #ifdef AUDIOTRACK_NATIVE_SAMPLERATE
359 GET_ID( GetStaticMethodID, AudioTrack.getNativeOutputSampleRate,
360 "getNativeOutputSampleRate", "(I)I", true );
361 #endif
362 GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true );
363 GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
364 GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
365 GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true );
366 GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION,
367 "ERROR_INVALID_OPERATION", true );
369 /* AudioTimestamp class init (if any) */
370 if( jfields.AudioTrack.getTimestamp )
372 GET_CLASS( "android/media/AudioTimestamp", true );
373 jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env,
374 clazz );
375 CHECK_EXCEPTION( "NewGlobalRef", true );
377 GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true );
378 GET_ID( GetFieldID, AudioTimestamp.framePosition,
379 "framePosition", "J", true );
380 GET_ID( GetFieldID, AudioTimestamp.nanoTime,
381 "nanoTime", "J", true );
384 #ifdef AUDIOTRACK_HW_LATENCY
385 /* AudioSystem class init */
386 GET_CLASS( "android/media/AudioSystem", false );
387 if( clazz )
389 jfields.AudioSystem.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
390 GET_ID( GetStaticMethodID, AudioSystem.getOutputLatency,
391 "getOutputLatency", "(I)I", false );
393 #endif
395 /* AudioFormat class init */
396 GET_CLASS( "android/media/AudioFormat", true );
397 GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
398 GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
399 #ifdef AUDIOTRACK_USE_FLOAT
400 GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
401 false );
402 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL &&
403 jfields.AudioTrack.writeFloat;
404 #else
405 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
406 #endif
408 if( jfields.AudioTrack.writeShortV23 )
410 GET_CONST_INT( AudioFormat.ENCODING_IEC61937, "ENCODING_IEC61937", false );
411 jfields.AudioFormat.has_ENCODING_IEC61937 = field != NULL;
413 else
414 jfields.AudioFormat.has_ENCODING_IEC61937 = false;
416 GET_CONST_INT( AudioFormat.ENCODING_AC3, "ENCODING_AC3", false );
417 jfields.AudioFormat.has_ENCODING_AC3 = field != NULL;
418 GET_CONST_INT( AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3", false );
419 jfields.AudioFormat.has_ENCODING_E_AC3 = field != NULL;
421 GET_CONST_INT( AudioFormat.ENCODING_DTS, "ENCODING_DTS", false );
422 jfields.AudioFormat.has_ENCODING_DTS = field != NULL;
423 GET_CONST_INT( AudioFormat.ENCODING_DTS_HD, "ENCODING_DTS_HD", false );
424 jfields.AudioFormat.has_ENCODING_DTS_HD = field != NULL;
426 GET_CONST_INT( AudioFormat.ENCODING_DOLBY_TRUEHD, "ENCODING_DOLBY_TRUEHD",
427 false );
428 jfields.AudioFormat.has_ENCODING_DOLBY_TRUEHD = field != NULL;
430 GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
431 GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
432 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_LEFT, "CHANNEL_OUT_FRONT_LEFT", true );
433 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_RIGHT, "CHANNEL_OUT_FRONT_RIGHT", true );
434 GET_CONST_INT( AudioFormat.CHANNEL_OUT_5POINT1, "CHANNEL_OUT_5POINT1", true );
435 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_LEFT, "CHANNEL_OUT_BACK_LEFT", true );
436 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_RIGHT, "CHANNEL_OUT_BACK_RIGHT", true );
437 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_CENTER, "CHANNEL_OUT_FRONT_CENTER", true );
438 GET_CONST_INT( AudioFormat.CHANNEL_OUT_LOW_FREQUENCY, "CHANNEL_OUT_LOW_FREQUENCY", true );
439 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_CENTER, "CHANNEL_OUT_BACK_CENTER", true );
440 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_LEFT, "CHANNEL_OUT_SIDE_LEFT", false );
441 if( field != NULL )
443 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_RIGHT, "CHANNEL_OUT_SIDE_RIGHT", true );
444 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = true;
445 } else
446 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = false;
448 /* AudioManager class init */
449 GET_CLASS( "android/media/AudioManager", true );
450 GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false );
451 jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
452 GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
454 #undef CHECK_EXCEPTION
455 #undef GET_CLASS
456 #undef GET_ID
457 #undef GET_CONST_INT
459 i_init_state = 1;
460 end:
461 ret = i_init_state == 1;
462 if( !ret )
463 msg_Err( p_aout, "AudioTrack jni init failed" );
464 vlc_mutex_unlock( &lock );
465 return ret;
468 static inline bool
469 check_exception( JNIEnv *env, audio_output_t *p_aout,
470 const char *method )
472 if( (*env)->ExceptionCheck( env ) )
474 aout_sys_t *p_sys = p_aout->sys;
476 p_sys->b_audiotrack_exception = true;
477 p_sys->b_error = true;
478 (*env)->ExceptionDescribe( env );
479 (*env)->ExceptionClear( env );
480 msg_Err( p_aout, "AudioTrack.%s triggered an exception !", method );
481 return true;
482 } else
483 return false;
485 #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, method )
487 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
489 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
490 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
491 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
492 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
494 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
495 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
496 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
497 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
498 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
500 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->timestamp.p_obj, jfields.AudioTimestamp.field )
502 static inline vlc_tick_t
503 frames_to_us( aout_sys_t *p_sys, uint64_t i_nb_frames )
505 return i_nb_frames * CLOCK_FREQ / p_sys->fmt.i_rate;
507 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
509 static inline uint64_t
510 bytes_to_frames( aout_sys_t *p_sys, size_t i_bytes )
512 return i_bytes * p_sys->fmt.i_frame_length / p_sys->fmt.i_bytes_per_frame;
514 #define BYTES_TO_FRAMES(x) bytes_to_frames( p_sys, (x) )
515 #define BYTES_TO_US(x) frames_to_us( p_sys, bytes_to_frames( p_sys, (x) ) )
517 static inline size_t
518 frames_to_bytes( aout_sys_t *p_sys, uint64_t i_frames )
520 return i_frames * p_sys->fmt.i_bytes_per_frame / p_sys->fmt.i_frame_length;
522 #define FRAMES_TO_BYTES(x) frames_to_bytes( p_sys, (x) )
525 * Get the AudioTrack position
527 * The doc says that the position is reset to zero after flush but it's not
528 * true for all devices or Android versions.
530 static uint64_t
531 AudioTrack_getPlaybackHeadPosition( JNIEnv *env, audio_output_t *p_aout )
533 /* Android doc:
534 * getPlaybackHeadPosition: Returns the playback head position expressed in
535 * frames. Though the "int" type is signed 32-bits, the value should be
536 * reinterpreted as if it is unsigned 32-bits. That is, the next position
537 * after 0x7FFFFFFF is (int) 0x80000000. This is a continuously advancing
538 * counter. It will wrap (overflow) periodically, for example approximately
539 * once every 27:03:11 hours:minutes:seconds at 44.1 kHz. It is reset to
540 * zero by flush(), reload(), and stop().
543 aout_sys_t *p_sys = p_aout->sys;
544 uint32_t i_pos;
546 /* int32_t to uint32_t */
547 i_pos = 0xFFFFFFFFL & JNI_AT_CALL_INT( getPlaybackHeadPosition );
549 /* uint32_t to uint64_t */
550 if( p_sys->headpos.i_last > i_pos )
551 p_sys->headpos.i_wrap_count++;
552 p_sys->headpos.i_last = i_pos;
553 return p_sys->headpos.i_last + ((uint64_t)p_sys->headpos.i_wrap_count << 32);
557 * Reset AudioTrack position
559 * Called after flush, or start
561 static void
562 AudioTrack_ResetPlaybackHeadPosition( JNIEnv *env, audio_output_t *p_aout )
564 (void) env;
565 aout_sys_t *p_sys = p_aout->sys;
567 p_sys->headpos.i_last = 0;
568 p_sys->headpos.i_wrap_count = 0;
572 * Reset AudioTrack SmoothPosition and TimestampPosition
574 static void
575 AudioTrack_ResetPositions( JNIEnv *env, audio_output_t *p_aout )
577 aout_sys_t *p_sys = p_aout->sys;
578 VLC_UNUSED( env );
580 p_sys->timestamp.i_play_time = vlc_tick_now();
581 p_sys->timestamp.i_last_time = 0;
582 p_sys->timestamp.i_frame_us = 0;
583 p_sys->timestamp.i_frame_pos = 0;
585 p_sys->smoothpos.i_count = 0;
586 p_sys->smoothpos.i_idx = 0;
587 p_sys->smoothpos.i_last_time = 0;
588 p_sys->smoothpos.i_us = 0;
589 p_sys->smoothpos.i_latency_us = 0;
593 * Reset all AudioTrack positions and internal state
595 static void
596 AudioTrack_Reset( JNIEnv *env, audio_output_t *p_aout )
598 aout_sys_t *p_sys = p_aout->sys;
600 AudioTrack_ResetPositions( env, p_aout );
601 AudioTrack_ResetPlaybackHeadPosition( env, p_aout );
602 p_sys->i_samples_written = 0;
606 * Get a smooth AudioTrack position
608 * This function smooth out the AudioTrack position since it has a very bad
609 * precision (+/- 20ms on old devices).
611 static vlc_tick_t
612 AudioTrack_GetSmoothPositionUs( JNIEnv *env, audio_output_t *p_aout )
614 aout_sys_t *p_sys = p_aout->sys;
615 uint64_t i_audiotrack_us;
616 vlc_tick_t i_now = vlc_tick_now();
618 /* Fetch an AudioTrack position every SMOOTHPOS_INTERVAL_US (30ms) */
619 if( i_now - p_sys->smoothpos.i_last_time >= SMOOTHPOS_INTERVAL_US )
621 i_audiotrack_us = FRAMES_TO_US( AudioTrack_getPlaybackHeadPosition( env, p_aout ) );
623 p_sys->smoothpos.i_last_time = i_now;
625 /* Base the position off the current time */
626 p_sys->smoothpos.p_us[p_sys->smoothpos.i_idx] = i_audiotrack_us - i_now;
627 p_sys->smoothpos.i_idx = (p_sys->smoothpos.i_idx + 1)
628 % SMOOTHPOS_SAMPLE_COUNT;
629 if( p_sys->smoothpos.i_count < SMOOTHPOS_SAMPLE_COUNT )
630 p_sys->smoothpos.i_count++;
632 /* Calculate the average position based off the current time */
633 p_sys->smoothpos.i_us = 0;
634 for( uint32_t i = 0; i < p_sys->smoothpos.i_count; ++i )
635 p_sys->smoothpos.i_us += p_sys->smoothpos.p_us[i];
636 p_sys->smoothpos.i_us /= p_sys->smoothpos.i_count;
638 if( jfields.AudioSystem.getOutputLatency )
640 int i_latency_ms = JNI_CALL( CallStaticIntMethod,
641 jfields.AudioSystem.clazz,
642 jfields.AudioSystem.getOutputLatency,
643 jfields.AudioManager.STREAM_MUSIC );
645 p_sys->smoothpos.i_latency_us = i_latency_ms > 0 ?
646 i_latency_ms * 1000L : 0;
649 if( p_sys->smoothpos.i_us != 0 )
650 return p_sys->smoothpos.i_us + i_now - p_sys->smoothpos.i_latency_us;
651 else
652 return 0;
655 static vlc_tick_t
656 AudioTrack_GetTimestampPositionUs( JNIEnv *env, audio_output_t *p_aout )
658 aout_sys_t *p_sys = p_aout->sys;
659 vlc_tick_t i_now;
661 if( !p_sys->timestamp.p_obj )
662 return 0;
664 i_now = vlc_tick_now();
666 /* Android doc:
667 * getTimestamp: Poll for a timestamp on demand.
669 * If you need to track timestamps during initial warmup or after a
670 * routing or mode change, you should request a new timestamp once per
671 * second until the reported timestamps show that the audio clock is
672 * stable. Thereafter, query for a new timestamp approximately once
673 * every 10 seconds to once per minute. Calling this method more often
674 * is inefficient. It is also counter-productive to call this method
675 * more often than recommended, because the short-term differences
676 * between successive timestamp reports are not meaningful. If you need
677 * a high-resolution mapping between frame position and presentation
678 * time, consider implementing that at application level, based on
679 * low-resolution timestamps.
682 /* Fetch an AudioTrack timestamp every AUDIOTIMESTAMP_INTERVAL_US (500ms) */
683 if( i_now - p_sys->timestamp.i_last_time >= AUDIOTIMESTAMP_INTERVAL_US )
685 p_sys->timestamp.i_last_time = i_now;
687 if( JNI_AT_CALL_BOOL( getTimestamp, p_sys->timestamp.p_obj ) )
689 p_sys->timestamp.i_frame_us = VLC_TICK_FROM_NS(JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime ));
690 p_sys->timestamp.i_frame_pos = JNI_AUDIOTIMESTAMP_GET_LONG( framePosition );
692 else
694 p_sys->timestamp.i_frame_us = 0;
695 p_sys->timestamp.i_frame_pos = 0;
699 /* frame time should be after last play time
700 * frame time shouldn't be in the future
701 * frame time should be less than 10 seconds old */
702 if( p_sys->timestamp.i_frame_us != 0 && p_sys->timestamp.i_frame_pos != 0
703 && p_sys->timestamp.i_frame_us > p_sys->timestamp.i_play_time
704 && i_now > p_sys->timestamp.i_frame_us
705 && ( i_now - p_sys->timestamp.i_frame_us ) <= VLC_TICK_FROM_SEC(10) )
707 jlong i_time_diff = i_now - p_sys->timestamp.i_frame_us;
708 jlong i_frames_diff = i_time_diff * p_sys->fmt.i_rate / CLOCK_FREQ;
709 return FRAMES_TO_US( p_sys->timestamp.i_frame_pos + i_frames_diff );
710 } else
711 return 0;
714 static int
715 TimeGet( audio_output_t *p_aout, vlc_tick_t *restrict p_delay )
717 aout_sys_t *p_sys = p_aout->sys;
718 vlc_tick_t i_audiotrack_us;
719 JNIEnv *env;
721 if( p_sys->b_passthrough )
722 return -1;
724 vlc_mutex_lock( &p_sys->lock );
726 if( p_sys->b_error || !p_sys->i_samples_written || !( env = GET_ENV() ) )
727 goto bailout;
729 i_audiotrack_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
731 if( i_audiotrack_us <= 0 )
732 i_audiotrack_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
734 /* Debug log for both delays */
735 #if 0
737 vlc_tick_t i_written_us = FRAMES_TO_US( p_sys->i_samples_written );
738 vlc_tick_t i_ts_us = AudioTrack_GetTimestampPositionUs( env, p_aout );
739 vlc_tick_t i_smooth_us = 0;
741 if( i_ts_us > 0 )
742 i_smooth_us = AudioTrack_GetSmoothPositionUs(env, p_aout );
743 else if ( p_sys->smoothpos.i_us != 0 )
744 i_smooth_us = p_sys->smoothpos.i_us + vlc_tick_now()
745 - p_sys->smoothpos.i_latency_us;
747 msg_Err( p_aout, "TimeGet: TimeStamp: %lld, Smooth: %lld (latency: %lld)",
748 i_ts_us ? i_written_us - i_ts_us : 0,
749 i_smooth_us ? i_written_us - i_smooth_us : 0,
750 p_sys->smoothpos.i_latency_us );
752 #endif
754 if( i_audiotrack_us > 0 )
756 /* AudioTrack delay */
757 vlc_tick_t i_delay = FRAMES_TO_US( p_sys->i_samples_written )
758 - i_audiotrack_us;
759 if( i_delay >= 0 )
761 /* Circular buffer delay */
762 i_delay += BYTES_TO_US( p_sys->circular.i_write
763 - p_sys->circular.i_read );
764 *p_delay = i_delay;
765 vlc_mutex_unlock( &p_sys->lock );
766 return 0;
768 else
770 msg_Warn( p_aout, "timing screwed, reset positions" );
771 AudioTrack_ResetPositions( env, p_aout );
775 bailout:
776 vlc_mutex_unlock( &p_sys->lock );
777 return -1;
780 static void
781 AudioTrack_GetChanOrder( uint16_t i_physical_channels, uint32_t p_chans_out[] )
783 #define HAS_CHAN( x ) ( ( i_physical_channels & (x) ) == (x) )
784 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
785 int i = 0;
787 if( HAS_CHAN( AOUT_CHAN_LEFT ) )
788 p_chans_out[i++] = AOUT_CHAN_LEFT;
789 if( HAS_CHAN( AOUT_CHAN_RIGHT ) )
790 p_chans_out[i++] = AOUT_CHAN_RIGHT;
792 if( HAS_CHAN( AOUT_CHAN_CENTER ) )
793 p_chans_out[i++] = AOUT_CHAN_CENTER;
795 if( HAS_CHAN( AOUT_CHAN_LFE ) )
796 p_chans_out[i++] = AOUT_CHAN_LFE;
798 if( HAS_CHAN( AOUT_CHAN_REARLEFT ) )
799 p_chans_out[i++] = AOUT_CHAN_REARLEFT;
800 if( HAS_CHAN( AOUT_CHAN_REARRIGHT ) )
801 p_chans_out[i++] = AOUT_CHAN_REARRIGHT;
803 if( HAS_CHAN( AOUT_CHAN_REARCENTER ) )
804 p_chans_out[i++] = AOUT_CHAN_REARCENTER;
806 if( HAS_CHAN( AOUT_CHAN_MIDDLELEFT ) )
807 p_chans_out[i++] = AOUT_CHAN_MIDDLELEFT;
808 if( HAS_CHAN( AOUT_CHAN_MIDDLERIGHT ) )
809 p_chans_out[i++] = AOUT_CHAN_MIDDLERIGHT;
811 assert( i <= AOUT_CHAN_MAX );
812 #undef HAS_CHAN
816 * Create an Android AudioTrack.
817 * returns -1 on error, 0 on success.
819 static int
820 AudioTrack_New( JNIEnv *env, audio_output_t *p_aout, unsigned int i_rate,
821 int i_channel_config, int i_format, int i_size )
823 aout_sys_t *p_sys = p_aout->sys;
824 jint session_id = var_InheritInteger( p_aout, "audiotrack-session-id" );
825 jobject p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC,
826 i_rate, i_channel_config, i_format,
827 i_size, jfields.AudioTrack.MODE_STREAM,
828 session_id );
829 if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
831 msg_Warn( p_aout, "AudioTrack Init failed" ) ;
832 return -1;
834 if( JNI_CALL_INT( p_audiotrack, jfields.AudioTrack.getState )
835 != jfields.AudioTrack.STATE_INITIALIZED )
837 JNI_CALL_VOID( p_audiotrack, jfields.AudioTrack.release );
838 (*env)->DeleteLocalRef( env, p_audiotrack );
839 msg_Err( p_aout, "AudioTrack getState failed" );
840 return -1;
843 p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
844 (*env)->DeleteLocalRef( env, p_audiotrack );
845 if( !p_sys->p_audiotrack )
846 return -1;
848 return 0;
852 * Destroy and recreate an Android AudioTrack using the same arguments.
853 * returns -1 on error, 0 on success.
855 static int
856 AudioTrack_Recreate( JNIEnv *env, audio_output_t *p_aout )
858 aout_sys_t *p_sys = p_aout->sys;
860 JNI_AT_CALL_VOID( release );
861 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
862 p_sys->p_audiotrack = NULL;
863 return AudioTrack_New( env, p_aout, p_sys->audiotrack_args.i_rate,
864 p_sys->audiotrack_args.i_channel_config,
865 p_sys->audiotrack_args.i_format,
866 p_sys->audiotrack_args.i_size );
870 * Configure and create an Android AudioTrack.
871 * returns -1 on configuration error, 0 on success.
873 static int
874 AudioTrack_Create( JNIEnv *env, audio_output_t *p_aout,
875 unsigned int i_rate,
876 int i_format,
877 uint16_t i_physical_channels )
879 aout_sys_t *p_sys = p_aout->sys;
880 int i_size, i_min_buffer_size, i_channel_config;
882 switch( i_physical_channels )
884 case AOUT_CHANS_7_1:
885 /* bitmask of CHANNEL_OUT_7POINT1 doesn't correspond to 5POINT1 and
886 * SIDES */
887 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1 |
888 jfields.AudioFormat.CHANNEL_OUT_SIDE_LEFT |
889 jfields.AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
890 break;
891 case AOUT_CHANS_5_1:
892 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1;
893 break;
894 case AOUT_CHAN_LEFT:
895 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_MONO;
896 break;
897 case AOUT_CHANS_STEREO:
898 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_STEREO;
899 break;
900 default:
901 vlc_assert_unreachable();
904 i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize, i_rate,
905 i_channel_config, i_format );
906 if( i_min_buffer_size <= 0 )
908 msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
909 return -1;
911 i_size = i_min_buffer_size * 2;
913 /* create AudioTrack object */
914 if( AudioTrack_New( env, p_aout, i_rate, i_channel_config,
915 i_format , i_size ) != 0 )
916 return -1;
918 p_sys->audiotrack_args.i_rate = i_rate;
919 p_sys->audiotrack_args.i_channel_config = i_channel_config;
920 p_sys->audiotrack_args.i_format = i_format;
921 p_sys->audiotrack_args.i_size = i_size;
923 return 0;
926 static bool
927 AudioTrack_HasEncoding( audio_output_t *p_aout, vlc_fourcc_t i_format,
928 bool *p_dtshd )
930 aout_sys_t *p_sys = p_aout->sys;
932 #define MATCH_ENCODING_FLAG(x) jfields.AudioFormat.has_##x && \
933 ( p_sys->i_encoding_flags == 0 || p_sys->i_encoding_flags & (1 << jfields.AudioFormat.x) )
935 *p_dtshd = false;
936 switch( i_format )
938 case VLC_CODEC_DTS:
939 if( MATCH_ENCODING_FLAG( ENCODING_DTS_HD )
940 && var_GetBool( p_aout, "dtshd" ) )
942 *p_dtshd = true;
943 return true;
945 return MATCH_ENCODING_FLAG( ENCODING_DTS );
946 case VLC_CODEC_A52:
947 return MATCH_ENCODING_FLAG( ENCODING_AC3 );
948 case VLC_CODEC_EAC3:
949 return MATCH_ENCODING_FLAG( ENCODING_E_AC3 );
950 case VLC_CODEC_TRUEHD:
951 case VLC_CODEC_MLP:
952 return MATCH_ENCODING_FLAG( ENCODING_DOLBY_TRUEHD );
953 default:
954 return false;
958 static int
959 StartPassthrough( JNIEnv *env, audio_output_t *p_aout )
961 aout_sys_t *p_sys = p_aout->sys;
962 int i_at_format;
964 if( jfields.AudioFormat.has_ENCODING_IEC61937 )
966 bool b_dtshd;
967 if( !AudioTrack_HasEncoding( p_aout, p_sys->fmt.i_format, &b_dtshd ) )
968 return VLC_EGENERIC;
969 i_at_format = jfields.AudioFormat.ENCODING_IEC61937;
970 switch( p_sys->fmt.i_format )
972 case VLC_CODEC_TRUEHD:
973 case VLC_CODEC_MLP:
974 p_sys->fmt.i_rate = 192000;
975 p_sys->fmt.i_bytes_per_frame = 16;
977 /* AudioFormat.ENCODING_IEC61937 documentation says that the
978 * channel layout must be stereo. Well, not for TrueHD
979 * apparently */
980 p_sys->fmt.i_physical_channels = AOUT_CHANS_7_1;
981 break;
982 case VLC_CODEC_DTS:
983 p_sys->fmt.i_bytes_per_frame = 4;
984 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
985 if( b_dtshd )
987 p_sys->fmt.i_rate = 192000;
988 p_sys->fmt.i_bytes_per_frame = 16;
990 break;
991 case VLC_CODEC_EAC3:
992 p_sys->fmt.i_rate = 192000;
993 case VLC_CODEC_A52:
994 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
995 p_sys->fmt.i_bytes_per_frame = 4;
996 break;
997 default:
998 return VLC_EGENERIC;
1000 p_sys->fmt.i_frame_length = 1;
1001 p_sys->fmt.i_channels = aout_FormatNbChannels( &p_sys->fmt );
1002 p_sys->fmt.i_format = VLC_CODEC_SPDIFL;
1004 else
1006 switch( p_sys->fmt.i_format )
1008 case VLC_CODEC_A52:
1009 if( !jfields.AudioFormat.has_ENCODING_AC3 )
1010 return VLC_EGENERIC;
1011 i_at_format = jfields.AudioFormat.ENCODING_AC3;
1012 break;
1013 case VLC_CODEC_DTS:
1014 if( !jfields.AudioFormat.has_ENCODING_DTS )
1015 return VLC_EGENERIC;
1016 i_at_format = jfields.AudioFormat.ENCODING_DTS;
1017 break;
1018 default:
1019 return VLC_EGENERIC;
1021 p_sys->fmt.i_bytes_per_frame = 4;
1022 p_sys->fmt.i_frame_length = 1;
1023 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1024 p_sys->fmt.i_channels = 2;
1025 p_sys->fmt.i_format = VLC_CODEC_SPDIFB;
1028 int i_ret = AudioTrack_Create( env, p_aout, p_sys->fmt.i_rate, i_at_format,
1029 p_sys->fmt.i_physical_channels );
1030 if( i_ret != VLC_SUCCESS )
1031 msg_Warn( p_aout, "SPDIF configuration failed" );
1032 else
1034 p_sys->b_passthrough = true;
1035 p_sys->i_chans_to_reorder = 0;
1038 return i_ret;
1041 static int
1042 StartPCM( JNIEnv *env, audio_output_t *p_aout, unsigned i_max_channels )
1044 aout_sys_t *p_sys = p_aout->sys;
1045 unsigned i_nb_channels;
1046 int i_at_format, i_ret;
1048 if (jfields.AudioTrack.getNativeOutputSampleRate)
1049 p_sys->fmt.i_rate =
1050 JNI_AT_CALL_STATIC_INT( getNativeOutputSampleRate,
1051 jfields.AudioManager.STREAM_MUSIC );
1052 else
1053 p_sys->fmt.i_rate = VLC_CLIP( p_sys->fmt.i_rate, 4000, 48000 );
1057 /* We can only accept U8, S16N, FL32, and AC3 */
1058 switch( p_sys->fmt.i_format )
1060 case VLC_CODEC_U8:
1061 i_at_format = jfields.AudioFormat.ENCODING_PCM_8BIT;
1062 break;
1063 case VLC_CODEC_S16N:
1064 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1065 break;
1066 case VLC_CODEC_FL32:
1067 if( jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
1068 i_at_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
1069 else
1071 p_sys->fmt.i_format = VLC_CODEC_S16N;
1072 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1074 break;
1075 default:
1076 p_sys->fmt.i_format = VLC_CODEC_S16N;
1077 i_at_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
1078 break;
1081 /* Android AudioTrack supports only mono, stereo, 5.1 and 7.1.
1082 * Android will downmix to stereo if audio output doesn't handle 5.1 or 7.1
1085 i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
1086 if( i_nb_channels == 0 )
1087 return VLC_EGENERIC;
1088 if( AOUT_FMT_LINEAR( &p_sys->fmt ) )
1089 i_nb_channels = __MIN( i_max_channels, i_nb_channels );
1090 if( i_nb_channels > 5 )
1092 if( i_nb_channels > 7 && jfields.AudioFormat.has_CHANNEL_OUT_SIDE )
1093 p_sys->fmt.i_physical_channels = AOUT_CHANS_7_1;
1094 else
1095 p_sys->fmt.i_physical_channels = AOUT_CHANS_5_1;
1096 } else
1098 if( i_nb_channels == 1 )
1099 p_sys->fmt.i_physical_channels = AOUT_CHAN_LEFT;
1100 else
1101 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1104 /* Try to create an AudioTrack with the most advanced channel and
1105 * format configuration. If AudioTrack_Create fails, try again with a
1106 * less advanced format (PCM S16N). If it fails again, try again with
1107 * Stereo channels. */
1108 i_ret = AudioTrack_Create( env, p_aout, p_sys->fmt.i_rate, i_at_format,
1109 p_sys->fmt.i_physical_channels );
1110 if( i_ret != 0 )
1112 if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
1114 msg_Warn( p_aout, "FL32 configuration failed, "
1115 "fallback to S16N PCM" );
1116 p_sys->fmt.i_format = VLC_CODEC_S16N;
1118 else if( p_sys->fmt.i_physical_channels & AOUT_CHANS_5_1 )
1120 msg_Warn( p_aout, "5.1 or 7.1 configuration failed, "
1121 "fallback to Stereo" );
1122 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1124 else
1125 break;
1127 } while( i_ret != 0 );
1129 if( i_ret != VLC_SUCCESS )
1130 return i_ret;
1132 uint32_t p_chans_out[AOUT_CHAN_MAX];
1133 memset( p_chans_out, 0, sizeof(p_chans_out) );
1134 AudioTrack_GetChanOrder( p_sys->fmt.i_physical_channels, p_chans_out );
1135 p_sys->i_chans_to_reorder =
1136 aout_CheckChannelReorder( NULL, p_chans_out,
1137 p_sys->fmt.i_physical_channels,
1138 p_sys->p_chan_table );
1139 aout_FormatPrepare( &p_sys->fmt );
1140 return VLC_SUCCESS;
1143 static int
1144 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
1146 aout_sys_t *p_sys = p_aout->sys;
1147 JNIEnv *env;
1148 int i_ret;
1149 bool b_try_passthrough;
1150 unsigned i_max_channels;
1152 if( p_sys->at_dev == AT_DEV_ENCODED )
1154 b_try_passthrough = true;
1155 i_max_channels = AT_DEV_MAX_CHANNELS;
1157 else
1159 b_try_passthrough = var_InheritBool( p_aout, "spdif" );
1160 i_max_channels = p_sys->at_dev == AT_DEV_STEREO ? 2 : AT_DEV_MAX_CHANNELS;
1163 if( !( env = GET_ENV() ) )
1164 return VLC_EGENERIC;
1166 p_sys->fmt = *p_fmt;
1168 aout_FormatPrint( p_aout, "VLC is looking for:", &p_sys->fmt );
1170 bool low_latency = false;
1171 if (p_sys->fmt.channel_type == AUDIO_CHANNEL_TYPE_AMBISONICS)
1173 p_sys->fmt.channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
1175 /* TODO: detect sink channel layout */
1176 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
1177 aout_FormatPrepare(&p_sys->fmt);
1178 low_latency = true;
1181 if( AOUT_FMT_LINEAR( &p_sys->fmt ) )
1182 i_ret = StartPCM( env, p_aout, i_max_channels );
1183 else if( b_try_passthrough )
1184 i_ret = StartPassthrough( env, p_aout );
1185 else
1186 return VLC_EGENERIC;
1188 if( i_ret != 0 )
1189 return VLC_EGENERIC;
1191 p_sys->i_max_audiotrack_samples = BYTES_TO_FRAMES( p_sys->audiotrack_args.i_size );
1193 #ifdef AUDIOTRACK_HW_LATENCY
1194 if( jfields.AudioTimestamp.clazz )
1196 /* create AudioTimestamp object */
1197 jobject p_obj = JNI_CALL( NewObject, jfields.AudioTimestamp.clazz,
1198 jfields.AudioTimestamp.ctor );
1199 if( p_obj )
1201 p_sys->timestamp.p_obj = (*env)->NewGlobalRef( env, p_obj );
1202 (*env)->DeleteLocalRef( env, p_obj );
1204 if( !p_sys->timestamp.p_obj )
1205 goto error;
1207 #endif
1209 AudioTrack_Reset( env, p_aout );
1211 if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
1213 msg_Dbg( p_aout, "using WRITE_FLOATARRAY");
1214 p_sys->i_write_type = WRITE_FLOATARRAY;
1216 else if( p_sys->fmt.i_format == VLC_CODEC_SPDIFL )
1218 assert( jfields.AudioFormat.has_ENCODING_IEC61937 );
1219 msg_Dbg( p_aout, "using WRITE_SHORTARRAYV23");
1220 p_sys->i_write_type = WRITE_SHORTARRAYV23;
1222 else if( jfields.AudioTrack.writeV23 )
1224 msg_Dbg( p_aout, "using WRITE_BYTEARRAYV23");
1225 p_sys->i_write_type = WRITE_BYTEARRAYV23;
1227 else if( jfields.AudioTrack.writeBufferV21 )
1229 msg_Dbg( p_aout, "using WRITE_BYTEBUFFER");
1230 p_sys->i_write_type = WRITE_BYTEBUFFER;
1232 else
1234 msg_Dbg( p_aout, "using WRITE_BYTEARRAY");
1235 p_sys->i_write_type = WRITE_BYTEARRAY;
1238 p_sys->circular.i_read = p_sys->circular.i_write = 0;
1239 p_sys->circular.i_size = (int)p_sys->fmt.i_rate
1240 * p_sys->fmt.i_bytes_per_frame
1241 / p_sys->fmt.i_frame_length;
1242 if (low_latency)
1244 /* 40 ms of buffering */
1245 p_sys->circular.i_size = p_sys->circular.i_size / 25;
1247 else
1249 /* 2 seconds of buffering */
1250 p_sys->circular.i_size = p_sys->circular.i_size * AOUT_MAX_PREPARE_TIME
1251 / CLOCK_FREQ;
1254 /* Allocate circular buffer */
1255 switch( p_sys->i_write_type )
1257 case WRITE_BYTEARRAY:
1258 case WRITE_BYTEARRAYV23:
1260 jbyteArray p_bytearray;
1262 p_bytearray = (*env)->NewByteArray( env, p_sys->circular.i_size );
1263 if( p_bytearray )
1265 p_sys->circular.u.p_bytearray = (*env)->NewGlobalRef( env, p_bytearray );
1266 (*env)->DeleteLocalRef( env, p_bytearray );
1269 if( !p_sys->circular.u.p_bytearray )
1271 msg_Err(p_aout, "byte array allocation failed");
1272 goto error;
1274 break;
1276 case WRITE_SHORTARRAYV23:
1278 jshortArray p_shortarray;
1280 p_shortarray = (*env)->NewShortArray( env,
1281 p_sys->circular.i_size / 2 );
1282 if( p_shortarray )
1284 p_sys->circular.u.p_shortarray = (*env)->NewGlobalRef( env, p_shortarray );
1285 (*env)->DeleteLocalRef( env, p_shortarray );
1287 if( !p_sys->circular.u.p_shortarray )
1289 msg_Err(p_aout, "short array allocation failed");
1290 goto error;
1292 break;
1294 case WRITE_FLOATARRAY:
1296 jfloatArray p_floatarray;
1298 p_floatarray = (*env)->NewFloatArray( env,
1299 p_sys->circular.i_size / 4 );
1300 if( p_floatarray )
1302 p_sys->circular.u.p_floatarray = (*env)->NewGlobalRef( env, p_floatarray );
1303 (*env)->DeleteLocalRef( env, p_floatarray );
1305 if( !p_sys->circular.u.p_floatarray )
1307 msg_Err(p_aout, "float array allocation failed");
1308 goto error;
1310 break;
1312 case WRITE_BYTEBUFFER:
1313 p_sys->circular.u.bytebuffer.p_data = malloc( p_sys->circular.i_size );
1314 if( !p_sys->circular.u.bytebuffer.p_data )
1316 msg_Err(p_aout, "bytebuffer allocation failed");
1317 goto error;
1319 break;
1322 /* Run AudioTrack_Thread */
1323 p_sys->b_thread_running = true;
1324 p_sys->b_thread_paused = false;
1325 if ( vlc_clone( &p_sys->thread, AudioTrack_Thread, p_aout,
1326 VLC_THREAD_PRIORITY_LOW ) )
1328 msg_Err(p_aout, "vlc clone failed");
1329 goto error;
1332 JNI_AT_CALL_VOID( play );
1333 CHECK_AT_EXCEPTION( "play" );
1335 *p_fmt = p_sys->fmt;
1336 aout_SoftVolumeStart( p_aout );
1338 aout_FormatPrint( p_aout, "VLC will output:", &p_sys->fmt );
1340 return VLC_SUCCESS;
1342 error:
1343 Stop( p_aout );
1344 return VLC_EGENERIC;
1347 static void
1348 Stop( audio_output_t *p_aout )
1350 aout_sys_t *p_sys = p_aout->sys;
1351 JNIEnv *env;
1353 if( !( env = GET_ENV() ) )
1354 return;
1356 /* Stop the AudioTrack thread */
1357 vlc_mutex_lock( &p_sys->lock );
1358 if( p_sys->b_thread_running )
1360 p_sys->b_thread_running = false;
1361 vlc_cond_signal( &p_sys->thread_cond );
1362 vlc_mutex_unlock( &p_sys->lock );
1363 vlc_join( p_sys->thread, NULL );
1365 else
1366 vlc_mutex_unlock( &p_sys->lock );
1368 /* Release the AudioTrack object */
1369 if( p_sys->p_audiotrack )
1371 if( !p_sys->b_audiotrack_exception )
1373 JNI_AT_CALL_VOID( stop );
1374 if( !CHECK_AT_EXCEPTION( "stop" ) )
1375 JNI_AT_CALL_VOID( release );
1377 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
1378 p_sys->p_audiotrack = NULL;
1381 /* Release the timestamp object */
1382 if( p_sys->timestamp.p_obj )
1384 (*env)->DeleteGlobalRef( env, p_sys->timestamp.p_obj );
1385 p_sys->timestamp.p_obj = NULL;
1388 /* Release the Circular buffer data */
1389 switch( p_sys->i_write_type )
1391 case WRITE_BYTEARRAY:
1392 case WRITE_BYTEARRAYV23:
1393 if( p_sys->circular.u.p_bytearray )
1395 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_bytearray );
1396 p_sys->circular.u.p_bytearray = NULL;
1398 break;
1399 case WRITE_SHORTARRAYV23:
1400 if( p_sys->circular.u.p_shortarray )
1402 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_shortarray );
1403 p_sys->circular.u.p_shortarray = NULL;
1405 break;
1406 case WRITE_FLOATARRAY:
1407 if( p_sys->circular.u.p_floatarray )
1409 (*env)->DeleteGlobalRef( env, p_sys->circular.u.p_floatarray );
1410 p_sys->circular.u.p_floatarray = NULL;
1412 break;
1413 case WRITE_BYTEBUFFER:
1414 free( p_sys->circular.u.bytebuffer.p_data );
1415 p_sys->circular.u.bytebuffer.p_data = NULL;
1416 break;
1419 p_sys->b_audiotrack_exception = false;
1420 p_sys->b_error = false;
1421 p_sys->b_passthrough = false;
1425 * Non blocking write function, run from AudioTrack_Thread.
1426 * Do a calculation between current position and audiotrack position and assure
1427 * that we won't wait in AudioTrack.write() method.
1429 static int
1430 AudioTrack_PlayByteArray( JNIEnv *env, audio_output_t *p_aout,
1431 size_t i_data_size, size_t i_data_offset,
1432 bool b_force )
1434 aout_sys_t *p_sys = p_aout->sys;
1435 uint64_t i_samples;
1436 uint64_t i_audiotrack_pos;
1437 uint64_t i_samples_pending;
1439 i_audiotrack_pos = AudioTrack_getPlaybackHeadPosition( env, p_aout );
1441 assert( i_audiotrack_pos <= p_sys->i_samples_written );
1442 if( i_audiotrack_pos > p_sys->i_samples_written )
1444 msg_Err( p_aout, "audiotrack position is ahead. Should NOT happen" );
1445 p_sys->i_samples_written = 0;
1446 p_sys->b_error = true;
1447 return 0;
1449 i_samples_pending = p_sys->i_samples_written - i_audiotrack_pos;
1451 /* check if audiotrack buffer is not full before writing on it. */
1452 if( b_force )
1454 msg_Warn( p_aout, "Force write. It may block..." );
1455 i_samples_pending = 0;
1456 } else if( i_samples_pending >= p_sys->i_max_audiotrack_samples )
1457 return 0;
1459 i_samples = __MIN( p_sys->i_max_audiotrack_samples - i_samples_pending,
1460 BYTES_TO_FRAMES( i_data_size ) );
1462 i_data_size = FRAMES_TO_BYTES( i_samples );
1464 return JNI_AT_CALL_INT( write, p_sys->circular.u.p_bytearray,
1465 i_data_offset, i_data_size );
1469 * Non blocking write function for Android M and after, run from
1470 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1471 * flags.
1473 static int
1474 AudioTrack_PlayByteArrayV23( JNIEnv *env, audio_output_t *p_aout,
1475 size_t i_data_size, size_t i_data_offset )
1477 aout_sys_t *p_sys = p_aout->sys;
1479 return JNI_AT_CALL_INT( writeV23, p_sys->circular.u.p_bytearray,
1480 i_data_offset, i_data_size,
1481 jfields.AudioTrack.WRITE_NON_BLOCKING );
1485 * Non blocking play function for Lollipop and after, run from
1486 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1487 * flags.
1489 static int
1490 AudioTrack_PlayByteBuffer( JNIEnv *env, audio_output_t *p_aout,
1491 size_t i_data_size, size_t i_data_offset )
1493 aout_sys_t *p_sys = p_aout->sys;
1495 /* The same DirectByteBuffer will be used until the data_offset reaches 0.
1496 * The internal position of this buffer is moved by the writeBufferV21
1497 * wall. */
1498 if( i_data_offset == 0 )
1500 /* No need to get a global ref, this object will be only used from the
1501 * same Thread */
1502 if( p_sys->circular.u.bytebuffer.p_obj )
1503 (*env)->DeleteLocalRef( env, p_sys->circular.u.bytebuffer.p_obj );
1505 p_sys->circular.u.bytebuffer.p_obj = (*env)->NewDirectByteBuffer( env,
1506 p_sys->circular.u.bytebuffer.p_data,
1507 p_sys->circular.i_size );
1508 if( !p_sys->circular.u.bytebuffer.p_obj )
1510 if( (*env)->ExceptionCheck( env ) )
1511 (*env)->ExceptionClear( env );
1512 return jfields.AudioTrack.ERROR;
1516 return JNI_AT_CALL_INT( writeBufferV21, p_sys->circular.u.bytebuffer.p_obj,
1517 i_data_size,
1518 jfields.AudioTrack.WRITE_NON_BLOCKING );
1522 * Non blocking short write function for Android M and after, run from
1523 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1524 * flags.
1526 static int
1527 AudioTrack_PlayShortArrayV23( JNIEnv *env, audio_output_t *p_aout,
1528 size_t i_data_size, size_t i_data_offset )
1530 aout_sys_t *p_sys = p_aout->sys;
1531 int i_ret;
1533 i_ret = JNI_AT_CALL_INT( writeShortV23, p_sys->circular.u.p_shortarray,
1534 i_data_offset / 2, i_data_size / 2,
1535 jfields.AudioTrack.WRITE_NON_BLOCKING );
1536 if( i_ret < 0 )
1537 return i_ret;
1538 else
1539 return i_ret * 2;
1543 * Non blocking play float function for Lollipop and after, run from
1544 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1545 * flags.
1547 static int
1548 AudioTrack_PlayFloatArray( JNIEnv *env, audio_output_t *p_aout,
1549 size_t i_data_size, size_t i_data_offset )
1551 aout_sys_t *p_sys = p_aout->sys;
1552 int i_ret;
1554 i_ret = JNI_AT_CALL_INT( writeFloat, p_sys->circular.u.p_floatarray,
1555 i_data_offset / 4, i_data_size / 4,
1556 jfields.AudioTrack.WRITE_NON_BLOCKING );
1557 if( i_ret < 0 )
1558 return i_ret;
1559 else
1560 return i_ret * 4;
1563 static int
1564 AudioTrack_Play( JNIEnv *env, audio_output_t *p_aout, size_t i_data_size,
1565 size_t i_data_offset, bool b_force )
1567 aout_sys_t *p_sys = p_aout->sys;
1568 int i_ret;
1570 switch( p_sys->i_write_type )
1572 case WRITE_BYTEARRAYV23:
1573 i_ret = AudioTrack_PlayByteArrayV23( env, p_aout, i_data_size,
1574 i_data_offset );
1575 break;
1576 case WRITE_BYTEBUFFER:
1577 i_ret = AudioTrack_PlayByteBuffer( env, p_aout, i_data_size,
1578 i_data_offset );
1579 break;
1580 case WRITE_SHORTARRAYV23:
1581 i_ret = AudioTrack_PlayShortArrayV23( env, p_aout, i_data_size,
1582 i_data_offset );
1583 break;
1584 case WRITE_BYTEARRAY:
1585 i_ret = AudioTrack_PlayByteArray( env, p_aout, i_data_size,
1586 i_data_offset, b_force );
1587 break;
1588 case WRITE_FLOATARRAY:
1589 i_ret = AudioTrack_PlayFloatArray( env, p_aout, i_data_size,
1590 i_data_offset );
1591 break;
1592 default:
1593 vlc_assert_unreachable();
1596 if( i_ret < 0 ) {
1597 if( jfields.AudioManager.has_ERROR_DEAD_OBJECT
1598 && i_ret == jfields.AudioManager.ERROR_DEAD_OBJECT )
1600 msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
1601 "try recreating AudioTrack" );
1602 if( ( i_ret = AudioTrack_Recreate( env, p_aout ) ) == 0 )
1604 AudioTrack_Reset( env, p_aout );
1605 JNI_AT_CALL_VOID( play );
1606 CHECK_AT_EXCEPTION( "play" );
1608 } else
1610 const char *str;
1611 if( i_ret == jfields.AudioTrack.ERROR_INVALID_OPERATION )
1612 str = "ERROR_INVALID_OPERATION";
1613 else if( i_ret == jfields.AudioTrack.ERROR_BAD_VALUE )
1614 str = "ERROR_BAD_VALUE";
1615 else
1616 str = "ERROR";
1617 msg_Err( p_aout, "Write failed: %s", str );
1618 p_sys->b_error = true;
1620 } else
1621 p_sys->i_samples_written += BYTES_TO_FRAMES( i_ret );
1622 return i_ret;
1626 * This thread will play the data coming from the circular buffer.
1628 static void *
1629 AudioTrack_Thread( void *p_data )
1631 audio_output_t *p_aout = p_data;
1632 aout_sys_t *p_sys = p_aout->sys;
1633 JNIEnv *env = GET_ENV();
1634 vlc_tick_t i_play_deadline = 0;
1635 vlc_tick_t i_last_time_blocked = 0;
1637 if( !env )
1638 return NULL;
1640 for( ;; )
1642 int i_ret = 0;
1643 bool b_forced;
1644 size_t i_data_offset;
1645 size_t i_data_size;
1647 vlc_mutex_lock( &p_sys->lock );
1649 /* Wait for free space in Audiotrack internal buffer */
1650 if( i_play_deadline != 0 && vlc_tick_now() < i_play_deadline )
1652 /* Don't wake up the thread when there is new data since we are
1653 * waiting for more space */
1654 p_sys->b_thread_waiting = true;
1655 while( p_sys->b_thread_running && i_ret != ETIMEDOUT )
1656 i_ret = vlc_cond_timedwait( &p_sys->thread_cond,
1657 &p_sys->lock,
1658 i_play_deadline );
1659 i_play_deadline = 0;
1660 p_sys->b_thread_waiting = false;
1663 /* Wait for not paused state */
1664 while( p_sys->b_thread_running && p_sys->b_thread_paused )
1666 i_last_time_blocked = 0;
1667 vlc_cond_wait( &p_sys->thread_cond, &p_sys->lock );
1670 /* Wait for more data in the circular buffer */
1671 while( p_sys->b_thread_running
1672 && p_sys->circular.i_read >= p_sys->circular.i_write )
1673 vlc_cond_wait( &p_sys->thread_cond, &p_sys->lock );
1675 if( !p_sys->b_thread_running || p_sys->b_error )
1677 vlc_mutex_unlock( &p_sys->lock );
1678 break;
1681 /* HACK: AudioFlinger can drop frames without notifying us and there is
1682 * no way to know it. If it happens, i_audiotrack_pos won't move and
1683 * the current code will be stuck because it'll assume that audiotrack
1684 * internal buffer is full when it's not. It may happen only after
1685 * Android 4.4.2 if we send frames too quickly. To fix this issue,
1686 * force the writing of the buffer after a certain delay. */
1687 if( i_last_time_blocked != 0 )
1688 b_forced = vlc_tick_now() - i_last_time_blocked >
1689 FRAMES_TO_US( p_sys->i_max_audiotrack_samples ) * 2;
1690 else
1691 b_forced = false;
1693 i_data_offset = p_sys->circular.i_read % p_sys->circular.i_size;
1694 i_data_size = __MIN( p_sys->circular.i_size - i_data_offset,
1695 p_sys->circular.i_write - p_sys->circular.i_read );
1697 i_ret = AudioTrack_Play( env, p_aout, i_data_size, i_data_offset,
1698 b_forced );
1699 if( i_ret >= 0 )
1701 if( p_sys->i_write_type == WRITE_BYTEARRAY )
1703 if( i_ret != 0 )
1704 i_last_time_blocked = 0;
1705 else if( i_last_time_blocked == 0 )
1706 i_last_time_blocked = vlc_tick_now();
1709 if( i_ret == 0 )
1710 i_play_deadline = vlc_tick_now() + __MAX( 10000, FRAMES_TO_US(
1711 p_sys->i_max_audiotrack_samples / 5 ) );
1712 else
1713 p_sys->circular.i_read += i_ret;
1716 vlc_cond_signal( &p_sys->aout_cond );
1717 vlc_mutex_unlock( &p_sys->lock );
1720 if( p_sys->circular.u.bytebuffer.p_obj )
1722 (*env)->DeleteLocalRef( env, p_sys->circular.u.bytebuffer.p_obj );
1723 p_sys->circular.u.bytebuffer.p_obj = NULL;
1726 return NULL;
1729 static void
1730 Play( audio_output_t *p_aout, block_t *p_buffer, vlc_tick_t i_date )
1732 JNIEnv *env = NULL;
1733 size_t i_buffer_offset = 0;
1734 aout_sys_t *p_sys = p_aout->sys;
1736 vlc_mutex_lock( &p_sys->lock );
1738 if( p_sys->b_error || !( env = GET_ENV() ) )
1739 goto bailout;
1741 if( p_sys->i_chans_to_reorder )
1742 aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
1743 p_sys->i_chans_to_reorder, p_sys->p_chan_table,
1744 p_sys->fmt.i_format );
1746 while( i_buffer_offset < p_buffer->i_buffer && !p_sys->b_error )
1748 size_t i_circular_free;
1749 size_t i_data_offset;
1750 size_t i_data_size;
1752 /* Wait for enough room in circular buffer */
1753 while( !p_sys->b_error && ( i_circular_free = p_sys->circular.i_size -
1754 ( p_sys->circular.i_write - p_sys->circular.i_read ) ) == 0 )
1755 vlc_cond_wait( &p_sys->aout_cond, &p_sys->lock );
1756 if( p_sys->b_error )
1757 goto bailout;
1759 i_data_offset = p_sys->circular.i_write % p_sys->circular.i_size;
1760 i_data_size = __MIN( p_buffer->i_buffer - i_buffer_offset,
1761 p_sys->circular.i_size - i_data_offset );
1762 i_data_size = __MIN( i_data_size, i_circular_free );
1764 switch( p_sys->i_write_type )
1766 case WRITE_BYTEARRAY:
1767 case WRITE_BYTEARRAYV23:
1768 (*env)->SetByteArrayRegion( env, p_sys->circular.u.p_bytearray,
1769 i_data_offset, i_data_size,
1770 (jbyte *)p_buffer->p_buffer
1771 + i_buffer_offset);
1772 break;
1773 case WRITE_SHORTARRAYV23:
1774 i_data_offset &= ~1;
1775 i_data_size &= ~1;
1776 (*env)->SetShortArrayRegion( env, p_sys->circular.u.p_shortarray,
1777 i_data_offset / 2, i_data_size / 2,
1778 (jshort *)p_buffer->p_buffer
1779 + i_buffer_offset / 2);
1780 break;
1781 case WRITE_FLOATARRAY:
1782 i_data_offset &= ~3;
1783 i_data_size &= ~3;
1784 (*env)->SetFloatArrayRegion( env, p_sys->circular.u.p_floatarray,
1785 i_data_offset / 4, i_data_size / 4,
1786 (jfloat *)p_buffer->p_buffer
1787 + i_buffer_offset / 4);
1789 break;
1790 case WRITE_BYTEBUFFER:
1791 memcpy( p_sys->circular.u.bytebuffer.p_data + i_data_offset,
1792 p_buffer->p_buffer + i_buffer_offset, i_data_size );
1793 break;
1796 i_buffer_offset += i_data_size;
1797 p_sys->circular.i_write += i_data_size;
1799 if( !p_sys->b_thread_waiting )
1800 vlc_cond_signal( &p_sys->thread_cond );
1803 bailout:
1804 vlc_mutex_unlock( &p_sys->lock );
1805 block_Release( p_buffer );
1806 (void) i_date;
1809 static void
1810 Pause( audio_output_t *p_aout, bool b_pause, vlc_tick_t i_date )
1812 aout_sys_t *p_sys = p_aout->sys;
1813 JNIEnv *env;
1814 VLC_UNUSED( i_date );
1816 vlc_mutex_lock( &p_sys->lock );
1818 if( p_sys->b_error || !( env = GET_ENV() ) )
1819 goto bailout;
1821 if( b_pause )
1823 p_sys->b_thread_paused = true;
1824 JNI_AT_CALL_VOID( pause );
1825 CHECK_AT_EXCEPTION( "pause" );
1826 } else
1828 p_sys->b_thread_paused = false;
1829 AudioTrack_ResetPositions( env, p_aout );
1830 JNI_AT_CALL_VOID( play );
1831 CHECK_AT_EXCEPTION( "play" );
1834 bailout:
1835 vlc_mutex_unlock( &p_sys->lock );
1838 static void
1839 Flush( audio_output_t *p_aout, bool b_wait )
1841 aout_sys_t *p_sys = p_aout->sys;
1842 JNIEnv *env;
1844 vlc_mutex_lock( &p_sys->lock );
1846 if( p_sys->b_error || !( env = GET_ENV() ) )
1847 goto bailout;
1849 /* Android doc:
1850 * stop(): Stops playing the audio data. When used on an instance created
1851 * in MODE_STREAM mode, audio will stop playing after the last buffer that
1852 * was written has been played. For an immediate stop, use pause(),
1853 * followed by flush() to discard audio data that hasn't been played back
1854 * yet.
1856 * flush(): Flushes the audio data currently queued for playback. Any data
1857 * that has not been played back will be discarded. No-op if not stopped
1858 * or paused, or if the track's creation mode is not MODE_STREAM.
1860 if( b_wait )
1862 /* Wait for the thread to process the circular buffer */
1863 while( !p_sys->b_error
1864 && p_sys->circular.i_read != p_sys->circular.i_write )
1865 vlc_cond_wait( &p_sys->aout_cond, &p_sys->lock );
1866 if( p_sys->b_error )
1867 goto bailout;
1869 JNI_AT_CALL_VOID( stop );
1870 if( CHECK_AT_EXCEPTION( "stop" ) )
1871 goto bailout;
1872 } else
1874 JNI_AT_CALL_VOID( pause );
1875 if( CHECK_AT_EXCEPTION( "pause" ) )
1876 goto bailout;
1877 JNI_AT_CALL_VOID( flush );
1879 p_sys->circular.i_read = p_sys->circular.i_write = 0;
1881 /* HACK: Before Android 4.4, the head position is not reset to zero and is
1882 * still moving after a flush or a stop. This prevents to get a precise
1883 * head position and there is no way to know when it stabilizes. Therefore
1884 * recreate an AudioTrack object in that case. The AudioTimestamp class was
1885 * added in API Level 19, so if this class is not found, the Android
1886 * Version is 4.3 or before */
1887 if( !jfields.AudioTimestamp.clazz && p_sys->i_samples_written > 0 )
1889 if( AudioTrack_Recreate( env, p_aout ) != 0 )
1891 p_sys->b_error = true;
1892 goto bailout;
1895 AudioTrack_Reset( env, p_aout );
1896 JNI_AT_CALL_VOID( play );
1897 CHECK_AT_EXCEPTION( "play" );
1899 bailout:
1900 vlc_mutex_unlock( &p_sys->lock );
1903 static int DeviceSelect(audio_output_t *p_aout, const char *p_id)
1905 aout_sys_t *p_sys = p_aout->sys;
1906 enum at_dev at_dev = AT_DEV_DEFAULT;
1908 if( p_id )
1910 for( unsigned int i = 0; at_devs[i].id; ++i )
1912 if( strncmp( p_id, at_devs[i].id, strlen( at_devs[i].id ) ) == 0 )
1914 at_dev = at_devs[i].at_dev;
1915 break;
1920 long long i_encoding_flags = 0;
1921 if( at_dev == AT_DEV_ENCODED )
1923 const size_t i_prefix_size = strlen( "encoded:" );
1924 if( strncmp( p_id, "encoded:", i_prefix_size ) == 0 )
1925 i_encoding_flags = atoll( p_id + i_prefix_size );
1928 if( at_dev != p_sys->at_dev || i_encoding_flags != p_sys->i_encoding_flags )
1930 p_sys->at_dev = at_dev;
1931 p_sys->i_encoding_flags = i_encoding_flags;
1932 aout_RestartRequest( p_aout, AOUT_RESTART_OUTPUT );
1933 msg_Dbg( p_aout, "selected device: %s", p_id );
1935 if( at_dev == AT_DEV_ENCODED )
1937 static const vlc_fourcc_t enc_fourccs[] = {
1938 VLC_CODEC_DTS, VLC_CODEC_A52, VLC_CODEC_EAC3, VLC_CODEC_TRUEHD,
1940 for( size_t i = 0;
1941 i < sizeof( enc_fourccs ) / sizeof( enc_fourccs[0] ); ++i )
1943 bool b_dtshd;
1944 if( AudioTrack_HasEncoding( p_aout, enc_fourccs[i], &b_dtshd ) )
1945 msg_Dbg( p_aout, "device has %4.4s passthrough support",
1946 b_dtshd ? "dtsh" : (const char *)&enc_fourccs[i] );
1950 aout_DeviceReport( p_aout, p_id );
1951 return VLC_SUCCESS;
1954 static int
1955 Open( vlc_object_t *obj )
1957 audio_output_t *p_aout = (audio_output_t *) obj;
1958 aout_sys_t *p_sys;
1959 JNIEnv *env = GET_ENV();
1961 if( !env || !InitJNIFields( p_aout, env ) )
1962 return VLC_EGENERIC;
1964 p_sys = calloc( 1, sizeof (aout_sys_t) );
1966 if( unlikely( p_sys == NULL ) )
1967 return VLC_ENOMEM;
1969 p_sys->at_dev = AT_DEV_DEFAULT;
1970 vlc_mutex_init(&p_sys->lock);
1971 vlc_cond_init(&p_sys->aout_cond);
1972 vlc_cond_init(&p_sys->thread_cond);
1974 p_aout->sys = p_sys;
1975 p_aout->start = Start;
1976 p_aout->stop = Stop;
1977 p_aout->play = Play;
1978 p_aout->pause = Pause;
1979 p_aout->flush = Flush;
1980 p_aout->time_get = TimeGet;
1981 p_aout->device_select = DeviceSelect;
1983 for( unsigned int i = 0; at_devs[i].id; ++i )
1984 aout_HotplugReport(p_aout, at_devs[i].id, at_devs[i].name);
1986 aout_SoftVolumeInit( p_aout );
1988 return VLC_SUCCESS;
1991 static void
1992 Close( vlc_object_t *obj )
1994 audio_output_t *p_aout = (audio_output_t *) obj;
1995 aout_sys_t *p_sys = p_aout->sys;
1997 vlc_mutex_destroy(&p_sys->lock);
1998 vlc_cond_destroy(&p_sys->aout_cond);
1999 vlc_cond_destroy(&p_sys->thread_cond);
2000 free( p_sys );