1 /*****************************************************************************
2 * audiotrack.c: Android Java AudioTrack audio output module
3 *****************************************************************************
4 * Copyright © 2012-2015 VLC authors and VideoLAN, VideoLabs
6 * Authors: Thomas Guillem <thomas@gllm.fr>
7 * Ming Hu <tewilove@gmail.com>
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.
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.
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 *****************************************************************************/
32 #include <sys/queue.h>
34 #include <vlc_atomic.h>
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
38 #include <vlc_threads.h>
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
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 );
49 typedef TAILQ_HEAD(, thread_cmd) THREAD_CMD_QUEUE;
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;
73 uint8_t i_chans_to_reorder; /* do we need channel reordering */
74 uint8_t p_chan_table[AOUT_CHAN_MAX];
81 /* JNIThread control */
86 /* Shared between two threads, must be locked */
87 bool b_thread_run; /* is thread alive */
88 THREAD_CMD_QUEUE thread_cmd_queue; /* thread cmd queue */
89 uint32_t i_samples_queued; /* number of samples queued */
92 /* Soft volume helper */
93 #include "audio_output/volume.h"
95 #define AUDIOTRACK_USE_FLOAT
96 // TODO: activate getTimestamp for new android versions
97 //#define AUDIOTRACK_USE_TIMESTAMP
100 set_shortname( "AudioTrack" )
101 set_description( N_( "Android AudioTrack audio output" ) )
102 set_capability( "audio output", 180 )
103 set_category( CAT_AUDIO )
104 set_subcategory( SUBCAT_AUDIO_AOUT )
106 add_shortcut( "audiotrack" )
107 set_callbacks( Open, Close )
112 TAILQ_ENTRY(thread_cmd) next;
124 audio_sample_format_t *p_fmt;
140 audio_sample_format_t *p_fmt;
147 void ( *pf_destroy )( struct thread_cmd * );
150 #define THREAD_NAME "android_audiotrack"
152 extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
153 extern void jni_detach_thread();
154 extern int jni_get_env(JNIEnv **env);
169 jmethodID writeFloat;
170 jmethodID getPlaybackHeadPosition;
171 jmethodID getTimestamp;
172 jmethodID getMinBufferSize;
173 jint STATE_INITIALIZED;
176 jint ERROR_BAD_VALUE;
177 jint ERROR_INVALID_OPERATION;
178 jint WRITE_NON_BLOCKING;
181 jint ENCODING_PCM_8BIT;
182 jint ENCODING_PCM_16BIT;
183 jint ENCODING_PCM_FLOAT;
184 bool has_ENCODING_PCM_FLOAT;
187 bool has_ENCODING_AC3;
188 jint CHANNEL_OUT_MONO;
189 jint CHANNEL_OUT_STEREO;
190 jint CHANNEL_OUT_FRONT_LEFT;
191 jint CHANNEL_OUT_FRONT_RIGHT;
192 jint CHANNEL_OUT_BACK_LEFT;
193 jint CHANNEL_OUT_BACK_RIGHT;
194 jint CHANNEL_OUT_FRONT_CENTER;
195 jint CHANNEL_OUT_LOW_FREQUENCY;
196 jint CHANNEL_OUT_BACK_CENTER;
197 jint CHANNEL_OUT_5POINT1;
198 jint CHANNEL_OUT_SIDE_LEFT;
199 jint CHANNEL_OUT_SIDE_RIGHT;
200 bool has_CHANNEL_OUT_SIDE;
203 jint ERROR_DEAD_OBJECT;
204 bool has_ERROR_DEAD_OBJECT;
210 jfieldID framePosition;
215 /* init all jni fields.
216 * Done only one time during the first initialisation */
218 InitJNIFields( audio_output_t *p_aout )
220 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
221 static int i_init_state = -1;
222 bool ret, b_attached = false;
227 vlc_mutex_lock( &lock );
229 if( i_init_state != -1 )
232 if( jni_get_env(&env) < 0 )
234 jni_attach_thread( &env, THREAD_NAME );
243 #define CHECK_EXCEPTION( what, critical ) do { \
244 if( (*env)->ExceptionOccurred( env ) ) \
246 msg_Err( p_aout, "%s failed", what ); \
247 (*env)->ExceptionClear( env ); \
255 #define GET_CLASS( str, critical ) do { \
256 clazz = (*env)->FindClass( env, (str) ); \
257 CHECK_EXCEPTION( str, critical ); \
259 #define GET_ID( get, id, str, args, critical ) do { \
260 jfields.id = (*env)->get( env, clazz, (str), (args) ); \
261 CHECK_EXCEPTION( #get, critical ); \
263 #define GET_CONST_INT( id, str, critical ) do { \
265 field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
266 CHECK_EXCEPTION( #id, critical ); \
269 jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
270 CHECK_EXCEPTION( #id, critical ); \
274 /* AudioTrack class init */
275 GET_CLASS( "android/media/AudioTrack", true );
276 jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
277 CHECK_EXCEPTION( "NewGlobalRef", true );
279 GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIII)V", true );
280 GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true );
281 GET_ID( GetMethodID, AudioTrack.getState, "getState", "()I", true );
282 GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true );
283 GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true );
284 GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true );
285 GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true );
287 GET_ID( GetMethodID, AudioTrack.writeV21, "write", "(Ljava/nio/ByteBuffer;II)I", false );
288 if( jfields.AudioTrack.writeV21 )
290 GET_CONST_INT( AudioTrack.WRITE_NON_BLOCKING, "WRITE_NON_BLOCKING", true );
291 #ifdef AUDIOTRACK_USE_FLOAT
292 GET_ID( GetMethodID, AudioTrack.writeFloat, "write", "([FIII)I", true );
295 GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
297 GET_ID( GetMethodID, AudioTrack.getTimestamp,
298 "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
299 GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
300 "getPlaybackHeadPosition", "()I", true );
302 GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize",
304 GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true );
305 GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
306 GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
307 GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true );
308 GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION,
309 "ERROR_INVALID_OPERATION", true );
311 /* AudioTimestamp class init (if any) */
312 if( jfields.AudioTrack.getTimestamp )
314 GET_CLASS( "android/media/AudioTimestamp", true );
315 jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env,
317 CHECK_EXCEPTION( "NewGlobalRef", true );
319 GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true );
320 GET_ID( GetFieldID, AudioTimestamp.framePosition,
321 "framePosition", "J", true );
322 GET_ID( GetFieldID, AudioTimestamp.nanoTime,
323 "nanoTime", "J", true );
326 /* AudioFormat class init */
327 GET_CLASS( "android/media/AudioFormat", true );
328 GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
329 GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
330 #ifdef AUDIOTRACK_USE_FLOAT
331 GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
333 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL &&
334 jfields.AudioTrack.writeFloat;
336 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
338 GET_CONST_INT( AudioFormat.ENCODING_AC3, "ENCODING_AC3", false );
341 GET_CONST_INT( AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3", false );
342 jfields.AudioFormat.has_ENCODING_AC3 = field != NULL;
344 jfields.AudioFormat.has_ENCODING_AC3 = false;
346 GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
347 GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
348 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_LEFT, "CHANNEL_OUT_FRONT_LEFT", true );
349 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_RIGHT, "CHANNEL_OUT_FRONT_RIGHT", true );
350 GET_CONST_INT( AudioFormat.CHANNEL_OUT_5POINT1, "CHANNEL_OUT_5POINT1", true );
351 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_LEFT, "CHANNEL_OUT_BACK_LEFT", true );
352 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_RIGHT, "CHANNEL_OUT_BACK_RIGHT", true );
353 GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_CENTER, "CHANNEL_OUT_FRONT_CENTER", true );
354 GET_CONST_INT( AudioFormat.CHANNEL_OUT_LOW_FREQUENCY, "CHANNEL_OUT_LOW_FREQUENCY", true );
355 GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_CENTER, "CHANNEL_OUT_BACK_CENTER", true );
356 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_LEFT, "CHANNEL_OUT_SIDE_LEFT", false );
359 GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_RIGHT, "CHANNEL_OUT_SIDE_RIGHT", true );
360 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = true;
362 jfields.AudioFormat.has_CHANNEL_OUT_SIDE = false;
364 /* AudioManager class init */
365 GET_CLASS( "android/media/AudioManager", true );
366 GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false );
367 jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
368 GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
370 #undef CHECK_EXCEPTION
377 ret = i_init_state == 1;
379 msg_Err( p_aout, "AudioTrack jni init failed" );
382 vlc_mutex_unlock( &lock );
387 check_exception( JNIEnv *env, audio_output_t *p_aout,
390 if( (*env)->ExceptionOccurred( env ) )
392 aout_sys_t *p_sys = p_aout->sys;
394 p_sys->b_audiotrack_exception = true;
395 (*env)->ExceptionClear( env );
396 msg_Err( p_aout, "AudioTrack.%s triggered an exception !", method );
401 #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, method )
403 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
405 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
406 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
407 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
408 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
410 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
411 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
412 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
413 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
414 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
416 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->p_audioTimestamp, jfields.AudioTimestamp.field )
418 static inline mtime_t
419 frames_to_us( aout_sys_t *p_sys, uint32_t i_nb_frames )
421 return i_nb_frames * CLOCK_FREQ / p_sys->fmt.i_rate;
423 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
425 static inline uint32_t
426 bytes_to_frames( aout_sys_t *p_sys, size_t i_bytes )
429 return i_bytes * A52_FRAME_NB / p_sys->i_bytes_per_frame;
431 return i_bytes / p_sys->i_bytes_per_frame;
433 #define BYTES_TO_FRAMES(x) bytes_to_frames( p_sys, (x) )
436 frames_to_bytes( aout_sys_t *p_sys, uint32_t i_frames )
439 return i_frames * p_sys->i_bytes_per_frame / A52_FRAME_NB;
441 return i_frames * p_sys->i_bytes_per_frame;
443 #define FRAMES_TO_BYTES(x) frames_to_bytes( p_sys, (x) )
445 static struct thread_cmd *
446 ThreadCmd_New( int id )
448 struct thread_cmd *p_cmd = calloc( 1, sizeof(struct thread_cmd) );
457 ThreadCmd_InsertHead( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
459 TAILQ_INSERT_HEAD( &p_sys->thread_cmd_queue, p_cmd, next);
460 vlc_cond_signal( &p_sys->cond );
464 ThreadCmd_InsertTail( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
466 TAILQ_INSERT_TAIL( &p_sys->thread_cmd_queue, p_cmd, next);
467 vlc_cond_signal( &p_sys->cond );
471 ThreadCmd_Wait( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
473 while( p_cmd->id != CMD_DONE )
474 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
476 return p_cmd->id == CMD_DONE;
480 ThreadCmd_FlushQueue( aout_sys_t *p_sys )
482 struct thread_cmd *p_cmd, *p_cmd_next;
484 for ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue );
485 p_cmd != NULL; p_cmd = p_cmd_next )
487 p_cmd_next = TAILQ_NEXT( p_cmd, next );
488 TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
489 if( p_cmd->pf_destroy )
490 p_cmd->pf_destroy( p_cmd );
495 JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout )
497 aout_sys_t *p_sys = p_aout->sys;
499 if( p_sys->p_audiotrack )
500 p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
502 p_sys->i_pos_initial = 0;
504 /* HACK: On some broken devices, head position is still moving after a
505 * flush or a stop. So, wait for the head position to be stabilized. */
506 if( unlikely( p_sys->i_pos_initial != 0 ) )
510 i_last_pos = p_sys->i_pos_initial;
512 p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
513 } while( p_sys->i_pos_initial != i_last_pos );
515 p_sys->i_samples_written = 0;
516 p_sys->i_samples_queued = 0;
520 JNIThread_GetAudioTrackPos( JNIEnv *env, audio_output_t *p_aout )
522 aout_sys_t *p_sys = p_aout->sys;
525 * getPlaybackHeadPosition: Returns the playback head position expressed in
526 * frames. Though the "int" type is signed 32-bits, the value should be
527 * reinterpreted as if it is unsigned 32-bits. That is, the next position
528 * after 0x7FFFFFFF is (int) 0x80000000. This is a continuously advancing
529 * counter. It will wrap (overflow) periodically, for example approximately
530 * once every 27:03:11 hours:minutes:seconds at 44.1 kHz. It is reset to
531 * zero by flush(), reload(), and stop().
534 return JNI_AT_CALL_INT( getPlaybackHeadPosition ) - p_sys->i_pos_initial;
538 JNIThread_TimeGet( JNIEnv *env, audio_output_t *p_aout, mtime_t *p_delay )
540 aout_sys_t *p_sys = p_aout->sys;
542 uint32_t i_audiotrack_delay = 0;
544 if( p_sys->i_samples_queued == 0 || p_sys->b_spdif )
546 if( p_sys->p_audioTimestamp )
548 mtime_t i_current_time = mdate();
550 * getTimestamp: Poll for a timestamp on demand.
552 * If you need to track timestamps during initial warmup or after a
553 * routing or mode change, you should request a new timestamp once per
554 * second until the reported timestamps show that the audio clock is
555 * stable. Thereafter, query for a new timestamp approximately once
556 * every 10 seconds to once per minute. Calling this method more often
557 * is inefficient. It is also counter-productive to call this method
558 * more often than recommended, because the short-term differences
559 * between successive timestamp reports are not meaningful. If you need
560 * a high-resolution mapping between frame position and presentation
561 * time, consider implementing that at application level, based on
562 * low-resolution timestamps.
565 if( JNI_AT_CALL_BOOL( getTimestamp, p_sys->p_audioTimestamp ) )
567 jlong i_frame_time = JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime ) / 1000;
568 /* frame time should be after last play time
569 * frame time shouldn't be in the future
570 * frame time should be less than 10 seconds old */
571 if( i_frame_time > p_sys->i_play_time
572 && i_current_time > i_frame_time
573 && ( i_current_time - i_frame_time ) <= INT64_C(10000000) )
575 jlong i_time_diff = i_current_time - i_frame_time;
576 jlong i_frames_diff = i_time_diff * p_sys->fmt.i_rate
578 i_frame_pos = JNI_AUDIOTIMESTAMP_GET_LONG( framePosition )
580 if( p_sys->i_samples_written > i_frame_pos )
581 i_audiotrack_delay = p_sys->i_samples_written - i_frame_pos;
585 if( i_audiotrack_delay == 0 )
587 uint32_t i_audiotrack_pos = JNIThread_GetAudioTrackPos( env, p_aout );
589 if( p_sys->i_samples_written > i_audiotrack_pos )
590 i_audiotrack_delay = p_sys->i_samples_written - i_audiotrack_pos;
593 if( i_audiotrack_delay > 0 )
595 *p_delay = FRAMES_TO_US( p_sys->i_samples_queued + i_audiotrack_delay );
602 AudioTrack_GetChanOrder( uint16_t i_physical_channels, uint32_t p_chans_out[] )
604 #define HAS_CHAN( x ) ( ( i_physical_channels & (x) ) == (x) )
605 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
608 if( HAS_CHAN( AOUT_CHAN_LEFT ) )
609 p_chans_out[i++] = AOUT_CHAN_LEFT;
610 if( HAS_CHAN( AOUT_CHAN_RIGHT ) )
611 p_chans_out[i++] = AOUT_CHAN_RIGHT;
613 if( HAS_CHAN( AOUT_CHAN_CENTER ) )
614 p_chans_out[i++] = AOUT_CHAN_CENTER;
616 if( HAS_CHAN( AOUT_CHAN_LFE ) )
617 p_chans_out[i++] = AOUT_CHAN_LFE;
619 if( HAS_CHAN( AOUT_CHAN_REARLEFT ) )
620 p_chans_out[i++] = AOUT_CHAN_REARLEFT;
621 if( HAS_CHAN( AOUT_CHAN_REARRIGHT ) )
622 p_chans_out[i++] = AOUT_CHAN_REARRIGHT;
624 if( HAS_CHAN( AOUT_CHAN_REARCENTER ) )
625 p_chans_out[i++] = AOUT_CHAN_REARCENTER;
627 if( HAS_CHAN( AOUT_CHAN_MIDDLELEFT ) )
628 p_chans_out[i++] = AOUT_CHAN_MIDDLELEFT;
629 if( HAS_CHAN( AOUT_CHAN_MIDDLERIGHT ) )
630 p_chans_out[i++] = AOUT_CHAN_MIDDLERIGHT;
632 assert( i <= AOUT_CHAN_MAX );
637 * Configure and create an Android AudioTrack.
638 * returns NULL on configuration error
641 JNIThread_NewAudioTrack( JNIEnv *env, audio_output_t *p_aout,
643 vlc_fourcc_t i_vlc_format,
644 uint16_t i_physical_channels,
645 int *p_audiotrack_size )
647 int i_size, i_min_buffer_size, i_channel_config, i_format;
648 jobject p_audiotrack;
650 switch( i_vlc_format )
653 i_format = jfields.AudioFormat.ENCODING_PCM_8BIT;
656 i_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
659 i_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
661 case VLC_CODEC_SPDIFB:
662 i_format = jfields.AudioFormat.ENCODING_AC3;
665 vlc_assert_unreachable();
668 switch( i_physical_channels )
671 /* bitmask of CHANNEL_OUT_7POINT1 doesn't correspond to 5POINT1 and
673 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1 |
674 jfields.AudioFormat.CHANNEL_OUT_SIDE_LEFT |
675 jfields.AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
678 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_5POINT1;
681 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_MONO;
684 case AOUT_CHANS_STEREO:
685 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_STEREO;
689 i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize, i_rate,
690 i_channel_config, i_format );
691 if( i_min_buffer_size <= 0 )
693 msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
696 if( i_vlc_format == VLC_CODEC_SPDIFB )
697 i_size = ( i_min_buffer_size / AOUT_SPDIF_SIZE + 1 ) * AOUT_SPDIF_SIZE;
699 i_size = i_min_buffer_size * 4;
701 /* create AudioTrack object */
702 p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate,
703 i_channel_config, i_format, i_size,
704 jfields.AudioTrack.MODE_STREAM );
705 if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
707 msg_Warn( p_aout, "AudioTrack Init failed" ) ;
710 if( JNI_CALL_INT( p_audiotrack, jfields.AudioTrack.getState )
711 != jfields.AudioTrack.STATE_INITIALIZED )
713 JNI_CALL_VOID( p_audiotrack, jfields.AudioTrack.release );
714 (*env)->DeleteLocalRef( env, p_audiotrack );
715 msg_Err( p_aout, "AudioTrack getState failed" );
718 *p_audiotrack_size = i_size;
724 JNIThread_Start( JNIEnv *env, audio_output_t *p_aout )
726 aout_sys_t *p_sys = p_aout->sys;
727 jobject p_audiotrack = NULL;
728 int i_nb_channels, i_audiotrack_size;
730 aout_FormatPrint( p_aout, "VLC is looking for:", &p_sys->fmt );
732 p_sys->fmt.i_original_channels = p_sys->fmt.i_physical_channels;
734 /* 4000 <= frequency <= 48000 */
735 p_sys->fmt.i_rate = VLC_CLIP( p_sys->fmt.i_rate, 4000, 48000 );
737 /* We can only accept U8, S16N, FL32, and AC3 */
738 switch( p_sys->fmt.i_format )
745 if( !jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
746 p_sys->fmt.i_format = VLC_CODEC_S16N;
749 if( jfields.AudioFormat.has_ENCODING_AC3
750 && var_InheritBool( p_aout, "spdif" ) )
751 p_sys->fmt.i_format = VLC_CODEC_SPDIFB;
752 else if( jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
753 p_sys->fmt.i_format = VLC_CODEC_FL32;
755 p_sys->fmt.i_format = VLC_CODEC_S16N;
758 p_sys->fmt.i_format = VLC_CODEC_S16N;
762 /* Android AudioTrack supports only mono, stereo, 5.1 and 7.1.
763 * Android will downmix to stereo if audio output doesn't handle 5.1 or 7.1
765 i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
766 if( i_nb_channels > 5 )
768 if( i_nb_channels > 7 && jfields.AudioFormat.has_CHANNEL_OUT_SIDE )
769 p_sys->fmt.i_physical_channels = AOUT_CHANS_7_1;
771 p_sys->fmt.i_physical_channels = AOUT_CHANS_5_1;
774 if( i_nb_channels == 1 )
775 p_sys->fmt.i_physical_channels = AOUT_CHAN_LEFT;
777 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
779 i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
783 /* Try to create an AudioTrack with the most advanced channel and
784 * format configuration. If NewAudioTrack fails, try again with a less
785 * advanced format (PCM S16N). If it fails again, try again with Stereo
787 p_audiotrack = JNIThread_NewAudioTrack( env, p_aout, p_sys->fmt.i_rate,
789 p_sys->fmt.i_physical_channels,
790 &i_audiotrack_size );
793 if( p_sys->fmt.i_format == VLC_CODEC_SPDIFB )
795 msg_Warn( p_aout, "SPDIF configuration failed, "
797 if( jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
798 p_sys->fmt.i_format = VLC_CODEC_FL32;
800 p_sys->fmt.i_format = VLC_CODEC_S16N;
802 else if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
804 msg_Warn( p_aout, "FL32 configuration failed, "
805 "fallback to S16N PCM" );
806 p_sys->fmt.i_format = VLC_CODEC_S16N;
808 else if( i_nb_channels > 5 )
810 msg_Warn( p_aout, "5.1 or 7.1 configuration failed, "
811 "fallback to Stereo" );
812 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
813 i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
818 } while( !p_audiotrack );
823 p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
824 (*env)->DeleteLocalRef( env, p_audiotrack );
825 if( !p_sys->p_audiotrack )
828 p_sys->b_spdif = p_sys->fmt.i_format == VLC_CODEC_SPDIFB;
831 p_sys->fmt.i_bytes_per_frame = AOUT_SPDIF_SIZE;
832 p_sys->fmt.i_frame_length = A52_FRAME_NB;
833 p_sys->i_bytes_per_frame = p_sys->fmt.i_bytes_per_frame;
837 uint32_t p_chans_out[AOUT_CHAN_MAX];
839 memset( p_chans_out, 0, sizeof(p_chans_out) );
840 AudioTrack_GetChanOrder( p_sys->fmt.i_physical_channels, p_chans_out );
841 p_sys->i_chans_to_reorder =
842 aout_CheckChannelReorder( NULL, p_chans_out,
843 p_sys->fmt.i_physical_channels,
844 p_sys->p_chan_table );
845 p_sys->i_bytes_per_frame = i_nb_channels *
846 aout_BitsPerSample( p_sys->fmt.i_format ) /
849 p_sys->i_max_audiotrack_samples = BYTES_TO_FRAMES( i_audiotrack_size );
851 #ifdef AUDIOTRACK_USE_TIMESTAMP
852 if( jfields.AudioTimestamp.clazz )
854 /* create AudioTimestamp object */
855 jobject p_audioTimestamp = JNI_CALL( NewObject,
856 jfields.AudioTimestamp.clazz,
857 jfields.AudioTimestamp.ctor );
858 if( !p_audioTimestamp )
860 JNIThread_Stop( env, p_aout );
863 p_sys->p_audioTimestamp = (*env)->NewGlobalRef( env, p_audioTimestamp );
864 (*env)->DeleteLocalRef( env, p_audioTimestamp );
865 if( !p_sys->p_audioTimestamp )
867 JNIThread_Stop( env, p_aout );
873 if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
875 msg_Dbg( p_aout, "using WRITE_FLOAT");
876 p_sys->i_write_type = WRITE_FLOAT;
878 else if( jfields.AudioTrack.writeV21 )
880 msg_Dbg( p_aout, "using WRITE_V21");
881 p_sys->i_write_type = WRITE_V21;
885 msg_Dbg( p_aout, "using WRITE");
886 p_sys->i_write_type = WRITE;
889 JNI_AT_CALL_VOID( play );
890 CHECK_AT_EXCEPTION( "play" );
891 p_sys->i_play_time = mdate();
893 aout_FormatPrint( p_aout, "VLC will output:", &p_sys->fmt );
899 JNIThread_Stop( JNIEnv *env, audio_output_t *p_aout )
901 aout_sys_t *p_sys = p_aout->sys;
903 if( p_sys->p_audiotrack )
905 if( !p_sys->b_audiotrack_exception )
907 JNI_AT_CALL_VOID( stop );
908 if( !CHECK_AT_EXCEPTION( "stop" ) )
909 JNI_AT_CALL_VOID( release );
911 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
912 p_sys->p_audiotrack = NULL;
914 p_sys->b_audiotrack_exception = false;
916 if( p_sys->p_audioTimestamp )
918 (*env)->DeleteGlobalRef( env, p_sys->p_audioTimestamp );
919 p_sys->p_audioTimestamp = NULL;
924 * Non blocking write function.
925 * Do a calculation between current position and audiotrack position and assure
926 * that we won't wait in AudioTrack.write() method
929 JNIThread_Write( JNIEnv *env, audio_output_t *p_aout, block_t *p_buffer,
930 size_t i_buffer_offset )
932 aout_sys_t *p_sys = p_aout->sys;
935 uint32_t i_audiotrack_pos;
936 uint32_t i_samples_pending;
938 i_data = p_buffer->i_buffer - i_buffer_offset;
939 i_audiotrack_pos = JNIThread_GetAudioTrackPos( env, p_aout );
940 if( i_audiotrack_pos > p_sys->i_samples_written )
942 msg_Warn( p_aout, "audiotrack position is ahead. Should NOT happen" );
943 JNIThread_InitDelay( env, p_aout );
946 i_samples_pending = p_sys->i_samples_written - i_audiotrack_pos;
948 /* check if audiotrack buffer is not full before writing on it. */
949 if( i_samples_pending >= p_sys->i_max_audiotrack_samples )
952 /* HACK: AudioFlinger can drop frames without notifying us and there is
953 * no way to know it. It it happens, i_audiotrack_pos won't move and
954 * the current code will be stuck because it'll assume that audiotrack
955 * internal buffer is full when it's not. It can happen only after
956 * Android 4.4.2 if we send frames too quickly. This HACK is just an
957 * other precaution since it shouldn't happen anymore thanks to the
958 * HACK in JNIThread_Play */
960 p_sys->i_audiotrack_stuck_count++;
961 if( p_sys->i_audiotrack_stuck_count > 100 )
963 msg_Warn( p_aout, "AudioFlinger underrun, force write" );
964 i_samples_pending = 0;
965 p_sys->i_audiotrack_stuck_count = 0;
968 p_sys->i_audiotrack_stuck_count = 0;
969 i_samples = __MIN( p_sys->i_max_audiotrack_samples - i_samples_pending,
970 BYTES_TO_FRAMES( i_data ) );
972 i_data = FRAMES_TO_BYTES( i_samples );
974 return JNI_AT_CALL_INT( write, p_sys->p_bytearray,
975 i_buffer_offset, i_data );
979 * Non blocking write function for Lollipop and after.
980 * It calls a new write method with WRITE_NON_BLOCKING flags.
983 JNIThread_WriteV21( JNIEnv *env, audio_output_t *p_aout, block_t *p_buffer,
984 size_t i_buffer_offset )
986 aout_sys_t *p_sys = p_aout->sys;
988 size_t i_data = p_buffer->i_buffer - i_buffer_offset;
989 uint8_t *p_data = p_buffer->p_buffer + i_buffer_offset;
991 if( !p_sys->p_bytebuffer )
993 jobject p_bytebuffer;
995 p_bytebuffer = (*env)->NewDirectByteBuffer( env, p_data, i_data );
997 return jfields.AudioTrack.ERROR_BAD_VALUE;
999 p_sys->p_bytebuffer = (*env)->NewGlobalRef( env, p_bytebuffer );
1000 (*env)->DeleteLocalRef( env, p_bytebuffer );
1002 if( !p_sys->p_bytebuffer || (*env)->ExceptionOccurred( env ) )
1004 p_sys->p_bytebuffer = NULL;
1005 (*env)->ExceptionClear( env );
1006 return jfields.AudioTrack.ERROR_BAD_VALUE;
1010 i_ret = JNI_AT_CALL_INT( writeV21, p_sys->p_bytebuffer, i_data,
1011 jfields.AudioTrack.WRITE_NON_BLOCKING );
1014 /* don't delete the bytebuffer if we wrote nothing, keep it for next
1016 (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
1017 p_sys->p_bytebuffer = NULL;
1023 * Non blocking write float function for Lollipop and after.
1024 * It calls a new write method with WRITE_NON_BLOCKING flags.
1027 JNIThread_WriteFloat( JNIEnv *env, audio_output_t *p_aout, block_t *p_buffer,
1028 size_t i_buffer_offset )
1030 aout_sys_t *p_sys = p_aout->sys;
1034 i_buffer_offset /= 4;
1035 i_data = p_buffer->i_buffer / 4 - i_buffer_offset;
1037 i_ret = JNI_AT_CALL_INT( writeFloat, p_sys->p_floatarray,
1038 i_buffer_offset, i_data,
1039 jfields.AudioTrack.WRITE_NON_BLOCKING );
1047 JNIThread_PreparePlay( JNIEnv *env, audio_output_t *p_aout,
1050 aout_sys_t *p_sys = p_aout->sys;
1052 if( p_sys->i_chans_to_reorder )
1053 aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
1054 p_sys->i_chans_to_reorder, p_sys->p_chan_table,
1055 p_sys->fmt.i_format );
1057 switch( p_sys->i_write_type )
1060 /* check if we need to realloc a ByteArray */
1061 if( p_buffer->i_buffer > p_sys->i_bytearray_size )
1063 jbyteArray p_bytearray;
1065 if( p_sys->p_bytearray )
1067 (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
1068 p_sys->p_bytearray = NULL;
1071 p_bytearray = (*env)->NewByteArray( env, p_buffer->i_buffer );
1074 p_sys->p_bytearray = (*env)->NewGlobalRef( env, p_bytearray );
1075 (*env)->DeleteLocalRef( env, p_bytearray );
1077 p_sys->i_bytearray_size = p_buffer->i_buffer;
1079 if( !p_sys->p_bytearray )
1080 return VLC_EGENERIC;
1082 /* copy p_buffer in to ByteArray */
1083 (*env)->SetByteArrayRegion( env, p_sys->p_bytearray, 0,
1085 (jbyte *)p_buffer->p_buffer);
1089 size_t i_data = p_buffer->i_buffer / 4;
1091 /* check if we need to realloc a floatArray */
1092 if( i_data > p_sys->i_floatarray_size )
1094 jfloatArray p_floatarray;
1096 if( p_sys->p_floatarray )
1098 (*env)->DeleteGlobalRef( env, p_sys->p_floatarray );
1099 p_sys->p_floatarray = NULL;
1102 p_floatarray = (*env)->NewFloatArray( env, i_data );
1105 p_sys->p_floatarray = (*env)->NewGlobalRef( env, p_floatarray );
1106 (*env)->DeleteLocalRef( env, p_floatarray );
1108 p_sys->i_floatarray_size = i_data;
1110 if( !p_sys->p_floatarray )
1111 return VLC_EGENERIC;
1113 /* copy p_buffer in to FloatArray */
1114 (*env)->SetFloatArrayRegion( env, p_sys->p_floatarray, 0, i_data,
1115 (jfloat *)p_buffer->p_buffer);
1127 JNIThread_Play( JNIEnv *env, audio_output_t *p_aout,
1128 block_t *p_buffer, size_t *p_buffer_offset, mtime_t *p_wait )
1130 aout_sys_t *p_sys = p_aout->sys;
1133 switch( p_sys->i_write_type )
1136 i_ret = JNIThread_WriteV21( env, p_aout, p_buffer, *p_buffer_offset );
1139 i_ret = JNIThread_Write( env, p_aout, p_buffer, *p_buffer_offset );
1142 i_ret = JNIThread_WriteFloat( env, p_aout, p_buffer, *p_buffer_offset );
1145 vlc_assert_unreachable();
1149 if( jfields.AudioManager.has_ERROR_DEAD_OBJECT
1150 && i_ret == jfields.AudioManager.ERROR_DEAD_OBJECT )
1152 msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
1153 "try recreating AudioTrack" );
1154 JNIThread_Stop( env, p_aout );
1155 i_ret = JNIThread_Start( env, p_aout );
1159 if( i_ret == jfields.AudioTrack.ERROR_INVALID_OPERATION )
1160 str = "ERROR_INVALID_OPERATION";
1161 else if( i_ret == jfields.AudioTrack.ERROR_BAD_VALUE )
1162 str = "ERROR_BAD_VALUE";
1165 msg_Err( p_aout, "Write failed: %s", str );
1167 } else if( i_ret == 0 )
1169 /* audiotrack internal buffer is full, wait a little: between 10ms and
1170 * 20ms depending on devices or rate */
1171 *p_wait = FRAMES_TO_US( p_sys->i_max_audiotrack_samples / 20 );
1174 uint32_t i_samples = BYTES_TO_FRAMES( i_ret );
1176 p_sys->i_samples_queued -= i_samples;
1177 p_sys->i_samples_written += i_samples;
1179 *p_buffer_offset += i_ret;
1181 /* HACK: There is a known issue in audiotrack, "due to an internal
1182 * timeout within the AudioTrackThread". It happens after android
1183 * 4.4.2, it's not a problem for Android 5.0 since we use an other way
1184 * to write samples. A working hack is to wait a little between each
1185 * write. This hack is done only for API 19 (AudioTimestamp was added
1188 if( p_sys->i_write_type == WRITE && jfields.AudioTimestamp.clazz )
1189 *p_wait = FRAMES_TO_US( i_samples ) / 2;
1191 return i_ret >= 0 ? VLC_SUCCESS : VLC_EGENERIC;
1195 JNIThread_Pause( JNIEnv *env, audio_output_t *p_aout,
1196 bool b_pause, mtime_t i_date )
1198 VLC_UNUSED( i_date );
1200 aout_sys_t *p_sys = p_aout->sys;
1204 JNI_AT_CALL_VOID( pause );
1205 CHECK_AT_EXCEPTION( "pause" );
1208 JNI_AT_CALL_VOID( play );
1209 CHECK_AT_EXCEPTION( "play" );
1210 p_sys->i_play_time = mdate();
1215 JNIThread_Flush( JNIEnv *env, audio_output_t *p_aout,
1218 aout_sys_t *p_sys = p_aout->sys;
1221 * stop(): Stops playing the audio data. When used on an instance created
1222 * in MODE_STREAM mode, audio will stop playing after the last buffer that
1223 * was written has been played. For an immediate stop, use pause(),
1224 * followed by flush() to discard audio data that hasn't been played back
1227 * flush(): Flushes the audio data currently queued for playback. Any data
1228 * that has not been played back will be discarded. No-op if not stopped
1229 * or paused, or if the track's creation mode is not MODE_STREAM.
1233 JNI_AT_CALL_VOID( stop );
1234 if( CHECK_AT_EXCEPTION( "stop" ) )
1238 JNI_AT_CALL_VOID( pause );
1239 if( CHECK_AT_EXCEPTION( "pause" ) )
1241 JNI_AT_CALL_VOID( flush );
1243 JNI_AT_CALL_VOID( play );
1244 CHECK_AT_EXCEPTION( "play" );
1245 p_sys->i_play_time = mdate();
1247 if( p_sys->p_bytebuffer )
1249 (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
1250 p_sys->p_bytebuffer = NULL;
1255 JNIThread( void *data )
1257 audio_output_t *p_aout = data;
1258 aout_sys_t *p_sys = p_aout->sys;
1259 bool b_error = false;
1260 bool b_paused = false;
1261 block_t *p_buffer = NULL;
1262 size_t i_buffer_offset = 0;
1263 mtime_t i_play_deadline = 0;
1266 jni_attach_thread( &env, THREAD_NAME );
1268 vlc_mutex_lock( &p_sys->mutex );
1272 while( p_sys->b_thread_run )
1274 struct thread_cmd *p_cmd;
1275 bool b_remove_cmd = true;
1277 /* wait to process a command */
1278 while( ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue ) ) == NULL
1279 && p_sys->b_thread_run )
1280 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
1282 if( !p_sys->b_thread_run || p_cmd == NULL )
1285 if( b_paused && p_cmd->id == CMD_PLAY )
1287 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
1291 if( p_cmd->id == CMD_PLAY && i_play_deadline > 0 )
1293 if( mdate() > i_play_deadline )
1294 i_play_deadline = 0;
1298 while( p_cmd == TAILQ_FIRST( &p_sys->thread_cmd_queue )
1299 && i_ret != ETIMEDOUT && p_sys->b_thread_run )
1300 i_ret = vlc_cond_timedwait( &p_sys->cond, &p_sys->mutex,
1306 /* process a command */
1310 assert( !p_sys->p_audiotrack );
1312 p_cmd->out.start.i_ret = -1;
1315 p_sys->fmt = *p_cmd->in.start.p_fmt;
1316 p_cmd->out.start.i_ret =
1317 JNIThread_Start( env, p_aout );
1318 JNIThread_InitDelay( env, p_aout );
1319 p_cmd->out.start.p_fmt = &p_sys->fmt;
1323 assert( p_sys->p_audiotrack );
1324 JNIThread_Stop( env, p_aout );
1325 JNIThread_InitDelay( env, p_aout );
1332 mtime_t i_play_wait = 0;
1334 assert( p_sys->p_audiotrack );
1337 if( p_buffer == NULL )
1339 p_buffer = p_cmd->in.play.p_buffer;
1340 b_error = JNIThread_PreparePlay( env, p_aout, p_buffer )
1345 b_error = JNIThread_Play( env, p_aout, p_buffer,
1347 &i_play_wait ) != VLC_SUCCESS;
1348 if( i_buffer_offset < p_buffer->i_buffer )
1350 /* buffer is not fully processed, try again with the
1351 * same cmd and buffer */
1352 b_remove_cmd = false;
1357 i_buffer_offset = 0;
1359 if( i_play_wait > 0 )
1360 i_play_deadline = mdate() + i_play_wait;
1364 assert( p_sys->p_audiotrack );
1367 JNIThread_Pause( env, p_aout,
1368 p_cmd->in.pause.b_pause,
1369 p_cmd->in.pause.i_date );
1370 b_paused = p_cmd->in.pause.b_pause;
1373 assert( p_sys->p_audiotrack );
1376 p_cmd->out.time_get.i_ret = -1;
1379 p_cmd->out.time_get.i_ret =
1380 JNIThread_TimeGet( env, p_aout,
1381 &p_cmd->out.time_get.i_delay );
1384 assert( p_sys->p_audiotrack );
1387 JNIThread_Flush( env, p_aout,
1388 p_cmd->in.flush.b_wait );
1389 JNIThread_InitDelay( env, p_aout );
1393 vlc_assert_unreachable();
1395 if( p_sys->b_audiotrack_exception )
1398 p_sys->i_samples_queued = 0;
1402 TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
1403 p_cmd->id = CMD_DONE;
1404 if( p_cmd->pf_destroy )
1405 p_cmd->pf_destroy( p_cmd );
1408 /* signal that command is processed */
1409 vlc_cond_signal( &p_sys->cond );
1414 if( p_sys->p_bytearray )
1415 (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
1416 if( p_sys->p_floatarray )
1417 (*env)->DeleteGlobalRef( env, p_sys->p_floatarray );
1418 if( p_sys->p_bytebuffer )
1419 (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
1420 jni_detach_thread();
1422 vlc_mutex_unlock( &p_sys->mutex );
1427 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
1429 int i_ret = VLC_EGENERIC;
1430 struct thread_cmd *p_cmd;
1431 aout_sys_t *p_sys = p_aout->sys;
1433 vlc_mutex_lock( &p_sys->mutex );
1435 p_cmd = ThreadCmd_New( CMD_START );
1438 /* ask the thread to process the Start command */
1439 p_cmd->in.start.p_fmt = p_fmt;
1441 ThreadCmd_InsertHead( p_sys, p_cmd );
1442 if( ThreadCmd_Wait( p_sys, p_cmd ) )
1444 i_ret = p_cmd->out.start.i_ret;
1445 if( i_ret == VLC_SUCCESS )
1446 *p_fmt = *p_cmd->out.start.p_fmt;
1451 vlc_mutex_unlock( &p_sys->mutex );
1453 if( i_ret == VLC_SUCCESS )
1454 aout_SoftVolumeStart( p_aout );
1460 Stop( audio_output_t *p_aout )
1462 aout_sys_t *p_sys = p_aout->sys;
1463 struct thread_cmd *p_cmd;
1465 vlc_mutex_lock( &p_sys->mutex );
1467 ThreadCmd_FlushQueue( p_sys );
1469 p_cmd = ThreadCmd_New( CMD_STOP );
1472 /* ask the thread to process the Stop command */
1473 ThreadCmd_InsertHead( p_sys, p_cmd );
1474 ThreadCmd_Wait( p_sys, p_cmd );
1479 vlc_mutex_unlock( &p_sys->mutex );
1483 PlayCmd_Destroy( struct thread_cmd *p_cmd )
1485 block_Release( p_cmd->in.play.p_buffer );
1490 Play( audio_output_t *p_aout, block_t *p_buffer )
1492 aout_sys_t *p_sys = p_aout->sys;
1493 struct thread_cmd *p_cmd;
1495 vlc_mutex_lock( &p_sys->mutex );
1497 while( p_sys->i_samples_queued != 0
1498 && FRAMES_TO_US( p_sys->i_samples_queued +
1499 p_buffer->i_nb_samples ) >= MAX_QUEUE_US )
1500 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
1502 p_cmd = ThreadCmd_New( CMD_PLAY );
1505 /* ask the thread to process the Play command */
1506 p_cmd->in.play.p_buffer = p_buffer;
1507 p_cmd->pf_destroy = PlayCmd_Destroy;
1509 ThreadCmd_InsertTail( p_sys, p_cmd );
1511 p_sys->i_samples_queued += p_buffer->i_nb_samples;
1513 block_Release( p_cmd->in.play.p_buffer );
1515 vlc_mutex_unlock( &p_sys->mutex );
1519 Pause( audio_output_t *p_aout, bool b_pause, mtime_t i_date )
1521 aout_sys_t *p_sys = p_aout->sys;
1522 struct thread_cmd *p_cmd;
1524 vlc_mutex_lock( &p_sys->mutex );
1526 p_cmd = ThreadCmd_New( CMD_PAUSE );
1529 /* ask the thread to process the Pause command */
1530 p_cmd->in.pause.b_pause = b_pause;
1531 p_cmd->in.pause.i_date = i_date;
1533 ThreadCmd_InsertHead( p_sys, p_cmd );
1534 ThreadCmd_Wait( p_sys, p_cmd );
1539 vlc_mutex_unlock( &p_sys->mutex );
1543 Flush( audio_output_t *p_aout, bool b_wait )
1545 aout_sys_t *p_sys = p_aout->sys;
1546 struct thread_cmd *p_cmd;
1548 vlc_mutex_lock( &p_sys->mutex );
1550 ThreadCmd_FlushQueue( p_sys );
1552 p_cmd = ThreadCmd_New( CMD_FLUSH );
1555 /* ask the thread to process the Flush command */
1556 p_cmd->in.flush.b_wait = b_wait;
1558 ThreadCmd_InsertHead( p_sys, p_cmd );
1559 ThreadCmd_Wait( p_sys, p_cmd );
1564 vlc_mutex_unlock( &p_sys->mutex );
1568 TimeGet( audio_output_t *p_aout, mtime_t *restrict p_delay )
1570 aout_sys_t *p_sys = p_aout->sys;
1571 struct thread_cmd *p_cmd;
1574 vlc_mutex_lock( &p_sys->mutex );
1576 p_cmd = ThreadCmd_New( CMD_TIME_GET );
1579 ThreadCmd_InsertHead( p_sys, p_cmd );
1580 ThreadCmd_Wait( p_sys, p_cmd );
1582 i_ret = p_cmd->out.time_get.i_ret;
1583 *p_delay = p_cmd->out.time_get.i_delay;
1587 vlc_mutex_unlock( &p_sys->mutex );
1594 Open( vlc_object_t *obj )
1596 audio_output_t *p_aout = (audio_output_t *) obj;
1599 if( !InitJNIFields( p_aout ) )
1600 return VLC_EGENERIC;
1602 p_sys = calloc( 1, sizeof (aout_sys_t) );
1604 if( unlikely( p_sys == NULL ) )
1607 vlc_mutex_init( &p_sys->mutex );
1608 vlc_cond_init( &p_sys->cond );
1609 TAILQ_INIT( &p_sys->thread_cmd_queue );
1611 p_aout->sys = p_sys;
1612 p_aout->start = Start;
1613 p_aout->stop = Stop;
1614 p_aout->play = Play;
1615 p_aout->pause = Pause;
1616 p_aout->flush = Flush;
1617 p_aout->time_get = TimeGet;
1619 aout_SoftVolumeInit( p_aout );
1621 /* create JNIThread */
1622 p_sys->b_thread_run = true;
1623 if( vlc_clone( &p_sys->thread,
1624 JNIThread, p_aout, VLC_THREAD_PRIORITY_AUDIO ) )
1626 msg_Err( p_aout, "JNIThread creation failed" );
1627 p_sys->b_thread_run = false;
1629 return VLC_EGENERIC;
1636 Close( vlc_object_t *obj )
1638 audio_output_t *p_aout = (audio_output_t *) obj;
1639 aout_sys_t *p_sys = p_aout->sys;
1641 /* kill the thread */
1642 vlc_mutex_lock( &p_sys->mutex );
1643 if( p_sys->b_thread_run )
1645 p_sys->b_thread_run = false;
1646 vlc_cond_signal( &p_sys->cond );
1647 vlc_mutex_unlock( &p_sys->mutex );
1648 vlc_join( p_sys->thread, NULL );
1650 vlc_mutex_unlock( &p_sys->mutex );
1652 vlc_mutex_destroy( &p_sys->mutex );
1653 vlc_cond_destroy( &p_sys->cond );