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