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