2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "AESinkAUDIOTRACK.h"
22 #include "Utils/AEUtil.h"
23 #include "Utils/AERingBuffer.h"
24 #include "android/activity/XBMCApp.h"
25 #include "settings/Settings.h"
26 #if defined(HAS_LIBAMCODEC)
27 #include "utils/AMLUtils.h"
29 #include "utils/log.h"
33 #if defined(__ARM_NEON__)
35 #include "utils/CPUInfo.h"
36 #include "android/jni/JNIThreading.h"
38 // LGPLv2 from PulseAudio
39 // float values from AE are pre-clamped so we do not need to clamp again here
40 static void pa_sconv_s16le_from_f32ne_neon(unsigned n, const float32_t *a, int16_t *b)
44 const float32x4_t half4 = vdupq_n_f32(0.5f);
45 const float32x4_t scale4 = vdupq_n_f32(32767.0f);
46 const uint32x4_t mask4 = vdupq_n_u32(0x80000000);
48 for (i = 0; i < (n & ~3); i += 4)
50 const float32x4_t v4 = vmulq_f32(vld1q_f32(&a[i]), scale4);
51 const float32x4_t w4 = vreinterpretq_f32_u32(
52 vorrq_u32(vandq_u32(vreinterpretq_u32_f32(v4), mask4), vreinterpretq_u32_f32(half4)));
53 vst1_s16(&b[i], vmovn_s32(vcvtq_s32_f32(vaddq_f32(v4, w4))));
57 b[i] = (int16_t) lrintf(a[i] * 0x7FFF);
61 static jint GetStaticIntField(JNIEnv *jenv, std::string class_name, std::string field_name)
63 class_name.insert(0, "android/media/");
64 jclass cls = jenv->FindClass(class_name.c_str());
65 jfieldID field = jenv->GetStaticFieldID(cls, field_name.c_str(), "I");
66 jint int_field = jenv->GetStaticIntField(cls, field);
67 jenv->DeleteLocalRef(cls);
71 CAEDeviceInfo CAESinkAUDIOTRACK::m_info;
72 ////////////////////////////////////////////////////////////////////////////////////////////
73 CAESinkAUDIOTRACK::CAESinkAUDIOTRACK()
74 : CThread("AudioTrack")
78 m_volume_changed = false;
81 m_sinkbuffer_sec = 0.0;
82 m_sinkbuffer_sec_per_byte = 0.0;
84 m_audiotrackbuffer_sec = 0.0;
85 m_audiotrack_empty_sec = 0.0;
86 m_audiotrack_empty_sec_tweaks = 0.0;
87 #if defined(HAS_LIBAMCODEC)
89 m_audiotrack_empty_sec_tweaks = 0.250;
94 CAESinkAUDIOTRACK::~CAESinkAUDIOTRACK()
98 bool CAESinkAUDIOTRACK::Initialize(AEAudioFormat &format, std::string &device)
102 if (AE_IS_RAW(m_format.m_dataFormat))
103 m_passthrough = true;
105 m_passthrough = false;
107 #if defined(HAS_LIBAMCODEC)
108 if (CSettings::Get().GetBool("videoplayer.useamcodec"))
109 aml_set_audio_passthrough(m_passthrough);
113 // default to 44100, all android devices support it.
114 // then check if we can support the requested rate.
115 unsigned int sampleRate = 44100;
116 for (size_t i = 0; i < m_info.m_sampleRates.size(); i++)
118 if (m_format.m_sampleRate == m_info.m_sampleRates[i])
120 sampleRate = m_format.m_sampleRate;
124 m_format.m_sampleRate = sampleRate;
126 // default to AE_FMT_S16LE,
127 // then check if we can support the requested format.
128 AEDataFormat dataFormat = AE_FMT_S16LE;
129 for (size_t i = 0; i < m_info.m_dataFormats.size(); i++)
131 if (m_format.m_dataFormat == m_info.m_dataFormats[i])
133 dataFormat = m_format.m_dataFormat;
137 m_format.m_dataFormat = dataFormat;
139 m_format.m_channelLayout = m_info.m_channels;
140 m_format.m_frameSize = m_format.m_channelLayout.Count() * (CAEUtil::DataFormatToBits(m_format.m_dataFormat) >> 3);
143 m_volume_changed = false;
144 // launch the process thread and wait for the
145 // AutoTrack jni object to get created and setup.
149 if(!m_inited.WaitMSec(100))
151 while(!m_inited.WaitMSec(1))
155 // m_min_frames is volatile and has been setup by Process()
156 m_format.m_frames = m_min_frames;
157 m_format.m_frameSamples = m_format.m_frames * m_format.m_channelLayout.Count();
163 void CAESinkAUDIOTRACK::Deinitialize()
165 // force m_bStop and set m_wake, if might be sleeping.
169 delete m_sinkbuffer, m_sinkbuffer = NULL;
171 _aligned_free(m_alignedS16), m_alignedS16 = NULL;
174 bool CAESinkAUDIOTRACK::IsCompatible(const AEAudioFormat &format, const std::string &device)
176 return ((m_format.m_sampleRate == format.m_sampleRate) &&
177 (m_format.m_dataFormat == format.m_dataFormat) &&
178 (m_format.m_channelLayout == format.m_channelLayout));
181 double CAESinkAUDIOTRACK::GetDelay()
183 // this includes any latency due to AudioTrack buffer,
184 // AudioMixer (if any) and audio hardware driver.
186 double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize();
187 sinkbuffer_seconds_to_empty += m_audiotrack_empty_sec;
188 if (sinkbuffer_seconds_to_empty > 0.0)
189 sinkbuffer_seconds_to_empty += m_audiotrack_empty_sec_tweaks;
190 return sinkbuffer_seconds_to_empty;
193 double CAESinkAUDIOTRACK::GetCacheTime()
195 // returns the time in seconds that it will take
196 // to underrun the buffer if no sample is added.
198 double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize();
199 sinkbuffer_seconds_to_empty += m_audiotrack_empty_sec;
200 if (sinkbuffer_seconds_to_empty > 0.0)
201 sinkbuffer_seconds_to_empty += m_audiotrack_empty_sec_tweaks;
202 return sinkbuffer_seconds_to_empty;
205 double CAESinkAUDIOTRACK::GetCacheTotal()
207 // total amount that the audio sink can buffer in units of seconds
209 return m_sinkbuffer_sec + m_audiotrackbuffer_sec;
212 unsigned int CAESinkAUDIOTRACK::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
214 // write as many frames of audio as we can fit into our internal buffer.
216 // our internal sink buffer is always AE_FMT_S16
217 unsigned int write_frames = m_sinkbuffer->GetWriteSize() / m_sink_frameSize;
218 if (write_frames > frames)
219 write_frames = frames;
221 if (hasAudio && write_frames)
223 switch(m_format.m_dataFormat)
226 m_sinkbuffer->Write(data, write_frames * m_sink_frameSize);
229 #if defined(__ARM_NEON__)
232 m_alignedS16 = (int16_t*)_aligned_malloc(m_format.m_frames * m_sink_frameSize, 16);
233 // neon convert AE_FMT_S16LE to AE_FMT_FLOAT
234 pa_sconv_s16le_from_f32ne_neon(write_frames * m_format.m_channelLayout.Count(), (const float32_t *)data, m_alignedS16);
235 m_sinkbuffer->Write((unsigned char*)m_alignedS16, write_frames * m_sink_frameSize);
243 // AddPackets runs under a non-idled AE thread we must block or sleep.
244 // Trying to calc the optimal sleep is tricky so just a minimal sleep.
248 return hasAudio ? write_frames:frames;
251 void CAESinkAUDIOTRACK::Drain()
253 CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Drain");
254 CSingleLock lock(m_drain_lock);
259 bool CAESinkAUDIOTRACK::HasVolume()
264 void CAESinkAUDIOTRACK::SetVolume(float scale)
266 // Android uses fixed steps, reverse scale back to percent
267 float gain = CAEUtil::ScaleToGain(scale);
268 m_volume = CAEUtil::GainToPercent(gain);
271 CSingleLock lock(m_volume_lock);
272 m_volume_changed = true;
276 void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
278 m_info.m_channels.Reset();
279 m_info.m_dataFormats.clear();
280 m_info.m_sampleRates.clear();
282 m_info.m_deviceType = AE_DEVTYPE_PCM;
283 m_info.m_deviceName = "AudioTrack";
284 m_info.m_displayName = "android";
285 m_info.m_displayNameExtra = "audiotrack";
286 m_info.m_channels += AE_CH_FL;
287 m_info.m_channels += AE_CH_FR;
288 m_info.m_sampleRates.push_back(44100);
289 m_info.m_sampleRates.push_back(48000);
290 m_info.m_dataFormats.push_back(AE_FMT_S16LE);
291 #if 0 && defined(__ARM_NEON__)
292 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
293 m_info.m_dataFormats.push_back(AE_FMT_FLOAT);
296 list.push_back(m_info);
299 void CAESinkAUDIOTRACK::Process()
301 CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Process");
303 JNIEnv *jenv = xbmc_jnienv();
305 jclass jcAudioTrack = jenv->FindClass("android/media/AudioTrack");
307 jmethodID jmInit = jenv->GetMethodID(jcAudioTrack, "<init>", "(IIIIII)V");
308 jmethodID jmPlay = jenv->GetMethodID(jcAudioTrack, "play", "()V");
309 jmethodID jmStop = jenv->GetMethodID(jcAudioTrack, "stop", "()V");
310 jmethodID jmFlush = jenv->GetMethodID(jcAudioTrack, "flush", "()V");
311 jmethodID jmRelease = jenv->GetMethodID(jcAudioTrack, "release", "()V");
312 jmethodID jmWrite = jenv->GetMethodID(jcAudioTrack, "write", "([BII)I");
313 jmethodID jmPlayState = jenv->GetMethodID(jcAudioTrack, "getPlayState", "()I");
314 jmethodID jmPlayHeadPosition = jenv->GetMethodID(jcAudioTrack, "getPlaybackHeadPosition", "()I");
315 jmethodID jmGetMinBufferSize = jenv->GetStaticMethodID(jcAudioTrack, "getMinBufferSize", "(III)I");
317 jint audioFormat = GetStaticIntField(jenv, "AudioFormat", "ENCODING_PCM_16BIT");
318 jint channelConfig = GetStaticIntField(jenv, "AudioFormat", "CHANNEL_OUT_STEREO");
320 jint min_buffer_size = jenv->CallStaticIntMethod(jcAudioTrack, jmGetMinBufferSize,
321 m_format.m_sampleRate, channelConfig, audioFormat);
323 m_sink_frameSize = m_format.m_channelLayout.Count() * CAEUtil::DataFormatToBits(AE_FMT_S16LE) >> 3;
324 m_min_frames = min_buffer_size / m_sink_frameSize;
326 m_audiotrackbuffer_sec = (double)m_min_frames / (double)m_format.m_sampleRate;
327 m_audiotrack_empty_sec = 0.0;
329 // setup a 1/4 second internal sink lockless ring buffer
330 m_sinkbuffer = new AERingBuffer(m_sink_frameSize * m_format.m_sampleRate / 4);
331 m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_sink_frameSize * m_format.m_sampleRate);
332 m_sinkbuffer_sec = (double)m_sinkbuffer_sec_per_byte * m_sinkbuffer->GetMaxSize();
334 jobject joAudioTrack = jenv->NewObject(jcAudioTrack, jmInit,
335 GetStaticIntField(jenv, "AudioManager", "STREAM_MUSIC"),
336 m_format.m_sampleRate,
340 GetStaticIntField(jenv, "AudioTrack", "MODE_STREAM"));
342 // Set the initial volume
346 CXBMCApp::SetSystemVolume(jenv, volume);
348 // The AudioTrack object has been created and waiting to play,
350 // yield to give other threads a chance to do some work.
353 // cache the playing int value.
354 jint playing = GetStaticIntField(jenv, "AudioTrack", "PLAYSTATE_PLAYING");
356 // create a java byte buffer for writing pcm data to AudioTrack.
357 jarray jbuffer = jenv->NewByteArray(min_buffer_size);
359 int64_t frames_written = 0;
360 int64_t frame_position = 0;
364 if (m_volume_changed && !m_passthrough)
366 // check of volume changes and make them,
367 // do it here to keep jni calls local to this thread.
368 CXBMCApp::SetSystemVolume(jenv, m_volume);
369 CSingleLock lock(m_volume_lock);
370 m_volume_changed = false;
374 unsigned char byte_drain[1024];
375 unsigned int byte_drain_size = m_sinkbuffer->GetReadSize();
376 if (byte_drain_size > 1024)
377 byte_drain_size = 1024;
378 while (byte_drain_size)
380 m_sinkbuffer->Read(byte_drain, byte_drain_size);
381 byte_drain_size = m_sinkbuffer->GetReadSize();
382 if (byte_drain_size > 1024)
383 byte_drain_size = 1024;
385 jenv->CallVoidMethod(joAudioTrack, jmStop);
386 jenv->CallVoidMethod(joAudioTrack, jmFlush);
387 CSingleLock lock(m_drain_lock);
391 unsigned int read_bytes = m_sinkbuffer->GetReadSize();
392 if (read_bytes > (unsigned int)min_buffer_size)
393 read_bytes = min_buffer_size;
397 // android will auto pause the playstate when it senses idle,
398 // check it and set playing if it does this. Do this before
399 // writing into its buffer.
400 if (jenv->CallIntMethod(joAudioTrack, jmPlayState) != playing)
401 jenv->CallVoidMethod( joAudioTrack, jmPlay);
403 // Write a buffer of audio data to Java AudioTrack.
404 // Warning, no other JNI function can be called after
405 // GetPrimitiveArrayCritical until ReleasePrimitiveArrayCritical.
406 void *pBuffer = jenv->GetPrimitiveArrayCritical(jbuffer, NULL);
409 m_sinkbuffer->Read((unsigned char*)pBuffer, read_bytes);
410 jenv->ReleasePrimitiveArrayCritical(jbuffer, pBuffer, 0);
411 // jmWrite is blocking and returns when the data has been transferred
412 // from the Java layer and queued for playback.
413 jenv->CallIntMethod(joAudioTrack, jmWrite, jbuffer, 0, read_bytes);
416 // calc the number of seconds until audiotrack buffer is empty.
417 frame_position = jenv->CallIntMethod(joAudioTrack, jmPlayHeadPosition);
418 if (frame_position == 0)
420 frames_written += read_bytes / m_sink_frameSize;
421 m_audiotrack_empty_sec = (double)(frames_written - frame_position) / m_format.m_sampleRate;
422 // some times, we can get frame_position
423 // ahead of frames_written, not a clue why. clamp it.
424 if (m_audiotrack_empty_sec < 0.0f)
425 m_audiotrack_empty_sec = 0.0f;
427 if (m_sinkbuffer->GetReadSize() == 0)
429 // the sink buffer is empty, stop playback.
430 // Audiotrack will playout any written contents.
431 jenv->CallVoidMethod(joAudioTrack, jmStop);
432 // sleep this audio thread, we will get woken when we have audio data.
433 m_wake.WaitMSec(250);
437 jenv->CallVoidMethod(joAudioTrack, jmStop);
438 jenv->CallVoidMethod(joAudioTrack, jmFlush);
439 jenv->CallVoidMethod(joAudioTrack, jmRelease);
441 // might toss an exception on jmRelease so catch it.
442 jthrowable exception = jenv->ExceptionOccurred();
445 jenv->ExceptionDescribe();
446 jenv->ExceptionClear();
449 jenv->DeleteLocalRef(jbuffer);
450 jenv->DeleteLocalRef(joAudioTrack);
451 jenv->DeleteLocalRef(jcAudioTrack);