]> git.sesse.net Git - vlc/blob - modules/audio_output/audiotrack.c
audiotrack: fix audioTimestamp leak
[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 */
59     size_t i_bytearray_size; /* size of the ByteArray */
60     audio_sample_format_t fmt; /* fmt setup by Start */
61     uint32_t i_pos_initial; /* initial position set by getPlaybackHeadPosition */
62     uint32_t i_samples_written; /* number of samples written since last flush */
63     mtime_t i_play_time; /* time when play was called */
64
65     /* JNIThread control */
66     vlc_mutex_t mutex;
67     vlc_cond_t cond;
68     vlc_thread_t thread;
69
70     /* Shared between two threads, must be locked */
71     bool b_thread_run; /* is thread alive */
72     THREAD_CMD_QUEUE thread_cmd_queue; /* thread cmd queue */
73     uint32_t i_samples_queued; /* number of samples queued */
74     uint32_t i_audiotrack_delay; /* audiotrack delay in samples */
75 };
76
77 /* Soft volume helper */
78 #include "audio_output/volume.h"
79
80 //#define AUDIOTRACK_USE_FLOAT
81
82 vlc_module_begin ()
83     set_shortname( "AudioTrack" )
84     set_description( N_( "Android AudioTrack audio output" ) )
85     set_capability( "audio output", 180 )
86     set_category( CAT_AUDIO )
87     set_subcategory( SUBCAT_AUDIO_AOUT )
88     add_sw_gain()
89     add_shortcut( "audiotrack" )
90     set_callbacks( Open, Close )
91 vlc_module_end ()
92
93 struct thread_cmd
94 {
95     TAILQ_ENTRY(thread_cmd) next;
96     enum {
97         CMD_START,
98         CMD_STOP,
99         CMD_PLAY,
100         CMD_PAUSE,
101         CMD_FLUSH,
102         CMD_DONE,
103     } id;
104     union {
105         struct {
106             audio_sample_format_t *p_fmt;
107         } start;
108         struct {
109             block_t *p_buffer;
110         } play;
111         struct {
112             bool b_pause;
113             mtime_t i_date;
114         } pause;
115         struct {
116             bool b_wait;
117         } flush;
118     } in;
119     union {
120         struct {
121             int i_ret;
122             audio_sample_format_t *p_fmt;
123         } start;
124     } out;
125     void ( *pf_destroy )( struct thread_cmd * );
126 };
127
128 #define THREAD_NAME "android_audiotrack"
129
130 extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
131 extern void jni_detach_thread();
132 extern int jni_get_env(JNIEnv **env);
133
134 static struct
135 {
136     struct {
137         jclass clazz;
138         jmethodID ctor;
139         jmethodID release;
140         jmethodID play;
141         jmethodID stop;
142         jmethodID flush;
143         jmethodID pause;
144         jmethodID write;
145         jmethodID getPlaybackHeadPosition;
146         jmethodID getTimestamp;
147         jmethodID getMinBufferSize;
148         jint MODE_STREAM;
149         jint ERROR;
150         jint ERROR_BAD_VALUE;
151         jint ERROR_INVALID_OPERATION;
152     } AudioTrack;
153     struct {
154         jint ENCODING_PCM_8BIT;
155         jint ENCODING_PCM_16BIT;
156         jint ENCODING_PCM_FLOAT;
157         bool has_ENCODING_PCM_FLOAT;
158         jint CHANNEL_OUT_MONO;
159         jint CHANNEL_OUT_STEREO;
160     } AudioFormat;
161     struct {
162         jint ERROR_DEAD_OBJECT;
163         bool has_ERROR_DEAD_OBJECT;
164         jint STREAM_MUSIC;
165     } AudioManager;
166     struct {
167         jclass clazz;
168         jmethodID ctor;
169         jfieldID framePosition;
170         jfieldID nanoTime;
171     } AudioTimestamp;
172 } jfields;
173
174 /* init all jni fields.
175  * Done only one time during the first initialisation */
176 static bool
177 InitJNIFields( audio_output_t *p_aout )
178 {
179     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
180     static int i_init_state = -1;
181     bool ret, b_attached = false;
182     jclass clazz;
183     jfieldID field;
184     JNIEnv* env = NULL;
185
186     vlc_mutex_lock( &lock );
187
188     if( i_init_state != -1 )
189         goto end;
190
191     if( jni_get_env(&env) < 0 )
192     {
193         jni_attach_thread( &env, THREAD_NAME );
194         if( !env )
195         {
196             i_init_state = 0;
197             goto end;
198         }
199         b_attached = true;
200     }
201
202 #define CHECK_EXCEPTION( what, critical ) do { \
203     if( (*env)->ExceptionOccurred( env ) ) \
204     { \
205         msg_Err( p_aout, "%s failed", what ); \
206         (*env)->ExceptionClear( env ); \
207         if( (critical) ) \
208         { \
209             i_init_state = 0; \
210             goto end; \
211         } \
212     } \
213 } while( 0 )
214 #define GET_CLASS( str, critical ) do { \
215     clazz = (*env)->FindClass( env, (str) ); \
216     CHECK_EXCEPTION( str, critical ); \
217 } while( 0 )
218 #define GET_ID( get, id, str, args, critical ) do { \
219     jfields.id = (*env)->get( env, clazz, (str), (args) ); \
220     CHECK_EXCEPTION( #get, critical ); \
221 } while( 0 )
222 #define GET_CONST_INT( id, str, critical ) do { \
223     field = NULL; \
224     field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
225     CHECK_EXCEPTION( #id, critical ); \
226     if( field ) \
227     { \
228         jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
229         CHECK_EXCEPTION( #id, critical ); \
230     } \
231 } while( 0 )
232
233     /* AudioTrack class init */
234     GET_CLASS( "android/media/AudioTrack", true );
235     jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
236     CHECK_EXCEPTION( "NewGlobalRef", true );
237
238     GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIII)V", true );
239     GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true );
240     GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true );
241     GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true );
242     GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true );
243     GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true );
244     GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
245
246     GET_ID( GetMethodID, AudioTrack.getTimestamp,
247             "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
248     GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
249             "getPlaybackHeadPosition", "()I", true );
250
251     GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize",
252             "(III)I", true );
253     GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
254     GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
255     GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true );
256     GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION ,
257                    "ERROR_INVALID_OPERATION", true );
258
259     /* AudioTimestamp class init (if any) */
260     if( jfields.AudioTrack.getTimestamp )
261     {
262         GET_CLASS( "android/media/AudioTimestamp", true );
263         jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env,
264                                                                       clazz );
265         CHECK_EXCEPTION( "NewGlobalRef", true );
266
267         GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true );
268         GET_ID( GetFieldID, AudioTimestamp.framePosition,
269                 "framePosition", "J", true );
270         GET_ID( GetFieldID, AudioTimestamp.nanoTime,
271                 "nanoTime", "J", true );
272     } else
273     {
274         jfields.AudioTimestamp.clazz = NULL;
275         jfields.AudioTimestamp.ctor = NULL;
276         jfields.AudioTimestamp.framePosition = NULL;
277         jfields.AudioTimestamp.nanoTime = NULL;
278     }
279
280     /* AudioFormat class init */
281     GET_CLASS( "android/media/AudioFormat", true );
282     GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
283     GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
284 #ifdef AUDIOTRACK_USE_FLOAT
285     GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
286                    false );
287     jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL;
288 #else
289     jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
290 #endif
291     GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
292     GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
293
294     /* AudioManager class init */
295     GET_CLASS( "android/media/AudioManager", true );
296     GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false );
297     jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
298     GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
299
300 #undef CHECK_EXCEPTION
301 #undef GET_CLASS
302 #undef GET_ID
303 #undef GET_CONST_INT
304
305     i_init_state = 1;
306 end:
307     ret = i_init_state == 1;
308     if( !ret )
309         msg_Err( p_aout, "AudioTrack jni init failed" );
310     if( b_attached )
311         jni_detach_thread();
312     vlc_mutex_unlock( &lock );
313     return ret;
314 }
315
316 static inline bool
317 check_exception( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
318                  const char *method )
319 {
320     if( (*env)->ExceptionOccurred( env ) )
321     {
322         (*env)->ExceptionClear( env );
323         *p_error = true;
324         msg_Err( p_aout, "AudioTrack.%s triggered an exception !", method );
325         return true;
326     } else
327         return false;
328 }
329 #define CHECK_EXCEPTION( method ) check_exception( env, p_error, p_aout, method )
330
331 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
332
333 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
334 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
335 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
336 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
337
338 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
339 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
340 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
341 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
342 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
343
344 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->p_audioTimestamp, jfields.AudioTimestamp.field )
345
346 static inline mtime_t
347 frames_to_us( aout_sys_t *p_sys, uint32_t i_nb_frames )
348 {
349     return  i_nb_frames * CLOCK_FREQ / p_sys->fmt.i_rate;
350 }
351 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
352
353 static struct thread_cmd *
354 ThreadCmd_New( int id )
355 {
356     struct thread_cmd *p_cmd = calloc( 1, sizeof(struct thread_cmd) );
357
358     if( p_cmd )
359         p_cmd->id = id;
360
361     return p_cmd;
362 }
363
364 static void
365 ThreadCmd_InsertHead( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
366 {
367     TAILQ_INSERT_HEAD( &p_sys->thread_cmd_queue, p_cmd, next);
368     vlc_cond_signal( &p_sys->cond );
369 }
370
371 static void
372 ThreadCmd_InsertTail( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
373 {
374     TAILQ_INSERT_TAIL( &p_sys->thread_cmd_queue, p_cmd, next);
375     vlc_cond_signal( &p_sys->cond );
376 }
377
378 static bool
379 ThreadCmd_Wait( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
380 {
381     while( p_cmd->id != CMD_DONE && p_sys->b_thread_run  )
382         vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
383
384     return p_cmd->id == CMD_DONE;
385 }
386
387 static void
388 ThreadCmd_FlushQueue( aout_sys_t *p_sys )
389 {
390     struct thread_cmd *p_cmd, *p_cmd_next;
391
392     for ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue );
393           p_cmd != NULL; p_cmd = p_cmd_next )
394     {
395         p_cmd_next = TAILQ_NEXT( p_cmd, next );
396         TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
397         if( p_cmd->pf_destroy )
398             p_cmd->pf_destroy( p_cmd );
399     }
400 }
401
402 static void
403 JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
404 {
405     aout_sys_t *p_sys = p_aout->sys;
406
407     p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
408
409     /* HACK: On some broken devices, head position is still moving after a
410      * flush or a stop. So, wait for the head position to be stabilized. */
411     if( unlikely( p_sys->i_pos_initial != 0 ) )
412     {
413         uint32_t i_last_pos;
414         do {
415             i_last_pos = p_sys->i_pos_initial;
416             msleep( 50000 );
417             p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
418         } while( p_sys->i_pos_initial != i_last_pos );
419     }
420     p_sys->i_samples_written = 0;
421     *p_delay = 0;
422 }
423
424 static void
425 JNIThread_SetDelay( JNIEnv *env, audio_output_t *p_aout, uint32_t *p_delay )
426 {
427     aout_sys_t *p_sys = p_aout->sys;
428     bool b_frame_delay_set = false;
429     jlong i_frame_pos;
430     mtime_t i_current_time = mdate();
431
432     if( p_sys->p_audioTimestamp )
433     {
434         /* Android doc:
435          * getTimestamp: Poll for a timestamp on demand.
436          *
437          * If you need to track timestamps during initial warmup or after a
438          * routing or mode change, you should request a new timestamp once per
439          * second until the reported timestamps show that the audio clock is
440          * stable. Thereafter, query for a new timestamp approximately once
441          * every 10 seconds to once per minute. Calling this method more often
442          * is inefficient. It is also counter-productive to call this method
443          * more often than recommended, because the short-term differences
444          * between successive timestamp reports are not meaningful. If you need
445          * a high-resolution mapping between frame position and presentation
446          * time, consider implementing that at application level, based on
447          * low-resolution timestamps.
448          */
449
450         if( JNI_AT_CALL_BOOL( getTimestamp, p_sys->p_audioTimestamp ) )
451         {
452             jlong i_frame_time = JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime ) / 1000;
453             /* frame time should be after last play time
454              * frame time shouldn't be in the future
455              * frame time should be less than 10 seconds old */
456             if( i_frame_time > p_sys->i_play_time
457                 && i_current_time > i_frame_time
458                 && ( i_current_time - i_frame_time ) <= INT64_C(10000000) )
459             {
460                 jlong i_time_diff = i_current_time - i_frame_time;
461                 jlong i_frames_diff = i_time_diff *  p_sys->fmt.i_rate
462                                       / CLOCK_FREQ;
463                 i_frame_pos = JNI_AUDIOTIMESTAMP_GET_LONG( framePosition )
464                               + i_frames_diff;
465                 b_frame_delay_set = true;
466             }
467         }
468     }
469     if( !b_frame_delay_set )
470     {
471         /* Android doc:
472          * getPlaybackHeadPosition: Returns the playback head position
473          * expressed in frames. Though the "int" type is signed 32-bits, the
474          * value should be reinterpreted as if it is unsigned 32-bits. That is,
475          * the next position after 0x7FFFFFFF is (int) 0x80000000. This is a
476          * continuously advancing counter. It will wrap (overflow)
477          * periodically, for example approximately once every 27:03:11
478          * hours:minutes:seconds at 44.1 kHz. It is reset to zero by flush(),
479          * reload(), and stop().
480          */
481
482         uint32_t i_head_pos = JNI_AT_CALL_INT( getPlaybackHeadPosition );
483         i_frame_pos = i_head_pos - p_sys->i_pos_initial;
484         b_frame_delay_set = true;
485     }
486
487     if( b_frame_delay_set && p_sys->i_samples_written > i_frame_pos )
488         *p_delay = p_sys->i_samples_written - i_frame_pos;
489 }
490
491 static int
492 JNIThread_Start( JNIEnv *env, bool *p_error, audio_output_t *p_aout )
493 {
494     struct aout_sys_t *p_sys = p_aout->sys;
495     int i_size, i_min_buffer_size, i_channel_config, i_rate, i_format,
496         i_format_size, i_nb_channels;
497     jobject p_audiotrack;
498
499     /* 4000 <= frequency <= 48000 */
500     i_rate = p_sys->fmt.i_rate;
501     if( i_rate < 4000 )
502         i_rate = 4000;
503     if( i_rate > 48000 )
504         i_rate = 48000;
505
506     /* We can only accept U8, S16N, and FL32 (depending on Android version) */
507     if( p_sys->fmt.i_format != VLC_CODEC_U8
508         && p_sys->fmt.i_format != VLC_CODEC_S16N
509         && p_sys->fmt.i_format != VLC_CODEC_FL32 )
510         p_sys->fmt.i_format = VLC_CODEC_S16N;
511
512     if( p_sys->fmt.i_format == VLC_CODEC_FL32
513         && !jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
514         p_sys->fmt.i_format = VLC_CODEC_S16N;
515
516     if( p_sys->fmt.i_format == VLC_CODEC_S16N )
517     {
518         i_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
519         i_format_size = 2;
520     } else if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
521     {
522         i_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
523         i_format_size = 4;
524     } else
525     {
526         i_format = jfields.AudioFormat.ENCODING_PCM_8BIT;
527         i_format_size = 1;
528     }
529     p_sys->fmt.i_original_channels = p_sys->fmt.i_physical_channels;
530
531     i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
532     switch( i_nb_channels )
533     {
534     case 1:
535         i_channel_config = jfields.AudioFormat.CHANNEL_OUT_MONO;
536         p_sys->fmt.i_physical_channels = AOUT_CHAN_CENTER;
537         break;
538     default:
539         i_nb_channels = 2; // XXX: AudioTrack handle only stereo for now
540     case 2:
541         i_channel_config = jfields.AudioFormat.CHANNEL_OUT_STEREO;
542         p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
543         break;
544     }
545
546     i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize, i_rate,
547                                                 i_channel_config, i_format );
548     if( i_min_buffer_size <= 0 )
549     {
550         msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
551         /* use a defaut min buffer size (shouldn't happen) */
552         i_min_buffer_size = i_nb_channels * i_format_size * 2024;
553     }
554
555     i_size = i_min_buffer_size * 2; // double buffering
556
557     /* create AudioTrack object */
558     p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate,
559                                i_channel_config, i_format, i_size,
560                                jfields.AudioTrack.MODE_STREAM );
561     if( CHECK_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
562         return VLC_EGENERIC;
563     p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
564     (*env)->DeleteLocalRef( env, p_audiotrack );
565     if( !p_sys->p_audiotrack )
566         return VLC_EGENERIC;
567
568     if( jfields.AudioTimestamp.clazz )
569     {
570         /* create AudioTimestamp object */
571         jobject p_audioTimestamp = JNI_CALL( NewObject,
572                                              jfields.AudioTimestamp.clazz,
573                                              jfields.AudioTimestamp.ctor );
574         if( CHECK_EXCEPTION( "AudioTimestamp<init>" ) || !p_audioTimestamp )
575             goto error;
576         p_sys->p_audioTimestamp = (*env)->NewGlobalRef( env, p_audioTimestamp );
577         (*env)->DeleteLocalRef( env, p_audioTimestamp );
578         if( !p_sys->p_audioTimestamp )
579             goto error;
580     }
581
582     p_sys->fmt.i_rate = i_rate;
583
584     JNI_AT_CALL_VOID( play );
585     CHECK_EXCEPTION( "play" );
586     p_sys->i_play_time = mdate();
587
588     return VLC_SUCCESS;
589 error:
590     if( p_sys->p_audiotrack )
591     {
592         JNI_AT_CALL_VOID( release );
593         (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
594         p_sys->p_audiotrack = NULL;
595     }
596     return VLC_EGENERIC;
597 }
598
599 static void
600 JNIThread_Stop( JNIEnv *env, bool *p_error, audio_output_t *p_aout )
601 {
602     aout_sys_t *p_sys = p_aout->sys;
603
604     JNI_AT_CALL_VOID( stop );
605     CHECK_EXCEPTION( "stop" );
606
607     JNI_AT_CALL_VOID( release );
608     (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
609     p_sys->p_audiotrack = NULL;
610
611     if( p_sys->p_audioTimestamp )
612     {
613         (*env)->DeleteGlobalRef( env, p_sys->p_audioTimestamp );
614         p_sys->p_audioTimestamp = NULL;
615     }
616 }
617
618 static void
619 JNIThread_Play( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
620                 block_t *p_buffer )
621 {
622     aout_sys_t *p_sys = p_aout->sys;
623     int i_offset = 0;
624
625     /* check if we need to realloc a ByteArray */
626     if( p_buffer->i_buffer > p_sys->i_bytearray_size )
627     {
628         jbyteArray p_bytearray;
629
630         if( p_sys->p_bytearray )
631         {
632             (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
633             p_sys->p_bytearray = NULL;
634         }
635
636         p_bytearray = (*env)->NewByteArray( env, p_buffer->i_buffer );
637         if( p_bytearray )
638         {
639             p_sys->p_bytearray = (*env)->NewGlobalRef( env, p_bytearray );
640             (*env)->DeleteLocalRef( env, p_bytearray );
641         }
642         p_sys->i_bytearray_size = p_buffer->i_buffer;
643     }
644     if( !p_sys->p_bytearray )
645     {
646         *p_error = true;
647         return;
648     }
649
650     /* copy p_buffer in to ByteArray */
651     (*env)->SetByteArrayRegion( env, p_sys->p_bytearray, 0,
652                                 p_buffer->i_buffer,
653                                 (jbyte *)p_buffer->p_buffer);
654
655     while ( p_buffer->i_buffer > (unsigned int) i_offset )
656     {
657         int i_ret;
658
659         /* write ByteArray */
660         i_ret = JNI_AT_CALL_INT( write, p_sys->p_bytearray, i_offset,
661                                  p_buffer->i_buffer - i_offset);
662         if( i_ret < 0 ) {
663             if( jfields.AudioManager.has_ERROR_DEAD_OBJECT
664                 && i_ret == jfields.AudioManager.ERROR_DEAD_OBJECT )
665             {
666                 msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
667                                   "try recreating AudioTrack" );
668                 JNIThread_Stop( env, p_error, p_aout );
669                 i_ret = JNIThread_Start( env, p_error, p_aout );
670                 if( i_ret == VLC_SUCCESS )
671                     continue;
672             } else
673             {
674                 const char *str;
675                 if( i_ret == jfields.AudioTrack.ERROR_INVALID_OPERATION )
676                     str = "ERROR_INVALID_OPERATION";
677                 else if( i_ret == jfields.AudioTrack.ERROR_BAD_VALUE )
678                     str = "ERROR_BAD_VALUE";
679                 else
680                     str = "ERROR";
681                 msg_Err( p_aout, "Write failed: %s", str );
682             }
683             *p_error = true;
684             break;
685         }
686
687         i_offset += i_ret;
688     }
689     p_sys->i_samples_written += p_buffer->i_nb_samples;
690 }
691
692 static void
693 JNIThread_Pause( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
694                  bool b_pause, mtime_t i_date )
695 {
696     VLC_UNUSED( i_date );
697
698     aout_sys_t *p_sys = p_aout->sys;
699
700     if( b_pause )
701     {
702         JNI_AT_CALL_VOID( pause );
703         CHECK_EXCEPTION( "pause" );
704     } else
705     {
706         JNI_AT_CALL_VOID( play );
707         CHECK_EXCEPTION( "play" );
708         p_sys->i_play_time = mdate();
709     }
710 }
711
712 static void
713 JNIThread_Flush( JNIEnv *env, bool *p_error, audio_output_t *p_aout,
714                  bool b_wait )
715 {
716     aout_sys_t *p_sys = p_aout->sys;
717
718     /* Android doc:
719      * stop(): Stops playing the audio data. When used on an instance created
720      * in MODE_STREAM mode, audio will stop playing after the last buffer that
721      * was written has been played. For an immediate stop, use pause(),
722      * followed by flush() to discard audio data that hasn't been played back
723      * yet.
724      *
725      * flush(): Flushes the audio data currently queued for playback. Any data
726      * that has not been played back will be discarded.  No-op if not stopped
727      * or paused, or if the track's creation mode is not MODE_STREAM.
728      */
729     if( b_wait )
730     {
731         JNI_AT_CALL_VOID( stop );
732         if( CHECK_EXCEPTION( "stop" ) )
733             return;
734     } else
735     {
736         JNI_AT_CALL_VOID( pause );
737         if( CHECK_EXCEPTION( "pause" ) )
738             return;
739         JNI_AT_CALL_VOID( flush );
740     }
741     JNI_AT_CALL_VOID( play );
742     CHECK_EXCEPTION( "play" );
743     p_sys->i_play_time = mdate();
744 }
745
746 static void *
747 JNIThread( void *data )
748 {
749     audio_output_t *p_aout = data;
750     aout_sys_t *p_sys = p_aout->sys;
751     bool b_error = false;
752     bool b_paused = false;
753     uint32_t i_audiotrack_delay = 0;
754     JNIEnv* env;
755
756     jni_attach_thread( &env, THREAD_NAME );
757
758     vlc_mutex_lock( &p_sys->mutex );
759     if( !env )
760         goto end;
761
762     while( p_sys->b_thread_run )
763     {
764         struct thread_cmd *p_cmd;
765
766         /* wait to process a command */
767         while( ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue ) ) == NULL
768                && p_sys->b_thread_run )
769             vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
770
771         if( !p_sys->b_thread_run || p_cmd == NULL )
772             break;
773
774         if( b_paused && p_cmd->id == CMD_PLAY )
775         {
776             vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
777             continue;
778         }
779
780         TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
781
782         if( p_cmd->id == CMD_PLAY )
783         {
784             p_sys->i_samples_queued -= p_cmd->in.play.p_buffer->i_nb_samples;
785             vlc_cond_signal( &p_sys->cond );
786         }
787
788         vlc_mutex_unlock( &p_sys->mutex );
789         /* process a command */
790         switch( p_cmd->id )
791         {
792             case CMD_START:
793                 p_sys->fmt = *p_cmd->in.start.p_fmt;
794                 p_cmd->out.start.i_ret =
795                         JNIThread_Start( env, &b_error, p_aout );
796                 JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
797                 p_cmd->out.start.p_fmt = &p_sys->fmt;
798                 b_paused = false;
799                 break;
800             case CMD_STOP:
801                 JNIThread_Stop( env, &b_error, p_aout );
802                 b_paused = false;
803                 break;
804             case CMD_PLAY:
805                 JNIThread_Play( env, &b_error, p_aout,
806                                 p_cmd->in.play.p_buffer );
807                 JNIThread_SetDelay( env, p_aout, &i_audiotrack_delay );
808                 break;
809             case CMD_PAUSE:
810                 JNIThread_Pause( env, &b_error, p_aout,
811                                  p_cmd->in.pause.b_pause,
812                                  p_cmd->in.pause.i_date );
813                 b_paused = p_cmd->in.pause.b_pause;
814                 break;
815             case CMD_FLUSH:
816                 JNIThread_Flush( env, &b_error, p_aout,
817                                  p_cmd->in.flush.b_wait );
818                 JNIThread_InitDelay( env, p_aout, &i_audiotrack_delay );
819                 break;
820             default:
821                 vlc_assert_unreachable();
822         }
823
824         vlc_mutex_lock( &p_sys->mutex );
825
826         p_sys->i_audiotrack_delay = i_audiotrack_delay;
827
828         p_cmd->id = CMD_DONE;
829         if( p_cmd->pf_destroy )
830             p_cmd->pf_destroy( p_cmd );
831
832         if( b_error )
833             p_sys->b_thread_run = false;
834
835         /* signal that command is processed */
836         vlc_cond_signal( &p_sys->cond );
837     }
838 end:
839     if( env )
840     {
841         if( p_sys->p_bytearray )
842             (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
843         jni_detach_thread();
844     }
845     p_sys->b_thread_run = false;
846     vlc_cond_signal( &p_sys->cond );
847     vlc_mutex_unlock( &p_sys->mutex );
848     return NULL;
849 }
850
851 static int
852 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
853 {
854     int i_ret = VLC_EGENERIC;
855     struct thread_cmd *p_cmd;
856     aout_sys_t *p_sys = p_aout->sys;
857
858     vlc_mutex_lock( &p_sys->mutex );
859
860     assert( !p_sys->b_thread_run );
861
862     /* create JNIThread */
863     p_sys->b_thread_run = true;
864     if( vlc_clone( &p_sys->thread,
865                    JNIThread, p_aout, VLC_THREAD_PRIORITY_AUDIO ) )
866     {
867         msg_Err( p_aout, "JNIThread creation failed" );
868         vlc_mutex_unlock( &p_sys->mutex );
869         return VLC_EGENERIC;
870     }
871
872     p_cmd = ThreadCmd_New( CMD_START );
873     if( p_cmd )
874     {
875         /* ask the thread to process the Start command */
876         p_cmd->in.start.p_fmt = p_fmt;
877
878         ThreadCmd_InsertHead( p_sys, p_cmd );
879         if( ThreadCmd_Wait( p_sys, p_cmd ) )
880         {
881             i_ret = p_cmd->out.start.i_ret;
882             if( i_ret == VLC_SUCCESS )
883                 *p_fmt = *p_cmd->out.start.p_fmt;
884         }
885         free( p_cmd );
886     }
887     vlc_mutex_unlock( &p_sys->mutex );
888
889     if( i_ret == VLC_SUCCESS )
890         aout_SoftVolumeStart( p_aout );
891
892     return i_ret;
893 }
894
895 static void
896 Stop( audio_output_t *p_aout )
897 {
898     aout_sys_t *p_sys = p_aout->sys;
899
900     vlc_mutex_lock( &p_sys->mutex );
901
902     if( p_sys->b_thread_run )
903     {
904         struct thread_cmd *p_cmd;
905
906         p_sys->i_samples_queued = 0;
907         ThreadCmd_FlushQueue( p_sys );
908
909         p_cmd = ThreadCmd_New( CMD_STOP );
910         if( p_cmd )
911         {
912             /* ask the thread to process the Stop command */
913             ThreadCmd_InsertHead( p_sys, p_cmd );
914             ThreadCmd_Wait( p_sys, p_cmd );
915
916             free( p_cmd );
917         }
918         /* kill the thread */
919         p_sys->b_thread_run = false;
920         vlc_cond_signal( &p_sys->cond );
921     }
922     vlc_mutex_unlock( &p_sys->mutex );
923
924     vlc_join( p_sys->thread, NULL );
925 }
926
927 static void
928 PlayCmd_Destroy( struct thread_cmd *p_cmd )
929 {
930     block_Release( p_cmd->in.play.p_buffer );
931     free( p_cmd );
932 }
933
934 static void
935 Play( audio_output_t *p_aout, block_t *p_buffer )
936 {
937     aout_sys_t *p_sys = p_aout->sys;
938
939     vlc_mutex_lock( &p_sys->mutex );
940
941     if( p_sys->b_thread_run )
942     {
943         struct thread_cmd *p_cmd;
944
945         while( p_sys->i_samples_queued != 0 && p_sys->b_thread_run
946                && FRAMES_TO_US( p_sys->i_samples_queued +
947                                 p_buffer->i_nb_samples ) >= MAX_QUEUE_US )
948             vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
949
950         p_cmd = ThreadCmd_New( CMD_PLAY );
951
952         if( p_cmd )
953         {
954             /* ask the thread to process the Play command */
955             p_cmd->in.play.p_buffer = p_buffer;
956             p_cmd->pf_destroy = PlayCmd_Destroy;
957
958             ThreadCmd_InsertTail( p_sys, p_cmd );
959
960             p_sys->i_samples_queued += p_buffer->i_nb_samples;
961         } else
962              block_Release( p_cmd->in.play.p_buffer );
963     }
964     vlc_mutex_unlock( &p_sys->mutex );
965 }
966
967 static void
968 Pause( audio_output_t *p_aout, bool b_pause, mtime_t i_date )
969 {
970     aout_sys_t *p_sys = p_aout->sys;
971
972     vlc_mutex_lock( &p_sys->mutex );
973
974     if( p_sys->b_thread_run )
975     {
976         struct thread_cmd *p_cmd = ThreadCmd_New( CMD_PAUSE );
977
978         if( p_cmd )
979         {
980             /* ask the thread to process the Pause command */
981             p_cmd->in.pause.b_pause = b_pause;
982             p_cmd->in.pause.i_date = i_date;
983
984             ThreadCmd_InsertHead( p_sys, p_cmd );
985             ThreadCmd_Wait( p_sys, p_cmd );
986
987             free( p_cmd );
988         }
989     }
990     vlc_mutex_unlock( &p_sys->mutex );
991 }
992
993 static void
994 Flush( audio_output_t *p_aout, bool b_wait )
995 {
996     aout_sys_t *p_sys = p_aout->sys;
997
998     vlc_mutex_lock( &p_sys->mutex );
999
1000     if( p_sys->b_thread_run )
1001     {
1002         struct thread_cmd *p_cmd;
1003
1004         p_sys->i_samples_queued = 0;
1005         ThreadCmd_FlushQueue( p_sys );
1006
1007         p_cmd = ThreadCmd_New( CMD_FLUSH );
1008         if( p_cmd)
1009         {
1010             /* ask the thread to process the Flush command */
1011             p_cmd->in.flush.b_wait = b_wait;
1012
1013             ThreadCmd_InsertHead( p_sys, p_cmd );
1014             ThreadCmd_Wait( p_sys, p_cmd );
1015
1016             free( p_cmd );
1017         }
1018     }
1019     vlc_mutex_unlock( &p_sys->mutex );
1020 }
1021
1022 static int
1023 TimeGet( audio_output_t *p_aout, mtime_t *restrict p_delay )
1024 {
1025     aout_sys_t *p_sys = p_aout->sys;
1026     int i_ret;
1027
1028     vlc_mutex_lock( &p_sys->mutex );
1029     if( p_sys->i_samples_queued != 0 )
1030     {
1031         *p_delay = FRAMES_TO_US( p_sys->i_samples_queued +
1032                                  p_sys->i_audiotrack_delay );
1033         i_ret = 0;
1034     } else
1035         i_ret = -1;
1036     vlc_mutex_unlock( &p_sys->mutex );
1037
1038     return i_ret;
1039 }
1040
1041
1042 static int
1043 Open( vlc_object_t *obj )
1044 {
1045     audio_output_t *p_aout = (audio_output_t *) obj;
1046     aout_sys_t *p_sys;
1047
1048     if( !InitJNIFields( p_aout ) )
1049         return VLC_EGENERIC;
1050
1051     p_sys = calloc( 1, sizeof (aout_sys_t) );
1052
1053     if( unlikely( p_sys == NULL ) )
1054         return VLC_ENOMEM;
1055
1056     vlc_mutex_init( &p_sys->mutex );
1057     vlc_cond_init( &p_sys->cond );
1058     TAILQ_INIT( &p_sys->thread_cmd_queue );
1059
1060     p_aout->sys = p_sys;
1061     p_aout->start = Start;
1062     p_aout->stop = Stop;
1063     p_aout->play = Play;
1064     p_aout->pause = Pause;
1065     p_aout->flush = Flush;
1066     p_aout->time_get = TimeGet;
1067
1068     aout_SoftVolumeInit( p_aout );
1069
1070     return VLC_SUCCESS;
1071 }
1072
1073 static void
1074 Close( vlc_object_t *obj )
1075 {
1076     audio_output_t *p_aout = (audio_output_t *) obj;
1077     aout_sys_t *p_sys = p_aout->sys;
1078
1079     vlc_mutex_destroy( &p_sys->mutex );
1080     vlc_cond_destroy( &p_sys->cond );
1081
1082     free( p_sys );
1083 }