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 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
36 #include "../video_output/android/utils.h"
38 #define SMOOTHPOS_SAMPLE_COUNT 10
39 #define SMOOTHPOS_INTERVAL_US VLC_TICK_FROM_MS(30) // 30ms
41 #define AUDIOTIMESTAMP_INTERVAL_US VLC_TICK_FROM_MS(500) // 500ms
43 static int Open( vlc_object_t
* );
44 static void Close( vlc_object_t
* );
45 static void Stop( audio_output_t
* );
46 static int Start( audio_output_t
*, audio_sample_format_t
* );
47 static void *AudioTrack_Thread( void * );
49 /* There is an undefined behavior when configuring AudioTrack with SPDIF or
50 * more than 2 channels when there is no HDMI out. It may succeed and the
51 * Android ressampler will be used to downmix to stereo. It may fails cleanly,
52 * and this module will be able to recover and fallback to stereo. Finally, in
53 * some rare cases, it may crash during init or while ressampling. Because of
54 * the last case we don't try up to 8 channels and we use AT_DEV_STEREO device
61 #define AT_DEV_DEFAULT AT_DEV_STEREO
62 #define AT_DEV_MAX_CHANNELS 8
69 { "stereo", "Up to 2 channels (compat mode).", AT_DEV_STEREO
},
70 { "pcm", "Up to 8 channels.", AT_DEV_PCM
},
72 /* With "encoded", the module will try to play every audio codecs via
75 * With "encoded:ENCODING_FLAGS_MASK", the module will try to play only
76 * codecs specified by ENCODING_FLAGS_MASK. This extra value is a long long
77 * that contains binary-shifted AudioFormat.ENCODING_* values. */
78 { "encoded", "Up to 8 channels, passthrough if available.", AT_DEV_ENCODED
},
79 { NULL
, NULL
, AT_DEV_DEFAULT
},
86 jobject p_audiotrack
; /* AudioTrack ref */
90 audio_sample_format_t fmt
; /* fmt setup by Start */
99 /* Used by AudioTrack_getPlaybackHeadPosition */
101 uint32_t i_wrap_count
;
105 /* Used by AudioTrack_GetTimestampPositionUs */
107 jobject p_obj
; /* AudioTimestamp ref */
108 vlc_tick_t i_frame_us
;
110 vlc_tick_t i_play_time
; /* time when play was called */
111 vlc_tick_t i_last_time
;
114 /* Used by AudioTrack_GetSmoothPositionUs */
118 vlc_tick_t p_us
[SMOOTHPOS_SAMPLE_COUNT
];
120 vlc_tick_t i_last_time
;
123 uint32_t i_max_audiotrack_samples
;
124 long long i_encoding_flags
;
126 uint8_t i_chans_to_reorder
; /* do we need channel reordering */
127 uint8_t p_chan_table
[AOUT_CHAN_MAX
];
137 vlc_thread_t thread
; /* AudioTrack_Thread */
139 vlc_cond_t aout_cond
; /* cond owned by aout */
140 vlc_cond_t thread_cond
; /* cond owned by AudioTrack_Thread */
142 /* These variables need locking on read and write */
143 bool b_thread_running
; /* Set to false by aout to stop the thread */
144 bool b_thread_paused
; /* If true, the thread won't process any data, see
146 bool b_thread_waiting
; /* If true, the thread is waiting for enough spaces
147 * in AudioTrack internal buffers */
149 uint64_t i_samples_written
; /* Number of samples written since last flush */
150 bool b_audiotrack_exception
; /* True if audiotrack threw an exception */
151 bool b_error
; /* generic error */
154 uint64_t i_read
; /* Number of bytes read */
155 uint64_t i_write
; /* Number of bytes written */
156 size_t i_size
; /* Size of the circular buffer in bytes */
158 jbyteArray p_bytearray
;
159 jfloatArray p_floatarray
;
160 jshortArray p_shortarray
;
170 // Don't use Float for now since 5.1/7.1 Float is down sampled to Stereo Float
171 //#define AUDIOTRACK_USE_FLOAT
172 //#define AUDIOTRACK_HW_LATENCY
174 /* Get AudioTrack native sample rate: if activated, most of the resampling
175 * will be done by VLC */
176 #define AUDIOTRACK_NATIVE_SAMPLERATE
178 #define AUDIOTRACK_SESSION_ID_TEXT " Id of audio session the AudioTrack must be attached to"
181 set_shortname( "AudioTrack" )
182 set_description( "Android AudioTrack audio output" )
183 set_capability( "audio output", 180 )
184 set_category( CAT_AUDIO
)
185 set_subcategory( SUBCAT_AUDIO_AOUT
)
186 add_integer( "audiotrack-session-id", 0,
187 AUDIOTRACK_SESSION_ID_TEXT
, NULL
, true )
189 add_shortcut( "audiotrack" )
190 set_callbacks( Open
, Close
)
193 #define THREAD_NAME "android_audiotrack"
194 #define GET_ENV() android_getEnv( VLC_OBJECT(p_aout), THREAD_NAME )
210 jmethodID writeShortV23
;
211 jmethodID writeBufferV21
;
212 jmethodID writeFloat
;
213 jmethodID getBufferSizeInFrames
;
214 jmethodID getLatency
;
215 jmethodID getPlaybackHeadPosition
;
216 jmethodID getTimestamp
;
217 jmethodID getMinBufferSize
;
218 jmethodID getNativeOutputSampleRate
;
220 jmethodID setStereoVolume
;
221 jint STATE_INITIALIZED
;
224 jint ERROR_BAD_VALUE
;
225 jint ERROR_INVALID_OPERATION
;
226 jint WRITE_NON_BLOCKING
;
232 jmethodID setLegacyStreamType
;
233 } AudioAttributes_Builder
;
235 jint ENCODING_PCM_8BIT
;
236 jint ENCODING_PCM_16BIT
;
237 jint ENCODING_PCM_FLOAT
;
238 bool has_ENCODING_PCM_FLOAT
;
240 bool has_ENCODING_AC3
;
242 bool has_ENCODING_E_AC3
;
243 jint ENCODING_DOLBY_TRUEHD
;
244 bool has_ENCODING_DOLBY_TRUEHD
;
246 bool has_ENCODING_DTS
;
247 jint ENCODING_DTS_HD
;
248 bool has_ENCODING_DTS_HD
;
249 jint ENCODING_IEC61937
;
250 bool has_ENCODING_IEC61937
;
251 jint CHANNEL_OUT_MONO
;
252 jint CHANNEL_OUT_STEREO
;
253 jint CHANNEL_OUT_FRONT_LEFT
;
254 jint CHANNEL_OUT_FRONT_RIGHT
;
255 jint CHANNEL_OUT_BACK_LEFT
;
256 jint CHANNEL_OUT_BACK_RIGHT
;
257 jint CHANNEL_OUT_FRONT_CENTER
;
258 jint CHANNEL_OUT_LOW_FREQUENCY
;
259 jint CHANNEL_OUT_BACK_CENTER
;
260 jint CHANNEL_OUT_5POINT1
;
261 jint CHANNEL_OUT_SIDE_LEFT
;
262 jint CHANNEL_OUT_SIDE_RIGHT
;
263 bool has_CHANNEL_OUT_SIDE
;
269 jmethodID setChannelMask
;
270 jmethodID setEncoding
;
271 jmethodID setSampleRate
;
272 } AudioFormat_Builder
;
274 jint ERROR_DEAD_OBJECT
;
275 bool has_ERROR_DEAD_OBJECT
;
281 jfieldID framePosition
;
286 /* init all jni fields.
287 * Done only one time during the first initialisation */
289 InitJNIFields( audio_output_t
*p_aout
, JNIEnv
* env
)
291 static vlc_mutex_t lock
= VLC_STATIC_MUTEX
;
292 static int i_init_state
= -1;
297 vlc_mutex_lock( &lock
);
299 if( i_init_state
!= -1 )
302 #define CHECK_EXCEPTION( what, critical ) do { \
303 if( (*env)->ExceptionCheck( env ) ) \
305 msg_Err( p_aout, "%s failed", what ); \
306 (*env)->ExceptionClear( env ); \
314 #define GET_CLASS( str, critical ) do { \
315 clazz = (*env)->FindClass( env, (str) ); \
316 CHECK_EXCEPTION( "FindClass(" str ")", critical ); \
318 #define GET_ID( get, id, str, args, critical ) do { \
319 jfields.id = (*env)->get( env, clazz, (str), (args) ); \
320 CHECK_EXCEPTION( #get "(" #id ")", critical ); \
322 #define GET_CONST_INT( id, str, critical ) do { \
324 field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
325 CHECK_EXCEPTION( "GetStaticFieldID(" #id ")", critical ); \
328 jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
329 CHECK_EXCEPTION( #id, critical ); \
333 /* AudioTrack class init */
334 GET_CLASS( "android/media/AudioTrack", true );
335 jfields
.AudioTrack
.clazz
= (jclass
) (*env
)->NewGlobalRef( env
, clazz
);
336 CHECK_EXCEPTION( "NewGlobalRef", true );
338 GET_ID( GetMethodID
, AudioTrack
.ctor
, "<init>",
339 "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;III)V", false );
340 jfields
.AudioTrack
.has_ctor_21
= jfields
.AudioTrack
.ctor
!= NULL
;
341 if( !jfields
.AudioTrack
.has_ctor_21
)
342 GET_ID( GetMethodID
, AudioTrack
.ctor
, "<init>", "(IIIIIII)V", true );
343 GET_ID( GetMethodID
, AudioTrack
.release
, "release", "()V", true );
344 GET_ID( GetMethodID
, AudioTrack
.getState
, "getState", "()I", true );
345 GET_ID( GetMethodID
, AudioTrack
.play
, "play", "()V", true );
346 GET_ID( GetMethodID
, AudioTrack
.stop
, "stop", "()V", true );
347 GET_ID( GetMethodID
, AudioTrack
.flush
, "flush", "()V", true );
348 GET_ID( GetMethodID
, AudioTrack
.pause
, "pause", "()V", true );
350 GET_ID( GetMethodID
, AudioTrack
.writeV23
, "write", "([BIII)I", false );
351 GET_ID( GetMethodID
, AudioTrack
.writeShortV23
, "write", "([SIII)I", false );
352 if( !jfields
.AudioTrack
.writeV23
)
353 GET_ID( GetMethodID
, AudioTrack
.writeBufferV21
, "write", "(Ljava/nio/ByteBuffer;II)I", false );
355 if( jfields
.AudioTrack
.writeV23
|| jfields
.AudioTrack
.writeBufferV21
)
357 GET_CONST_INT( AudioTrack
.WRITE_NON_BLOCKING
, "WRITE_NON_BLOCKING", true );
358 #ifdef AUDIOTRACK_USE_FLOAT
359 GET_ID( GetMethodID
, AudioTrack
.writeFloat
, "write", "([FIII)I", true );
362 GET_ID( GetMethodID
, AudioTrack
.write
, "write", "([BII)I", true );
364 GET_ID( GetMethodID
, AudioTrack
.getBufferSizeInFrames
,
365 "getBufferSizeInFrames", "()I", false );
367 #ifdef AUDIOTRACK_HW_LATENCY
368 GET_ID( GetMethodID
, AudioTrack
.getLatency
, "getLatency", "()I", false );
371 GET_ID( GetMethodID
, AudioTrack
.getTimestamp
,
372 "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false );
373 GET_ID( GetMethodID
, AudioTrack
.getPlaybackHeadPosition
,
374 "getPlaybackHeadPosition", "()I", true );
376 GET_ID( GetStaticMethodID
, AudioTrack
.getMinBufferSize
, "getMinBufferSize",
378 #ifdef AUDIOTRACK_NATIVE_SAMPLERATE
379 GET_ID( GetStaticMethodID
, AudioTrack
.getNativeOutputSampleRate
,
380 "getNativeOutputSampleRate", "(I)I", true );
382 GET_ID( GetMethodID
, AudioTrack
.setVolume
,
383 "setVolume", "(F)I", false );
384 if( !jfields
.AudioTrack
.setVolume
)
385 GET_ID( GetMethodID
, AudioTrack
.setStereoVolume
,
386 "setStereoVolume", "(FF)I", true );
387 GET_CONST_INT( AudioTrack
.STATE_INITIALIZED
, "STATE_INITIALIZED", true );
388 GET_CONST_INT( AudioTrack
.MODE_STREAM
, "MODE_STREAM", true );
389 GET_CONST_INT( AudioTrack
.ERROR
, "ERROR", true );
390 GET_CONST_INT( AudioTrack
.ERROR_BAD_VALUE
, "ERROR_BAD_VALUE", true );
391 GET_CONST_INT( AudioTrack
.ERROR_INVALID_OPERATION
,
392 "ERROR_INVALID_OPERATION", true );
394 if( jfields
.AudioTrack
.has_ctor_21
)
396 /* AudioAttributes_Builder class init */
397 GET_CLASS( "android/media/AudioAttributes$Builder", true );
398 jfields
.AudioAttributes_Builder
.clazz
= (jclass
) (*env
)->NewGlobalRef( env
, clazz
);
399 CHECK_EXCEPTION( "NewGlobalRef", true );
400 GET_ID( GetMethodID
, AudioAttributes_Builder
.ctor
, "<init>",
402 GET_ID( GetMethodID
, AudioAttributes_Builder
.build
, "build",
403 "()Landroid/media/AudioAttributes;", true );
404 GET_ID( GetMethodID
, AudioAttributes_Builder
.setLegacyStreamType
, "setLegacyStreamType",
405 "(I)Landroid/media/AudioAttributes$Builder;", true );
407 /* AudioFormat_Builder class init */
408 GET_CLASS( "android/media/AudioFormat$Builder", true );
409 jfields
.AudioFormat_Builder
.clazz
= (jclass
) (*env
)->NewGlobalRef( env
, clazz
);
410 CHECK_EXCEPTION( "NewGlobalRef", true );
411 GET_ID( GetMethodID
, AudioFormat_Builder
.ctor
, "<init>",
413 GET_ID( GetMethodID
, AudioFormat_Builder
.build
, "build",
414 "()Landroid/media/AudioFormat;", true );
415 GET_ID( GetMethodID
, AudioFormat_Builder
.setChannelMask
, "setChannelMask",
416 "(I)Landroid/media/AudioFormat$Builder;", true );
417 GET_ID( GetMethodID
, AudioFormat_Builder
.setEncoding
, "setEncoding",
418 "(I)Landroid/media/AudioFormat$Builder;", true );
419 GET_ID( GetMethodID
, AudioFormat_Builder
.setSampleRate
, "setSampleRate",
420 "(I)Landroid/media/AudioFormat$Builder;", true );
423 /* AudioTimestamp class init (if any) */
424 if( jfields
.AudioTrack
.getTimestamp
)
426 GET_CLASS( "android/media/AudioTimestamp", true );
427 jfields
.AudioTimestamp
.clazz
= (jclass
) (*env
)->NewGlobalRef( env
,
429 CHECK_EXCEPTION( "NewGlobalRef", true );
431 GET_ID( GetMethodID
, AudioTimestamp
.ctor
, "<init>", "()V", true );
432 GET_ID( GetFieldID
, AudioTimestamp
.framePosition
,
433 "framePosition", "J", true );
434 GET_ID( GetFieldID
, AudioTimestamp
.nanoTime
,
435 "nanoTime", "J", true );
438 /* AudioFormat class init */
439 GET_CLASS( "android/media/AudioFormat", true );
440 GET_CONST_INT( AudioFormat
.ENCODING_PCM_8BIT
, "ENCODING_PCM_8BIT", true );
441 GET_CONST_INT( AudioFormat
.ENCODING_PCM_16BIT
, "ENCODING_PCM_16BIT", true );
442 #ifdef AUDIOTRACK_USE_FLOAT
443 GET_CONST_INT( AudioFormat
.ENCODING_PCM_FLOAT
, "ENCODING_PCM_FLOAT",
445 jfields
.AudioFormat
.has_ENCODING_PCM_FLOAT
= field
!= NULL
&&
446 jfields
.AudioTrack
.writeFloat
;
448 jfields
.AudioFormat
.has_ENCODING_PCM_FLOAT
= false;
451 if( jfields
.AudioTrack
.writeShortV23
)
453 GET_CONST_INT( AudioFormat
.ENCODING_IEC61937
, "ENCODING_IEC61937", false );
454 jfields
.AudioFormat
.has_ENCODING_IEC61937
= field
!= NULL
;
457 jfields
.AudioFormat
.has_ENCODING_IEC61937
= false;
459 GET_CONST_INT( AudioFormat
.ENCODING_AC3
, "ENCODING_AC3", false );
460 jfields
.AudioFormat
.has_ENCODING_AC3
= field
!= NULL
;
461 GET_CONST_INT( AudioFormat
.ENCODING_E_AC3
, "ENCODING_E_AC3", false );
462 jfields
.AudioFormat
.has_ENCODING_E_AC3
= field
!= NULL
;
464 GET_CONST_INT( AudioFormat
.ENCODING_DTS
, "ENCODING_DTS", false );
465 jfields
.AudioFormat
.has_ENCODING_DTS
= field
!= NULL
;
466 GET_CONST_INT( AudioFormat
.ENCODING_DTS_HD
, "ENCODING_DTS_HD", false );
467 jfields
.AudioFormat
.has_ENCODING_DTS_HD
= field
!= NULL
;
469 GET_CONST_INT( AudioFormat
.ENCODING_DOLBY_TRUEHD
, "ENCODING_DOLBY_TRUEHD",
471 jfields
.AudioFormat
.has_ENCODING_DOLBY_TRUEHD
= field
!= NULL
;
473 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_MONO
, "CHANNEL_OUT_MONO", true );
474 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_STEREO
, "CHANNEL_OUT_STEREO", true );
475 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_FRONT_LEFT
, "CHANNEL_OUT_FRONT_LEFT", true );
476 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_FRONT_RIGHT
, "CHANNEL_OUT_FRONT_RIGHT", true );
477 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_5POINT1
, "CHANNEL_OUT_5POINT1", true );
478 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_BACK_LEFT
, "CHANNEL_OUT_BACK_LEFT", true );
479 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_BACK_RIGHT
, "CHANNEL_OUT_BACK_RIGHT", true );
480 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_FRONT_CENTER
, "CHANNEL_OUT_FRONT_CENTER", true );
481 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_LOW_FREQUENCY
, "CHANNEL_OUT_LOW_FREQUENCY", true );
482 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_BACK_CENTER
, "CHANNEL_OUT_BACK_CENTER", true );
483 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_SIDE_LEFT
, "CHANNEL_OUT_SIDE_LEFT", false );
486 GET_CONST_INT( AudioFormat
.CHANNEL_OUT_SIDE_RIGHT
, "CHANNEL_OUT_SIDE_RIGHT", true );
487 jfields
.AudioFormat
.has_CHANNEL_OUT_SIDE
= true;
489 jfields
.AudioFormat
.has_CHANNEL_OUT_SIDE
= false;
491 /* AudioManager class init */
492 GET_CLASS( "android/media/AudioManager", true );
493 GET_CONST_INT( AudioManager
.ERROR_DEAD_OBJECT
, "ERROR_DEAD_OBJECT", false );
494 jfields
.AudioManager
.has_ERROR_DEAD_OBJECT
= field
!= NULL
;
495 GET_CONST_INT( AudioManager
.STREAM_MUSIC
, "STREAM_MUSIC", true );
497 #undef CHECK_EXCEPTION
504 ret
= i_init_state
== 1;
506 msg_Err( p_aout
, "AudioTrack jni init failed" );
507 vlc_mutex_unlock( &lock
);
512 check_exception( JNIEnv
*env
, audio_output_t
*p_aout
,
513 const char *class, const char *method
)
515 if( (*env
)->ExceptionCheck( env
) )
517 aout_sys_t
*p_sys
= p_aout
->sys
;
519 p_sys
->b_audiotrack_exception
= true;
520 p_sys
->b_error
= true;
521 (*env
)->ExceptionDescribe( env
);
522 (*env
)->ExceptionClear( env
);
523 msg_Err( p_aout
, "%s.%s triggered an exception !", class, method
);
529 #define CHECK_EXCEPTION( class, method ) check_exception( env, p_aout, class, method )
530 #define CHECK_AT_EXCEPTION( method ) check_exception( env, p_aout, "AudioTrack", method )
532 #define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
534 #define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
535 #define JNI_CALL_BOOL( obj, method, ... ) JNI_CALL( CallBooleanMethod, obj, method, ##__VA_ARGS__ )
536 #define JNI_CALL_OBJECT( obj, method, ... ) JNI_CALL( CallObjectMethod, obj, method, ##__VA_ARGS__ )
537 #define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
538 #define JNI_CALL_STATIC_INT( clazz, method, ... ) JNI_CALL( CallStaticIntMethod, clazz, method, ##__VA_ARGS__ )
540 #define JNI_AT_NEW( ... ) JNI_CALL( NewObject, jfields.AudioTrack.clazz, jfields.AudioTrack.ctor, ##__VA_ARGS__ )
541 #define JNI_AT_CALL_INT( method, ... ) JNI_CALL_INT( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
542 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
543 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
544 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
546 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->timestamp.p_obj, jfields.AudioTimestamp.field )
548 static inline vlc_tick_t
549 frames_to_us( aout_sys_t
*p_sys
, uint64_t i_nb_frames
)
551 return vlc_tick_from_samples(i_nb_frames
, p_sys
->fmt
.i_rate
);
553 #define FRAMES_TO_US(x) frames_to_us( p_sys, (x) )
555 static inline uint64_t
556 bytes_to_frames( aout_sys_t
*p_sys
, size_t i_bytes
)
558 return i_bytes
* p_sys
->fmt
.i_frame_length
/ p_sys
->fmt
.i_bytes_per_frame
;
560 #define BYTES_TO_FRAMES(x) bytes_to_frames( p_sys, (x) )
561 #define BYTES_TO_US(x) frames_to_us( p_sys, bytes_to_frames( p_sys, (x) ) )
564 frames_to_bytes( aout_sys_t
*p_sys
, uint64_t i_frames
)
566 return i_frames
* p_sys
->fmt
.i_bytes_per_frame
/ p_sys
->fmt
.i_frame_length
;
568 #define FRAMES_TO_BYTES(x) frames_to_bytes( p_sys, (x) )
571 * Get the AudioTrack position
573 * The doc says that the position is reset to zero after flush but it's not
574 * true for all devices or Android versions.
577 AudioTrack_getPlaybackHeadPosition( JNIEnv
*env
, audio_output_t
*p_aout
)
580 * getPlaybackHeadPosition: Returns the playback head position expressed in
581 * frames. Though the "int" type is signed 32-bits, the value should be
582 * reinterpreted as if it is unsigned 32-bits. That is, the next position
583 * after 0x7FFFFFFF is (int) 0x80000000. This is a continuously advancing
584 * counter. It will wrap (overflow) periodically, for example approximately
585 * once every 27:03:11 hours:minutes:seconds at 44.1 kHz. It is reset to
586 * zero by flush(), reload(), and stop().
589 aout_sys_t
*p_sys
= p_aout
->sys
;
592 /* int32_t to uint32_t */
593 i_pos
= 0xFFFFFFFFL
& JNI_AT_CALL_INT( getPlaybackHeadPosition
);
595 /* uint32_t to uint64_t */
596 if( p_sys
->headpos
.i_last
> i_pos
)
597 p_sys
->headpos
.i_wrap_count
++;
598 p_sys
->headpos
.i_last
= i_pos
;
599 return p_sys
->headpos
.i_last
+ ((uint64_t)p_sys
->headpos
.i_wrap_count
<< 32);
603 * Reset AudioTrack position
605 * Called after flush, or start
608 AudioTrack_ResetPlaybackHeadPosition( JNIEnv
*env
, audio_output_t
*p_aout
)
611 aout_sys_t
*p_sys
= p_aout
->sys
;
613 p_sys
->headpos
.i_last
= 0;
614 p_sys
->headpos
.i_wrap_count
= 0;
618 * Reset AudioTrack SmoothPosition and TimestampPosition
621 AudioTrack_ResetPositions( JNIEnv
*env
, audio_output_t
*p_aout
)
623 aout_sys_t
*p_sys
= p_aout
->sys
;
626 p_sys
->timestamp
.i_play_time
= vlc_tick_now();
627 p_sys
->timestamp
.i_last_time
= 0;
628 p_sys
->timestamp
.i_frame_us
= 0;
629 p_sys
->timestamp
.i_frame_pos
= 0;
631 p_sys
->smoothpos
.i_count
= 0;
632 p_sys
->smoothpos
.i_idx
= 0;
633 p_sys
->smoothpos
.i_last_time
= 0;
634 p_sys
->smoothpos
.i_us
= 0;
638 * Reset all AudioTrack positions and internal state
641 AudioTrack_Reset( JNIEnv
*env
, audio_output_t
*p_aout
)
643 aout_sys_t
*p_sys
= p_aout
->sys
;
645 AudioTrack_ResetPositions( env
, p_aout
);
646 AudioTrack_ResetPlaybackHeadPosition( env
, p_aout
);
647 p_sys
->i_samples_written
= 0;
651 AudioTrack_GetLatencyUs( JNIEnv
*env
, audio_output_t
*p_aout
)
653 aout_sys_t
*p_sys
= p_aout
->sys
;
655 if( jfields
.AudioTrack
.getLatency
)
657 int i_latency_ms
= JNI_AT_CALL_INT( getLatency
);
659 /* getLatency() includes the latency due to AudioTrack buffer size,
660 * AudioMixer (if any) and audio hardware driver. We only need the
661 * audio hardware latency */
662 if( i_latency_ms
> 0 )
664 vlc_tick_t i_latency_us
= VLC_TICK_FROM_MS( i_latency_ms
)
665 - FRAMES_TO_US( p_sys
->i_max_audiotrack_samples
);
666 return i_latency_us
>= 0 ? i_latency_us
: 0;
674 * Get a smooth AudioTrack position
676 * This function smooth out the AudioTrack position since it has a very bad
677 * precision (+/- 20ms on old devices).
680 AudioTrack_GetSmoothPositionUs( JNIEnv
*env
, audio_output_t
*p_aout
)
682 aout_sys_t
*p_sys
= p_aout
->sys
;
683 uint64_t i_audiotrack_us
;
684 vlc_tick_t i_now
= vlc_tick_now();
686 /* Fetch an AudioTrack position every SMOOTHPOS_INTERVAL_US (30ms) */
687 if( i_now
- p_sys
->smoothpos
.i_last_time
>= SMOOTHPOS_INTERVAL_US
)
689 i_audiotrack_us
= FRAMES_TO_US( AudioTrack_getPlaybackHeadPosition( env
, p_aout
) );
690 if( i_audiotrack_us
== 0 )
693 p_sys
->smoothpos
.i_last_time
= i_now
;
695 /* Base the position off the current time */
696 p_sys
->smoothpos
.p_us
[p_sys
->smoothpos
.i_idx
] = i_audiotrack_us
- i_now
;
697 p_sys
->smoothpos
.i_idx
= (p_sys
->smoothpos
.i_idx
+ 1)
698 % SMOOTHPOS_SAMPLE_COUNT
;
699 if( p_sys
->smoothpos
.i_count
< SMOOTHPOS_SAMPLE_COUNT
)
700 p_sys
->smoothpos
.i_count
++;
702 /* Calculate the average position based off the current time */
703 p_sys
->smoothpos
.i_us
= 0;
704 for( uint32_t i
= 0; i
< p_sys
->smoothpos
.i_count
; ++i
)
705 p_sys
->smoothpos
.i_us
+= p_sys
->smoothpos
.p_us
[i
];
706 p_sys
->smoothpos
.i_us
/= p_sys
->smoothpos
.i_count
;
709 if( p_sys
->smoothpos
.i_us
!= 0 )
710 return p_sys
->smoothpos
.i_us
+ i_now
- AudioTrack_GetLatencyUs( env
, p_aout
);
717 AudioTrack_GetTimestampPositionUs( JNIEnv
*env
, audio_output_t
*p_aout
)
719 aout_sys_t
*p_sys
= p_aout
->sys
;
722 if( !p_sys
->timestamp
.p_obj
)
725 i_now
= vlc_tick_now();
728 * getTimestamp: Poll for a timestamp on demand.
730 * If you need to track timestamps during initial warmup or after a
731 * routing or mode change, you should request a new timestamp once per
732 * second until the reported timestamps show that the audio clock is
733 * stable. Thereafter, query for a new timestamp approximately once
734 * every 10 seconds to once per minute. Calling this method more often
735 * is inefficient. It is also counter-productive to call this method
736 * more often than recommended, because the short-term differences
737 * between successive timestamp reports are not meaningful. If you need
738 * a high-resolution mapping between frame position and presentation
739 * time, consider implementing that at application level, based on
740 * low-resolution timestamps.
743 /* Fetch an AudioTrack timestamp every AUDIOTIMESTAMP_INTERVAL_US (500ms) */
744 if( i_now
- p_sys
->timestamp
.i_last_time
>= AUDIOTIMESTAMP_INTERVAL_US
)
746 p_sys
->timestamp
.i_last_time
= i_now
;
748 if( JNI_AT_CALL_BOOL( getTimestamp
, p_sys
->timestamp
.p_obj
) )
750 p_sys
->timestamp
.i_frame_us
= VLC_TICK_FROM_NS(JNI_AUDIOTIMESTAMP_GET_LONG( nanoTime
));
751 p_sys
->timestamp
.i_frame_pos
= JNI_AUDIOTIMESTAMP_GET_LONG( framePosition
);
755 p_sys
->timestamp
.i_frame_us
= 0;
756 p_sys
->timestamp
.i_frame_pos
= 0;
760 /* frame time should be after last play time
761 * frame time shouldn't be in the future
762 * frame time should be less than 10 seconds old */
763 if( p_sys
->timestamp
.i_frame_us
!= 0 && p_sys
->timestamp
.i_frame_pos
!= 0
764 && p_sys
->timestamp
.i_frame_us
> p_sys
->timestamp
.i_play_time
765 && i_now
> p_sys
->timestamp
.i_frame_us
766 && ( i_now
- p_sys
->timestamp
.i_frame_us
) <= VLC_TICK_FROM_SEC(10) )
768 vlc_tick_t i_time_diff
= i_now
- p_sys
->timestamp
.i_frame_us
;
769 jlong i_frames_diff
= samples_from_vlc_tick(i_time_diff
, p_sys
->fmt
.i_rate
);
770 return FRAMES_TO_US( p_sys
->timestamp
.i_frame_pos
+ i_frames_diff
);
776 TimeGet( audio_output_t
*p_aout
, vlc_tick_t
*restrict p_delay
)
778 aout_sys_t
*p_sys
= p_aout
->sys
;
779 vlc_tick_t i_audiotrack_us
;
782 if( p_sys
->b_passthrough
)
785 vlc_mutex_lock( &p_sys
->lock
);
787 if( p_sys
->b_error
|| !p_sys
->i_samples_written
|| !( env
= GET_ENV() ) )
790 i_audiotrack_us
= AudioTrack_GetTimestampPositionUs( env
, p_aout
);
792 if( i_audiotrack_us
<= 0 )
793 i_audiotrack_us
= AudioTrack_GetSmoothPositionUs(env
, p_aout
);
795 /* Debug log for both delays */
798 vlc_tick_t i_ts_us
= AudioTrack_GetTimestampPositionUs( env
, p_aout
);
799 vlc_tick_t i_smooth_us
= AudioTrack_GetSmoothPositionUs(env
, p_aout
);
800 vlc_tick_t i_latency_us
= AudioTrack_GetLatencyUs( env
, p_aout
);
802 msg_Err( p_aout
, "TimeGet: TimeStamp: %"PRId64
", Smooth: %"PRId64
" (latency: %"PRId64
")",
803 i_ts_us
, i_smooth_us
, i_latency_us
);
807 if( i_audiotrack_us
> 0 )
809 /* AudioTrack delay */
810 vlc_tick_t i_delay
= FRAMES_TO_US( p_sys
->i_samples_written
)
814 /* Circular buffer delay */
815 i_delay
+= BYTES_TO_US( p_sys
->circular
.i_write
816 - p_sys
->circular
.i_read
);
818 vlc_mutex_unlock( &p_sys
->lock
);
823 msg_Warn( p_aout
, "timing screwed, reset positions" );
824 AudioTrack_ResetPositions( env
, p_aout
);
829 vlc_mutex_unlock( &p_sys
->lock
);
834 AudioTrack_GetChanOrder( uint16_t i_physical_channels
, uint32_t p_chans_out
[] )
836 #define HAS_CHAN( x ) ( ( i_physical_channels & (x) ) == (x) )
837 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
840 if( HAS_CHAN( AOUT_CHAN_LEFT
) )
841 p_chans_out
[i
++] = AOUT_CHAN_LEFT
;
842 if( HAS_CHAN( AOUT_CHAN_RIGHT
) )
843 p_chans_out
[i
++] = AOUT_CHAN_RIGHT
;
845 if( HAS_CHAN( AOUT_CHAN_CENTER
) )
846 p_chans_out
[i
++] = AOUT_CHAN_CENTER
;
848 if( HAS_CHAN( AOUT_CHAN_LFE
) )
849 p_chans_out
[i
++] = AOUT_CHAN_LFE
;
851 if( HAS_CHAN( AOUT_CHAN_REARLEFT
) )
852 p_chans_out
[i
++] = AOUT_CHAN_REARLEFT
;
853 if( HAS_CHAN( AOUT_CHAN_REARRIGHT
) )
854 p_chans_out
[i
++] = AOUT_CHAN_REARRIGHT
;
856 if( HAS_CHAN( AOUT_CHAN_REARCENTER
) )
857 p_chans_out
[i
++] = AOUT_CHAN_REARCENTER
;
859 if( HAS_CHAN( AOUT_CHAN_MIDDLELEFT
) )
860 p_chans_out
[i
++] = AOUT_CHAN_MIDDLELEFT
;
861 if( HAS_CHAN( AOUT_CHAN_MIDDLERIGHT
) )
862 p_chans_out
[i
++] = AOUT_CHAN_MIDDLERIGHT
;
864 assert( i
<= AOUT_CHAN_MAX
);
869 AudioTrack_New21( JNIEnv
*env
, audio_output_t
*p_aout
, unsigned int i_rate
,
870 int i_channel_config
, int i_format
, int i_size
,
873 jobject p_audiotrack
= NULL
;
874 jobject p_aattr_builder
= NULL
;
875 jobject p_audio_attributes
= NULL
;
876 jobject p_afmt_builder
= NULL
;
877 jobject p_audio_format
= NULL
;
882 jfields
.AudioAttributes_Builder
.clazz
,
883 jfields
.AudioAttributes_Builder
.ctor
);
884 if( !p_aattr_builder
)
887 ref
= JNI_CALL_OBJECT( p_aattr_builder
,
888 jfields
.AudioAttributes_Builder
.setLegacyStreamType
,
889 jfields
.AudioManager
.STREAM_MUSIC
);
890 (*env
)->DeleteLocalRef( env
, ref
);
893 JNI_CALL_OBJECT( p_aattr_builder
,
894 jfields
.AudioAttributes_Builder
.build
);
895 if( !p_audio_attributes
)
898 p_afmt_builder
= JNI_CALL( NewObject
,
899 jfields
.AudioFormat_Builder
.clazz
,
900 jfields
.AudioFormat_Builder
.ctor
);
901 if( !p_afmt_builder
)
904 ref
= JNI_CALL_OBJECT( p_afmt_builder
,
905 jfields
.AudioFormat_Builder
.setChannelMask
,
907 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setChannelMask" ) )
909 (*env
)->DeleteLocalRef( env
, ref
);
912 (*env
)->DeleteLocalRef( env
, ref
);
914 ref
= JNI_CALL_OBJECT( p_afmt_builder
,
915 jfields
.AudioFormat_Builder
.setEncoding
,
917 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setEncoding" ) )
919 (*env
)->DeleteLocalRef( env
, ref
);
922 (*env
)->DeleteLocalRef( env
, ref
);
924 ref
= JNI_CALL_OBJECT( p_afmt_builder
,
925 jfields
.AudioFormat_Builder
.setSampleRate
,
927 if( CHECK_EXCEPTION( "AudioFormat.Builder", "setSampleRate" ) )
929 (*env
)->DeleteLocalRef( env
, ref
);
932 (*env
)->DeleteLocalRef( env
, ref
);
934 p_audio_format
= JNI_CALL_OBJECT( p_afmt_builder
,
935 jfields
.AudioFormat_Builder
.build
);
939 p_audiotrack
= JNI_AT_NEW( p_audio_attributes
, p_audio_format
, i_size
,
940 jfields
.AudioTrack
.MODE_STREAM
, session_id
);
943 (*env
)->DeleteLocalRef( env
, p_aattr_builder
);
944 (*env
)->DeleteLocalRef( env
, p_audio_attributes
);
945 (*env
)->DeleteLocalRef( env
, p_afmt_builder
);
946 (*env
)->DeleteLocalRef( env
, p_audio_format
);
951 AudioTrack_NewLegacy( JNIEnv
*env
, audio_output_t
*p_aout
, unsigned int i_rate
,
952 int i_channel_config
, int i_format
, int i_size
,
955 VLC_UNUSED( p_aout
);
956 return JNI_AT_NEW( jfields
.AudioManager
.STREAM_MUSIC
, i_rate
,
957 i_channel_config
, i_format
, i_size
,
958 jfields
.AudioTrack
.MODE_STREAM
, session_id
);
962 * Create an Android AudioTrack.
963 * returns -1 on error, 0 on success.
966 AudioTrack_New( JNIEnv
*env
, audio_output_t
*p_aout
, unsigned int i_rate
,
967 int i_channel_config
, int i_format
, int i_size
)
969 aout_sys_t
*p_sys
= p_aout
->sys
;
970 jint session_id
= var_InheritInteger( p_aout
, "audiotrack-session-id" );
972 jobject p_audiotrack
;
973 if( jfields
.AudioTrack
.has_ctor_21
)
974 p_audiotrack
= AudioTrack_New21( env
, p_aout
, i_rate
, i_channel_config
,
975 i_format
, i_size
, session_id
);
977 p_audiotrack
= AudioTrack_NewLegacy( env
, p_aout
, i_rate
,
978 i_channel_config
, i_format
, i_size
,
980 if( CHECK_AT_EXCEPTION( "AudioTrack<init>" ) || !p_audiotrack
)
982 msg_Warn( p_aout
, "AudioTrack Init failed" );
985 if( JNI_CALL_INT( p_audiotrack
, jfields
.AudioTrack
.getState
)
986 != jfields
.AudioTrack
.STATE_INITIALIZED
)
988 JNI_CALL_VOID( p_audiotrack
, jfields
.AudioTrack
.release
);
989 (*env
)->DeleteLocalRef( env
, p_audiotrack
);
990 msg_Err( p_aout
, "AudioTrack getState failed" );
994 p_sys
->p_audiotrack
= (*env
)->NewGlobalRef( env
, p_audiotrack
);
995 (*env
)->DeleteLocalRef( env
, p_audiotrack
);
996 if( !p_sys
->p_audiotrack
)
1003 * Destroy and recreate an Android AudioTrack using the same arguments.
1004 * returns -1 on error, 0 on success.
1007 AudioTrack_Recreate( JNIEnv
*env
, audio_output_t
*p_aout
)
1009 aout_sys_t
*p_sys
= p_aout
->sys
;
1011 JNI_AT_CALL_VOID( release
);
1012 (*env
)->DeleteGlobalRef( env
, p_sys
->p_audiotrack
);
1013 p_sys
->p_audiotrack
= NULL
;
1014 return AudioTrack_New( env
, p_aout
, p_sys
->audiotrack_args
.i_rate
,
1015 p_sys
->audiotrack_args
.i_channel_config
,
1016 p_sys
->audiotrack_args
.i_format
,
1017 p_sys
->audiotrack_args
.i_size
);
1021 * Configure and create an Android AudioTrack.
1022 * returns -1 on configuration error, 0 on success.
1025 AudioTrack_Create( JNIEnv
*env
, audio_output_t
*p_aout
,
1026 unsigned int i_rate
,
1028 uint16_t i_physical_channels
)
1030 aout_sys_t
*p_sys
= p_aout
->sys
;
1031 int i_size
, i_min_buffer_size
, i_channel_config
;
1033 switch( i_physical_channels
)
1035 case AOUT_CHANS_7_1
:
1036 /* bitmask of CHANNEL_OUT_7POINT1 doesn't correspond to 5POINT1 and
1038 i_channel_config
= jfields
.AudioFormat
.CHANNEL_OUT_5POINT1
|
1039 jfields
.AudioFormat
.CHANNEL_OUT_SIDE_LEFT
|
1040 jfields
.AudioFormat
.CHANNEL_OUT_SIDE_RIGHT
;
1042 case AOUT_CHANS_5_1
:
1043 i_channel_config
= jfields
.AudioFormat
.CHANNEL_OUT_5POINT1
;
1045 case AOUT_CHAN_LEFT
:
1046 i_channel_config
= jfields
.AudioFormat
.CHANNEL_OUT_MONO
;
1048 case AOUT_CHANS_STEREO
:
1049 i_channel_config
= jfields
.AudioFormat
.CHANNEL_OUT_STEREO
;
1052 vlc_assert_unreachable();
1055 i_min_buffer_size
= JNI_AT_CALL_STATIC_INT( getMinBufferSize
, i_rate
,
1056 i_channel_config
, i_format
);
1057 if( i_min_buffer_size
<= 0 )
1059 msg_Warn( p_aout
, "getMinBufferSize returned an invalid size" ) ;
1062 i_size
= i_min_buffer_size
* 2;
1064 /* create AudioTrack object */
1065 if( AudioTrack_New( env
, p_aout
, i_rate
, i_channel_config
,
1066 i_format
, i_size
) != 0 )
1069 p_sys
->audiotrack_args
.i_rate
= i_rate
;
1070 p_sys
->audiotrack_args
.i_channel_config
= i_channel_config
;
1071 p_sys
->audiotrack_args
.i_format
= i_format
;
1072 p_sys
->audiotrack_args
.i_size
= i_size
;
1078 AudioTrack_HasEncoding( audio_output_t
*p_aout
, vlc_fourcc_t i_format
)
1080 aout_sys_t
*p_sys
= p_aout
->sys
;
1082 #define MATCH_ENCODING_FLAG(x) jfields.AudioFormat.has_##x && \
1083 ( p_sys->i_encoding_flags == 0 || p_sys->i_encoding_flags & (1 << jfields.AudioFormat.x) )
1087 case VLC_CODEC_DTSHD
:
1088 return MATCH_ENCODING_FLAG( ENCODING_DTS_HD
);
1090 return MATCH_ENCODING_FLAG( ENCODING_DTS
);
1092 return MATCH_ENCODING_FLAG( ENCODING_AC3
);
1093 case VLC_CODEC_EAC3
:
1094 return MATCH_ENCODING_FLAG( ENCODING_E_AC3
);
1095 case VLC_CODEC_TRUEHD
:
1097 return MATCH_ENCODING_FLAG( ENCODING_DOLBY_TRUEHD
);
1104 StartPassthrough( JNIEnv
*env
, audio_output_t
*p_aout
)
1106 aout_sys_t
*p_sys
= p_aout
->sys
;
1109 if( !AudioTrack_HasEncoding( p_aout
, p_sys
->fmt
.i_format
) )
1110 return VLC_EGENERIC
;
1112 if( jfields
.AudioFormat
.has_ENCODING_IEC61937
)
1114 i_at_format
= jfields
.AudioFormat
.ENCODING_IEC61937
;
1115 switch( p_sys
->fmt
.i_format
)
1117 case VLC_CODEC_TRUEHD
:
1119 p_sys
->fmt
.i_rate
= 192000;
1120 p_sys
->fmt
.i_bytes_per_frame
= 16;
1122 /* AudioFormat.ENCODING_IEC61937 documentation says that the
1123 * channel layout must be stereo. Well, not for TrueHD
1125 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_7_1
;
1128 p_sys
->fmt
.i_bytes_per_frame
= 4;
1129 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_STEREO
;
1131 case VLC_CODEC_DTSHD
:
1132 p_sys
->fmt
.i_bytes_per_frame
= 4;
1133 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_STEREO
;
1134 p_sys
->fmt
.i_rate
= 192000;
1135 p_sys
->fmt
.i_bytes_per_frame
= 16;
1137 case VLC_CODEC_EAC3
:
1138 p_sys
->fmt
.i_rate
= 192000;
1140 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_STEREO
;
1141 p_sys
->fmt
.i_bytes_per_frame
= 4;
1144 return VLC_EGENERIC
;
1146 p_sys
->fmt
.i_frame_length
= 1;
1147 p_sys
->fmt
.i_channels
= aout_FormatNbChannels( &p_sys
->fmt
);
1148 p_sys
->fmt
.i_format
= VLC_CODEC_SPDIFL
;
1152 switch( p_sys
->fmt
.i_format
)
1155 if( !jfields
.AudioFormat
.has_ENCODING_AC3
)
1156 return VLC_EGENERIC
;
1157 i_at_format
= jfields
.AudioFormat
.ENCODING_AC3
;
1159 case VLC_CODEC_EAC3
:
1160 if( !jfields
.AudioFormat
.has_ENCODING_E_AC3
)
1161 return VLC_EGENERIC
;
1162 i_at_format
= jfields
.AudioFormat
.ENCODING_E_AC3
;
1165 if( !jfields
.AudioFormat
.has_ENCODING_DTS
)
1166 return VLC_EGENERIC
;
1167 i_at_format
= jfields
.AudioFormat
.ENCODING_DTS
;
1170 return VLC_EGENERIC
;
1172 p_sys
->fmt
.i_bytes_per_frame
= 4;
1173 p_sys
->fmt
.i_frame_length
= 1;
1174 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_STEREO
;
1175 p_sys
->fmt
.i_channels
= 2;
1176 p_sys
->fmt
.i_format
= VLC_CODEC_SPDIFB
;
1179 int i_ret
= AudioTrack_Create( env
, p_aout
, p_sys
->fmt
.i_rate
, i_at_format
,
1180 p_sys
->fmt
.i_physical_channels
);
1181 if( i_ret
!= VLC_SUCCESS
)
1182 msg_Warn( p_aout
, "SPDIF configuration failed" );
1185 p_sys
->b_passthrough
= true;
1186 p_sys
->i_chans_to_reorder
= 0;
1193 StartPCM( JNIEnv
*env
, audio_output_t
*p_aout
, unsigned i_max_channels
)
1195 aout_sys_t
*p_sys
= p_aout
->sys
;
1196 unsigned i_nb_channels
;
1197 int i_at_format
, i_ret
;
1199 if (jfields
.AudioTrack
.getNativeOutputSampleRate
)
1201 JNI_AT_CALL_STATIC_INT( getNativeOutputSampleRate
,
1202 jfields
.AudioManager
.STREAM_MUSIC
);
1204 p_sys
->fmt
.i_rate
= VLC_CLIP( p_sys
->fmt
.i_rate
, 4000, 48000 );
1208 /* We can only accept U8, S16N, FL32, and AC3 */
1209 switch( p_sys
->fmt
.i_format
)
1212 i_at_format
= jfields
.AudioFormat
.ENCODING_PCM_8BIT
;
1214 case VLC_CODEC_S16N
:
1215 i_at_format
= jfields
.AudioFormat
.ENCODING_PCM_16BIT
;
1217 case VLC_CODEC_FL32
:
1218 if( jfields
.AudioFormat
.has_ENCODING_PCM_FLOAT
)
1219 i_at_format
= jfields
.AudioFormat
.ENCODING_PCM_FLOAT
;
1222 p_sys
->fmt
.i_format
= VLC_CODEC_S16N
;
1223 i_at_format
= jfields
.AudioFormat
.ENCODING_PCM_16BIT
;
1227 p_sys
->fmt
.i_format
= VLC_CODEC_S16N
;
1228 i_at_format
= jfields
.AudioFormat
.ENCODING_PCM_16BIT
;
1232 /* Android AudioTrack supports only mono, stereo, 5.1 and 7.1.
1233 * Android will downmix to stereo if audio output doesn't handle 5.1 or 7.1
1236 i_nb_channels
= aout_FormatNbChannels( &p_sys
->fmt
);
1237 if( i_nb_channels
== 0 )
1238 return VLC_EGENERIC
;
1239 if( AOUT_FMT_LINEAR( &p_sys
->fmt
) )
1240 i_nb_channels
= __MIN( i_max_channels
, i_nb_channels
);
1241 if( i_nb_channels
> 5 )
1243 if( i_nb_channels
> 7 && jfields
.AudioFormat
.has_CHANNEL_OUT_SIDE
)
1244 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_7_1
;
1246 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_5_1
;
1249 if( i_nb_channels
== 1 )
1250 p_sys
->fmt
.i_physical_channels
= AOUT_CHAN_LEFT
;
1252 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_STEREO
;
1255 /* Try to create an AudioTrack with the most advanced channel and
1256 * format configuration. If AudioTrack_Create fails, try again with a
1257 * less advanced format (PCM S16N). If it fails again, try again with
1258 * Stereo channels. */
1259 i_ret
= AudioTrack_Create( env
, p_aout
, p_sys
->fmt
.i_rate
, i_at_format
,
1260 p_sys
->fmt
.i_physical_channels
);
1263 if( p_sys
->fmt
.i_format
== VLC_CODEC_FL32
)
1265 msg_Warn( p_aout
, "FL32 configuration failed, "
1266 "fallback to S16N PCM" );
1267 p_sys
->fmt
.i_format
= VLC_CODEC_S16N
;
1269 else if( p_sys
->fmt
.i_physical_channels
& AOUT_CHANS_5_1
)
1271 msg_Warn( p_aout
, "5.1 or 7.1 configuration failed, "
1272 "fallback to Stereo" );
1273 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_STEREO
;
1278 } while( i_ret
!= 0 );
1280 if( i_ret
!= VLC_SUCCESS
)
1283 uint32_t p_chans_out
[AOUT_CHAN_MAX
];
1284 memset( p_chans_out
, 0, sizeof(p_chans_out
) );
1285 AudioTrack_GetChanOrder( p_sys
->fmt
.i_physical_channels
, p_chans_out
);
1286 p_sys
->i_chans_to_reorder
=
1287 aout_CheckChannelReorder( NULL
, p_chans_out
,
1288 p_sys
->fmt
.i_physical_channels
,
1289 p_sys
->p_chan_table
);
1290 aout_FormatPrepare( &p_sys
->fmt
);
1295 Start( audio_output_t
*p_aout
, audio_sample_format_t
*restrict p_fmt
)
1297 aout_sys_t
*p_sys
= p_aout
->sys
;
1300 bool b_try_passthrough
;
1301 unsigned i_max_channels
;
1303 if( p_sys
->at_dev
== AT_DEV_ENCODED
)
1305 b_try_passthrough
= true;
1306 i_max_channels
= AT_DEV_MAX_CHANNELS
;
1310 b_try_passthrough
= var_InheritBool( p_aout
, "spdif" );
1311 i_max_channels
= p_sys
->at_dev
== AT_DEV_STEREO
? 2 : AT_DEV_MAX_CHANNELS
;
1314 if( !( env
= GET_ENV() ) )
1315 return VLC_EGENERIC
;
1317 p_sys
->fmt
= *p_fmt
;
1319 aout_FormatPrint( p_aout
, "VLC is looking for:", &p_sys
->fmt
);
1321 bool low_latency
= false;
1322 if (p_sys
->fmt
.channel_type
== AUDIO_CHANNEL_TYPE_AMBISONICS
)
1324 p_sys
->fmt
.channel_type
= AUDIO_CHANNEL_TYPE_BITMAP
;
1326 /* TODO: detect sink channel layout */
1327 p_sys
->fmt
.i_physical_channels
= AOUT_CHANS_STEREO
;
1328 aout_FormatPrepare(&p_sys
->fmt
);
1332 if( AOUT_FMT_LINEAR( &p_sys
->fmt
) )
1333 i_ret
= StartPCM( env
, p_aout
, i_max_channels
);
1334 else if( b_try_passthrough
)
1335 i_ret
= StartPassthrough( env
, p_aout
);
1337 return VLC_EGENERIC
;
1340 return VLC_EGENERIC
;
1342 if( jfields
.AudioTrack
.getBufferSizeInFrames
)
1343 p_sys
->i_max_audiotrack_samples
= JNI_AT_CALL_INT( getBufferSizeInFrames
);
1345 p_sys
->i_max_audiotrack_samples
= BYTES_TO_FRAMES( p_sys
->audiotrack_args
.i_size
);
1347 #ifdef AUDIOTRACK_HW_LATENCY
1348 if( jfields
.AudioTimestamp
.clazz
)
1350 /* create AudioTimestamp object */
1351 jobject p_obj
= JNI_CALL( NewObject
, jfields
.AudioTimestamp
.clazz
,
1352 jfields
.AudioTimestamp
.ctor
);
1355 p_sys
->timestamp
.p_obj
= (*env
)->NewGlobalRef( env
, p_obj
);
1356 (*env
)->DeleteLocalRef( env
, p_obj
);
1358 if( !p_sys
->timestamp
.p_obj
)
1363 AudioTrack_Reset( env
, p_aout
);
1365 if( p_sys
->fmt
.i_format
== VLC_CODEC_FL32
)
1367 msg_Dbg( p_aout
, "using WRITE_FLOATARRAY");
1368 p_sys
->i_write_type
= WRITE_FLOATARRAY
;
1370 else if( p_sys
->fmt
.i_format
== VLC_CODEC_SPDIFL
)
1372 assert( jfields
.AudioFormat
.has_ENCODING_IEC61937
);
1373 msg_Dbg( p_aout
, "using WRITE_SHORTARRAYV23");
1374 p_sys
->i_write_type
= WRITE_SHORTARRAYV23
;
1376 else if( jfields
.AudioTrack
.writeV23
)
1378 msg_Dbg( p_aout
, "using WRITE_BYTEARRAYV23");
1379 p_sys
->i_write_type
= WRITE_BYTEARRAYV23
;
1381 else if( jfields
.AudioTrack
.writeBufferV21
)
1383 msg_Dbg( p_aout
, "using WRITE_BYTEBUFFER");
1384 p_sys
->i_write_type
= WRITE_BYTEBUFFER
;
1388 msg_Dbg( p_aout
, "using WRITE_BYTEARRAY");
1389 p_sys
->i_write_type
= WRITE_BYTEARRAY
;
1392 p_sys
->circular
.i_read
= p_sys
->circular
.i_write
= 0;
1393 p_sys
->circular
.i_size
= (int)p_sys
->fmt
.i_rate
1394 * p_sys
->fmt
.i_bytes_per_frame
1395 / p_sys
->fmt
.i_frame_length
;
1398 /* 40 ms of buffering */
1399 p_sys
->circular
.i_size
= p_sys
->circular
.i_size
/ 25;
1403 /* 2 seconds of buffering */
1404 p_sys
->circular
.i_size
= samples_from_vlc_tick(AOUT_MAX_PREPARE_TIME
, p_sys
->circular
.i_size
);
1407 /* Allocate circular buffer */
1408 switch( p_sys
->i_write_type
)
1410 case WRITE_BYTEARRAY
:
1411 case WRITE_BYTEARRAYV23
:
1413 jbyteArray p_bytearray
;
1415 p_bytearray
= (*env
)->NewByteArray( env
, p_sys
->circular
.i_size
);
1418 p_sys
->circular
.u
.p_bytearray
= (*env
)->NewGlobalRef( env
, p_bytearray
);
1419 (*env
)->DeleteLocalRef( env
, p_bytearray
);
1422 if( !p_sys
->circular
.u
.p_bytearray
)
1424 msg_Err(p_aout
, "byte array allocation failed");
1429 case WRITE_SHORTARRAYV23
:
1431 jshortArray p_shortarray
;
1433 p_shortarray
= (*env
)->NewShortArray( env
,
1434 p_sys
->circular
.i_size
/ 2 );
1437 p_sys
->circular
.u
.p_shortarray
= (*env
)->NewGlobalRef( env
, p_shortarray
);
1438 (*env
)->DeleteLocalRef( env
, p_shortarray
);
1440 if( !p_sys
->circular
.u
.p_shortarray
)
1442 msg_Err(p_aout
, "short array allocation failed");
1447 case WRITE_FLOATARRAY
:
1449 jfloatArray p_floatarray
;
1451 p_floatarray
= (*env
)->NewFloatArray( env
,
1452 p_sys
->circular
.i_size
/ 4 );
1455 p_sys
->circular
.u
.p_floatarray
= (*env
)->NewGlobalRef( env
, p_floatarray
);
1456 (*env
)->DeleteLocalRef( env
, p_floatarray
);
1458 if( !p_sys
->circular
.u
.p_floatarray
)
1460 msg_Err(p_aout
, "float array allocation failed");
1465 case WRITE_BYTEBUFFER
:
1466 p_sys
->circular
.u
.bytebuffer
.p_data
= malloc( p_sys
->circular
.i_size
);
1467 if( !p_sys
->circular
.u
.bytebuffer
.p_data
)
1469 msg_Err(p_aout
, "bytebuffer allocation failed");
1475 /* Run AudioTrack_Thread */
1476 p_sys
->b_thread_running
= true;
1477 p_sys
->b_thread_paused
= false;
1478 if ( vlc_clone( &p_sys
->thread
, AudioTrack_Thread
, p_aout
,
1479 VLC_THREAD_PRIORITY_LOW
) )
1481 msg_Err(p_aout
, "vlc clone failed");
1485 JNI_AT_CALL_VOID( play
);
1486 CHECK_AT_EXCEPTION( "play" );
1488 *p_fmt
= p_sys
->fmt
;
1490 p_aout
->volume_set(p_aout
, p_sys
->volume
);
1492 p_aout
->mute_set(p_aout
, true);
1493 aout_FormatPrint( p_aout
, "VLC will output:", &p_sys
->fmt
);
1499 return VLC_EGENERIC
;
1503 Stop( audio_output_t
*p_aout
)
1505 aout_sys_t
*p_sys
= p_aout
->sys
;
1508 if( !( env
= GET_ENV() ) )
1511 /* Stop the AudioTrack thread */
1512 vlc_mutex_lock( &p_sys
->lock
);
1513 if( p_sys
->b_thread_running
)
1515 p_sys
->b_thread_running
= false;
1516 vlc_cond_signal( &p_sys
->thread_cond
);
1517 vlc_mutex_unlock( &p_sys
->lock
);
1518 vlc_join( p_sys
->thread
, NULL
);
1521 vlc_mutex_unlock( &p_sys
->lock
);
1523 /* Release the AudioTrack object */
1524 if( p_sys
->p_audiotrack
)
1526 if( !p_sys
->b_audiotrack_exception
)
1528 JNI_AT_CALL_VOID( stop
);
1529 if( !CHECK_AT_EXCEPTION( "stop" ) )
1530 JNI_AT_CALL_VOID( release
);
1532 (*env
)->DeleteGlobalRef( env
, p_sys
->p_audiotrack
);
1533 p_sys
->p_audiotrack
= NULL
;
1536 /* Release the timestamp object */
1537 if( p_sys
->timestamp
.p_obj
)
1539 (*env
)->DeleteGlobalRef( env
, p_sys
->timestamp
.p_obj
);
1540 p_sys
->timestamp
.p_obj
= NULL
;
1543 /* Release the Circular buffer data */
1544 switch( p_sys
->i_write_type
)
1546 case WRITE_BYTEARRAY
:
1547 case WRITE_BYTEARRAYV23
:
1548 if( p_sys
->circular
.u
.p_bytearray
)
1550 (*env
)->DeleteGlobalRef( env
, p_sys
->circular
.u
.p_bytearray
);
1551 p_sys
->circular
.u
.p_bytearray
= NULL
;
1554 case WRITE_SHORTARRAYV23
:
1555 if( p_sys
->circular
.u
.p_shortarray
)
1557 (*env
)->DeleteGlobalRef( env
, p_sys
->circular
.u
.p_shortarray
);
1558 p_sys
->circular
.u
.p_shortarray
= NULL
;
1561 case WRITE_FLOATARRAY
:
1562 if( p_sys
->circular
.u
.p_floatarray
)
1564 (*env
)->DeleteGlobalRef( env
, p_sys
->circular
.u
.p_floatarray
);
1565 p_sys
->circular
.u
.p_floatarray
= NULL
;
1568 case WRITE_BYTEBUFFER
:
1569 free( p_sys
->circular
.u
.bytebuffer
.p_data
);
1570 p_sys
->circular
.u
.bytebuffer
.p_data
= NULL
;
1574 p_sys
->b_audiotrack_exception
= false;
1575 p_sys
->b_error
= false;
1576 p_sys
->b_passthrough
= false;
1580 * Non blocking write function, run from AudioTrack_Thread.
1581 * Do a calculation between current position and audiotrack position and assure
1582 * that we won't wait in AudioTrack.write() method.
1585 AudioTrack_PlayByteArray( JNIEnv
*env
, audio_output_t
*p_aout
,
1586 size_t i_data_size
, size_t i_data_offset
,
1589 aout_sys_t
*p_sys
= p_aout
->sys
;
1591 uint64_t i_audiotrack_pos
;
1592 uint64_t i_samples_pending
;
1594 i_audiotrack_pos
= AudioTrack_getPlaybackHeadPosition( env
, p_aout
);
1596 assert( i_audiotrack_pos
<= p_sys
->i_samples_written
);
1597 if( i_audiotrack_pos
> p_sys
->i_samples_written
)
1599 msg_Err( p_aout
, "audiotrack position is ahead. Should NOT happen" );
1600 p_sys
->i_samples_written
= 0;
1601 p_sys
->b_error
= true;
1604 i_samples_pending
= p_sys
->i_samples_written
- i_audiotrack_pos
;
1606 /* check if audiotrack buffer is not full before writing on it. */
1609 msg_Warn( p_aout
, "Force write. It may block..." );
1610 i_samples_pending
= 0;
1611 } else if( i_samples_pending
>= p_sys
->i_max_audiotrack_samples
)
1614 i_samples
= __MIN( p_sys
->i_max_audiotrack_samples
- i_samples_pending
,
1615 BYTES_TO_FRAMES( i_data_size
) );
1617 i_data_size
= FRAMES_TO_BYTES( i_samples
);
1619 return JNI_AT_CALL_INT( write
, p_sys
->circular
.u
.p_bytearray
,
1620 i_data_offset
, i_data_size
);
1624 * Non blocking write function for Android M and after, run from
1625 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1629 AudioTrack_PlayByteArrayV23( JNIEnv
*env
, audio_output_t
*p_aout
,
1630 size_t i_data_size
, size_t i_data_offset
)
1632 aout_sys_t
*p_sys
= p_aout
->sys
;
1634 return JNI_AT_CALL_INT( writeV23
, p_sys
->circular
.u
.p_bytearray
,
1635 i_data_offset
, i_data_size
,
1636 jfields
.AudioTrack
.WRITE_NON_BLOCKING
);
1640 * Non blocking play function for Lollipop and after, run from
1641 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1645 AudioTrack_PlayByteBuffer( JNIEnv
*env
, audio_output_t
*p_aout
,
1646 size_t i_data_size
, size_t i_data_offset
)
1648 aout_sys_t
*p_sys
= p_aout
->sys
;
1650 /* The same DirectByteBuffer will be used until the data_offset reaches 0.
1651 * The internal position of this buffer is moved by the writeBufferV21
1653 if( i_data_offset
== 0 )
1655 /* No need to get a global ref, this object will be only used from the
1657 if( p_sys
->circular
.u
.bytebuffer
.p_obj
)
1658 (*env
)->DeleteLocalRef( env
, p_sys
->circular
.u
.bytebuffer
.p_obj
);
1660 p_sys
->circular
.u
.bytebuffer
.p_obj
= (*env
)->NewDirectByteBuffer( env
,
1661 p_sys
->circular
.u
.bytebuffer
.p_data
,
1662 p_sys
->circular
.i_size
);
1663 if( !p_sys
->circular
.u
.bytebuffer
.p_obj
)
1665 if( (*env
)->ExceptionCheck( env
) )
1666 (*env
)->ExceptionClear( env
);
1667 return jfields
.AudioTrack
.ERROR
;
1671 return JNI_AT_CALL_INT( writeBufferV21
, p_sys
->circular
.u
.bytebuffer
.p_obj
,
1673 jfields
.AudioTrack
.WRITE_NON_BLOCKING
);
1677 * Non blocking short write function for Android M and after, run from
1678 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1682 AudioTrack_PlayShortArrayV23( JNIEnv
*env
, audio_output_t
*p_aout
,
1683 size_t i_data_size
, size_t i_data_offset
)
1685 aout_sys_t
*p_sys
= p_aout
->sys
;
1688 i_ret
= JNI_AT_CALL_INT( writeShortV23
, p_sys
->circular
.u
.p_shortarray
,
1689 i_data_offset
/ 2, i_data_size
/ 2,
1690 jfields
.AudioTrack
.WRITE_NON_BLOCKING
);
1698 * Non blocking play float function for Lollipop and after, run from
1699 * AudioTrack_Thread. It calls a new write method with WRITE_NON_BLOCKING
1703 AudioTrack_PlayFloatArray( JNIEnv
*env
, audio_output_t
*p_aout
,
1704 size_t i_data_size
, size_t i_data_offset
)
1706 aout_sys_t
*p_sys
= p_aout
->sys
;
1709 i_ret
= JNI_AT_CALL_INT( writeFloat
, p_sys
->circular
.u
.p_floatarray
,
1710 i_data_offset
/ 4, i_data_size
/ 4,
1711 jfields
.AudioTrack
.WRITE_NON_BLOCKING
);
1719 AudioTrack_Play( JNIEnv
*env
, audio_output_t
*p_aout
, size_t i_data_size
,
1720 size_t i_data_offset
, bool b_force
)
1722 aout_sys_t
*p_sys
= p_aout
->sys
;
1725 switch( p_sys
->i_write_type
)
1727 case WRITE_BYTEARRAYV23
:
1728 i_ret
= AudioTrack_PlayByteArrayV23( env
, p_aout
, i_data_size
,
1731 case WRITE_BYTEBUFFER
:
1732 i_ret
= AudioTrack_PlayByteBuffer( env
, p_aout
, i_data_size
,
1735 case WRITE_SHORTARRAYV23
:
1736 i_ret
= AudioTrack_PlayShortArrayV23( env
, p_aout
, i_data_size
,
1739 case WRITE_BYTEARRAY
:
1740 i_ret
= AudioTrack_PlayByteArray( env
, p_aout
, i_data_size
,
1741 i_data_offset
, b_force
);
1743 case WRITE_FLOATARRAY
:
1744 i_ret
= AudioTrack_PlayFloatArray( env
, p_aout
, i_data_size
,
1748 vlc_assert_unreachable();
1752 if( jfields
.AudioManager
.has_ERROR_DEAD_OBJECT
1753 && i_ret
== jfields
.AudioManager
.ERROR_DEAD_OBJECT
)
1755 msg_Warn( p_aout
, "ERROR_DEAD_OBJECT: "
1756 "try recreating AudioTrack" );
1757 if( ( i_ret
= AudioTrack_Recreate( env
, p_aout
) ) == 0 )
1759 AudioTrack_Reset( env
, p_aout
);
1760 JNI_AT_CALL_VOID( play
);
1761 CHECK_AT_EXCEPTION( "play" );
1766 if( i_ret
== jfields
.AudioTrack
.ERROR_INVALID_OPERATION
)
1767 str
= "ERROR_INVALID_OPERATION";
1768 else if( i_ret
== jfields
.AudioTrack
.ERROR_BAD_VALUE
)
1769 str
= "ERROR_BAD_VALUE";
1772 msg_Err( p_aout
, "Write failed: %s", str
);
1773 p_sys
->b_error
= true;
1776 p_sys
->i_samples_written
+= BYTES_TO_FRAMES( i_ret
);
1781 * This thread will play the data coming from the circular buffer.
1784 AudioTrack_Thread( void *p_data
)
1786 audio_output_t
*p_aout
= p_data
;
1787 aout_sys_t
*p_sys
= p_aout
->sys
;
1788 JNIEnv
*env
= GET_ENV();
1789 vlc_tick_t i_play_deadline
= 0;
1790 vlc_tick_t i_last_time_blocked
= 0;
1799 size_t i_data_offset
;
1802 vlc_mutex_lock( &p_sys
->lock
);
1804 /* Wait for free space in Audiotrack internal buffer */
1805 if( i_play_deadline
!= 0 && vlc_tick_now() < i_play_deadline
)
1807 /* Don't wake up the thread when there is new data since we are
1808 * waiting for more space */
1809 p_sys
->b_thread_waiting
= true;
1810 while( p_sys
->b_thread_running
&& i_ret
== 0 )
1811 i_ret
= vlc_cond_timedwait( &p_sys
->thread_cond
,
1814 i_play_deadline
= 0;
1815 p_sys
->b_thread_waiting
= false;
1818 /* Wait for not paused state */
1819 while( p_sys
->b_thread_running
&& p_sys
->b_thread_paused
)
1821 i_last_time_blocked
= 0;
1822 vlc_cond_wait( &p_sys
->thread_cond
, &p_sys
->lock
);
1825 /* Wait for more data in the circular buffer */
1826 while( p_sys
->b_thread_running
1827 && p_sys
->circular
.i_read
>= p_sys
->circular
.i_write
)
1828 vlc_cond_wait( &p_sys
->thread_cond
, &p_sys
->lock
);
1830 if( !p_sys
->b_thread_running
|| p_sys
->b_error
)
1832 vlc_mutex_unlock( &p_sys
->lock
);
1836 /* HACK: AudioFlinger can drop frames without notifying us and there is
1837 * no way to know it. If it happens, i_audiotrack_pos won't move and
1838 * the current code will be stuck because it'll assume that audiotrack
1839 * internal buffer is full when it's not. It may happen only after
1840 * Android 4.4.2 if we send frames too quickly. To fix this issue,
1841 * force the writing of the buffer after a certain delay. */
1842 if( i_last_time_blocked
!= 0 )
1843 b_forced
= vlc_tick_now() - i_last_time_blocked
>
1844 FRAMES_TO_US( p_sys
->i_max_audiotrack_samples
) * 2;
1848 i_data_offset
= p_sys
->circular
.i_read
% p_sys
->circular
.i_size
;
1849 i_data_size
= __MIN( p_sys
->circular
.i_size
- i_data_offset
,
1850 p_sys
->circular
.i_write
- p_sys
->circular
.i_read
);
1852 i_ret
= AudioTrack_Play( env
, p_aout
, i_data_size
, i_data_offset
,
1856 if( p_sys
->i_write_type
== WRITE_BYTEARRAY
)
1859 i_last_time_blocked
= 0;
1860 else if( i_last_time_blocked
== 0 )
1861 i_last_time_blocked
= vlc_tick_now();
1865 i_play_deadline
= vlc_tick_now() + __MAX( 10000, FRAMES_TO_US(
1866 p_sys
->i_max_audiotrack_samples
/ 5 ) );
1868 p_sys
->circular
.i_read
+= i_ret
;
1871 vlc_cond_signal( &p_sys
->aout_cond
);
1872 vlc_mutex_unlock( &p_sys
->lock
);
1875 if( p_sys
->circular
.u
.bytebuffer
.p_obj
)
1877 (*env
)->DeleteLocalRef( env
, p_sys
->circular
.u
.bytebuffer
.p_obj
);
1878 p_sys
->circular
.u
.bytebuffer
.p_obj
= NULL
;
1885 ConvertFromIEC61937( audio_output_t
*p_aout
, block_t
*p_buffer
)
1887 /* This function is only used for Android API 23 when AudioTrack is
1888 * configured with ENCODING_ AC3/E_AC3/DTS. In that case, only the codec
1889 * data is needed (without the IEC61937 encapsulation). This function
1890 * recovers the codec data from an EC61937 frame. It is the opposite of the
1891 * code found in converter/tospdif.c. We could also request VLC core to
1892 * send us the codec data directly, but in that case, we wouldn't benefit
1893 * from the eac3 block merger of tospdif.c. */
1895 VLC_UNUSED( p_aout
);
1896 uint8_t i_length_mul
;
1898 if( p_buffer
->i_buffer
< 6 )
1901 switch( GetWBE( &p_buffer
->p_buffer
[4] ) & 0xFF )
1903 case 0x01: /* IEC61937_AC3 */
1906 case 0x15: /* IEC61937_EAC3 */
1909 case 0x0B: /* IEC61937_DTS1 */
1910 case 0x0C: /* IEC61937_DTS2 */
1911 case 0x0D: /* IEC61937_DTS3 */
1914 case 0x11: /* IEC61937_DTSHD */
1918 vlc_assert_unreachable();
1920 uint16_t i_length
= GetWBE( &p_buffer
->p_buffer
[6] );
1924 i_length
/= i_length_mul
;
1925 if( i_length
> p_buffer
->i_buffer
- 8 )
1928 p_buffer
->p_buffer
+= 8; /* SPDIF_HEADER_SIZE */
1929 p_buffer
->i_buffer
= i_length
;
1935 Play( audio_output_t
*p_aout
, block_t
*p_buffer
, vlc_tick_t i_date
)
1938 size_t i_buffer_offset
= 0;
1939 aout_sys_t
*p_sys
= p_aout
->sys
;
1941 if( p_sys
->b_passthrough
&& p_sys
->fmt
.i_format
== VLC_CODEC_SPDIFB
1942 && ConvertFromIEC61937( p_aout
, p_buffer
) != 0 )
1944 block_Release(p_buffer
);
1948 vlc_mutex_lock( &p_sys
->lock
);
1950 if( p_sys
->b_error
|| !( env
= GET_ENV() ) )
1953 if( p_sys
->i_chans_to_reorder
)
1954 aout_ChannelReorder( p_buffer
->p_buffer
, p_buffer
->i_buffer
,
1955 p_sys
->i_chans_to_reorder
, p_sys
->p_chan_table
,
1956 p_sys
->fmt
.i_format
);
1958 while( i_buffer_offset
< p_buffer
->i_buffer
&& !p_sys
->b_error
)
1960 size_t i_circular_free
;
1961 size_t i_data_offset
;
1964 /* Wait for enough room in circular buffer */
1965 while( !p_sys
->b_error
&& ( i_circular_free
= p_sys
->circular
.i_size
-
1966 ( p_sys
->circular
.i_write
- p_sys
->circular
.i_read
) ) == 0 )
1967 vlc_cond_wait( &p_sys
->aout_cond
, &p_sys
->lock
);
1968 if( p_sys
->b_error
)
1971 i_data_offset
= p_sys
->circular
.i_write
% p_sys
->circular
.i_size
;
1972 i_data_size
= __MIN( p_buffer
->i_buffer
- i_buffer_offset
,
1973 p_sys
->circular
.i_size
- i_data_offset
);
1974 i_data_size
= __MIN( i_data_size
, i_circular_free
);
1976 switch( p_sys
->i_write_type
)
1978 case WRITE_BYTEARRAY
:
1979 case WRITE_BYTEARRAYV23
:
1980 (*env
)->SetByteArrayRegion( env
, p_sys
->circular
.u
.p_bytearray
,
1981 i_data_offset
, i_data_size
,
1982 (jbyte
*)p_buffer
->p_buffer
1985 case WRITE_SHORTARRAYV23
:
1986 i_data_offset
&= ~1;
1988 (*env
)->SetShortArrayRegion( env
, p_sys
->circular
.u
.p_shortarray
,
1989 i_data_offset
/ 2, i_data_size
/ 2,
1990 (jshort
*)p_buffer
->p_buffer
1991 + i_buffer_offset
/ 2);
1993 case WRITE_FLOATARRAY
:
1994 i_data_offset
&= ~3;
1996 (*env
)->SetFloatArrayRegion( env
, p_sys
->circular
.u
.p_floatarray
,
1997 i_data_offset
/ 4, i_data_size
/ 4,
1998 (jfloat
*)p_buffer
->p_buffer
1999 + i_buffer_offset
/ 4);
2002 case WRITE_BYTEBUFFER
:
2003 memcpy( p_sys
->circular
.u
.bytebuffer
.p_data
+ i_data_offset
,
2004 p_buffer
->p_buffer
+ i_buffer_offset
, i_data_size
);
2008 i_buffer_offset
+= i_data_size
;
2009 p_sys
->circular
.i_write
+= i_data_size
;
2011 if( !p_sys
->b_thread_waiting
)
2012 vlc_cond_signal( &p_sys
->thread_cond
);
2016 vlc_mutex_unlock( &p_sys
->lock
);
2017 block_Release( p_buffer
);
2022 Pause( audio_output_t
*p_aout
, bool b_pause
, vlc_tick_t i_date
)
2024 aout_sys_t
*p_sys
= p_aout
->sys
;
2026 VLC_UNUSED( i_date
);
2028 vlc_mutex_lock( &p_sys
->lock
);
2030 if( p_sys
->b_error
|| !( env
= GET_ENV() ) )
2035 p_sys
->b_thread_paused
= true;
2036 JNI_AT_CALL_VOID( pause
);
2037 CHECK_AT_EXCEPTION( "pause" );
2040 p_sys
->b_thread_paused
= false;
2041 AudioTrack_ResetPositions( env
, p_aout
);
2042 JNI_AT_CALL_VOID( play
);
2043 CHECK_AT_EXCEPTION( "play" );
2047 vlc_mutex_unlock( &p_sys
->lock
);
2051 Flush( audio_output_t
*p_aout
)
2053 aout_sys_t
*p_sys
= p_aout
->sys
;
2056 vlc_mutex_lock( &p_sys
->lock
);
2058 if( p_sys
->b_error
|| !( env
= GET_ENV() ) )
2062 * stop(): Stops playing the audio data. When used on an instance created
2063 * in MODE_STREAM mode, audio will stop playing after the last buffer that
2064 * was written has been played. For an immediate stop, use pause(),
2065 * followed by flush() to discard audio data that hasn't been played back
2068 * flush(): Flushes the audio data currently queued for playback. Any data
2069 * that has not been played back will be discarded. No-op if not stopped
2070 * or paused, or if the track's creation mode is not MODE_STREAM.
2072 JNI_AT_CALL_VOID( pause
);
2073 if( CHECK_AT_EXCEPTION( "pause" ) )
2075 JNI_AT_CALL_VOID( flush
);
2076 p_sys
->circular
.i_read
= p_sys
->circular
.i_write
= 0;
2078 /* HACK: Before Android 4.4, the head position is not reset to zero and is
2079 * still moving after a flush or a stop. This prevents to get a precise
2080 * head position and there is no way to know when it stabilizes. Therefore
2081 * recreate an AudioTrack object in that case. The AudioTimestamp class was
2082 * added in API Level 19, so if this class is not found, the Android
2083 * Version is 4.3 or before */
2084 if( !jfields
.AudioTimestamp
.clazz
&& p_sys
->i_samples_written
> 0 )
2086 if( AudioTrack_Recreate( env
, p_aout
) != 0 )
2088 p_sys
->b_error
= true;
2092 AudioTrack_Reset( env
, p_aout
);
2093 JNI_AT_CALL_VOID( play
);
2094 CHECK_AT_EXCEPTION( "play" );
2097 vlc_mutex_unlock( &p_sys
->lock
);
2101 VolumeSet( audio_output_t
*p_aout
, float volume
)
2103 aout_sys_t
*p_sys
= p_aout
->sys
;
2109 p_sys
->volume
= 1.f
;
2113 p_sys
->volume
= volume
;
2115 if( !p_sys
->b_error
&& p_sys
->p_audiotrack
!= NULL
&& ( env
= GET_ENV() ) )
2117 if( jfields
.AudioTrack
.setVolume
)
2119 JNI_AT_CALL_INT( setVolume
, volume
);
2120 CHECK_AT_EXCEPTION( "setVolume" );
2123 JNI_AT_CALL_INT( setStereoVolume
, volume
, volume
);
2124 CHECK_AT_EXCEPTION( "setStereoVolume" );
2127 aout_VolumeReport(p_aout
, volume
);
2128 aout_GainRequest(p_aout
, gain
* gain
* gain
);
2133 MuteSet( audio_output_t
*p_aout
, bool mute
)
2135 aout_sys_t
*p_sys
= p_aout
->sys
;
2139 if( !p_sys
->b_error
&& p_sys
->p_audiotrack
!= NULL
&& ( env
= GET_ENV() ) )
2141 if( jfields
.AudioTrack
.setVolume
)
2143 JNI_AT_CALL_INT( setVolume
, mute
? 0.0f
: p_sys
->volume
);
2144 CHECK_AT_EXCEPTION( "setVolume" );
2147 JNI_AT_CALL_INT( setStereoVolume
, mute
? 0.0f
: p_sys
->volume
, mute
? 0.0f
: p_sys
->volume
);
2148 CHECK_AT_EXCEPTION( "setStereoVolume" );
2151 aout_MuteReport(p_aout
, mute
);
2155 static int DeviceSelect(audio_output_t
*p_aout
, const char *p_id
)
2157 aout_sys_t
*p_sys
= p_aout
->sys
;
2158 enum at_dev at_dev
= AT_DEV_DEFAULT
;
2162 for( unsigned int i
= 0; at_devs
[i
].id
; ++i
)
2164 if( strncmp( p_id
, at_devs
[i
].id
, strlen( at_devs
[i
].id
) ) == 0 )
2166 at_dev
= at_devs
[i
].at_dev
;
2172 long long i_encoding_flags
= 0;
2173 if( at_dev
== AT_DEV_ENCODED
)
2175 const size_t i_prefix_size
= strlen( "encoded:" );
2176 if( strncmp( p_id
, "encoded:", i_prefix_size
) == 0 )
2177 i_encoding_flags
= atoll( p_id
+ i_prefix_size
);
2180 if( at_dev
!= p_sys
->at_dev
|| i_encoding_flags
!= p_sys
->i_encoding_flags
)
2182 p_sys
->at_dev
= at_dev
;
2183 p_sys
->i_encoding_flags
= i_encoding_flags
;
2184 aout_RestartRequest( p_aout
, AOUT_RESTART_OUTPUT
);
2185 msg_Dbg( p_aout
, "selected device: %s", p_id
);
2187 if( at_dev
== AT_DEV_ENCODED
)
2189 static const vlc_fourcc_t enc_fourccs
[] = {
2190 VLC_CODEC_DTS
, VLC_CODEC_DTSHD
, VLC_CODEC_A52
, VLC_CODEC_EAC3
,
2194 i
< sizeof( enc_fourccs
) / sizeof( enc_fourccs
[0] ); ++i
)
2196 if( AudioTrack_HasEncoding( p_aout
, enc_fourccs
[i
] ) )
2197 msg_Dbg( p_aout
, "device has %4.4s passthrough support",
2198 (const char *)&enc_fourccs
[i
] );
2202 aout_DeviceReport( p_aout
, p_id
);
2207 Open( vlc_object_t
*obj
)
2209 audio_output_t
*p_aout
= (audio_output_t
*) obj
;
2211 JNIEnv
*env
= GET_ENV();
2213 if( !env
|| !InitJNIFields( p_aout
, env
) )
2214 return VLC_EGENERIC
;
2216 p_sys
= calloc( 1, sizeof (aout_sys_t
) );
2218 if( unlikely( p_sys
== NULL
) )
2221 p_sys
->at_dev
= AT_DEV_DEFAULT
;
2222 vlc_mutex_init(&p_sys
->lock
);
2223 vlc_cond_init(&p_sys
->aout_cond
);
2224 vlc_cond_init(&p_sys
->thread_cond
);
2226 p_aout
->sys
= p_sys
;
2227 p_aout
->start
= Start
;
2228 p_aout
->stop
= Stop
;
2229 p_aout
->play
= Play
;
2230 p_aout
->pause
= Pause
;
2231 p_aout
->flush
= Flush
;
2232 p_aout
->time_get
= TimeGet
;
2233 p_aout
->device_select
= DeviceSelect
;
2235 for( unsigned int i
= 0; at_devs
[i
].id
; ++i
)
2236 aout_HotplugReport(p_aout
, at_devs
[i
].id
, at_devs
[i
].name
);
2238 p_aout
->volume_set
= VolumeSet
;
2239 p_aout
->mute_set
= MuteSet
;
2240 p_sys
->volume
= 1.0f
;
2241 p_sys
->mute
= false;
2247 Close( vlc_object_t
*obj
)
2249 audio_output_t
*p_aout
= (audio_output_t
*) obj
;
2250 aout_sys_t
*p_sys
= p_aout
->sys
;