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