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