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 * );
48 typedef TAILQ_HEAD(, thread_cmd) THREAD_CMD_QUEUE;
55 /* Owned by JNIThread */
56 jobject p_audiotrack; /* AudioTrack ref */
57 jobject p_audioTimestamp; /* AudioTimestamp ref */
58 jbyteArray p_bytearray; /* ByteArray ref (for Write) */
59 size_t i_bytearray_size; /* size of the ByteArray */
60 jobject p_bytebuffer; /* ByteBuffer ref (for WriteV21) */
61 audio_sample_format_t fmt; /* fmt setup by Start */
62 uint32_t i_pos_initial; /* initial position set by getPlaybackHeadPosition */
63 uint32_t i_samples_written; /* number of samples written since last flush */
64 uint32_t i_bytes_per_frame; /* byte per frame */
65 uint32_t i_max_audiotrack_samples;
66 mtime_t i_play_time; /* time when play was called */
67 bool b_audiotrack_exception; /* true if audiotrack throwed an exception */
68 int i_audiotrack_stuck_count;
70 /* JNIThread control */
75 /* Shared between two threads, must be locked */
76 bool b_thread_run; /* is thread alive */
77 THREAD_CMD_QUEUE thread_cmd_queue; /* thread cmd queue */
78 uint32_t i_samples_queued; /* number of samples queued */
81 /* Soft volume helper */
82 #include "audio_output/volume.h"
84 //#define AUDIOTRACK_USE_FLOAT
85 // TODO: activate getTimestamp for new android versions
86 //#define AUDIOTRACK_USE_TIMESTAMP
89 set_shortname( "AudioTrack" )
90 set_description( N_( "Android AudioTrack audio output" ) )
91 set_capability( "audio output", 180 )
92 set_category( CAT_AUDIO )
93 set_subcategory( SUBCAT_AUDIO_AOUT )
95 add_shortcut( "audiotrack" )
96 set_callbacks( Open, Close )
101 TAILQ_ENTRY(thread_cmd) next;
113 audio_sample_format_t *p_fmt;
129 audio_sample_format_t *p_fmt;
136 void ( *pf_destroy )( struct thread_cmd * );
139 #define THREAD_NAME "android_audiotrack"
141 extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
142 extern void jni_detach_thread();
143 extern int jni_get_env(JNIEnv **env);
158 jmethodID getPlaybackHeadPosition;
159 jmethodID getTimestamp;
160 jmethodID getMinBufferSize;
161 jint STATE_INITIALIZED;
164 jint ERROR_BAD_VALUE;
165 jint ERROR_INVALID_OPERATION;
166 jint WRITE_NON_BLOCKING;
169 jint ENCODING_PCM_8BIT;
170 jint ENCODING_PCM_16BIT;
171 jint ENCODING_PCM_FLOAT;
172 bool has_ENCODING_PCM_FLOAT;
173 jint CHANNEL_OUT_MONO;
174 jint CHANNEL_OUT_STEREO;
177 jint ERROR_DEAD_OBJECT;
178 bool has_ERROR_DEAD_OBJECT;
184 jfieldID framePosition;
189 /* init all jni fields.
190 * Done only one time during the first initialisation */
192 InitJNIFields( audio_output_t *p_aout )
194 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
195 static int i_init_state = -1;
196 bool ret, b_attached = false;
201 vlc_mutex_lock( &lock );
203 if( i_init_state != -1 )
206 if( jni_get_env(&env) < 0 )
208 jni_attach_thread( &env, THREAD_NAME );
217 #define CHECK_EXCEPTION( what, critical ) do { \
218 if( (*env)->ExceptionOccurred( env ) ) \
220 msg_Err( p_aout, "%s failed", what ); \
221 (*env)->ExceptionClear( env ); \
229 #define GET_CLASS( str, critical ) do { \
230 clazz = (*env)->FindClass( env, (str) ); \
231 CHECK_EXCEPTION( str, critical ); \
233 #define GET_ID( get, id, str, args, critical ) do { \
234 jfields.id = (*env)->get( env, clazz, (str), (args) ); \
235 CHECK_EXCEPTION( #get, critical ); \
237 #define GET_CONST_INT( id, str, critical ) do { \
239 field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
240 CHECK_EXCEPTION( #id, critical ); \
243 jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
244 CHECK_EXCEPTION( #id, critical ); \
248 /* AudioTrack class init */
249 GET_CLASS( "android/media/AudioTrack", true );
250 jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
251 CHECK_EXCEPTION( "NewGlobalRef", true );
253 GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIII)V", true );
254 GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true );
255 GET_ID( GetMethodID, AudioTrack.getState, "getState", "()I", true );
256 GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true );
257 GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true );
258 GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true );
259 GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true );
261 GET_ID( GetMethodID, AudioTrack.writeV21, "write", "(Ljava/nio/ByteBuffer;II)I", false );
262 if( jfields.AudioTrack.writeV21 )
264 jfields.AudioTrack.write = NULL;
265 GET_CONST_INT( AudioTrack.WRITE_NON_BLOCKING, "WRITE_NON_BLOCKING", true );
267 GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true );
269 GET_ID( GetMethodID, AudioTrack.getTimestamp,
270 "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
271 GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition,
272 "getPlaybackHeadPosition", "()I", true );
274 GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize",
276 GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true );
277 GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
278 GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
279 GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true );
280 GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION,
281 "ERROR_INVALID_OPERATION", true );
283 /* AudioTimestamp class init (if any) */
284 if( jfields.AudioTrack.getTimestamp )
286 GET_CLASS( "android/media/AudioTimestamp", true );
287 jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env,
289 CHECK_EXCEPTION( "NewGlobalRef", true );
291 GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true );
292 GET_ID( GetFieldID, AudioTimestamp.framePosition,
293 "framePosition", "J", true );
294 GET_ID( GetFieldID, AudioTimestamp.nanoTime,
295 "nanoTime", "J", true );
298 jfields.AudioTimestamp.clazz = NULL;
299 jfields.AudioTimestamp.ctor = NULL;
300 jfields.AudioTimestamp.framePosition = NULL;
301 jfields.AudioTimestamp.nanoTime = NULL;
304 /* AudioFormat class init */
305 GET_CLASS( "android/media/AudioFormat", true );
306 GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
307 GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
308 #ifdef AUDIOTRACK_USE_FLOAT
309 GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
311 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL;
313 jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false;
315 GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
316 GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
318 /* AudioManager class init */
319 GET_CLASS( "android/media/AudioManager", true );
320 GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false );
321 jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
322 GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
324 #undef CHECK_EXCEPTION
331 ret = i_init_state == 1;
333 msg_Err( p_aout, "AudioTrack jni init failed" );
336 vlc_mutex_unlock( &lock );
341 check_exception( JNIEnv *env, audio_output_t *p_aout,
344 if( (*env)->ExceptionOccurred( env ) )
346 aout_sys_t *p_sys = p_aout->sys;
348 p_sys->b_audiotrack_exception = true;
349 (*env)->ExceptionClear( env );
350 msg_Err( p_aout, "AudioTrack.%s triggered an exception !", method );
355 #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, method )
357 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
359 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
360 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
361 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
362 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
364 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
365 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
366 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
367 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
368 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
370 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->p_audioTimestamp, jfields.AudioTimestamp.field )
372 static inline mtime_t
373 frames_to_us( aout_sys_t *p_sys, uint32_t i_nb_frames )
375 return i_nb_frames * CLOCK_FREQ / p_sys->fmt.i_rate;
377 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
379 static struct thread_cmd *
380 ThreadCmd_New( int id )
382 struct thread_cmd *p_cmd = calloc( 1, sizeof(struct thread_cmd) );
391 ThreadCmd_InsertHead( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
393 TAILQ_INSERT_HEAD( &p_sys->thread_cmd_queue, p_cmd, next);
394 vlc_cond_signal( &p_sys->cond );
398 ThreadCmd_InsertTail( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
400 TAILQ_INSERT_TAIL( &p_sys->thread_cmd_queue, p_cmd, next);
401 vlc_cond_signal( &p_sys->cond );
405 ThreadCmd_Wait( aout_sys_t *p_sys, struct thread_cmd *p_cmd )
407 while( p_cmd->id != CMD_DONE )
408 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
410 return p_cmd->id == CMD_DONE;
414 ThreadCmd_FlushQueue( aout_sys_t *p_sys )
416 struct thread_cmd *p_cmd, *p_cmd_next;
418 for ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue );
419 p_cmd != NULL; p_cmd = p_cmd_next )
421 p_cmd_next = TAILQ_NEXT( p_cmd, next );
422 TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
423 if( p_cmd->pf_destroy )
424 p_cmd->pf_destroy( p_cmd );
429 JNIThread_InitDelay( JNIEnv *env, audio_output_t *p_aout )
431 aout_sys_t *p_sys = p_aout->sys;
433 if( p_sys->p_audiotrack )
434 p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
436 p_sys->i_pos_initial = 0;
438 /* HACK: On some broken devices, head position is still moving after a
439 * flush or a stop. So, wait for the head position to be stabilized. */
440 if( unlikely( p_sys->i_pos_initial != 0 ) )
444 i_last_pos = p_sys->i_pos_initial;
446 p_sys->i_pos_initial = JNI_AT_CALL_INT( getPlaybackHeadPosition );
447 } while( p_sys->i_pos_initial != i_last_pos );
449 p_sys->i_samples_written = 0;
450 p_sys->i_samples_queued = 0;
454 JNIThread_GetAudioTrackPos( JNIEnv *env, audio_output_t *p_aout )
456 aout_sys_t *p_sys = p_aout->sys;
459 * getPlaybackHeadPosition: Returns the playback head position expressed in
460 * frames. Though the "int" type is signed 32-bits, the value should be
461 * reinterpreted as if it is unsigned 32-bits. That is, the next position
462 * after 0x7FFFFFFF is (int) 0x80000000. This is a continuously advancing
463 * counter. It will wrap (overflow) periodically, for example approximately
464 * once every 27:03:11 hours:minutes:seconds at 44.1 kHz. It is reset to
465 * zero by flush(), reload(), and stop().
468 return JNI_AT_CALL_INT( getPlaybackHeadPosition ) - p_sys->i_pos_initial;
472 JNIThread_TimeGet( JNIEnv *env, audio_output_t *p_aout, mtime_t *p_delay )
474 aout_sys_t *p_sys = p_aout->sys;
476 uint32_t i_audiotrack_delay = 0;
478 if( p_sys->i_samples_queued == 0 )
480 if( p_sys->p_audioTimestamp )
482 mtime_t i_current_time = mdate();
484 * getTimestamp: Poll for a timestamp on demand.
486 * If you need to track timestamps during initial warmup or after a
487 * routing or mode change, you should request a new timestamp once per
488 * second until the reported timestamps show that the audio clock is
489 * stable. Thereafter, query for a new timestamp approximately once
490 * every 10 seconds to once per minute. Calling this method more often
491 * is inefficient. It is also counter-productive to call this method
492 * more often than recommended, because the short-term differences
493 * between successive timestamp reports are not meaningful. If you need
494 * a high-resolution mapping between frame position and presentation
495 * time, consider implementing that at application level, based on
496 * low-resolution timestamps.
499 if( JNI_AT_CALL_BOOL( getTimestamp, p_sys->p_audioTimestamp ) )
501 jlong i_frame_time = JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime ) / 1000;
502 /* frame time should be after last play time
503 * frame time shouldn't be in the future
504 * frame time should be less than 10 seconds old */
505 if( i_frame_time > p_sys->i_play_time
506 && i_current_time > i_frame_time
507 && ( i_current_time - i_frame_time ) <= INT64_C(10000000) )
509 jlong i_time_diff = i_current_time - i_frame_time;
510 jlong i_frames_diff = i_time_diff * p_sys->fmt.i_rate
512 i_frame_pos = JNI_AUDIOTIMESTAMP_GET_LONG( framePosition )
514 if( p_sys->i_samples_written > i_frame_pos )
515 i_audiotrack_delay = p_sys->i_samples_written - i_frame_pos;
519 if( i_audiotrack_delay == 0 )
521 uint32_t i_audiotrack_pos = JNIThread_GetAudioTrackPos( env, p_aout );
523 if( p_sys->i_samples_written > i_audiotrack_pos )
524 i_audiotrack_delay = p_sys->i_samples_written - i_audiotrack_pos;
527 if( i_audiotrack_delay > 0 )
529 *p_delay = FRAMES_TO_US( p_sys->i_samples_queued + i_audiotrack_delay );
536 JNIThread_Start( JNIEnv *env, audio_output_t *p_aout )
538 struct aout_sys_t *p_sys = p_aout->sys;
539 int i_size, i_min_buffer_size, i_channel_config, i_rate, i_format,
540 i_format_size, i_nb_channels;
541 jobject p_audiotrack;
543 /* 4000 <= frequency <= 48000 */
544 i_rate = p_sys->fmt.i_rate;
550 /* We can only accept U8, S16N, and FL32 (depending on Android version) */
551 if( p_sys->fmt.i_format != VLC_CODEC_U8
552 && p_sys->fmt.i_format != VLC_CODEC_S16N
553 && p_sys->fmt.i_format != VLC_CODEC_FL32 )
554 p_sys->fmt.i_format = VLC_CODEC_S16N;
556 if( p_sys->fmt.i_format == VLC_CODEC_FL32
557 && !jfields.AudioFormat.has_ENCODING_PCM_FLOAT )
558 p_sys->fmt.i_format = VLC_CODEC_S16N;
560 if( p_sys->fmt.i_format == VLC_CODEC_S16N )
562 i_format = jfields.AudioFormat.ENCODING_PCM_16BIT;
564 } else if( p_sys->fmt.i_format == VLC_CODEC_FL32 )
566 i_format = jfields.AudioFormat.ENCODING_PCM_FLOAT;
570 i_format = jfields.AudioFormat.ENCODING_PCM_8BIT;
573 p_sys->fmt.i_original_channels = p_sys->fmt.i_physical_channels;
575 i_nb_channels = aout_FormatNbChannels( &p_sys->fmt );
576 switch( i_nb_channels )
579 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_MONO;
580 p_sys->fmt.i_physical_channels = AOUT_CHAN_CENTER;
583 i_nb_channels = 2; // XXX: AudioTrack handle only stereo for now
585 i_channel_config = jfields.AudioFormat.CHANNEL_OUT_STEREO;
586 p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
590 i_min_buffer_size = JNI_AT_CALL_STATIC_INT( getMinBufferSize, i_rate,
591 i_channel_config, i_format );
592 if( i_min_buffer_size <= 0 )
594 msg_Warn( p_aout, "getMinBufferSize returned an invalid size" ) ;
595 /* use a defaut min buffer size (shouldn't happen) */
596 i_min_buffer_size = i_nb_channels * i_format_size * 2048;
599 i_size = i_min_buffer_size * 4;
600 p_sys->i_bytes_per_frame = i_nb_channels * i_format_size;
601 p_sys->i_max_audiotrack_samples = i_size / p_sys->i_bytes_per_frame;
603 /* create AudioTrack object */
604 p_audiotrack = JNI_AT_NEW( jfields.AudioManager.STREAM_MUSIC, i_rate,
605 i_channel_config, i_format, i_size,
606 jfields.AudioTrack.MODE_STREAM );
607 if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack )
609 p_sys->p_audiotrack = (*env)->NewGlobalRef( env, p_audiotrack );
610 (*env)->DeleteLocalRef( env, p_audiotrack );
611 if( !p_sys->p_audiotrack )
613 if( JNI_AT_CALL_INT( getState ) != jfields.AudioTrack.STATE_INITIALIZED )
615 msg_Err( p_aout, "AudioTrack init failed" );
619 #ifdef AUDIOTRACK_USE_TIMESTAMP
620 if( jfields.AudioTimestamp.clazz )
622 /* create AudioTimestamp object */
623 jobject p_audioTimestamp = JNI_CALL( NewObject,
624 jfields.AudioTimestamp.clazz,
625 jfields.AudioTimestamp.ctor );
626 if( !p_audioTimestamp )
628 p_sys->p_audioTimestamp = (*env)->NewGlobalRef( env, p_audioTimestamp );
629 (*env)->DeleteLocalRef( env, p_audioTimestamp );
630 if( !p_sys->p_audioTimestamp )
635 p_sys->fmt.i_rate = i_rate;
637 JNI_AT_CALL_VOID( play );
638 CHECK_AT_EXCEPTION( "play" );
639 p_sys->i_play_time = mdate();
643 if( p_sys->p_audiotrack )
645 JNI_AT_CALL_VOID( release );
646 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
647 p_sys->p_audiotrack = NULL;
653 JNIThread_Stop( JNIEnv *env, audio_output_t *p_aout )
655 aout_sys_t *p_sys = p_aout->sys;
657 if( !p_sys->b_audiotrack_exception )
659 JNI_AT_CALL_VOID( stop );
660 if( !CHECK_AT_EXCEPTION( "stop" ) )
661 JNI_AT_CALL_VOID( release );
663 p_sys->b_audiotrack_exception = false;
664 (*env)->DeleteGlobalRef( env, p_sys->p_audiotrack );
665 p_sys->p_audiotrack = NULL;
667 if( p_sys->p_audioTimestamp )
669 (*env)->DeleteGlobalRef( env, p_sys->p_audioTimestamp );
670 p_sys->p_audioTimestamp = NULL;
675 * Non blocking write function.
676 * Do a calculation between current position and audiotrack position and assure
677 * that we won't wait in AudioTrack.write() method
680 JNIThread_Write( JNIEnv *env, audio_output_t *p_aout, block_t *p_buffer )
682 aout_sys_t *p_sys = p_aout->sys;
683 uint8_t *p_data = p_buffer->p_buffer;
686 uint32_t i_audiotrack_pos;
687 uint32_t i_samples_pending;
689 i_audiotrack_pos = JNIThread_GetAudioTrackPos( env, p_aout );
690 if( i_audiotrack_pos > p_sys->i_samples_written )
692 msg_Warn( p_aout, "audiotrack position is ahead. Should NOT happen" );
693 JNIThread_InitDelay( env, p_aout );
696 i_samples_pending = p_sys->i_samples_written - i_audiotrack_pos;
698 /* check if audiotrack buffer is not full before writing on it. */
699 if( i_samples_pending >= p_sys->i_max_audiotrack_samples )
702 /* HACK: AudioFlinger can drop frames without notifying us and there is
703 * no way to know it. It it happens, i_audiotrack_pos won't move and
704 * the current code will be stuck because it'll assume that audiotrack
705 * internal buffer is full when it's not. It can happen only after
706 * Android 4.4.2 if we send frames too quickly. This HACK is just an
707 * other precaution since it shouldn't happen anymore thanks to the
708 * HACK in JNIThread_Play */
710 p_sys->i_audiotrack_stuck_count++;
711 if( p_sys->i_audiotrack_stuck_count > 100 )
713 msg_Warn( p_aout, "AudioFlinger underrun, force write" );
714 i_samples_pending = 0;
715 p_sys->i_audiotrack_stuck_count = 0;
718 p_sys->i_audiotrack_stuck_count = 0;
719 i_samples = __MIN( p_sys->i_max_audiotrack_samples - i_samples_pending,
720 p_buffer->i_nb_samples );
722 i_data = i_samples * p_sys->i_bytes_per_frame;
724 /* check if we need to realloc a ByteArray */
725 if( i_data > p_sys->i_bytearray_size )
727 jbyteArray p_bytearray;
729 if( p_sys->p_bytearray )
731 (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
732 p_sys->p_bytearray = NULL;
735 p_bytearray = (*env)->NewByteArray( env, i_data );
738 p_sys->p_bytearray = (*env)->NewGlobalRef( env, p_bytearray );
739 (*env)->DeleteLocalRef( env, p_bytearray );
741 p_sys->i_bytearray_size = i_data;
743 if( !p_sys->p_bytearray )
744 return jfields.AudioTrack.ERROR_BAD_VALUE;
746 /* copy p_buffer in to ByteArray */
747 (*env)->SetByteArrayRegion( env, p_sys->p_bytearray, 0, i_data,
750 return JNI_AT_CALL_INT( write, p_sys->p_bytearray, 0, i_data );
754 * Non blocking write function for Lollipop and after.
755 * It calls a new write method with WRITE_NON_BLOCKING flags.
758 JNIThread_WriteV21( JNIEnv *env, audio_output_t *p_aout, block_t *p_buffer )
760 aout_sys_t *p_sys = p_aout->sys;
763 if( !p_sys->p_bytebuffer )
765 jobject p_bytebuffer;
767 p_bytebuffer = (*env)->NewDirectByteBuffer( env, p_buffer->p_buffer,
768 p_buffer->i_buffer );
770 return jfields.AudioTrack.ERROR_BAD_VALUE;
772 p_sys->p_bytebuffer = (*env)->NewGlobalRef( env, p_bytebuffer );
773 (*env)->DeleteLocalRef( env, p_bytebuffer );
775 if( !p_sys->p_bytebuffer || (*env)->ExceptionOccurred( env ) )
777 p_sys->p_bytebuffer = NULL;
778 (*env)->ExceptionClear( env );
779 return jfields.AudioTrack.ERROR_BAD_VALUE;
783 i_ret = JNI_AT_CALL_INT( writeV21, p_sys->p_bytebuffer, p_buffer->i_buffer,
784 jfields.AudioTrack.WRITE_NON_BLOCKING );
787 /* don't delete the bytebuffer if we wrote nothing, keep it for next
789 (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
790 p_sys->p_bytebuffer = NULL;
796 JNIThread_Play( JNIEnv *env, audio_output_t *p_aout,
797 block_t **pp_buffer, mtime_t *p_wait )
799 aout_sys_t *p_sys = p_aout->sys;
800 block_t *p_buffer = *pp_buffer;
803 if( jfields.AudioTrack.writeV21 )
804 i_ret = JNIThread_WriteV21( env, p_aout, p_buffer );
806 i_ret = JNIThread_Write( env, p_aout, p_buffer );
809 if( jfields.AudioManager.has_ERROR_DEAD_OBJECT
810 && i_ret == jfields.AudioManager.ERROR_DEAD_OBJECT )
812 msg_Warn( p_aout, "ERROR_DEAD_OBJECT: "
813 "try recreating AudioTrack" );
814 JNIThread_Stop( env, p_aout );
815 i_ret = JNIThread_Start( env, p_aout );
819 if( i_ret == jfields.AudioTrack.ERROR_INVALID_OPERATION )
820 str = "ERROR_INVALID_OPERATION";
821 else if( i_ret == jfields.AudioTrack.ERROR_BAD_VALUE )
822 str = "ERROR_BAD_VALUE";
825 msg_Err( p_aout, "Write failed: %s", str );
827 } else if( i_ret == 0 )
829 /* audiotrack internal buffer is full, wait a little: between 10ms and
830 * 20ms depending on devices or rate */
831 *p_wait = FRAMES_TO_US( p_sys->i_max_audiotrack_samples / 20 );
834 uint32_t i_samples = i_ret / p_sys->i_bytes_per_frame;
835 p_sys->i_samples_queued -= i_samples;
836 p_sys->i_samples_written += i_samples;
838 p_buffer->p_buffer += i_ret;
839 p_buffer->i_buffer -= i_ret;
840 p_buffer->i_nb_samples -= i_samples;
841 if( p_buffer->i_buffer == 0 )
844 /* HACK: There is a known issue in audiotrack, "due to an internal
845 * timeout within the AudioTrackThread". It happens after android
846 * 4.4.2, it's not a problem for Android 5.0 since we use an other way
847 * to write samples. A working hack is to wait a little between each
848 * write. This hack is done only for API 19 (AudioTimestamp was added
851 if( jfields.AudioTimestamp.clazz && !jfields.AudioTrack.writeV21 )
852 *p_wait = FRAMES_TO_US( i_samples ) / 2;
854 return i_ret >= 0 ? VLC_SUCCESS : VLC_EGENERIC;
858 JNIThread_Pause( JNIEnv *env, audio_output_t *p_aout,
859 bool b_pause, mtime_t i_date )
861 VLC_UNUSED( i_date );
863 aout_sys_t *p_sys = p_aout->sys;
867 JNI_AT_CALL_VOID( pause );
868 CHECK_AT_EXCEPTION( "pause" );
871 JNI_AT_CALL_VOID( play );
872 CHECK_AT_EXCEPTION( "play" );
873 p_sys->i_play_time = mdate();
878 JNIThread_Flush( JNIEnv *env, audio_output_t *p_aout,
881 aout_sys_t *p_sys = p_aout->sys;
884 * stop(): Stops playing the audio data. When used on an instance created
885 * in MODE_STREAM mode, audio will stop playing after the last buffer that
886 * was written has been played. For an immediate stop, use pause(),
887 * followed by flush() to discard audio data that hasn't been played back
890 * flush(): Flushes the audio data currently queued for playback. Any data
891 * that has not been played back will be discarded. No-op if not stopped
892 * or paused, or if the track's creation mode is not MODE_STREAM.
896 JNI_AT_CALL_VOID( stop );
897 if( CHECK_AT_EXCEPTION( "stop" ) )
901 JNI_AT_CALL_VOID( pause );
902 if( CHECK_AT_EXCEPTION( "pause" ) )
904 JNI_AT_CALL_VOID( flush );
906 JNI_AT_CALL_VOID( play );
907 CHECK_AT_EXCEPTION( "play" );
908 p_sys->i_play_time = mdate();
910 if( p_sys->p_bytebuffer )
912 (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
913 p_sys->p_bytebuffer = NULL;
918 JNIThread( void *data )
920 audio_output_t *p_aout = data;
921 aout_sys_t *p_sys = p_aout->sys;
922 bool b_error = false;
923 bool b_paused = false;
924 block_t *p_buffer = NULL;
925 mtime_t i_play_deadline = 0;
928 jni_attach_thread( &env, THREAD_NAME );
930 vlc_mutex_lock( &p_sys->mutex );
934 while( p_sys->b_thread_run )
936 struct thread_cmd *p_cmd;
937 bool b_remove_cmd = true;
939 /* wait to process a command */
940 while( ( p_cmd = TAILQ_FIRST( &p_sys->thread_cmd_queue ) ) == NULL
941 && p_sys->b_thread_run )
942 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
944 if( !p_sys->b_thread_run || p_cmd == NULL )
947 if( b_paused && p_cmd->id == CMD_PLAY )
949 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
953 if( p_cmd->id == CMD_PLAY && i_play_deadline > 0 )
955 if( mdate() > i_play_deadline )
960 while( p_cmd == TAILQ_FIRST( &p_sys->thread_cmd_queue )
961 && i_ret != ETIMEDOUT && p_sys->b_thread_run )
962 i_ret = vlc_cond_timedwait( &p_sys->cond, &p_sys->mutex,
968 /* process a command */
972 assert( !p_sys->p_audiotrack );
974 p_cmd->out.start.i_ret = -1;
977 p_sys->fmt = *p_cmd->in.start.p_fmt;
978 p_cmd->out.start.i_ret =
979 JNIThread_Start( env, p_aout );
980 JNIThread_InitDelay( env, p_aout );
981 p_cmd->out.start.p_fmt = &p_sys->fmt;
985 assert( p_sys->p_audiotrack );
986 JNIThread_Stop( env, p_aout );
987 JNIThread_InitDelay( env, p_aout );
994 mtime_t i_play_wait = 0;
996 assert( p_sys->p_audiotrack );
999 if( p_buffer == NULL )
1000 p_buffer = p_cmd->in.play.p_buffer;
1001 b_error = JNIThread_Play( env, p_aout, &p_buffer,
1002 &i_play_wait ) != VLC_SUCCESS;
1003 if( p_buffer != NULL )
1004 b_remove_cmd = false;
1005 if( i_play_wait > 0 )
1006 i_play_deadline = mdate() + i_play_wait;
1010 assert( p_sys->p_audiotrack );
1013 JNIThread_Pause( env, p_aout,
1014 p_cmd->in.pause.b_pause,
1015 p_cmd->in.pause.i_date );
1016 b_paused = p_cmd->in.pause.b_pause;
1019 assert( p_sys->p_audiotrack );
1022 p_cmd->out.time_get.i_ret =
1023 JNIThread_TimeGet( env, p_aout,
1024 &p_cmd->out.time_get.i_delay );
1027 assert( p_sys->p_audiotrack );
1030 JNIThread_Flush( env, p_aout,
1031 p_cmd->in.flush.b_wait );
1032 JNIThread_InitDelay( env, p_aout );
1036 vlc_assert_unreachable();
1038 if( p_sys->b_audiotrack_exception )
1043 TAILQ_REMOVE( &p_sys->thread_cmd_queue, p_cmd, next );
1044 p_cmd->id = CMD_DONE;
1045 if( p_cmd->pf_destroy )
1046 p_cmd->pf_destroy( p_cmd );
1049 /* signal that command is processed */
1050 vlc_cond_signal( &p_sys->cond );
1055 if( p_sys->p_bytearray )
1056 (*env)->DeleteGlobalRef( env, p_sys->p_bytearray );
1057 if( p_sys->p_bytebuffer )
1058 (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
1059 jni_detach_thread();
1061 vlc_mutex_unlock( &p_sys->mutex );
1066 Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
1068 int i_ret = VLC_EGENERIC;
1069 struct thread_cmd *p_cmd;
1070 aout_sys_t *p_sys = p_aout->sys;
1072 vlc_mutex_lock( &p_sys->mutex );
1074 p_cmd = ThreadCmd_New( CMD_START );
1077 /* ask the thread to process the Start command */
1078 p_cmd->in.start.p_fmt = p_fmt;
1080 ThreadCmd_InsertHead( p_sys, p_cmd );
1081 if( ThreadCmd_Wait( p_sys, p_cmd ) )
1083 i_ret = p_cmd->out.start.i_ret;
1084 if( i_ret == VLC_SUCCESS )
1085 *p_fmt = *p_cmd->out.start.p_fmt;
1090 vlc_mutex_unlock( &p_sys->mutex );
1092 if( i_ret == VLC_SUCCESS )
1093 aout_SoftVolumeStart( p_aout );
1099 Stop( audio_output_t *p_aout )
1101 aout_sys_t *p_sys = p_aout->sys;
1102 struct thread_cmd *p_cmd;
1104 vlc_mutex_lock( &p_sys->mutex );
1106 ThreadCmd_FlushQueue( p_sys );
1108 p_cmd = ThreadCmd_New( CMD_STOP );
1111 /* ask the thread to process the Stop command */
1112 ThreadCmd_InsertHead( p_sys, p_cmd );
1113 ThreadCmd_Wait( p_sys, p_cmd );
1118 vlc_mutex_unlock( &p_sys->mutex );
1122 PlayCmd_Destroy( struct thread_cmd *p_cmd )
1124 block_Release( p_cmd->in.play.p_buffer );
1129 Play( audio_output_t *p_aout, block_t *p_buffer )
1131 aout_sys_t *p_sys = p_aout->sys;
1132 struct thread_cmd *p_cmd;
1134 vlc_mutex_lock( &p_sys->mutex );
1136 while( p_sys->i_samples_queued != 0
1137 && FRAMES_TO_US( p_sys->i_samples_queued +
1138 p_buffer->i_nb_samples ) >= MAX_QUEUE_US )
1139 vlc_cond_wait( &p_sys->cond, &p_sys->mutex );
1141 p_cmd = ThreadCmd_New( CMD_PLAY );
1144 /* ask the thread to process the Play command */
1145 p_cmd->in.play.p_buffer = p_buffer;
1146 p_cmd->pf_destroy = PlayCmd_Destroy;
1148 ThreadCmd_InsertTail( p_sys, p_cmd );
1150 p_sys->i_samples_queued += p_buffer->i_nb_samples;
1152 block_Release( p_cmd->in.play.p_buffer );
1154 vlc_mutex_unlock( &p_sys->mutex );
1158 Pause( audio_output_t *p_aout, bool b_pause, mtime_t i_date )
1160 aout_sys_t *p_sys = p_aout->sys;
1161 struct thread_cmd *p_cmd;
1163 vlc_mutex_lock( &p_sys->mutex );
1165 p_cmd = ThreadCmd_New( CMD_PAUSE );
1168 /* ask the thread to process the Pause command */
1169 p_cmd->in.pause.b_pause = b_pause;
1170 p_cmd->in.pause.i_date = i_date;
1172 ThreadCmd_InsertHead( p_sys, p_cmd );
1173 ThreadCmd_Wait( p_sys, p_cmd );
1178 vlc_mutex_unlock( &p_sys->mutex );
1182 Flush( audio_output_t *p_aout, bool b_wait )
1184 aout_sys_t *p_sys = p_aout->sys;
1185 struct thread_cmd *p_cmd;
1187 vlc_mutex_lock( &p_sys->mutex );
1189 ThreadCmd_FlushQueue( p_sys );
1191 p_cmd = ThreadCmd_New( CMD_FLUSH );
1194 /* ask the thread to process the Flush command */
1195 p_cmd->in.flush.b_wait = b_wait;
1197 ThreadCmd_InsertHead( p_sys, p_cmd );
1198 ThreadCmd_Wait( p_sys, p_cmd );
1203 vlc_mutex_unlock( &p_sys->mutex );
1207 TimeGet( audio_output_t *p_aout, mtime_t *restrict p_delay )
1209 aout_sys_t *p_sys = p_aout->sys;
1210 struct thread_cmd *p_cmd;
1213 vlc_mutex_lock( &p_sys->mutex );
1215 p_cmd = ThreadCmd_New( CMD_TIME_GET );
1218 ThreadCmd_InsertHead( p_sys, p_cmd );
1219 ThreadCmd_Wait( p_sys, p_cmd );
1221 i_ret = p_cmd->out.time_get.i_ret;
1222 *p_delay = p_cmd->out.time_get.i_delay;
1226 vlc_mutex_unlock( &p_sys->mutex );
1233 Open( vlc_object_t *obj )
1235 audio_output_t *p_aout = (audio_output_t *) obj;
1238 if( !InitJNIFields( p_aout ) )
1239 return VLC_EGENERIC;
1241 p_sys = calloc( 1, sizeof (aout_sys_t) );
1243 if( unlikely( p_sys == NULL ) )
1246 vlc_mutex_init( &p_sys->mutex );
1247 vlc_cond_init( &p_sys->cond );
1248 TAILQ_INIT( &p_sys->thread_cmd_queue );
1250 p_aout->sys = p_sys;
1251 p_aout->start = Start;
1252 p_aout->stop = Stop;
1253 p_aout->play = Play;
1254 p_aout->pause = Pause;
1255 p_aout->flush = Flush;
1256 p_aout->time_get = TimeGet;
1258 aout_SoftVolumeInit( p_aout );
1260 /* create JNIThread */
1261 p_sys->b_thread_run = true;
1262 if( vlc_clone( &p_sys->thread,
1263 JNIThread, p_aout, VLC_THREAD_PRIORITY_AUDIO ) )
1265 msg_Err( p_aout, "JNIThread creation failed" );
1266 p_sys->b_thread_run = false;
1268 return VLC_EGENERIC;
1275 Close( vlc_object_t *obj )
1277 audio_output_t *p_aout = (audio_output_t *) obj;
1278 aout_sys_t *p_sys = p_aout->sys;
1280 /* kill the thread */
1281 vlc_mutex_lock( &p_sys->mutex );
1282 if( p_sys->b_thread_run )
1284 p_sys->b_thread_run = false;
1285 vlc_cond_signal( &p_sys->cond );
1286 vlc_mutex_unlock( &p_sys->mutex );
1287 vlc_join( p_sys->thread, NULL );
1289 vlc_mutex_unlock( &p_sys->mutex );
1291 vlc_mutex_destroy( &p_sys->mutex );
1292 vlc_cond_destroy( &p_sys->cond );