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