]> git.sesse.net Git - vlc/blob - modules/audio_output/audiotrack.c
audiotrack: Fix deadlock with Android 4.4.2, 4.4.3 and 4.4.4
[vlc] / modules / audio_output / audiotrack.c
1 /*****************************************************************************
2  * audiotrack.c: Android Java AudioTrack audio output module
3  *****************************************************************************
4  * Copyright © 2012-2015 VLC authors and VideoLAN, VideoLabs
5  *
6  * Authors: Thomas Guillem <thomas@gllm.fr>
7  *          Ming Hu <tewilove@gmail.com>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <assert.h>
29 #include <jni.h>
30 #include <dlfcn.h>
31 #include <stdbool.h>
32 #include <sys/queue.h>
33
34 #include <vlc_atomic.h>
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_aout.h>
38 #include <vlc_threads.h>
39
40 /* Maximum VLC buffers queued by the internal queue in microseconds. This delay
41  * doesn't include audiotrack delay */
42 #define MAX_QUEUE_US INT64_C(1000000) // 1000ms
43
44 static int  Open( vlc_object_t * );
45 static void Close( vlc_object_t * );
46
47 struct thread_cmd;
48 typedef TAILQ_HEAD(, thread_cmd) THREAD_CMD_QUEUE;
49
50 struct aout_sys_t {
51     /* sw gain */
52     float soft_gain;
53     bool soft_mute;
54
55     /* Owned by JNIThread */
56     jobject p_audiotrack; /* AudioTrack ref */
57     jobject p_audioTimestamp; /* AudioTimestamp ref */
58     jbyteArray p_bytearray; /* ByteArray ref (for Write) */
59     size_t i_bytearray_size; /* size of the ByteArray */
60     jobject p_bytebuffer; /* ByteBuffer ref (for WriteV21) */
61     audio_sample_format_t fmt; /* fmt setup by Start */
62     uint32_t i_pos_initial; /* initial position set by getPlaybackHeadPosition */
63     uint32_t i_samples_written; /* number of samples written since last flush */
64     uint32_t i_bytes_per_frame; /* byte per frame */
65     uint32_t i_max_audiotrack_samples;
66     mtime_t i_play_time; /* time when play was called */
67     bool b_audiotrack_exception; /* true if audiotrack throwed an exception */
68     int i_audiotrack_stuck_count;
69
70     /* JNIThread control */
71     vlc_mutex_t mutex;
72     vlc_cond_t cond;
73     vlc_thread_t thread;
74
75     /* Shared between two threads, must be locked */
76     bool b_thread_run; /* is thread alive */
77     THREAD_CMD_QUEUE thread_cmd_queue; /* thread cmd queue */
78     uint32_t i_samples_queued; /* number of samples queued */
79 };
80
81 /* Soft volume helper */
82 #include "audio_output/volume.h"
83
84 //#define AUDIOTRACK_USE_FLOAT
85 // TODO: activate getTimestamp for new android versions
86 //#define AUDIOTRACK_USE_TIMESTAMP
87
88 vlc_module_begin ()
89     set_shortname( "AudioTrack" )
90     set_description( N_( "Android AudioTrack audio output" ) )
91     set_capability( "audio output", 180 )
92     set_category( CAT_AUDIO )
93     set_subcategory( SUBCAT_AUDIO_AOUT )
94     add_sw_gain()
95     add_shortcut( "audiotrack" )
96     set_callbacks( Open, Close )
97 vlc_module_end ()
98
99 struct thread_cmd
100 {
101     TAILQ_ENTRY(thread_cmd) next;
102     enum {
103         CMD_START,
104         CMD_STOP,
105         CMD_PLAY,
106         CMD_PAUSE,
107         CMD_TIME_GET,
108         CMD_FLUSH,
109         CMD_DONE,
110     } id;
111     union {
112         struct {
113             audio_sample_format_t *p_fmt;
114         } start;
115         struct {
116             block_t *p_buffer;
117         } play;
118         struct {
119             bool b_pause;
120             mtime_t i_date;
121         } pause;
122         struct {
123             bool b_wait;
124         } flush;
125     } in;
126     union {
127         struct {
128             int i_ret;
129             audio_sample_format_t *p_fmt;
130         } start;
131         struct {
132             int i_ret;
133             mtime_t i_delay;
134         } time_get;
135     } out;
136     void ( *pf_destroy )( struct thread_cmd * );
137 };
138
139 #define THREAD_NAME "android_audiotrack"
140
141 extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
142 extern void jni_detach_thread();
143 extern int jni_get_env(JNIEnv **env);
144
145 static struct
146 {
147     struct {
148         jclass clazz;
149         jmethodID ctor;
150         jmethodID release;
151         jmethodID getState;
152         jmethodID play;
153         jmethodID stop;
154         jmethodID flush;
155         jmethodID pause;
156         jmethodID write;
157         jmethodID writeV21;
158         jmethodID getPlaybackHeadPosition;
159         jmethodID getTimestamp;
160         jmethodID getMinBufferSize;
161         jint STATE_INITIALIZED;
162         jint MODE_STREAM;
163         jint ERROR;
164         jint ERROR_BAD_VALUE;
165         jint ERROR_INVALID_OPERATION;
166         jint WRITE_NON_BLOCKING;
167     } AudioTrack;
168     struct {
169         jint ENCODING_PCM_8BIT;
170         jint ENCODING_PCM_16BIT;
171         jint ENCODING_PCM_FLOAT;
172         bool has_ENCODING_PCM_FLOAT;
173         jint CHANNEL_OUT_MONO;
174         jint CHANNEL_OUT_STEREO;
175     } AudioFormat;
176     struct {
177         jint ERROR_DEAD_OBJECT;
178         bool has_ERROR_DEAD_OBJECT;
179         jint STREAM_MUSIC;
180     } AudioManager;
181     struct {
182         jclass clazz;
183         jmethodID ctor;
184         jfieldID framePosition;
185         jfieldID nanoTime;
186     } AudioTimestamp;
187 } jfields;
188
189 /* init all jni fields.
190  * Done only one time during the first initialisation */
191 static bool
192 InitJNIFields( audio_output_t *p_aout )
193 {
194     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
195     static int i_init_state = -1;
196     bool ret, b_attached = false;
197     jclass clazz;
198     jfieldID field;
199     JNIEnv* env = NULL;
200
201     vlc_mutex_lock( &lock );
202
203     if( i_init_state != -1 )
204         goto end;
205
206     if( jni_get_env(&env) < 0 )
207     {
208         jni_attach_thread( &env, THREAD_NAME );
209         if( !env )
210         {
211             i_init_state = 0;
212             goto end;
213         }
214         b_attached = true;
215     }
216
217 #define CHECK_EXCEPTION( what, critical ) do { \
218     if( (*env)->ExceptionOccurred( env ) ) \
219     { \
220         msg_Err( p_aout, "%s failed", what ); \
221         (*env)->ExceptionClear( env ); \
222         if( (critical) ) \
223         { \
224             i_init_state = 0; \
225             goto end; \
226         } \
227     } \
228 } while( 0 )
229 #define GET_CLASS( str, critical ) do { \
230     clazz = (*env)->FindClass( env, (str) ); \
231     CHECK_EXCEPTION( str, critical ); \
232 } while( 0 )
233 #define GET_ID( get, id, str, args, critical ) do { \
234     jfields.id = (*env)->get( env, clazz, (str), (args) ); \
235     CHECK_EXCEPTION( #get, critical ); \
236 } while( 0 )
237 #define GET_CONST_INT( id, str, critical ) do { \
238     field = NULL; \
239     field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
240     CHECK_EXCEPTION( #id, critical ); \
241     if( field ) \
242     { \
243         jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
244         CHECK_EXCEPTION( #id, critical ); \
245     } \
246 } while( 0 )
247
248     /* AudioTrack class init */
249     GET_CLASS( "android/media/AudioTrack", true );
250     jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
251     CHECK_EXCEPTION( "NewGlobalRef", true );
252
253     GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIII)V", true );
254     GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true );
255     GET_ID( GetMethodID, AudioTrack.getState, "getState", "()I", true );
256     GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true );
257     GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true );
258     GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true );
259     GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true );
260
261     GET_ID( GetMethodID, AudioTrack.writeV21, "write", "(Ljava/nio/ByteBuffer;II)I", false );
262     if( jfields.AudioTrack.writeV21 )
263     {
264         jfields.AudioTrack.write = NULL;
265         GET_CONST_INT( AudioTrack.WRITE_NON_BLOCKING, "WRITE_NON_BLOCKING", true );
266     } else
267         GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
268
269     GET_ID( GetMethodID, AudioTrack.getTimestamp,
270             "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
271     GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
272             "getPlaybackHeadPosition", "()I", true );
273
274     GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize",
275             "(III)I", true );
276     GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true );
277     GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
278     GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
279     GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true );
280     GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION,
281                    "ERROR_INVALID_OPERATION", true );
282
283     /* AudioTimestamp class init (if any) */
284     if( jfields.AudioTrack.getTimestamp )
285     {
286         GET_CLASS( "android/media/AudioTimestamp", true );
287         jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env,
288                                                                       clazz );
289         CHECK_EXCEPTION( "NewGlobalRef", true );
290
291         GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true );
292         GET_ID( GetFieldID, AudioTimestamp.framePosition,
293                 "framePosition", "J", true );
294         GET_ID( GetFieldID, AudioTimestamp.nanoTime,
295                 "nanoTime", "J", true );
296     } else
297     {
298         jfields.AudioTimestamp.clazz = NULL;
299         jfields.AudioTimestamp.ctor = NULL;
300         jfields.AudioTimestamp.framePosition = NULL;
301         jfields.AudioTimestamp.nanoTime = NULL;
302     }
303
304     /* AudioFormat class init */
305     GET_CLASS( "android/media/AudioFormat", true );
306     GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
307     GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
308 #ifdef AUDIOTRACK_USE_FLOAT
309     GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
310                    false );
311     jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL;
312 #else
313     jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
314 #endif
315     GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
316     GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
317
318     /* AudioManager class init */
319     GET_CLASS( "android/media/AudioManager", true );
320     GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false );
321     jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
322     GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
323
324 #undef CHECK_EXCEPTION
325 #undef GET_CLASS
326 #undef GET_ID
327 #undef GET_CONST_INT
328
329     i_init_state = 1;
330 end:
331     ret = i_init_state == 1;
332     if( !ret )
333         msg_Err( p_aout, "AudioTrack jni init failed" );
334     if( b_attached )
335         jni_detach_thread();
336     vlc_mutex_unlock( &lock );
337     return ret;
338 }
339
340 static inline bool
341 check_exception( JNIEnv *env, audio_output_t *p_aout,
342                  const char *method )
343 {
344     if( (*env)->ExceptionOccurred( env ) )
345     {
346         aout_sys_t *p_sys = p_aout->sys;
347
348         p_sys->b_audiotrack_exception = true;
349         (*env)->ExceptionClear( env );
350         msg_Err( p_aout, "AudioTrack.%s triggered an exception !", method );
351         return true;
352     } else
353         return false;
354 }
355 #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, method )
356
357 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
358
359 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
360 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
361 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
362 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
363
364 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
365 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
366 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
367 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
368 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
369
370 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->p_audioTimestamp, jfields.AudioTimestamp.field )
371
372 static inline mtime_t
373 frames_to_us( aout_sys_t *p_sys, uint32_t i_nb_frames )
374 {
375     return  i_nb_frames * CLOCK_FREQ / p_sys->fmt.i_rate;
376 }
377 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
378
379 static struct thread_cmd *
380 ThreadCmd_New( int id )
381 {
382     struct thread_cmd *p_cmd = calloc( 1, sizeof(struct thread_cmd) );
383
384     if( p_cmd )
385         p_cmd->id = id;
386
387     return p_cmd;
388 }
389
390 static void
391 ThreadCmd_InsertHead( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
392 {
393     TAILQ_INSERT_HEAD( &p_sys->thread_cmd_queue, p_cmd, next);
394     vlc_cond_signal( &p_sys->cond );
395 }
396
397 static void
398 ThreadCmd_InsertTail( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
399 {
400     TAILQ_INSERT_TAIL( &p_sys->thread_cmd_queue, p_cmd, next);
401     vlc_cond_signal( &p_sys->cond );
402 }
403
404 static bool
405 ThreadCmd_Wait( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
406 {
407     while( p_cmd->id != CMD_DONE )
408         vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
409
410     return p_cmd->id == CMD_DONE;
411 }
412
413 static void
414 ThreadCmd_FlushQueue( aout_sys_t *p_sys )
415 {
416     struct thread_cmd *p_cmd, *p_cmd_next;
417
418     for ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue );
419           p_cmd != NULL; p_cmd = p_cmd_next )
420     {
421         p_cmd_next = TAILQ_NEXT( p_cmd, next );
422         TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
423         if( p_cmd->pf_destroy )
424             p_cmd->pf_destroy( p_cmd );
425     }
426 }
427
428 static void
429 JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout )
430 {
431     aout_sys_t *p_sys = p_aout->sys;
432
433     if( p_sys->p_audiotrack )
434         p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
435     else
436         p_sys->i_pos_initial = 0;
437
438     /* HACK: On some broken devices, head position is still moving after a
439      * flush or a stop. So, wait for the head position to be stabilized. */
440     if( unlikely( p_sys->i_pos_initial != 0 ) )
441     {
442         uint32_t i_last_pos;
443         do {
444             i_last_pos = p_sys->i_pos_initial;
445             msleep( 50000 );
446             p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
447         } while( p_sys->i_pos_initial != i_last_pos );
448     }
449     p_sys->i_samples_written = 0;
450     p_sys->i_samples_queued = 0;
451 }
452
453 static uint32_t
454 JNIThread_GetAudioTrackPos( JNIEnv *env, audio_output_t *p_aout )
455 {
456     aout_sys_t *p_sys = p_aout->sys;
457
458     /* Android doc:
459      * getPlaybackHeadPosition: Returns the playback head position expressed in
460      * frames. Though the "int" type is signed 32-bits, the value should be
461      * reinterpreted as if it is unsigned 32-bits. That is, the next position
462      * after 0x7FFFFFFF is (int) 0x80000000. This is a continuously advancing
463      * counter. It will wrap (overflow) periodically, for example approximately
464      * once every 27:03:11 hours:minutes:seconds at 44.1 kHz. It is reset to
465      * zero by flush(), reload(), and stop().
466      */
467
468     return JNI_AT_CALL_INT( getPlaybackHeadPosition ) - p_sys->i_pos_initial;
469 }
470
471 static int
472 JNIThread_TimeGet( JNIEnv *env, audio_output_t *p_aout, mtime_t *p_delay )
473 {
474     aout_sys_t *p_sys = p_aout->sys;
475     jlong i_frame_pos;
476     uint32_t i_audiotrack_delay = 0;
477
478     if( p_sys->i_samples_queued == 0 )
479         return -1;
480     if( p_sys->p_audioTimestamp )
481     {
482         mtime_t i_current_time = mdate();
483         /* Android doc:
484          * getTimestamp: Poll for a timestamp on demand.
485          *
486          * If you need to track timestamps during initial warmup or after a
487          * routing or mode change, you should request a new timestamp once per
488          * second until the reported timestamps show that the audio clock is
489          * stable. Thereafter, query for a new timestamp approximately once
490          * every 10 seconds to once per minute. Calling this method more often
491          * is inefficient. It is also counter-productive to call this method
492          * more often than recommended, because the short-term differences
493          * between successive timestamp reports are not meaningful. If you need
494          * a high-resolution mapping between frame position and presentation
495          * time, consider implementing that at application level, based on
496          * low-resolution timestamps.
497          */
498
499         if( JNI_AT_CALL_BOOL( getTimestamp, p_sys->p_audioTimestamp ) )
500         {
501             jlong i_frame_time = JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime ) / 1000;
502             /* frame time should be after last play time
503              * frame time shouldn't be in the future
504              * frame time should be less than 10 seconds old */
505             if( i_frame_time > p_sys->i_play_time
506                 && i_current_time > i_frame_time
507                 && ( i_current_time - i_frame_time ) <= INT64_C(10000000) )
508             {
509                 jlong i_time_diff = i_current_time - i_frame_time;
510                 jlong i_frames_diff = i_time_diff *  p_sys->fmt.i_rate
511                                       / CLOCK_FREQ;
512                 i_frame_pos = JNI_AUDIOTIMESTAMP_GET_LONG( framePosition )
513                               + i_frames_diff;
514                 if( p_sys->i_samples_written > i_frame_pos )
515                     i_audiotrack_delay =  p_sys->i_samples_written - i_frame_pos;
516             }
517         }
518     }
519     if( i_audiotrack_delay == 0 )
520     {
521         uint32_t i_audiotrack_pos = JNIThread_GetAudioTrackPos( env, p_aout );
522
523         if( p_sys->i_samples_written > i_audiotrack_pos )
524             i_audiotrack_delay = p_sys->i_samples_written - i_audiotrack_pos;
525     }
526
527     if( i_audiotrack_delay > 0 )
528     {
529         *p_delay = FRAMES_TO_US( p_sys->i_samples_queued + i_audiotrack_delay );
530         return 0;
531     } else
532         return -1;
533 }
534
535 static int
536 JNIThread_Start( JNIEnv *env, audio_output_t *p_aout )
537 {
538     struct aout_sys_t *p_sys = p_aout->sys;
539     int i_size, i_min_buffer_size, i_channel_config, i_rate, i_format,
540         i_format_size, i_nb_channels;
541     jobject p_audiotrack;
542
543     /* 4000 <= frequency <= 48000 */
544     i_rate = p_sys->fmt.i_rate;
545     if( i_rate < 4000 )
546         i_rate = 4000;
547     if( i_rate > 48000 )
548         i_rate = 48000;
549
550     /* We can only accept U8, S16N, and FL32 (depending on Android version) */
551     if( p_sys->fmt.i_format != VLC_CODEC_U8
552         && p_sys->fmt.i_format != VLC_CODEC_S16N
553         && p_sys->fmt.i_format != VLC_CODEC_FL32 )
554         p_sys->fmt.i_format = VLC_CODEC_S16N;
555
556     if( p_sys->fmt.i_format == VLC_CODEC_FL32
557         && !jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
558         p_sys->fmt.i_format = VLC_CODEC_S16N;
559
560     if( p_sys->fmt.i_format == VLC_CODEC_S16N )
561     {
562         i_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
563         i_format_size = 2;
564     } else if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
565     {
566         i_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
567         i_format_size = 4;
568     } else
569     {
570         i_format = jfields.AudioFormat.ENCODING_PCM_8BIT;
571         i_format_size = 1;
572     }
573     p_sys->fmt.i_original_channels = p_sys->fmt.i_physical_channels;
574
575     i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
576     switch( i_nb_channels )
577     {
578     case 1:
579         i_channel_config = jfields.AudioFormat.CHANNEL_OUT_MONO;
580         p_sys->fmt.i_physical_channels = AOUT_CHAN_CENTER;
581         break;
582     default:
583         i_nb_channels = 2; // XXX: AudioTrack handle only stereo for now
584     case 2:
585         i_channel_config = jfields.AudioFormat.CHANNEL_OUT_STEREO;
586         p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
587         break;
588     }
589
590     i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize, i_rate,
591                                                 i_channel_config, i_format );
592     if( i_min_buffer_size <= 0 )
593     {
594         msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
595         /* use a defaut min buffer size (shouldn't happen) */
596         i_min_buffer_size = i_nb_channels * i_format_size * 2048;
597     }
598
599     i_size = i_min_buffer_size * 4;
600     p_sys->i_bytes_per_frame = i_nb_channels * i_format_size;
601     p_sys->i_max_audiotrack_samples = i_size / p_sys->i_bytes_per_frame;
602
603     /* create AudioTrack object */
604     p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate,
605                                i_channel_config, i_format, i_size,
606                                jfields.AudioTrack.MODE_STREAM );
607     if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
608         return VLC_EGENERIC;
609     p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
610     (*env)->DeleteLocalRef( env, p_audiotrack );
611     if( !p_sys->p_audiotrack )
612         return VLC_EGENERIC;
613     if( JNI_AT_CALL_INT( getState ) != jfields.AudioTrack.STATE_INITIALIZED )
614     {
615         msg_Err( p_aout, "AudioTrack init failed" );
616         goto error;
617     }
618
619 #ifdef AUDIOTRACK_USE_TIMESTAMP
620     if( jfields.AudioTimestamp.clazz )
621     {
622         /* create AudioTimestamp object */
623         jobject p_audioTimestamp = JNI_CALL( NewObject,
624                                              jfields.AudioTimestamp.clazz,
625                                              jfields.AudioTimestamp.ctor );
626         if( !p_audioTimestamp )
627             goto error;
628         p_sys->p_audioTimestamp = (*env)->NewGlobalRef( env, p_audioTimestamp );
629         (*env)->DeleteLocalRef( env, p_audioTimestamp );
630         if( !p_sys->p_audioTimestamp )
631             goto error;
632     }
633 #endif
634
635     p_sys->fmt.i_rate = i_rate;
636
637     JNI_AT_CALL_VOID( play );
638     CHECK_AT_EXCEPTION( "play" );
639     p_sys->i_play_time = mdate();
640
641     return VLC_SUCCESS;
642 error:
643     if( p_sys->p_audiotrack )
644     {
645         JNI_AT_CALL_VOID( release );
646         (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
647         p_sys->p_audiotrack = NULL;
648     }
649     return VLC_EGENERIC;
650 }
651
652 static void
653 JNIThread_Stop( JNIEnv *env, audio_output_t *p_aout )
654 {
655     aout_sys_t *p_sys = p_aout->sys;
656
657     if( !p_sys->b_audiotrack_exception )
658     {
659         JNI_AT_CALL_VOID( stop );
660         if( !CHECK_AT_EXCEPTION( "stop" ) )
661             JNI_AT_CALL_VOID( release );
662     }
663     p_sys->b_audiotrack_exception = false;
664     (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
665     p_sys->p_audiotrack = NULL;
666
667     if( p_sys->p_audioTimestamp )
668     {
669         (*env)->DeleteGlobalRef( env, p_sys->p_audioTimestamp );
670         p_sys->p_audioTimestamp = NULL;
671     }
672 }
673
674 /**
675  * Non blocking write function.
676  * Do a calculation between current position and audiotrack position and assure
677  * that we won't wait in AudioTrack.write() method
678  */
679 static int
680 JNIThread_Write( JNIEnv *env, audio_output_t *p_aout, block_t *p_buffer )
681 {
682     aout_sys_t *p_sys = p_aout->sys;
683     uint8_t *p_data = p_buffer->p_buffer;
684     size_t i_data;
685     uint32_t i_samples;
686     uint32_t i_audiotrack_pos;
687     uint32_t i_samples_pending;
688
689     i_audiotrack_pos = JNIThread_GetAudioTrackPos( env, p_aout );
690     if( i_audiotrack_pos > p_sys->i_samples_written )
691     {
692         msg_Warn( p_aout, "audiotrack position is ahead. Should NOT happen" );
693         JNIThread_InitDelay( env, p_aout );
694         return 0;
695     }
696     i_samples_pending = p_sys->i_samples_written - i_audiotrack_pos;
697
698     /* check if audiotrack buffer is not full before writing on it. */
699     if( i_samples_pending >= p_sys->i_max_audiotrack_samples )
700     {
701
702         /* HACK: AudioFlinger can drop frames without notifying us and there is
703          * no way to know it. It it happens, i_audiotrack_pos won't move and
704          * the current code will be stuck because it'll assume that audiotrack
705          * internal buffer is full when it's not. It can happen only after
706          * Android 4.4.2 if we send frames too quickly. This HACK is just an
707          * other precaution since it shouldn't happen anymore thanks to the
708          * HACK in JNIThread_Play */
709
710         p_sys->i_audiotrack_stuck_count++;
711         if( p_sys->i_audiotrack_stuck_count > 100 )
712         {
713             msg_Warn( p_aout, "AudioFlinger underrun, force write" );
714             i_samples_pending = 0;
715             p_sys->i_audiotrack_stuck_count = 0;
716         }
717     } else
718         p_sys->i_audiotrack_stuck_count = 0;
719     i_samples = __MIN( p_sys->i_max_audiotrack_samples - i_samples_pending,
720                        p_buffer->i_nb_samples );
721
722     i_data = i_samples * p_sys->i_bytes_per_frame;
723
724     /* check if we need to realloc a ByteArray */
725     if( i_data > p_sys->i_bytearray_size )
726     {
727         jbyteArray p_bytearray;
728
729         if( p_sys->p_bytearray )
730         {
731             (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
732             p_sys->p_bytearray = NULL;
733         }
734
735         p_bytearray = (*env)->NewByteArray( env, i_data );
736         if( p_bytearray )
737         {
738             p_sys->p_bytearray = (*env)->NewGlobalRef( env, p_bytearray );
739             (*env)->DeleteLocalRef( env, p_bytearray );
740         }
741         p_sys->i_bytearray_size = i_data;
742     }
743     if( !p_sys->p_bytearray )
744         return jfields.AudioTrack.ERROR_BAD_VALUE;
745
746     /* copy p_buffer in to ByteArray */
747     (*env)->SetByteArrayRegion( env, p_sys->p_bytearray, 0, i_data,
748                                 (jbyte *)p_data);
749
750     return JNI_AT_CALL_INT( write, p_sys->p_bytearray, 0, i_data );
751 }
752
753 /**
754  * Non blocking write function for Lollipop and after.
755  * It calls a new write method with WRITE_NON_BLOCKING flags.
756  */
757 static int
758 JNIThread_WriteV21( JNIEnv *env, audio_output_t *p_aout, block_t *p_buffer )
759 {
760     aout_sys_t *p_sys = p_aout->sys;
761     int i_ret;
762
763     if( !p_sys->p_bytebuffer )
764     {
765         jobject p_bytebuffer;
766
767         p_bytebuffer = (*env)->NewDirectByteBuffer( env, p_buffer->p_buffer,
768                                                     p_buffer->i_buffer );
769         if( !p_bytebuffer )
770             return jfields.AudioTrack.ERROR_BAD_VALUE;
771
772         p_sys->p_bytebuffer = (*env)->NewGlobalRef( env, p_bytebuffer );
773         (*env)->DeleteLocalRef( env, p_bytebuffer );
774
775         if( !p_sys->p_bytebuffer || (*env)->ExceptionOccurred( env ) )
776         {
777             p_sys->p_bytebuffer = NULL;
778             (*env)->ExceptionClear( env );
779             return jfields.AudioTrack.ERROR_BAD_VALUE;
780         }
781     }
782
783     i_ret = JNI_AT_CALL_INT( writeV21, p_sys->p_bytebuffer, p_buffer->i_buffer,
784                              jfields.AudioTrack.WRITE_NON_BLOCKING );
785     if( i_ret > 0 )
786     {
787         /* don't delete the bytebuffer if we wrote nothing, keep it for next
788          * call */
789         (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
790         p_sys->p_bytebuffer = NULL;
791     }
792     return i_ret;
793 }
794
795 static int
796 JNIThread_Play( JNIEnv *env, audio_output_t *p_aout,
797                 block_t **pp_buffer, mtime_t *p_wait )
798 {
799     aout_sys_t *p_sys = p_aout->sys;
800     block_t *p_buffer = *pp_buffer;
801     int i_ret;
802
803     if( jfields.AudioTrack.writeV21 )
804         i_ret = JNIThread_WriteV21( env, p_aout, p_buffer );
805     else
806         i_ret = JNIThread_Write( env, p_aout, p_buffer );
807
808     if( i_ret < 0 ) {
809         if( jfields.AudioManager.has_ERROR_DEAD_OBJECT
810             && i_ret == jfields.AudioManager.ERROR_DEAD_OBJECT )
811         {
812             msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
813                               "try recreating AudioTrack" );
814             JNIThread_Stop( env, p_aout );
815             i_ret = JNIThread_Start( env, p_aout );
816         } else
817         {
818             const char *str;
819             if( i_ret == jfields.AudioTrack.ERROR_INVALID_OPERATION )
820                 str = "ERROR_INVALID_OPERATION";
821             else if( i_ret == jfields.AudioTrack.ERROR_BAD_VALUE )
822                 str = "ERROR_BAD_VALUE";
823             else
824                 str = "ERROR";
825             msg_Err( p_aout, "Write failed: %s", str );
826         }
827     } else if( i_ret == 0 )
828     {
829         /* audiotrack internal buffer is full, wait a little: between 10ms and
830          * 20ms depending on devices or rate */
831         *p_wait = FRAMES_TO_US( p_sys->i_max_audiotrack_samples / 20 );
832     } else
833     {
834         uint32_t i_samples = i_ret / p_sys->i_bytes_per_frame;
835         p_sys->i_samples_queued -= i_samples;
836         p_sys->i_samples_written += i_samples;
837
838         p_buffer->p_buffer += i_ret;
839         p_buffer->i_buffer -= i_ret;
840         p_buffer->i_nb_samples -= i_samples;
841         if( p_buffer->i_buffer == 0 )
842             *pp_buffer = NULL;
843
844         /* HACK: There is a known issue in audiotrack, "due to an internal
845          * timeout within the AudioTrackThread". It happens after android
846          * 4.4.2, it's not a problem for Android 5.0 since we use an other way
847          * to write samples. A working hack is to wait a little between each
848          * write. This hack is done only for API 19 (AudioTimestamp was added
849          * in API 19). */
850
851         if( jfields.AudioTimestamp.clazz && !jfields.AudioTrack.writeV21 )
852             *p_wait = FRAMES_TO_US( i_samples ) / 2;
853     }
854     return i_ret >= 0 ? VLC_SUCCESS : VLC_EGENERIC;
855 }
856
857 static void
858 JNIThread_Pause( JNIEnv *env, audio_output_t *p_aout,
859                  bool b_pause, mtime_t i_date )
860 {
861     VLC_UNUSED( i_date );
862
863     aout_sys_t *p_sys = p_aout->sys;
864
865     if( b_pause )
866     {
867         JNI_AT_CALL_VOID( pause );
868         CHECK_AT_EXCEPTION( "pause" );
869     } else
870     {
871         JNI_AT_CALL_VOID( play );
872         CHECK_AT_EXCEPTION( "play" );
873         p_sys->i_play_time = mdate();
874     }
875 }
876
877 static void
878 JNIThread_Flush( JNIEnv *env, audio_output_t *p_aout,
879                  bool b_wait )
880 {
881     aout_sys_t *p_sys = p_aout->sys;
882
883     /* Android doc:
884      * stop(): Stops playing the audio data. When used on an instance created
885      * in MODE_STREAM mode, audio will stop playing after the last buffer that
886      * was written has been played. For an immediate stop, use pause(),
887      * followed by flush() to discard audio data that hasn't been played back
888      * yet.
889      *
890      * flush(): Flushes the audio data currently queued for playback. Any data
891      * that has not been played back will be discarded.  No-op if not stopped
892      * or paused, or if the track's creation mode is not MODE_STREAM.
893      */
894     if( b_wait )
895     {
896         JNI_AT_CALL_VOID( stop );
897         if( CHECK_AT_EXCEPTION( "stop" ) )
898             return;
899     } else
900     {
901         JNI_AT_CALL_VOID( pause );
902         if( CHECK_AT_EXCEPTION( "pause" ) )
903             return;
904         JNI_AT_CALL_VOID( flush );
905     }
906     JNI_AT_CALL_VOID( play );
907     CHECK_AT_EXCEPTION( "play" );
908     p_sys->i_play_time = mdate();
909
910     if( p_sys->p_bytebuffer )
911     {
912         (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
913         p_sys->p_bytebuffer = NULL;
914     }
915 }
916
917 static void *
918 JNIThread( void *data )
919 {
920     audio_output_t *p_aout = data;
921     aout_sys_t *p_sys = p_aout->sys;
922     bool b_error = false;
923     bool b_paused = false;
924     block_t *p_buffer = NULL;
925     mtime_t i_play_deadline = 0;
926     JNIEnv* env;
927
928     jni_attach_thread( &env, THREAD_NAME );
929
930     vlc_mutex_lock( &p_sys->mutex );
931     if( !env )
932         goto end;
933
934     while( p_sys->b_thread_run )
935     {
936         struct thread_cmd *p_cmd;
937         bool b_remove_cmd = true;
938
939         /* wait to process a command */
940         while( ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue ) ) == NULL
941                && p_sys->b_thread_run )
942             vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
943
944         if( !p_sys->b_thread_run || p_cmd == NULL )
945             break;
946
947         if( b_paused && p_cmd->id == CMD_PLAY )
948         {
949             vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
950             continue;
951         }
952
953         if( p_cmd->id == CMD_PLAY && i_play_deadline > 0 )
954         {
955             if( mdate() > i_play_deadline )
956                 i_play_deadline = 0;
957             else
958             {
959                 int i_ret = 0;
960                 while( p_cmd == TAILQ_FIRST( &p_sys->thread_cmd_queue )
961                        && i_ret != ETIMEDOUT && p_sys->b_thread_run )
962                     i_ret = vlc_cond_timedwait( &p_sys->cond, &p_sys->mutex,
963                                                 i_play_deadline );
964                 continue;
965             }
966         }
967
968         /* process a command */
969         switch( p_cmd->id )
970         {
971             case CMD_START:
972                 assert( !p_sys->p_audiotrack );
973                 if( b_error ) {
974                     p_cmd->out.start.i_ret = -1;
975                     break;
976                 }
977                 p_sys->fmt = *p_cmd->in.start.p_fmt;
978                 p_cmd->out.start.i_ret =
979                         JNIThread_Start( env, p_aout );
980                 JNIThread_InitDelay( env, p_aout );
981                 p_cmd->out.start.p_fmt = &p_sys->fmt;
982                 b_paused = false;
983                 break;
984             case CMD_STOP:
985                 assert( p_sys->p_audiotrack );
986                 JNIThread_Stop( env, p_aout );
987                 JNIThread_InitDelay( env, p_aout );
988                 b_paused = false;
989                 b_error = false;
990                 p_buffer = NULL;
991                 break;
992             case CMD_PLAY:
993             {
994                 mtime_t i_play_wait = 0;
995
996                 assert( p_sys->p_audiotrack );
997                 if( b_error )
998                     break;
999                 if( p_buffer == NULL )
1000                     p_buffer = p_cmd->in.play.p_buffer;
1001                 b_error = JNIThread_Play( env, p_aout, &p_buffer,
1002                                           &i_play_wait ) != VLC_SUCCESS;
1003                 if( p_buffer != NULL )
1004                     b_remove_cmd = false;
1005                 if( i_play_wait > 0 )
1006                     i_play_deadline = mdate() + i_play_wait;
1007                 break;
1008             }
1009             case CMD_PAUSE:
1010                 assert( p_sys->p_audiotrack );
1011                 if( b_error )
1012                     break;
1013                 JNIThread_Pause( env, p_aout,
1014                                  p_cmd->in.pause.b_pause,
1015                                  p_cmd->in.pause.i_date );
1016                 b_paused = p_cmd->in.pause.b_pause;
1017                 break;
1018             case CMD_TIME_GET:
1019                 assert( p_sys->p_audiotrack );
1020                 if( b_error )
1021                     break;
1022                 p_cmd->out.time_get.i_ret =
1023                         JNIThread_TimeGet( env, p_aout,
1024                                            &p_cmd->out.time_get.i_delay );
1025                 break;
1026             case CMD_FLUSH:
1027                 assert( p_sys->p_audiotrack );
1028                 if( b_error )
1029                     break;
1030                 JNIThread_Flush( env, p_aout,
1031                                  p_cmd->in.flush.b_wait );
1032                 JNIThread_InitDelay( env, p_aout );
1033                 p_buffer = NULL;
1034                 break;
1035             default:
1036                 vlc_assert_unreachable();
1037         }
1038         if( p_sys->b_audiotrack_exception )
1039             b_error = true;
1040
1041         if( b_remove_cmd )
1042         {
1043             TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
1044             p_cmd->id = CMD_DONE;
1045             if( p_cmd->pf_destroy )
1046                 p_cmd->pf_destroy( p_cmd );
1047         }
1048
1049         /* signal that command is processed */
1050         vlc_cond_signal( &p_sys->cond );
1051     }
1052 end:
1053     if( env )
1054     {
1055         if( p_sys->p_bytearray )
1056             (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
1057         if( p_sys->p_bytebuffer )
1058             (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
1059         jni_detach_thread();
1060     }
1061     vlc_mutex_unlock( &p_sys->mutex );
1062     return NULL;
1063 }
1064
1065 static int
1066 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
1067 {
1068     int i_ret = VLC_EGENERIC;
1069     struct thread_cmd *p_cmd;
1070     aout_sys_t *p_sys = p_aout->sys;
1071
1072     vlc_mutex_lock( &p_sys->mutex );
1073
1074     p_cmd = ThreadCmd_New( CMD_START );
1075     if( p_cmd )
1076     {
1077         /* ask the thread to process the Start command */
1078         p_cmd->in.start.p_fmt = p_fmt;
1079
1080         ThreadCmd_InsertHead( p_sys, p_cmd );
1081         if( ThreadCmd_Wait( p_sys, p_cmd ) )
1082         {
1083             i_ret = p_cmd->out.start.i_ret;
1084             if( i_ret == VLC_SUCCESS )
1085                 *p_fmt = *p_cmd->out.start.p_fmt;
1086         }
1087         free( p_cmd );
1088     }
1089
1090     vlc_mutex_unlock( &p_sys->mutex );
1091
1092     if( i_ret == VLC_SUCCESS )
1093         aout_SoftVolumeStart( p_aout );
1094
1095     return i_ret;
1096 }
1097
1098 static void
1099 Stop( audio_output_t *p_aout )
1100 {
1101     aout_sys_t *p_sys = p_aout->sys;
1102     struct thread_cmd *p_cmd;
1103
1104     vlc_mutex_lock( &p_sys->mutex );
1105
1106     ThreadCmd_FlushQueue( p_sys );
1107
1108     p_cmd = ThreadCmd_New( CMD_STOP );
1109     if( p_cmd )
1110     {
1111         /* ask the thread to process the Stop command */
1112         ThreadCmd_InsertHead( p_sys, p_cmd );
1113         ThreadCmd_Wait( p_sys, p_cmd );
1114
1115         free( p_cmd );
1116     }
1117
1118     vlc_mutex_unlock( &p_sys->mutex );
1119 }
1120
1121 static void
1122 PlayCmd_Destroy( struct thread_cmd *p_cmd )
1123 {
1124     block_Release( p_cmd->in.play.p_buffer );
1125     free( p_cmd );
1126 }
1127
1128 static void
1129 Play( audio_output_t *p_aout, block_t *p_buffer )
1130 {
1131     aout_sys_t *p_sys = p_aout->sys;
1132     struct thread_cmd *p_cmd;
1133
1134     vlc_mutex_lock( &p_sys->mutex );
1135
1136     while( p_sys->i_samples_queued != 0
1137            && FRAMES_TO_US( p_sys->i_samples_queued +
1138                             p_buffer->i_nb_samples ) >= MAX_QUEUE_US )
1139         vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
1140
1141     p_cmd = ThreadCmd_New( CMD_PLAY );
1142     if( p_cmd )
1143     {
1144         /* ask the thread to process the Play command */
1145         p_cmd->in.play.p_buffer = p_buffer;
1146         p_cmd->pf_destroy = PlayCmd_Destroy;
1147
1148         ThreadCmd_InsertTail( p_sys, p_cmd );
1149
1150         p_sys->i_samples_queued += p_buffer->i_nb_samples;
1151     } else
1152          block_Release( p_cmd->in.play.p_buffer );
1153
1154     vlc_mutex_unlock( &p_sys->mutex );
1155 }
1156
1157 static void
1158 Pause( audio_output_t *p_aout, bool b_pause, mtime_t i_date )
1159 {
1160     aout_sys_t *p_sys = p_aout->sys;
1161     struct thread_cmd *p_cmd;
1162
1163     vlc_mutex_lock( &p_sys->mutex );
1164
1165     p_cmd = ThreadCmd_New( CMD_PAUSE );
1166     if( p_cmd )
1167     {
1168         /* ask the thread to process the Pause command */
1169         p_cmd->in.pause.b_pause = b_pause;
1170         p_cmd->in.pause.i_date = i_date;
1171
1172         ThreadCmd_InsertHead( p_sys, p_cmd );
1173         ThreadCmd_Wait( p_sys, p_cmd );
1174
1175         free( p_cmd );
1176     }
1177
1178     vlc_mutex_unlock( &p_sys->mutex );
1179 }
1180
1181 static void
1182 Flush( audio_output_t *p_aout, bool b_wait )
1183 {
1184     aout_sys_t *p_sys = p_aout->sys;
1185     struct thread_cmd *p_cmd;
1186
1187     vlc_mutex_lock( &p_sys->mutex );
1188
1189     ThreadCmd_FlushQueue( p_sys );
1190
1191     p_cmd = ThreadCmd_New( CMD_FLUSH );
1192     if( p_cmd)
1193     {
1194         /* ask the thread to process the Flush command */
1195         p_cmd->in.flush.b_wait = b_wait;
1196
1197         ThreadCmd_InsertHead( p_sys, p_cmd );
1198         ThreadCmd_Wait( p_sys, p_cmd );
1199
1200         free( p_cmd );
1201     }
1202
1203     vlc_mutex_unlock( &p_sys->mutex );
1204 }
1205
1206 static int
1207 TimeGet( audio_output_t *p_aout, mtime_t *restrict p_delay )
1208 {
1209     aout_sys_t *p_sys = p_aout->sys;
1210     struct thread_cmd *p_cmd;
1211     int i_ret = -1;
1212
1213     vlc_mutex_lock( &p_sys->mutex );
1214
1215     p_cmd = ThreadCmd_New( CMD_TIME_GET );
1216     if( p_cmd)
1217     {
1218         ThreadCmd_InsertHead( p_sys, p_cmd );
1219         ThreadCmd_Wait( p_sys, p_cmd );
1220
1221         i_ret = p_cmd->out.time_get.i_ret;
1222         *p_delay = p_cmd->out.time_get.i_delay;
1223         free( p_cmd );
1224     }
1225
1226     vlc_mutex_unlock( &p_sys->mutex );
1227
1228     return i_ret;
1229 }
1230
1231
1232 static int
1233 Open( vlc_object_t *obj )
1234 {
1235     audio_output_t *p_aout = (audio_output_t *) obj;
1236     aout_sys_t *p_sys;
1237
1238     if( !InitJNIFields( p_aout ) )
1239         return VLC_EGENERIC;
1240
1241     p_sys = calloc( 1, sizeof (aout_sys_t) );
1242
1243     if( unlikely( p_sys == NULL ) )
1244         return VLC_ENOMEM;
1245
1246     vlc_mutex_init( &p_sys->mutex );
1247     vlc_cond_init( &p_sys->cond );
1248     TAILQ_INIT( &p_sys->thread_cmd_queue );
1249
1250     p_aout->sys = p_sys;
1251     p_aout->start = Start;
1252     p_aout->stop = Stop;
1253     p_aout->play = Play;
1254     p_aout->pause = Pause;
1255     p_aout->flush = Flush;
1256     p_aout->time_get = TimeGet;
1257
1258     aout_SoftVolumeInit( p_aout );
1259
1260     /* create JNIThread */
1261     p_sys->b_thread_run = true;
1262     if( vlc_clone( &p_sys->thread,
1263                    JNIThread, p_aout, VLC_THREAD_PRIORITY_AUDIO ) )
1264     {
1265         msg_Err( p_aout, "JNIThread creation failed" );
1266         p_sys->b_thread_run = false;
1267         Close( obj );
1268         return VLC_EGENERIC;
1269     }
1270
1271     return VLC_SUCCESS;
1272 }
1273
1274 static void
1275 Close( vlc_object_t *obj )
1276 {
1277     audio_output_t *p_aout = (audio_output_t *) obj;
1278     aout_sys_t *p_sys = p_aout->sys;
1279
1280     /* kill the thread */
1281     vlc_mutex_lock( &p_sys->mutex );
1282     if( p_sys->b_thread_run )
1283     {
1284         p_sys->b_thread_run = false;
1285         vlc_cond_signal( &p_sys->cond );
1286         vlc_mutex_unlock( &p_sys->mutex );
1287         vlc_join( p_sys->thread, NULL );
1288     } else
1289         vlc_mutex_unlock( &p_sys->mutex );
1290
1291     vlc_mutex_destroy( &p_sys->mutex );
1292     vlc_cond_destroy( &p_sys->cond );
1293
1294     free( p_sys );
1295 }