From 507b2860cfe0bb4a712064f1c503caa9a7325886 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 31 Jul 2013 16:12:13 -0700 Subject: Consistent style for comparisons of raw pointers to NULL Change-Id: Iec102a5ccb2fe69229887b5432cd1fb66f26f0cf --- media/libmedia/IAudioFlinger.cpp | 50 +++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 16 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index be818c6..22ad453 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -132,7 +132,7 @@ public: lStatus = reply.readInt32(); track = interface_cast(reply.readStrongBinder()); } - if (status) { + if (status != NULL) { *status = lStatus; } return track; @@ -180,7 +180,7 @@ public: lStatus = reply.readInt32(); record = interface_cast(reply.readStrongBinder()); } - if (status) { + if (status != NULL) { *status = lStatus; } return record; @@ -397,15 +397,25 @@ public: audio_io_handle_t output = (audio_io_handle_t) reply.readInt32(); ALOGV("openOutput() returned output, %d", output); devices = (audio_devices_t)reply.readInt32(); - if (pDevices != NULL) *pDevices = devices; + if (pDevices != NULL) { + *pDevices = devices; + } samplingRate = reply.readInt32(); - if (pSamplingRate != NULL) *pSamplingRate = samplingRate; + if (pSamplingRate != NULL) { + *pSamplingRate = samplingRate; + } format = (audio_format_t) reply.readInt32(); - if (pFormat != NULL) *pFormat = format; + if (pFormat != NULL) { + *pFormat = format; + } channelMask = (audio_channel_mask_t)reply.readInt32(); - if (pChannelMask != NULL) *pChannelMask = channelMask; + if (pChannelMask != NULL) { + *pChannelMask = channelMask; + } latency = reply.readInt32(); - if (pLatencyMs != NULL) *pLatencyMs = latency; + if (pLatencyMs != NULL) { + *pLatencyMs = latency; + } return output; } @@ -469,13 +479,21 @@ public: remote()->transact(OPEN_INPUT, data, &reply); audio_io_handle_t input = (audio_io_handle_t) reply.readInt32(); devices = (audio_devices_t)reply.readInt32(); - if (pDevices != NULL) *pDevices = devices; + if (pDevices != NULL) { + *pDevices = devices; + } samplingRate = reply.readInt32(); - if (pSamplingRate != NULL) *pSamplingRate = samplingRate; + if (pSamplingRate != NULL) { + *pSamplingRate = samplingRate; + } format = (audio_format_t) reply.readInt32(); - if (pFormat != NULL) *pFormat = format; + if (pFormat != NULL) { + *pFormat = format; + } channelMask = (audio_channel_mask_t)reply.readInt32(); - if (pChannelMask != NULL) *pChannelMask = channelMask; + if (pChannelMask != NULL) { + *pChannelMask = channelMask; + } return input; } @@ -517,11 +535,11 @@ public: status_t status = reply.readInt32(); if (status == NO_ERROR) { uint32_t tmp = reply.readInt32(); - if (halFrames) { + if (halFrames != NULL) { *halFrames = tmp; } tmp = reply.readInt32(); - if (dspFrames) { + if (dspFrames != NULL) { *dspFrames = tmp; } } @@ -639,7 +657,7 @@ public: if (pDesc == NULL) { return effect; - if (status) { + if (status != NULL) { *status = BAD_VALUE; } } @@ -657,7 +675,7 @@ public: } else { lStatus = reply.readInt32(); int tmp = reply.readInt32(); - if (id) { + if (id != NULL) { *id = tmp; } tmp = reply.readInt32(); @@ -667,7 +685,7 @@ public: effect = interface_cast(reply.readStrongBinder()); reply.read(pDesc, sizeof(effect_descriptor_t)); } - if (status) { + if (status != NULL) { *status = lStatus; } -- cgit v1.1 From 397edb3377e5775f4df60afb8bf6d4711e5adc0e Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 30 Aug 2013 15:10:13 -0700 Subject: Fix AudioTrack pause followed by stop Now the stop is not a nop. Bug: 10993355 Change-Id: Idfbfd6d14897574578b80648a16e0fc73765cb6c --- media/libmedia/AudioTrack.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 754a4e3..8302d4a 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -436,8 +436,7 @@ status_t AudioTrack::start() void AudioTrack::stop() { AutoMutex lock(mLock); - // FIXME pause then stop should not be a nop - if (mState != STATE_ACTIVE) { + if (mState != STATE_ACTIVE && mState != STATE_PAUSED) { return; } -- cgit v1.1 From 96f04886d1c1bfbc422e2be033ea66be83e42441 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 20 Sep 2013 09:28:56 -0700 Subject: Simplify AudioTrack stream end and fix race Bug: 10994052 Change-Id: Ib2e38e7a600bcffef8cbc68c1722e40fbbc7ea67 --- media/libmedia/AudioTrack.cpp | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 754a4e3..5e805c9 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1416,6 +1416,7 @@ nsecs_t AudioTrack::processAudioBuffer(const sp& thread) } size_t misalignment = mProxy->getMisalignment(); uint32_t sequence = mSequence; + sp proxy = mProxy; // These fields don't need to be cached, because they are assigned only by set(): // mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFrameSizeAF, mFlags @@ -1424,35 +1425,32 @@ nsecs_t AudioTrack::processAudioBuffer(const sp& thread) mLock.unlock(); if (waitStreamEnd) { - AutoMutex lock(mLock); - - sp proxy = mProxy; - sp iMem = mCblkMemory; - struct timespec timeout; timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC; timeout.tv_nsec = 0; - mLock.unlock(); - status_t status = mProxy->waitStreamEndDone(&timeout); - mLock.lock(); + status_t status = proxy->waitStreamEndDone(&timeout); switch (status) { case NO_ERROR: case DEAD_OBJECT: case TIMED_OUT: - mLock.unlock(); mCbf(EVENT_STREAM_END, mUserData, NULL); - mLock.lock(); - if (mState == STATE_STOPPING) { - mState = STATE_STOPPED; - if (status != DEAD_OBJECT) { - return NS_INACTIVE; + { + AutoMutex lock(mLock); + // The previously assigned value of waitStreamEnd is no longer valid, + // since the mutex has been unlocked and either the callback handler + // or another thread could have re-started the AudioTrack during that time. + waitStreamEnd = mState == STATE_STOPPING; + if (waitStreamEnd) { + mState = STATE_STOPPED; } } - return 0; - default: - return 0; + if (waitStreamEnd && status != DEAD_OBJECT) { + return NS_INACTIVE; + } + break; } + return 0; } // perform callbacks while unlocked -- cgit v1.1 From 462fd2fa9eef642b0574aa7409de0bde3fec8d43 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Mon, 14 Jan 2013 14:12:05 -0800 Subject: Assign blame for playback wakelocks. Set a work source for the playback wakelock, so that playback is counted against the requesting app instead of the media server. Change-Id: I7329f88a288a95a582a78005a1c3d16a5a611e31 --- media/libmedia/AudioTrack.cpp | 20 +++++++++++++++----- media/libmedia/IAudioFlinger.cpp | 5 ++++- 2 files changed, 19 insertions(+), 6 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a50ed1f..df58909 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -101,7 +101,8 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -109,7 +110,8 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, - 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo); + 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, + offloadInfo, uid); } AudioTrack::AudioTrack( @@ -124,7 +126,8 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -132,7 +135,7 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, - sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo); + sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, uid); } AudioTrack::~AudioTrack() @@ -169,7 +172,8 @@ status_t AudioTrack::set( bool threadCanCallJava, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) { switch (transferType) { case TRANSFER_DEFAULT: @@ -313,6 +317,11 @@ status_t AudioTrack::set( mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; mSessionId = sessionId; + if (uid == -1 || (IPCThreadState::self()->getCallingPid() != getpid())) { + mClientUid = IPCThreadState::self()->getCallingUid(); + } else { + mClientUid = uid; + } mAuxEffectId = 0; mFlags = flags; mCbf = cbf; @@ -961,6 +970,7 @@ status_t AudioTrack::createTrack_l( tid, &mSessionId, mName, + mClientUid, &status); if (track == 0) { diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index f9f6779..9df10f0 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -96,6 +96,7 @@ public: pid_t tid, int *sessionId, String8& name, + int clientUid, status_t *status) { Parcel data, reply; @@ -121,6 +122,7 @@ public: lSessionId = *sessionId; } data.writeInt32(lSessionId); + data.writeInt32(clientUid); status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply); if (lStatus != NO_ERROR) { ALOGE("createTrack error: %s", strerror(-lStatus)); @@ -780,6 +782,7 @@ status_t BnAudioFlinger::onTransact( audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); + int clientUid = data.readInt32(); String8 name; status_t status; sp track; @@ -791,7 +794,7 @@ status_t BnAudioFlinger::onTransact( track = createTrack( (audio_stream_type_t) streamType, sampleRate, format, channelMask, frameCount, &flags, buffer, output, tid, - &sessionId, name, &status); + &sessionId, name, clientUid, &status); } reply->writeInt32(flags); reply->writeInt32(sessionId); -- cgit v1.1 From 79c5786cf5a5d572cfcf21c3d40613d86bb4093a Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 30 Oct 2013 09:47:17 -0700 Subject: Clean up channel mask handling Use type audio_channel_mask_t instead of uint32_t. Use function audio_channel_out_mask_from_count() to convert from channel count to channel mask instead of hard-coded assumption. Rename 'channels' to 'channelMask' to avoid confusion with channel count. Change-Id: I21a85e668458b773d108f95c2381eef9c4816251 --- media/libmedia/SoundPool.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 22e9fad..b420c95 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -600,16 +600,15 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV // wrong audio audio buffer size (mAudioBufferSize) unsigned long toggle = mToggle ^ 1; void *userData = (void *)((unsigned long)this | toggle); - uint32_t channels = (numChannels == 2) ? - AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO; + audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels); // do not create a new audio track if current track is compatible with sample parameters #ifdef USE_SHARED_MEM_BUFFER newTrack = new AudioTrack(streamType, sampleRate, sample->format(), - channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData); + channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData); #else newTrack = new AudioTrack(streamType, sampleRate, sample->format(), - channels, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, + channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, bufferFrames); #endif oldTrack = mAudioTrack; -- cgit v1.1 From 8ba90326d683b035d99e24db669093e4602a7149 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 30 Oct 2013 11:29:27 -0700 Subject: Remove default channel mask for AudioTrack It doesn't make sense to have a default channel mask, since the caller needs to know what format it will use when supplying data, and there is currently no API to return the channel mask of an AudioTrack. audio_is_output_channel() does not allow 0, so it will catch any stragglers (I'm not aware of any). Also move channel mask validation earlier. Change-Id: Ia018ded8711455581a2a935f37432b049422d492 --- media/libmedia/AudioTrack.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index df58909..8319dcd 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -250,9 +250,6 @@ status_t AudioTrack::set( if (format == AUDIO_FORMAT_DEFAULT) { format = AUDIO_FORMAT_PCM_16_BIT; } - if (channelMask == 0) { - channelMask = AUDIO_CHANNEL_OUT_STEREO; - } // validate parameters if (!audio_is_valid_format(format)) { @@ -260,6 +257,11 @@ status_t AudioTrack::set( return BAD_VALUE; } + if (!audio_is_output_channel(channelMask)) { + ALOGE("Invalid channel mask %#x", channelMask); + return BAD_VALUE; + } + // AudioFlinger does not currently support 8-bit data in shared memory if (format == AUDIO_FORMAT_PCM_8_BIT && sharedBuffer != 0) { ALOGE("8-bit data in shared memory is not supported"); @@ -282,10 +284,6 @@ status_t AudioTrack::set( flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); } - if (!audio_is_output_channel(channelMask)) { - ALOGE("Invalid channel mask %#x", channelMask); - return BAD_VALUE; - } mChannelMask = channelMask; uint32_t channelCount = popcount(channelMask); mChannelCount = channelCount; -- cgit v1.1 From a1d401d9f4a6ba477f0e07204e0b9481befcc928 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 20 Nov 2013 14:37:13 -0800 Subject: Check all server-provided sp If the sp from server is non-0, make sure it also has a non-NULL pointer(). If it is NULL, treat it as if the sp<> was 0. Change-Id: I6d0bd786587eb73fac38af787c11eba541880685 --- media/libmedia/IAudioRecord.cpp | 3 +++ media/libmedia/IAudioTrack.cpp | 6 ++++++ media/libmedia/IEffect.cpp | 3 +++ 3 files changed, 12 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp index 4a7de65..9866d70 100644 --- a/media/libmedia/IAudioRecord.cpp +++ b/media/libmedia/IAudioRecord.cpp @@ -50,6 +50,9 @@ public: status_t status = remote()->transact(GET_CBLK, data, &reply); if (status == NO_ERROR) { cblk = interface_cast(reply.readStrongBinder()); + if (cblk != 0 && cblk->pointer() == NULL) { + cblk.clear(); + } } return cblk; } diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index 3cd9cfd..ffc21fc 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -60,6 +60,9 @@ public: status_t status = remote()->transact(GET_CBLK, data, &reply); if (status == NO_ERROR) { cblk = interface_cast(reply.readStrongBinder()); + if (cblk != 0 && cblk->pointer() == NULL) { + cblk.clear(); + } } return cblk; } @@ -122,6 +125,9 @@ public: status = reply.readInt32(); if (status == NO_ERROR) { *buffer = interface_cast(reply.readStrongBinder()); + if (*buffer != 0 && (*buffer)->pointer() == NULL) { + (*buffer).clear(); + } } } return status; diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp index a303a8f..b94012a 100644 --- a/media/libmedia/IEffect.cpp +++ b/media/libmedia/IEffect.cpp @@ -117,6 +117,9 @@ public: status_t status = remote()->transact(GET_CBLK, data, &reply); if (status == NO_ERROR) { cblk = interface_cast(reply.readStrongBinder()); + if (cblk != 0 && cblk->pointer() == NULL) { + cblk.clear(); + } } return cblk; } -- cgit v1.1 From 6f59db12a64f4496866952a251122ccb77a36c6b Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 26 Jul 2013 17:16:50 -0700 Subject: update offloaded audio track sampling rate AudioPlayer must read the sampling rate from offloaded audio sinks whenever a new time position is computed as the decoder can update the sampling rate on the fly. Change-Id: I997e5248cfd4017aeceb4e11689324ded2a5bc88 --- media/libmedia/AudioTrack.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 8319dcd..4b93714 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -600,6 +600,19 @@ uint32_t AudioTrack::getSampleRate() const } AutoMutex lock(mLock); + + // sample rate can be updated during playback by the offloaded decoder so we need to + // query the HAL and update if needed. +// FIXME use Proxy return channel to update the rate from server and avoid polling here + if (isOffloaded()) { + if (mOutput != 0) { + uint32_t sampleRate = 0; + status_t status = AudioSystem::getSamplingRate(mOutput, mStreamType, &sampleRate); + if (status == NO_ERROR) { + mSampleRate = sampleRate; + } + } + } return mSampleRate; } -- cgit v1.1 From b31788687736666e58b852e744a93f772d3f7148 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 27 Nov 2013 14:29:13 -0800 Subject: AudioTrack: fix position callback after restore When restoring an AudioTrack, the next position callback point should not be modified and set ahead of current buffer head. Otherwise, as frames are dropped, the new position is never reached and an application relying on position callbacks to reload the buffer would be stalled. Bug: 11868603. Change-Id: I93b2a311642a0c89944b78bcc0482d4ceed98ae4 --- media/libmedia/AudioTrack.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 4b93714..0f4d490 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1685,7 +1685,6 @@ status_t AudioTrack::restoreTrack_l(const char *from) // take the frames that will be lost by track recreation into account in saved position size_t position = mProxy->getPosition() + mProxy->getFramesFilled(); - mNewPosition = position + mUpdatePeriod; size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0; result = createTrack_l(mStreamType, mSampleRate, -- cgit v1.1 From 544ad2be674423238c47650d2c8588ba7dfc9ed2 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Wed, 13 Nov 2013 14:18:21 -0800 Subject: Better character set encoding detection Id3 tags are supposed to be ISO-8859-1 or unicode, but often aren't. To better detect the real encoding we now use ICU to detect possible encodings for a given byte sequence, then apply additional heuristics to determine the most likely one. b/5564857 Change-Id: I53bc83b006433da5c2f2ccfcd770ddb3a26b64d0 --- media/libmedia/Android.mk | 5 +- media/libmedia/CharacterEncodingDetector.cpp | 364 ++++ media/libmedia/CharacterEncodingDetector.h | 61 + media/libmedia/CharacterEncodingDetectorTables.h | 2092 ++++++++++++++++++++++ media/libmedia/MediaScannerClient.cpp | 202 +-- media/libmedia/autodetect.cpp | 885 --------- media/libmedia/autodetect.h | 37 - 7 files changed, 2541 insertions(+), 1105 deletions(-) create mode 100644 media/libmedia/CharacterEncodingDetector.cpp create mode 100644 media/libmedia/CharacterEncodingDetector.h create mode 100644 media/libmedia/CharacterEncodingDetectorTables.h delete mode 100644 media/libmedia/autodetect.cpp delete mode 100644 media/libmedia/autodetect.h (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 56e7787..8aa54dc 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -44,7 +44,7 @@ LOCAL_SRC_FILES:= \ IAudioPolicyService.cpp \ MediaScanner.cpp \ MediaScannerClient.cpp \ - autodetect.cpp \ + CharacterEncodingDetector.cpp \ IMediaDeathNotifier.cpp \ MediaProfiles.cpp \ IEffect.cpp \ @@ -65,7 +65,7 @@ LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiat # Consider a separate a library for SingleStateQueueInstantiations. LOCAL_SHARED_LIBRARIES := \ - libui liblog libcutils libutils libbinder libsonivox libicuuc libexpat \ + libui liblog libcutils libutils libbinder libsonivox libicuuc libicui18n libexpat \ libcamera_client libstagefright_foundation \ libgui libdl libaudioutils @@ -77,6 +77,7 @@ LOCAL_C_INCLUDES := \ $(call include-path-for, graphics corecg) \ $(TOP)/frameworks/native/include/media/openmax \ external/icu4c/common \ + external/icu4c/i18n \ $(call include-path-for, audio-effects) \ $(call include-path-for, audio-utils) diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp new file mode 100644 index 0000000..eb091ac --- /dev/null +++ b/media/libmedia/CharacterEncodingDetector.cpp @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "CharacterEncodingDector" +#include + +#include "CharacterEncodingDetector.h" +#include "CharacterEncodingDetectorTables.h" + +#include "utils/Vector.h" +#include "StringArray.h" + +#include "unicode/ucnv.h" +#include "unicode/ucsdet.h" +#include "unicode/ustring.h" + +namespace android { + +CharacterEncodingDetector::CharacterEncodingDetector() { + + UErrorCode status = U_ZERO_ERROR; + mUtf8Conv = ucnv_open("UTF-8", &status); + if (U_FAILURE(status)) { + ALOGE("could not create UConverter for UTF-8"); + mUtf8Conv = NULL; + } +} + +CharacterEncodingDetector::~CharacterEncodingDetector() { + ucnv_close(mUtf8Conv); +} + +void CharacterEncodingDetector::addTag(const char *name, const char *value) { + mNames.push_back(name); + mValues.push_back(value); +} + +size_t CharacterEncodingDetector::size() { + return mNames.size(); +} + +status_t CharacterEncodingDetector::getTag(int index, const char **name, const char**value) { + if (index >= mNames.size()) { + return BAD_VALUE; + } + + *name = mNames.getEntry(index); + *value = mValues.getEntry(index); + return OK; +} + +static bool isPrintableAscii(const char *value, size_t len) { + for (size_t i = 0; i < len; i++) { + if ((value[i] & 0x80) || value[i] < 0x20 || value[i] == 0x7f) { + return false; + } + } + return true; +} + +void CharacterEncodingDetector::detectAndConvert() { + + int size = mNames.size(); + ALOGV("%d tags before conversion", size); + for (int i = 0; i < size; i++) { + ALOGV("%s: %s", mNames.getEntry(i), mValues.getEntry(i)); + } + + if (size && mUtf8Conv) { + + UErrorCode status = U_ZERO_ERROR; + UCharsetDetector *csd = ucsdet_open(&status); + const UCharsetMatch *ucm; + + // try combined detection of artist/album/title etc. + char buf[1024]; + buf[0] = 0; + int idx; + for (int i = 0; i < size; i++) { + const char *name = mNames.getEntry(i); + const char *value = mValues.getEntry(i); + if (!isPrintableAscii(value, strlen(value)) && ( + !strcmp(name, "artist") || + !strcmp(name, "albumartist") || + !strcmp(name, "composer") || + !strcmp(name, "genre") || + !strcmp(name, "album") || + !strcmp(name, "title"))) { + strlcat(buf, value, sizeof(buf)); + // separate tags by space so ICU's ngram detector can do its job + strlcat(buf, " ", sizeof(buf)); + } + } + ucsdet_setText(csd, buf, strlen(buf), &status); + + int32_t matches; + const UCharsetMatch** ucma = ucsdet_detectAll(csd, &matches, &status); + const char *combinedenc = "???"; + + const UCharsetMatch* bestCombinedMatch = getPreferred(buf, strlen(buf), ucma, matches); + + if (bestCombinedMatch != NULL) { + combinedenc = ucsdet_getName(bestCombinedMatch, &status); + } + + for (int i = 0; i < size; i++) { + const char *name = mNames.getEntry(i); + uint8_t* src = (uint8_t *)mValues.getEntry(i); + int len = strlen((char *)src); + uint8_t* dest = src; + + ALOGV("@@@ checking %s", name); + const char *s = mValues.getEntry(i); + int32_t inputLength = strlen(s); + const char *enc; + + if (!strcmp(name, "artist") || + !strcmp(name, "albumartist") || + !strcmp(name, "composer") || + !strcmp(name, "genre") || + !strcmp(name, "album") || + !strcmp(name, "title")) { + // use encoding determined from the combination of artist/album/title etc. + enc = combinedenc; + } else { + ucsdet_setText(csd, s, inputLength, &status); + ucm = ucsdet_detect(csd, &status); + if (!ucm) { + mValues.setEntry(i, "???"); + continue; + } + enc = ucsdet_getName(ucm, &status); + ALOGV("@@@@ recognized charset: %s for %s confidence %d", + enc, mNames.getEntry(i), ucsdet_getConfidence(ucm, &status)); + } + + if (strcmp(enc,"UTF-8") != 0) { + // only convert if the source encoding isn't already UTF-8 + ALOGV("@@@ using converter %s for %s", enc, mNames.getEntry(i)); + UConverter *conv = ucnv_open(enc, &status); + if (U_FAILURE(status)) { + ALOGE("could not create UConverter for %s", enc); + continue; + } + + // convert from native encoding to UTF-8 + const char* source = mValues.getEntry(i); + int targetLength = len * 3 + 1; + char* buffer = new char[targetLength]; + // don't normally check for NULL, but in this case targetLength may be large + if (!buffer) + break; + char* target = buffer; + + ucnv_convertEx(mUtf8Conv, conv, &target, target + targetLength, + &source, source + strlen(source), + NULL, NULL, NULL, NULL, TRUE, TRUE, &status); + + if (U_FAILURE(status)) { + ALOGE("ucnv_convertEx failed: %d", status); + mValues.setEntry(i, "???"); + } else { + // zero terminate + *target = 0; + mValues.setEntry(i, buffer); + } + + delete[] buffer; + + ucnv_close(conv); + } + } + + for (int i = size - 1; i >= 0; --i) { + if (strlen(mValues.getEntry(i)) == 0) { + ALOGV("erasing %s because entry is empty", mNames.getEntry(i)); + mNames.erase(i); + mValues.erase(i); + } + } + + ucsdet_close(csd); + } +} + +/* + * When ICU detects multiple encoding matches, apply additional heuristics to determine + * which one is the best match, since ICU can't always be trusted to make the right choice. + * + * What this method does is: + * - decode the input using each of the matches found + * - recalculate the starting confidence level for multibyte encodings using a different + * algorithm and larger frequent character lists than ICU + * - devalue encoding where the conversion contains unlikely characters (symbols, reserved, etc) + * - pick the highest match + */ +const UCharsetMatch *CharacterEncodingDetector::getPreferred( + const char *input, size_t len, const UCharsetMatch** ucma, size_t nummatches) { + + Vector matches; + UErrorCode status = U_ZERO_ERROR; + + ALOGV("%d matches", nummatches); + for (size_t i = 0; i < nummatches; i++) { + const char *encname = ucsdet_getName(ucma[i], &status); + int confidence = ucsdet_getConfidence(ucma[i], &status); + ALOGV("%d: %s %d", i, encname, confidence); + matches.push_back(ucma[i]); + } + + size_t num = matches.size(); + if (num == 0) { + return NULL; + } + if (num == 1) { + return matches[0]; + } + + ALOGV("considering %d matches", num); + + // keep track of how many "special" characters result when converting the input using each + // encoding + Vector newconfidence; + for (size_t i = 0; i < num; i++) { + const uint16_t *freqdata = NULL; + float freqcoverage = 0; + status = U_ZERO_ERROR; + const char *encname = ucsdet_getName(matches[i], &status); + int confidence = ucsdet_getConfidence(matches[i], &status); + if (!strcmp("GB18030", encname)) { + freqdata = frequent_zhCN; + freqcoverage = frequent_zhCN_coverage; + } else if (!strcmp("Big5", encname)) { + freqdata = frequent_zhTW; + freqcoverage = frequent_zhTW_coverage; + } else if (!strcmp("EUC-KR", encname)) { + freqdata = frequent_ko; + freqcoverage = frequent_ko_coverage; + } else if (!strcmp("EUC-JP", encname)) { + freqdata = frequent_ja; + freqcoverage = frequent_ja_coverage; + } else if (!strcmp("Shift_JIS", encname)) { + freqdata = frequent_ja; + freqcoverage = frequent_ja_coverage; + } + + ALOGV("%d: %s %d", i, encname, confidence); + UConverter *conv = ucnv_open(encname, &status); + const char *source = input; + const char *sourceLimit = input + len; + status = U_ZERO_ERROR; + int demerit = 0; + int frequentchars = 0; + int totalchars = 0; + while (true) { + // demerit the current encoding for each "special" character found after conversion. + // The amount of demerit is somewhat arbitrarily chosen. + int inchar; + if (source != sourceLimit) { + inchar = (source[0] << 8) + source[1]; + } + UChar32 c = ucnv_getNextUChar(conv, &source, sourceLimit, &status); + if (!U_SUCCESS(status)) { + break; + } + if (c < 0x20 || (c >= 0x7f && c <= 0x009f)) { + ALOGV("control character %x", c); + demerit += 100; + } else if ((c >= 0xa0 && c <= 0xbe) // symbols, superscripts + || (c == 0xd7) || (c == 0xf7) // multiplication and division signs + || (c >= 0x2000 && c <= 0x209f)) { // punctuation, superscripts + ALOGV("unlikely character %x", c); + demerit += 10; + } else if (c >= 0xe000 && c <= 0xf8ff) { + ALOGV("private use character %x", c); + demerit += 30; + } else if (c >= 0x2190 && c <= 0x2bff) { + // this range comprises various symbol ranges that are unlikely to appear in + // music file metadata. + ALOGV("symbol %x", c); + demerit += 10; + } else if (c == 0xfffd) { + ALOGV("replacement character"); + demerit += 50; + } else if (c >= 0xfff0 && c <= 0xfffc) { + ALOGV("unicode special %x", c); + demerit += 50; + } else if (freqdata != NULL) { + totalchars++; + if (isFrequent(freqdata, c)) { + frequentchars++; + } + } + } + if (freqdata != NULL && totalchars != 0) { + int myconfidence = 10 + float((100 * frequentchars) / totalchars) / freqcoverage; + ALOGV("ICU confidence: %d, my confidence: %d (%d %d)", confidence, myconfidence, + totalchars, frequentchars); + if (myconfidence > 100) myconfidence = 100; + if (myconfidence < 0) myconfidence = 0; + confidence = myconfidence; + } + ALOGV("%d-%d=%d", confidence, demerit, confidence - demerit); + newconfidence.push_back(confidence - demerit); + ucnv_close(conv); + if (i == 0 && (confidence - demerit) == 100) { + // no need to check any further, we'll end up using this match anyway + break; + } + } + + // find match with highest confidence after adjusting for unlikely characters + int highest = newconfidence[0]; + size_t highestidx = 0; + num = newconfidence.size(); + for (size_t i = 1; i < num; i++) { + if (newconfidence[i] > highest) { + highest = newconfidence[i]; + highestidx = i; + } + } + status = U_ZERO_ERROR; + ALOGV("selecting '%s' w/ %d confidence", ucsdet_getName(matches[highestidx], &status), highest); + return matches[highestidx]; +} + + +bool CharacterEncodingDetector::isFrequent(const uint16_t *values, uint32_t c) { + + int start = 0; + int end = 511; // All the tables have 512 entries + int mid = (start+end)/2; + + while(start <= end) { + if(c == values[mid]) { + return true; + } else if (c > values[mid]) { + start = mid + 1; + } else { + end = mid - 1; + } + + mid = (start + end) / 2; + } + + return false; +} + + +} // namespace android diff --git a/media/libmedia/CharacterEncodingDetector.h b/media/libmedia/CharacterEncodingDetector.h new file mode 100644 index 0000000..3655a91 --- /dev/null +++ b/media/libmedia/CharacterEncodingDetector.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CHARACTER_ENCODING_DETECTOR_H +#define _CHARACTER_ENCODING_DETECTOR_H + +#include + +#include "StringArray.h" + +#include "unicode/ucnv.h" +#include "unicode/ucsdet.h" +#include "unicode/ustring.h" + +namespace android { + +class CharacterEncodingDetector { + + public: + CharacterEncodingDetector(); + ~CharacterEncodingDetector(); + + void addTag(const char *name, const char *value); + size_t size(); + + void detectAndConvert(); + status_t getTag(int index, const char **name, const char**value); + + private: + const UCharsetMatch *getPreferred( + const char *input, size_t len, const UCharsetMatch** ucma, size_t matches); + + bool isFrequent(const uint16_t *values, uint32_t c); + + // cached name and value strings, for native encoding support. + // TODO: replace these with byte blob arrays that don't require the data to be + // singlenullbyte-terminated + StringArray mNames; + StringArray mValues; + + UConverter* mUtf8Conv; +}; + + + +}; // namespace android + +#endif diff --git a/media/libmedia/CharacterEncodingDetectorTables.h b/media/libmedia/CharacterEncodingDetectorTables.h new file mode 100644 index 0000000..1fe1137 --- /dev/null +++ b/media/libmedia/CharacterEncodingDetectorTables.h @@ -0,0 +1,2092 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// The 512 most frequently occuring characters for the zhCN language in a sample of the Internet. +// Ordered by codepoint, comment shows character and ranking by frequency +const uint16_t frequent_zhCN[] = { + 0x4E00, // 一, #2 + 0x4E07, // 万, #306 + 0x4E09, // 三, #138 + 0x4E0A, // 上, #16 + 0x4E0B, // 下, #25 + 0x4E0D, // 不, #7 + 0x4E0E, // 与, #133 + 0x4E13, // 专, #151 + 0x4E16, // 世, #346 + 0x4E1A, // 业, #39 + 0x4E1C, // 东, #197 + 0x4E24, // 两, #376 + 0x4E2A, // 个, #23 + 0x4E2D, // 中, #4 + 0x4E3A, // 为, #31 + 0x4E3B, // 主, #95 + 0x4E3E, // 举, #418 + 0x4E48, // 么, #93 + 0x4E4B, // 之, #131 + 0x4E50, // 乐, #130 + 0x4E5F, // 也, #145 + 0x4E66, // 书, #283 + 0x4E70, // 买, #483 + 0x4E86, // 了, #13 + 0x4E8B, // 事, #168 + 0x4E8C, // 二, #218 + 0x4E8E, // 于, #64 + 0x4E94, // 五, #430 + 0x4E9A, // 亚, #468 + 0x4E9B, // 些, #366 + 0x4EA4, // 交, #243 + 0x4EA7, // 产, #86 + 0x4EAB, // 享, #345 + 0x4EAC, // 京, #206 + 0x4EBA, // 人, #3 + 0x4EC0, // 什, #287 + 0x4ECB, // 介, #478 + 0x4ECE, // 从, #381 + 0x4ED6, // 他, #129 + 0x4EE3, // 代, #241 + 0x4EE5, // 以, #51 + 0x4EEC, // 们, #83 + 0x4EF6, // 件, #141 + 0x4EF7, // 价, #140 + 0x4EFB, // 任, #383 + 0x4F01, // 企, #439 + 0x4F18, // 优, #374 + 0x4F1A, // 会, #29 + 0x4F20, // 传, #222 + 0x4F46, // 但, #451 + 0x4F4D, // 位, #208 + 0x4F53, // 体, #98 + 0x4F55, // 何, #339 + 0x4F5C, // 作, #44 + 0x4F60, // 你, #76 + 0x4F7F, // 使, #272 + 0x4F9B, // 供, #375 + 0x4FDD, // 保, #180 + 0x4FE1, // 信, #84 + 0x4FEE, // 修, #437 + 0x503C, // 值, #450 + 0x505A, // 做, #368 + 0x5065, // 健, #484 + 0x50CF, // 像, #487 + 0x513F, // 儿, #326 + 0x5143, // 元, #202 + 0x5148, // 先, #485 + 0x5149, // 光, #254 + 0x514B, // 克, #503 + 0x514D, // 免, #349 + 0x5165, // 入, #156 + 0x5168, // 全, #47 + 0x516C, // 公, #35 + 0x5171, // 共, #448 + 0x5173, // 关, #49 + 0x5176, // 其, #195 + 0x5177, // 具, #329 + 0x5185, // 内, #109 + 0x518C, // 册, #225 + 0x519B, // 军, #466 + 0x51FA, // 出, #53 + 0x51FB, // 击, #359 + 0x5206, // 分, #22 + 0x5217, // 列, #410 + 0x521B, // 创, #399 + 0x5229, // 利, #296 + 0x522B, // 别, #372 + 0x5230, // 到, #33 + 0x5236, // 制, #192 + 0x524D, // 前, #117 + 0x529B, // 力, #173 + 0x529E, // 办, #436 + 0x529F, // 功, #455 + 0x52A0, // 加, #97 + 0x52A1, // 务, #100 + 0x52A8, // 动, #46 + 0x52A9, // 助, #365 + 0x5305, // 包, #331 + 0x5316, // 化, #155 + 0x5317, // 北, #194 + 0x533A, // 区, #105 + 0x533B, // 医, #234 + 0x5341, // 十, #294 + 0x534E, // 华, #205 + 0x5355, // 单, #259 + 0x5357, // 南, #182 + 0x535A, // 博, #153 + 0x5361, // 卡, #332 + 0x539F, // 原, #271 + 0x53BB, // 去, #282 + 0x53C2, // 参, #500 + 0x53CA, // 及, #255 + 0x53CB, // 友, #186 + 0x53CD, // 反, #422 + 0x53D1, // 发, #15 + 0x53D7, // 受, #507 + 0x53D8, // 变, #395 + 0x53E3, // 口, #293 + 0x53EA, // 只, #340 + 0x53EF, // 可, #45 + 0x53F0, // 台, #267 + 0x53F7, // 号, #121 + 0x53F8, // 司, #150 + 0x5404, // 各, #491 + 0x5408, // 合, #115 + 0x540C, // 同, #189 + 0x540D, // 名, #127 + 0x540E, // 后, #75 + 0x5411, // 向, #459 + 0x5427, // 吧, #353 + 0x544A, // 告, #318 + 0x5458, // 员, #232 + 0x5468, // 周, #347 + 0x548C, // 和, #43 + 0x54C1, // 品, #36 + 0x5546, // 商, #148 + 0x5668, // 器, #228 + 0x56DB, // 四, #352 + 0x56DE, // 回, #38 + 0x56E0, // 因, #355 + 0x56E2, // 团, #412 + 0x56ED, // 园, #470 + 0x56FD, // 国, #12 + 0x56FE, // 图, #32 + 0x5728, // 在, #10 + 0x5730, // 地, #30 + 0x573A, // 场, #177 + 0x575B, // 坛, #364 + 0x578B, // 型, #274 + 0x57CE, // 城, #172 + 0x57FA, // 基, #315 + 0x58EB, // 士, #434 + 0x58F0, // 声, #397 + 0x5904, // 处, #416 + 0x5907, // 备, #270 + 0x590D, // 复, #122 + 0x5916, // 外, #190 + 0x591A, // 多, #40 + 0x5927, // 大, #8 + 0x5929, // 天, #52 + 0x592A, // 太, #456 + 0x5934, // 头, #258 + 0x5973, // 女, #65 + 0x597D, // 好, #62 + 0x5982, // 如, #135 + 0x5A31, // 娱, #452 + 0x5B50, // 子, #37 + 0x5B57, // 字, #285 + 0x5B66, // 学, #19 + 0x5B89, // 安, #144 + 0x5B8C, // 完, #469 + 0x5B9A, // 定, #179 + 0x5B9D, // 宝, #188 + 0x5B9E, // 实, #154 + 0x5BA2, // 客, #174 + 0x5BB6, // 家, #26 + 0x5BB9, // 容, #307 + 0x5BC6, // 密, #471 + 0x5BF9, // 对, #90 + 0x5BFC, // 导, #348 + 0x5C06, // 将, #265 + 0x5C0F, // 小, #28 + 0x5C11, // 少, #379 + 0x5C14, // 尔, #490 + 0x5C31, // 就, #101 + 0x5C55, // 展, #291 + 0x5C71, // 山, #239 + 0x5DDE, // 州, #227 + 0x5DE5, // 工, #73 + 0x5DF1, // 己, #480 + 0x5DF2, // 已, #310 + 0x5E02, // 市, #78 + 0x5E03, // 布, #350 + 0x5E08, // 师, #277 + 0x5E16, // 帖, #396 + 0x5E26, // 带, #449 + 0x5E2E, // 帮, #461 + 0x5E38, // 常, #319 + 0x5E73, // 平, #217 + 0x5E74, // 年, #20 + 0x5E76, // 并, #440 + 0x5E7F, // 广, #166 + 0x5E93, // 库, #446 + 0x5E94, // 应, #187 + 0x5E97, // 店, #320 + 0x5EA6, // 度, #114 + 0x5EB7, // 康, #499 + 0x5EFA, // 建, #211 + 0x5F00, // 开, #72 + 0x5F0F, // 式, #207 + 0x5F15, // 引, #495 + 0x5F20, // 张, #385 + 0x5F3A, // 强, #404 + 0x5F53, // 当, #233 + 0x5F55, // 录, #146 + 0x5F62, // 形, #494 + 0x5F69, // 彩, #356 + 0x5F71, // 影, #214 + 0x5F88, // 很, #300 + 0x5F97, // 得, #193 + 0x5FAE, // 微, #245 + 0x5FC3, // 心, #70 + 0x5FEB, // 快, #324 + 0x6001, // 态, #508 + 0x600E, // 怎, #370 + 0x6027, // 性, #99 + 0x603B, // 总, #398 + 0x606F, // 息, #176 + 0x60A8, // 您, #251 + 0x60C5, // 情, #87 + 0x60F3, // 想, #290 + 0x610F, // 意, #184 + 0x611F, // 感, #253 + 0x620F, // 戏, #237 + 0x6210, // 成, #71 + 0x6211, // 我, #11 + 0x6216, // 或, #321 + 0x6218, // 战, #369 + 0x6237, // 户, #215 + 0x623F, // 房, #236 + 0x6240, // 所, #147 + 0x624B, // 手, #55 + 0x624D, // 才, #407 + 0x6253, // 打, #281 + 0x6280, // 技, #203 + 0x6295, // 投, #408 + 0x62A4, // 护, #502 + 0x62A5, // 报, #113 + 0x62DB, // 招, #363 + 0x6301, // 持, #403 + 0x6307, // 指, #414 + 0x636E, // 据, #409 + 0x6392, // 排, #377 + 0x63A5, // 接, #266 + 0x63A8, // 推, #244 + 0x63D0, // 提, #181 + 0x641C, // 搜, #301 + 0x64AD, // 播, #401 + 0x652F, // 支, #400 + 0x6536, // 收, #158 + 0x653E, // 放, #317 + 0x653F, // 政, #380 + 0x6548, // 效, #496 + 0x6559, // 教, #170 + 0x6570, // 数, #136 + 0x6587, // 文, #21 + 0x6599, // 料, #295 + 0x65AF, // 斯, #473 + 0x65B0, // 新, #14 + 0x65B9, // 方, #68 + 0x65C5, // 旅, #457 + 0x65E0, // 无, #164 + 0x65E5, // 日, #50 + 0x65F6, // 时, #18 + 0x660E, // 明, #132 + 0x6613, // 易, #428 + 0x661F, // 星, #240 + 0x662F, // 是, #6 + 0x663E, // 显, #486 + 0x66F4, // 更, #103 + 0x6700, // 最, #61 + 0x6708, // 月, #80 + 0x6709, // 有, #5 + 0x670D, // 服, #94 + 0x671F, // 期, #139 + 0x672C, // 本, #56 + 0x672F, // 术, #216 + 0x673A, // 机, #27 + 0x6743, // 权, #250 + 0x6761, // 条, #309 + 0x6765, // 来, #42 + 0x677F, // 板, #505 + 0x6797, // 林, #475 + 0x679C, // 果, #212 + 0x67E5, // 查, #165 + 0x6807, // 标, #269 + 0x6821, // 校, #462 + 0x6837, // 样, #314 + 0x683C, // 格, #238 + 0x6848, // 案, #378 + 0x697C, // 楼, #342 + 0x6A21, // 模, #413 + 0x6B21, // 次, #263 + 0x6B22, // 欢, #443 + 0x6B3E, // 款, #358 + 0x6B63, // 正, #219 + 0x6B64, // 此, #362 + 0x6BD4, // 比, #298 + 0x6C11, // 民, #279 + 0x6C14, // 气, #303 + 0x6C34, // 水, #163 + 0x6C42, // 求, #373 + 0x6C5F, // 江, #336 + 0x6CA1, // 没, #229 + 0x6CBB, // 治, #425 + 0x6CD5, // 法, #85 + 0x6CE8, // 注, #119 + 0x6D3B, // 活, #231 + 0x6D41, // 流, #280 + 0x6D4B, // 测, #460 + 0x6D77, // 海, #124 + 0x6D88, // 消, #415 + 0x6DF1, // 深, #477 + 0x6E05, // 清, #311 + 0x6E38, // 游, #81 + 0x6E90, // 源, #325 + 0x706B, // 火, #498 + 0x70B9, // 点, #58 + 0x70ED, // 热, #183 + 0x7136, // 然, #308 + 0x7167, // 照, #431 + 0x7231, // 爱, #223 + 0x7247, // 片, #128 + 0x7248, // 版, #91 + 0x724C, // 牌, #429 + 0x7269, // 物, #169 + 0x7279, // 特, #224 + 0x738B, // 王, #351 + 0x73A9, // 玩, #476 + 0x73B0, // 现, #125 + 0x7403, // 球, #367 + 0x7406, // 理, #69 + 0x751F, // 生, #24 + 0x7528, // 用, #17 + 0x7531, // 由, #441 + 0x7535, // 电, #34 + 0x7537, // 男, #275 + 0x754C, // 界, #419 + 0x75C5, // 病, #371 + 0x767B, // 登, #204 + 0x767D, // 白, #338 + 0x767E, // 百, #157 + 0x7684, // 的, #1 + 0x76D8, // 盘, #493 + 0x76EE, // 目, #261 + 0x76F4, // 直, #391 + 0x76F8, // 相, #143 + 0x7701, // 省, #464 + 0x770B, // 看, #54 + 0x771F, // 真, #249 + 0x7740, // 着, #302 + 0x77E5, // 知, #142 + 0x7801, // 码, #257 + 0x7814, // 研, #387 + 0x793A, // 示, #334 + 0x793E, // 社, #343 + 0x795E, // 神, #330 + 0x798F, // 福, #509 + 0x79BB, // 离, #454 + 0x79CD, // 种, #278 + 0x79D1, // 科, #126 + 0x79EF, // 积, #390 + 0x7A0B, // 程, #209 + 0x7A76, // 究, #504 + 0x7A7A, // 空, #312 + 0x7ACB, // 立, #393 + 0x7AD9, // 站, #107 + 0x7AE0, // 章, #304 + 0x7B2C, // 第, #96 + 0x7B49, // 等, #210 + 0x7B54, // 答, #256 + 0x7B80, // 简, #474 + 0x7BA1, // 管, #221 + 0x7C7B, // 类, #246 + 0x7CBE, // 精, #226 + 0x7CFB, // 系, #89 + 0x7D22, // 索, #354 + 0x7EA2, // 红, #417 + 0x7EA7, // 级, #178 + 0x7EBF, // 线, #108 + 0x7EC4, // 组, #389 + 0x7EC6, // 细, #442 + 0x7ECF, // 经, #74 + 0x7ED3, // 结, #333 + 0x7ED9, // 给, #384 + 0x7EDC, // 络, #472 + 0x7EDF, // 统, #344 + 0x7F16, // 编, #424 + 0x7F51, // 网, #9 + 0x7F6E, // 置, #411 + 0x7F8E, // 美, #60 + 0x8001, // 老, #292 + 0x8003, // 考, #288 + 0x8005, // 者, #106 + 0x800C, // 而, #297 + 0x8054, // 联, #159 + 0x80B2, // 育, #327 + 0x80FD, // 能, #59 + 0x81EA, // 自, #77 + 0x8272, // 色, #198 + 0x8282, // 节, #361 + 0x82B1, // 花, #299 + 0x82F1, // 英, #316 + 0x8350, // 荐, #402 + 0x836F, // 药, #481 + 0x8425, // 营, #394 + 0x85CF, // 藏, #337 + 0x884C, // 行, #41 + 0x8868, // 表, #104 + 0x88AB, // 被, #289 + 0x88C5, // 装, #161 + 0x897F, // 西, #199 + 0x8981, // 要, #48 + 0x89C1, // 见, #360 + 0x89C2, // 观, #423 + 0x89C4, // 规, #453 + 0x89C6, // 视, #120 + 0x89E3, // 解, #264 + 0x8A00, // 言, #433 + 0x8BA1, // 计, #191 + 0x8BA4, // 认, #482 + 0x8BA9, // 让, #421 + 0x8BAE, // 议, #427 + 0x8BAF, // 讯, #388 + 0x8BB0, // 记, #273 + 0x8BBA, // 论, #66 + 0x8BBE, // 设, #162 + 0x8BC1, // 证, #201 + 0x8BC4, // 评, #111 + 0x8BC6, // 识, #463 + 0x8BD5, // 试, #323 + 0x8BDD, // 话, #247 + 0x8BE2, // 询, #432 + 0x8BE5, // 该, #447 + 0x8BE6, // 详, #497 + 0x8BED, // 语, #268 + 0x8BF4, // 说, #112 + 0x8BF7, // 请, #213 + 0x8BFB, // 读, #341 + 0x8C03, // 调, #438 + 0x8D22, // 财, #488 + 0x8D28, // 质, #386 + 0x8D2D, // 购, #260 + 0x8D34, // 贴, #510 + 0x8D39, // 费, #242 + 0x8D44, // 资, #116 + 0x8D77, // 起, #220 + 0x8D85, // 超, #406 + 0x8DEF, // 路, #235 + 0x8EAB, // 身, #262 + 0x8F66, // 车, #82 + 0x8F6C, // 转, #322 + 0x8F7D, // 载, #175 + 0x8FBE, // 达, #435 + 0x8FC7, // 过, #118 + 0x8FD0, // 运, #357 + 0x8FD1, // 近, #492 + 0x8FD8, // 还, #171 + 0x8FD9, // 这, #57 + 0x8FDB, // 进, #160 + 0x8FDE, // 连, #489 + 0x9009, // 选, #328 + 0x901A, // 通, #137 + 0x901F, // 速, #458 + 0x9020, // 造, #511 + 0x9053, // 道, #79 + 0x90A3, // 那, #305 + 0x90E8, // 部, #102 + 0x90FD, // 都, #167 + 0x914D, // 配, #479 + 0x9152, // 酒, #444 + 0x91CC, // 里, #196 + 0x91CD, // 重, #230 + 0x91CF, // 量, #248 + 0x91D1, // 金, #134 + 0x9500, // 销, #465 + 0x957F, // 长, #152 + 0x95E8, // 门, #185 + 0x95EE, // 问, #92 + 0x95F4, // 间, #88 + 0x95FB, // 闻, #313 + 0x9605, // 阅, #467 + 0x9633, // 阳, #420 + 0x9645, // 际, #501 + 0x9650, // 限, #286 + 0x9662, // 院, #276 + 0x96C6, // 集, #284 + 0x9700, // 需, #405 + 0x9762, // 面, #123 + 0x97F3, // 音, #335 + 0x9875, // 页, #63 + 0x9879, // 项, #506 + 0x9891, // 频, #200 + 0x9898, // 题, #110 + 0x98CE, // 风, #252 + 0x98DF, // 食, #445 + 0x9996, // 首, #149 + 0x9999, // 香, #512 + 0x9A6C, // 马, #392 + 0x9A8C, // 验, #382 + 0x9AD8, // 高, #67 + 0x9F99, // 龙, #426 +}; +// the percentage of the sample covered by the above characters +static const float frequent_zhCN_coverage=0.718950369339973; + +// The 512 most frequently occuring characters for the zhTW language in a sample of the Internet. +// Ordered by codepoint, comment shows character and ranking by frequency +const uint16_t frequent_zhTW[] = { + 0x4E00, // 一, #2 + 0x4E09, // 三, #131 + 0x4E0A, // 上, #12 + 0x4E0B, // 下, #37 + 0x4E0D, // 不, #6 + 0x4E16, // 世, #312 + 0x4E26, // 並, #434 + 0x4E2D, // 中, #9 + 0x4E3B, // 主, #97 + 0x4E4B, // 之, #55 + 0x4E5F, // 也, #95 + 0x4E86, // 了, #19 + 0x4E8B, // 事, #128 + 0x4E8C, // 二, #187 + 0x4E94, // 五, #339 + 0x4E9B, // 些, #435 + 0x4E9E, // 亞, #432 + 0x4EA4, // 交, #264 + 0x4EAB, // 享, #160 + 0x4EBA, // 人, #3 + 0x4EC0, // 什, #483 + 0x4ECA, // 今, #380 + 0x4ECB, // 介, #468 + 0x4ED6, // 他, #65 + 0x4EE3, // 代, #284 + 0x4EE5, // 以, #26 + 0x4EF6, // 件, #234 + 0x4EFB, // 任, #381 + 0x4EFD, // 份, #447 + 0x4F46, // 但, #281 + 0x4F4D, // 位, #202 + 0x4F4F, // 住, #471 + 0x4F55, // 何, #334 + 0x4F5C, // 作, #56 + 0x4F60, // 你, #64 + 0x4F7F, // 使, #236 + 0x4F86, // 來, #38 + 0x4F9B, // 供, #397 + 0x4FBF, // 便, #440 + 0x4FC2, // 係, #506 + 0x4FDD, // 保, #161 + 0x4FE1, // 信, #268 + 0x4FEE, // 修, #473 + 0x500B, // 個, #27 + 0x5011, // 們, #109 + 0x505A, // 做, #383 + 0x5065, // 健, #415 + 0x5099, // 備, #461 + 0x50B3, // 傳, #277 + 0x50CF, // 像, #403 + 0x50F9, // 價, #93 + 0x512A, // 優, #396 + 0x5143, // 元, #158 + 0x5148, // 先, #382 + 0x5149, // 光, #216 + 0x514D, // 免, #321 + 0x5152, // 兒, #374 + 0x5165, // 入, #58 + 0x5167, // 內, #106 + 0x5168, // 全, #67 + 0x5169, // 兩, #322 + 0x516C, // 公, #53 + 0x516D, // 六, #493 + 0x5171, // 共, #456 + 0x5176, // 其, #148 + 0x5177, // 具, #328 + 0x518A, // 冊, #360 + 0x518D, // 再, #311 + 0x51FA, // 出, #44 + 0x5206, // 分, #15 + 0x5217, // 列, #259 + 0x5225, // 別, #361 + 0x5229, // 利, #251 + 0x5230, // 到, #29 + 0x5247, // 則, #511 + 0x524D, // 前, #82 + 0x5275, // 創, #409 + 0x529B, // 力, #176 + 0x529F, // 功, #430 + 0x52A0, // 加, #87 + 0x52A9, // 助, #465 + 0x52D5, // 動, #48 + 0x52D9, // 務, #102 + 0x5305, // 包, #248 + 0x5316, // 化, #223 + 0x5317, // 北, #145 + 0x5340, // 區, #60 + 0x5341, // 十, #242 + 0x5357, // 南, #261 + 0x535A, // 博, #484 + 0x5361, // 卡, #327 + 0x5370, // 印, #498 + 0x5373, // 即, #351 + 0x539F, // 原, #237 + 0x53BB, // 去, #190 + 0x53C3, // 參, #444 + 0x53C8, // 又, #426 + 0x53CA, // 及, #136 + 0x53CB, // 友, #142 + 0x53D6, // 取, #422 + 0x53D7, // 受, #410 + 0x53E3, // 口, #357 + 0x53EA, // 只, #250 + 0x53EF, // 可, #35 + 0x53F0, // 台, #34 + 0x53F8, // 司, #226 + 0x5403, // 吃, #362 + 0x5404, // 各, #454 + 0x5408, // 合, #147 + 0x540C, // 同, #173 + 0x540D, // 名, #108 + 0x544A, // 告, #186 + 0x548C, // 和, #130 + 0x54C1, // 品, #23 + 0x54E1, // 員, #150 + 0x5546, // 商, #75 + 0x554F, // 問, #120 + 0x559C, // 喜, #502 + 0x55AE, // 單, #210 + 0x55CE, // 嗎, #443 + 0x5668, // 器, #305 + 0x56DB, // 四, #318 + 0x56DE, // 回, #59 + 0x56E0, // 因, #253 + 0x570B, // 國, #21 + 0x5712, // 園, #345 + 0x5716, // 圖, #73 + 0x5718, // 團, #338 + 0x5728, // 在, #11 + 0x5730, // 地, #50 + 0x578B, // 型, #270 + 0x57CE, // 城, #466 + 0x57FA, // 基, #349 + 0x5831, // 報, #127 + 0x5834, // 場, #165 + 0x58EB, // 士, #372 + 0x5916, // 外, #152 + 0x591A, // 多, #54 + 0x5927, // 大, #8 + 0x5929, // 天, #43 + 0x592A, // 太, #343 + 0x5947, // 奇, #325 + 0x5973, // 女, #85 + 0x5979, // 她, #420 + 0x597D, // 好, #22 + 0x5982, // 如, #144 + 0x5B50, // 子, #46 + 0x5B57, // 字, #275 + 0x5B78, // 學, #49 + 0x5B89, // 安, #239 + 0x5B8C, // 完, #320 + 0x5B9A, // 定, #159 + 0x5BA2, // 客, #188 + 0x5BB6, // 家, #31 + 0x5BB9, // 容, #244 + 0x5BE6, // 實, #198 + 0x5BF6, // 寶, #367 + 0x5C07, // 將, #232 + 0x5C08, // 專, #133 + 0x5C0B, // 尋, #352 + 0x5C0D, // 對, #126 + 0x5C0E, // 導, #418 + 0x5C0F, // 小, #20 + 0x5C11, // 少, #368 + 0x5C31, // 就, #63 + 0x5C55, // 展, #341 + 0x5C71, // 山, #273 + 0x5DE5, // 工, #121 + 0x5DF1, // 己, #402 + 0x5DF2, // 已, #299 + 0x5E02, // 市, #81 + 0x5E2B, // 師, #262 + 0x5E36, // 帶, #470 + 0x5E38, // 常, #303 + 0x5E73, // 平, #297 + 0x5E74, // 年, #30 + 0x5E97, // 店, #171 + 0x5EA6, // 度, #220 + 0x5EB7, // 康, #441 + 0x5EE3, // 廣, #279 + 0x5EFA, // 建, #254 + 0x5F0F, // 式, #155 + 0x5F15, // 引, #346 + 0x5F35, // 張, #366 + 0x5F37, // 強, #437 + 0x5F71, // 影, #94 + 0x5F88, // 很, #177 + 0x5F8C, // 後, #66 + 0x5F97, // 得, #113 + 0x5F9E, // 從, #436 + 0x5FC3, // 心, #57 + 0x5FEB, // 快, #292 + 0x6027, // 性, #175 + 0x606F, // 息, #378 + 0x60A8, // 您, #252 + 0x60C5, // 情, #123 + 0x60F3, // 想, #178 + 0x610F, // 意, #168 + 0x611B, // 愛, #125 + 0x611F, // 感, #211 + 0x61C9, // 應, #164 + 0x6210, // 成, #86 + 0x6211, // 我, #7 + 0x6216, // 或, #199 + 0x6230, // 戰, #438 + 0x6232, // 戲, #309 + 0x6236, // 戶, #497 + 0x623F, // 房, #274 + 0x6240, // 所, #79 + 0x624B, // 手, #68 + 0x624D, // 才, #400 + 0x6253, // 打, #278 + 0x627E, // 找, #449 + 0x6280, // 技, #332 + 0x6295, // 投, #425 + 0x62C9, // 拉, #500 + 0x62CD, // 拍, #398 + 0x6307, // 指, #407 + 0x6392, // 排, #458 + 0x63A5, // 接, #326 + 0x63A8, // 推, #153 + 0x63D0, // 提, #235 + 0x641C, // 搜, #314 + 0x6469, // 摩, #472 + 0x6536, // 收, #249 + 0x6539, // 改, #508 + 0x653E, // 放, #331 + 0x653F, // 政, #295 + 0x6559, // 教, #184 + 0x6574, // 整, #394 + 0x6578, // 數, #134 + 0x6587, // 文, #16 + 0x6599, // 料, #167 + 0x65AF, // 斯, #476 + 0x65B0, // 新, #10 + 0x65B9, // 方, #96 + 0x65BC, // 於, #70 + 0x65C5, // 旅, #289 + 0x65E5, // 日, #18 + 0x660E, // 明, #118 + 0x6613, // 易, #482 + 0x661F, // 星, #205 + 0x662F, // 是, #5 + 0x6642, // 時, #13 + 0x66F4, // 更, #149 + 0x66F8, // 書, #209 + 0x6700, // 最, #51 + 0x6703, // 會, #14 + 0x6708, // 月, #25 + 0x6709, // 有, #4 + 0x670D, // 服, #99 + 0x671F, // 期, #139 + 0x672A, // 未, #404 + 0x672C, // 本, #45 + 0x6771, // 東, #221 + 0x677F, // 板, #364 + 0x6797, // 林, #330 + 0x679C, // 果, #179 + 0x67E5, // 查, #283 + 0x683C, // 格, #157 + 0x6848, // 案, #392 + 0x689D, // 條, #406 + 0x696D, // 業, #103 + 0x6A02, // 樂, #116 + 0x6A13, // 樓, #411 + 0x6A19, // 標, #384 + 0x6A23, // 樣, #306 + 0x6A5F, // 機, #40 + 0x6AA2, // 檢, #359 + 0x6B0A, // 權, #228 + 0x6B21, // 次, #227 + 0x6B3E, // 款, #276 + 0x6B4C, // 歌, #496 + 0x6B61, // 歡, #427 + 0x6B63, // 正, #206 + 0x6B64, // 此, #247 + 0x6BCF, // 每, #391 + 0x6BD4, // 比, #257 + 0x6C11, // 民, #230 + 0x6C23, // 氣, #200 + 0x6C34, // 水, #140 + 0x6C42, // 求, #501 + 0x6C92, // 沒, #162 + 0x6CD5, // 法, #89 + 0x6D3B, // 活, #124 + 0x6D41, // 流, #315 + 0x6D77, // 海, #258 + 0x6D88, // 消, #342 + 0x6E05, // 清, #329 + 0x6E2F, // 港, #293 + 0x6F14, // 演, #491 + 0x7063, // 灣, #195 + 0x70BA, // 為, #39 + 0x7121, // 無, #107 + 0x7136, // 然, #215 + 0x7167, // 照, #376 + 0x71B1, // 熱, #245 + 0x7247, // 片, #90 + 0x7248, // 版, #112 + 0x724C, // 牌, #467 + 0x7269, // 物, #110 + 0x7279, // 特, #183 + 0x738B, // 王, #287 + 0x73A9, // 玩, #354 + 0x73FE, // 現, #143 + 0x7403, // 球, #350 + 0x7406, // 理, #105 + 0x751F, // 生, #24 + 0x7522, // 產, #201 + 0x7528, // 用, #17 + 0x7531, // 由, #288 + 0x7537, // 男, #298 + 0x754C, // 界, #399 + 0x7559, // 留, #218 + 0x756B, // 畫, #412 + 0x7576, // 當, #185 + 0x767B, // 登, #138 + 0x767C, // 發, #28 + 0x767D, // 白, #377 + 0x767E, // 百, #393 + 0x7684, // 的, #1 + 0x76EE, // 目, #271 + 0x76F4, // 直, #379 + 0x76F8, // 相, #98 + 0x770B, // 看, #52 + 0x771F, // 真, #180 + 0x773C, // 眼, #433 + 0x77E5, // 知, #170 + 0x78BC, // 碼, #481 + 0x793A, // 示, #353 + 0x793E, // 社, #333 + 0x795E, // 神, #304 + 0x7968, // 票, #477 + 0x798F, // 福, #494 + 0x79C1, // 私, #507 + 0x79D1, // 科, #280 + 0x7A0B, // 程, #272 + 0x7A2E, // 種, #337 + 0x7A4D, // 積, #385 + 0x7A7A, // 空, #324 + 0x7ACB, // 立, #286 + 0x7AD9, // 站, #117 + 0x7AE0, // 章, #141 + 0x7B2C, // 第, #135 + 0x7B49, // 等, #240 + 0x7BA1, // 管, #340 + 0x7BC0, // 節, #431 + 0x7BC7, // 篇, #479 + 0x7C21, // 簡, #499 + 0x7CBE, // 精, #213 + 0x7CFB, // 系, #212 + 0x7D04, // 約, #462 + 0x7D05, // 紅, #452 + 0x7D1A, // 級, #267 + 0x7D30, // 細, #486 + 0x7D44, // 組, #335 + 0x7D50, // 結, #243 + 0x7D66, // 給, #355 + 0x7D71, // 統, #375 + 0x7D93, // 經, #111 + 0x7DB2, // 網, #32 + 0x7DDA, // 線, #151 + 0x7E23, // 縣, #439 + 0x7E3D, // 總, #370 + 0x7F8E, // 美, #41 + 0x7FA9, // 義, #504 + 0x8001, // 老, #290 + 0x8003, // 考, #428 + 0x8005, // 者, #92 + 0x800C, // 而, #217 + 0x805E, // 聞, #181 + 0x806F, // 聯, #310 + 0x8072, // 聲, #413 + 0x80A1, // 股, #390 + 0x80B2, // 育, #453 + 0x80FD, // 能, #71 + 0x8166, // 腦, #408 + 0x81EA, // 自, #61 + 0x81F3, // 至, #344 + 0x8207, // 與, #84 + 0x8209, // 舉, #463 + 0x8272, // 色, #192 + 0x82B1, // 花, #255 + 0x82F1, // 英, #348 + 0x83EF, // 華, #196 + 0x842C, // 萬, #316 + 0x843D, // 落, #308 + 0x8457, // 著, #233 + 0x85A6, // 薦, #401 + 0x85CF, // 藏, #503 + 0x85DD, // 藝, #488 + 0x8655, // 處, #419 + 0x865F, // 號, #191 + 0x884C, // 行, #47 + 0x8853, // 術, #395 + 0x8868, // 表, #77 + 0x88AB, // 被, #291 + 0x88DD, // 裝, #256 + 0x88E1, // 裡, #369 + 0x88FD, // 製, #510 + 0x897F, // 西, #300 + 0x8981, // 要, #36 + 0x898B, // 見, #307 + 0x8996, // 視, #204 + 0x89BA, // 覺, #450 + 0x89BD, // 覽, #387 + 0x89C0, // 觀, #365 + 0x89E3, // 解, #323 + 0x8A00, // 言, #169 + 0x8A02, // 訂, #423 + 0x8A08, // 計, #225 + 0x8A0A, // 訊, #156 + 0x8A0E, // 討, #373 + 0x8A18, // 記, #222 + 0x8A2D, // 設, #174 + 0x8A3B, // 註, #356 + 0x8A55, // 評, #246 + 0x8A66, // 試, #448 + 0x8A71, // 話, #229 + 0x8A72, // 該, #446 + 0x8A8D, // 認, #464 + 0x8A9E, // 語, #371 + 0x8AAA, // 說, #91 + 0x8ABF, // 調, #509 + 0x8ACB, // 請, #119 + 0x8AD6, // 論, #114 + 0x8B1D, // 謝, #389 + 0x8B49, // 證, #429 + 0x8B58, // 識, #416 + 0x8B70, // 議, #485 + 0x8B77, // 護, #475 + 0x8B80, // 讀, #386 + 0x8B8A, // 變, #388 + 0x8B93, // 讓, #336 + 0x8CA8, // 貨, #313 + 0x8CB7, // 買, #260 + 0x8CBB, // 費, #203 + 0x8CC7, // 資, #62 + 0x8CE3, // 賣, #294 + 0x8CEA, // 質, #457 + 0x8CFC, // 購, #189 + 0x8D77, // 起, #214 + 0x8D85, // 超, #296 + 0x8DDF, // 跟, #489 + 0x8DEF, // 路, #137 + 0x8EAB, // 身, #197 + 0x8ECA, // 車, #76 + 0x8F09, // 載, #301 + 0x8F49, // 轉, #282 + 0x8FD1, // 近, #414 + 0x9001, // 送, #363 + 0x9019, // 這, #42 + 0x901A, // 通, #207 + 0x901F, // 速, #495 + 0x9020, // 造, #455 + 0x9023, // 連, #285 + 0x9032, // 進, #231 + 0x904A, // 遊, #132 + 0x904B, // 運, #219 + 0x904E, // 過, #101 + 0x9053, // 道, #146 + 0x9054, // 達, #417 + 0x9078, // 選, #182 + 0x9084, // 還, #154 + 0x908A, // 邊, #487 + 0x90A3, // 那, #269 + 0x90E8, // 部, #78 + 0x90FD, // 都, #104 + 0x914D, // 配, #421 + 0x9152, // 酒, #512 + 0x91AB, // 醫, #358 + 0x91CD, // 重, #224 + 0x91CF, // 量, #319 + 0x91D1, // 金, #115 + 0x9304, // 錄, #302 + 0x9577, // 長, #172 + 0x9580, // 門, #193 + 0x958B, // 開, #72 + 0x9593, // 間, #80 + 0x95B1, // 閱, #405 + 0x95DC, // 關, #74 + 0x963F, // 阿, #460 + 0x9650, // 限, #265 + 0x9662, // 院, #474 + 0x9664, // 除, #478 + 0x969B, // 際, #459 + 0x96C6, // 集, #347 + 0x96E2, // 離, #442 + 0x96FB, // 電, #33 + 0x9700, // 需, #445 + 0x975E, // 非, #451 + 0x9762, // 面, #129 + 0x97F3, // 音, #194 + 0x9801, // 頁, #83 + 0x982D, // 頭, #238 + 0x984C, // 題, #122 + 0x985E, // 類, #163 + 0x98A8, // 風, #266 + 0x98DF, // 食, #208 + 0x9910, // 餐, #469 + 0x9928, // 館, #424 + 0x9996, // 首, #166 + 0x9999, // 香, #263 + 0x99AC, // 馬, #317 + 0x9A57, // 驗, #492 + 0x9AD4, // 體, #100 + 0x9AD8, // 高, #88 + 0x9EBC, // 麼, #241 + 0x9EC3, // 黃, #480 + 0x9ED1, // 黑, #490 + 0x9EDE, // 點, #69 + 0x9F8D, // 龍, #505 +}; +// the percentage of the sample covered by the above characters +static const float frequent_zhTW_coverage=0.704841200026877; + +// The 512 most frequently occuring characters for the ja language in a sample of the Internet. +// Ordered by codepoint, comment shows character and ranking by frequency +const uint16_t frequent_ja[] = { + 0x3005, // 々, #352 + 0x3041, // ぁ, #486 + 0x3042, // あ, #50 + 0x3044, // い, #2 + 0x3046, // う, #33 + 0x3048, // え, #83 + 0x304A, // お, #37 + 0x304B, // か, #21 + 0x304C, // が, #17 + 0x304D, // き, #51 + 0x304E, // ぎ, #324 + 0x304F, // く, #38 + 0x3050, // ぐ, #334 + 0x3051, // け, #60 + 0x3052, // げ, #296 + 0x3053, // こ, #34 + 0x3054, // ご, #100 + 0x3055, // さ, #31 + 0x3056, // ざ, #378 + 0x3057, // し, #4 + 0x3058, // じ, #121 + 0x3059, // す, #12 + 0x305A, // ず, #215 + 0x305B, // せ, #86 + 0x305D, // そ, #68 + 0x305F, // た, #11 + 0x3060, // だ, #42 + 0x3061, // ち, #67 + 0x3063, // っ, #23 + 0x3064, // つ, #73 + 0x3066, // て, #7 + 0x3067, // で, #6 + 0x3068, // と, #14 + 0x3069, // ど, #75 + 0x306A, // な, #8 + 0x306B, // に, #5 + 0x306D, // ね, #123 + 0x306E, // の, #1 + 0x306F, // は, #16 + 0x3070, // ば, #150 + 0x3071, // ぱ, #259 + 0x3072, // ひ, #364 + 0x3073, // び, #266 + 0x3075, // ふ, #484 + 0x3076, // ぶ, #330 + 0x3078, // へ, #146 + 0x3079, // べ, #207 + 0x307B, // ほ, #254 + 0x307E, // ま, #18 + 0x307F, // み, #74 + 0x3080, // む, #285 + 0x3081, // め, #78 + 0x3082, // も, #32 + 0x3083, // ゃ, #111 + 0x3084, // や, #85 + 0x3086, // ゆ, #392 + 0x3087, // ょ, #224 + 0x3088, // よ, #63 + 0x3089, // ら, #29 + 0x308A, // り, #28 + 0x308B, // る, #9 + 0x308C, // れ, #35 + 0x308D, // ろ, #127 + 0x308F, // わ, #88 + 0x3092, // を, #19 + 0x3093, // ん, #22 + 0x30A1, // ァ, #193 + 0x30A2, // ア, #27 + 0x30A3, // ィ, #70 + 0x30A4, // イ, #15 + 0x30A6, // ウ, #89 + 0x30A7, // ェ, #134 + 0x30A8, // エ, #81 + 0x30A9, // ォ, #225 + 0x30AA, // オ, #76 + 0x30AB, // カ, #52 + 0x30AC, // ガ, #147 + 0x30AD, // キ, #66 + 0x30AE, // ギ, #246 + 0x30AF, // ク, #25 + 0x30B0, // グ, #39 + 0x30B1, // ケ, #137 + 0x30B2, // ゲ, #200 + 0x30B3, // コ, #46 + 0x30B4, // ゴ, #183 + 0x30B5, // サ, #64 + 0x30B6, // ザ, #221 + 0x30B7, // シ, #48 + 0x30B8, // ジ, #55 + 0x30B9, // ス, #13 + 0x30BA, // ズ, #103 + 0x30BB, // セ, #109 + 0x30BC, // ゼ, #499 + 0x30BD, // ソ, #175 + 0x30BF, // タ, #45 + 0x30C0, // ダ, #104 + 0x30C1, // チ, #71 + 0x30C3, // ッ, #20 + 0x30C4, // ツ, #119 + 0x30C6, // テ, #59 + 0x30C7, // デ, #82 + 0x30C8, // ト, #10 + 0x30C9, // ド, #44 + 0x30CA, // ナ, #102 + 0x30CB, // ニ, #72 + 0x30CD, // ネ, #117 + 0x30CE, // ノ, #192 + 0x30CF, // ハ, #164 + 0x30D0, // バ, #62 + 0x30D1, // パ, #90 + 0x30D2, // ヒ, #398 + 0x30D3, // ビ, #77 + 0x30D4, // ピ, #135 + 0x30D5, // フ, #47 + 0x30D6, // ブ, #56 + 0x30D7, // プ, #43 + 0x30D8, // ヘ, #268 + 0x30D9, // ベ, #157 + 0x30DA, // ペ, #125 + 0x30DB, // ホ, #155 + 0x30DC, // ボ, #168 + 0x30DD, // ポ, #114 + 0x30DE, // マ, #57 + 0x30DF, // ミ, #97 + 0x30E0, // ム, #69 + 0x30E1, // メ, #53 + 0x30E2, // モ, #142 + 0x30E3, // ャ, #93 + 0x30E4, // ヤ, #258 + 0x30E5, // ュ, #79 + 0x30E6, // ユ, #405 + 0x30E7, // ョ, #98 + 0x30E9, // ラ, #26 + 0x30EA, // リ, #30 + 0x30EB, // ル, #24 + 0x30EC, // レ, #41 + 0x30ED, // ロ, #40 + 0x30EF, // ワ, #144 + 0x30F3, // ン, #3 + 0x30F4, // ヴ, #483 + 0x30FD, // ヽ, #501 + 0x4E00, // 一, #84 + 0x4E07, // 万, #337 + 0x4E09, // 三, #323 + 0x4E0A, // 上, #133 + 0x4E0B, // 下, #180 + 0x4E0D, // 不, #277 + 0x4E16, // 世, #385 + 0x4E2D, // 中, #87 + 0x4E3B, // 主, #432 + 0x4E88, // 予, #326 + 0x4E8B, // 事, #95 + 0x4E8C, // 二, #394 + 0x4E95, // 井, #468 + 0x4EA4, // 交, #410 + 0x4EAC, // 京, #260 + 0x4EBA, // 人, #61 + 0x4ECA, // 今, #184 + 0x4ECB, // 介, #358 + 0x4ED5, // 仕, #391 + 0x4ED6, // 他, #256 + 0x4ED8, // 付, #243 + 0x4EE3, // 代, #280 + 0x4EE5, // 以, #216 + 0x4EF6, // 件, #190 + 0x4F1A, // 会, #105 + 0x4F4D, // 位, #177 + 0x4F4F, // 住, #376 + 0x4F53, // 体, #223 + 0x4F55, // 何, #294 + 0x4F5C, // 作, #154 + 0x4F7F, // 使, #233 + 0x4F9B, // 供, #503 + 0x4FA1, // 価, #217 + 0x4FBF, // 便, #511 + 0x4FDD, // 保, #279 + 0x4FE1, // 信, #271 + 0x500B, // 個, #415 + 0x50CF, // 像, #178 + 0x512A, // 優, #403 + 0x5143, // 元, #384 + 0x5148, // 先, #311 + 0x5149, // 光, #488 + 0x5165, // 入, #115 + 0x5168, // 全, #173 + 0x516C, // 公, #287 + 0x5177, // 具, #447 + 0x5185, // 内, #169 + 0x5186, // 円, #131 + 0x5199, // 写, #275 + 0x51FA, // 出, #110 + 0x5206, // 分, #130 + 0x5207, // 切, #401 + 0x521D, // 初, #319 + 0x5225, // 別, #290 + 0x5229, // 利, #226 + 0x5236, // 制, #507 + 0x524D, // 前, #124 + 0x529B, // 力, #272 + 0x52A0, // 加, #249 + 0x52D5, // 動, #120 + 0x52D9, // 務, #421 + 0x52DF, // 募, #476 + 0x5316, // 化, #308 + 0x5317, // 北, #341 + 0x533A, // 区, #348 + 0x539F, // 原, #321 + 0x53C2, // 参, #452 + 0x53CB, // 友, #451 + 0x53D6, // 取, #237 + 0x53D7, // 受, #354 + 0x53E3, // 口, #289 + 0x53E4, // 古, #339 + 0x53EF, // 可, #298 + 0x53F0, // 台, #439 + 0x53F7, // 号, #361 + 0x5408, // 合, #118 + 0x540C, // 同, #263 + 0x540D, // 名, #65 + 0x5411, // 向, #434 + 0x544A, // 告, #386 + 0x5468, // 周, #393 + 0x5473, // 味, #299 + 0x548C, // 和, #350 + 0x54C1, // 品, #96 + 0x54E1, // 員, #293 + 0x5546, // 商, #198 + 0x554F, // 問, #158 + 0x55B6, // 営, #438 + 0x5668, // 器, #366 + 0x56DE, // 回, #143 + 0x56F3, // 図, #444 + 0x56FD, // 国, #153 + 0x5712, // 園, #435 + 0x571F, // 土, #239 + 0x5728, // 在, #351 + 0x5730, // 地, #163 + 0x578B, // 型, #430 + 0x5831, // 報, #112 + 0x5834, // 場, #139 + 0x58F2, // 売, #232 + 0x5909, // 変, #306 + 0x5916, // 外, #222 + 0x591A, // 多, #336 + 0x5927, // 大, #80 + 0x5929, // 天, #278 + 0x5973, // 女, #161 + 0x597D, // 好, #349 + 0x5A5A, // 婚, #479 + 0x5B50, // 子, #113 + 0x5B57, // 字, #492 + 0x5B66, // 学, #132 + 0x5B89, // 安, #295 + 0x5B9A, // 定, #145 + 0x5B9F, // 実, #220 + 0x5BA4, // 室, #482 + 0x5BAE, // 宮, #487 + 0x5BB6, // 家, #211 + 0x5BB9, // 容, #333 + 0x5BFE, // 対, #252 + 0x5C02, // 専, #474 + 0x5C0F, // 小, #212 + 0x5C11, // 少, #377 + 0x5C4B, // 屋, #284 + 0x5C71, // 山, #206 + 0x5CA1, // 岡, #429 + 0x5CF6, // 島, #297 + 0x5DDD, // 川, #253 + 0x5DE5, // 工, #374 + 0x5E02, // 市, #159 + 0x5E2F, // 帯, #416 + 0x5E38, // 常, #437 + 0x5E73, // 平, #390 + 0x5E74, // 年, #54 + 0x5E83, // 広, #367 + 0x5E97, // 店, #149 + 0x5EA6, // 度, #269 + 0x5EAB, // 庫, #380 + 0x5F0F, // 式, #265 + 0x5F15, // 引, #345 + 0x5F37, // 強, #446 + 0x5F53, // 当, #240 + 0x5F62, // 形, #502 + 0x5F8C, // 後, #230 + 0x5F97, // 得, #490 + 0x5FC3, // 心, #307 + 0x5FC5, // 必, #422 + 0x5FDC, // 応, #356 + 0x601D, // 思, #189 + 0x6027, // 性, #201 + 0x6075, // 恵, #400 + 0x60C5, // 情, #140 + 0x60F3, // 想, #477 + 0x610F, // 意, #305 + 0x611B, // 愛, #273 + 0x611F, // 感, #257 + 0x6210, // 成, #262 + 0x6226, // 戦, #365 + 0x6240, // 所, #236 + 0x624B, // 手, #160 + 0x6295, // 投, #129 + 0x6301, // 持, #355 + 0x6307, // 指, #425 + 0x63A2, // 探, #369 + 0x63B2, // 掲, #399 + 0x643A, // 携, #459 + 0x652F, // 支, #512 + 0x653E, // 放, #469 + 0x6559, // 教, #270 + 0x6570, // 数, #181 + 0x6587, // 文, #202 + 0x6599, // 料, #106 + 0x65B0, // 新, #99 + 0x65B9, // 方, #126 + 0x65C5, // 旅, #445 + 0x65E5, // 日, #36 + 0x660E, // 明, #300 + 0x6620, // 映, #418 + 0x6642, // 時, #107 + 0x66F4, // 更, #359 + 0x66F8, // 書, #174 + 0x6700, // 最, #152 + 0x6708, // 月, #49 + 0x6709, // 有, #302 + 0x671F, // 期, #332 + 0x6728, // 木, #203 + 0x672C, // 本, #92 + 0x6750, // 材, #489 + 0x6751, // 村, #466 + 0x6765, // 来, #267 + 0x6771, // 東, #191 + 0x677F, // 板, #411 + 0x679C, // 果, #441 + 0x6821, // 校, #327 + 0x682A, // 株, #412 + 0x683C, // 格, #228 + 0x691C, // 検, #179 + 0x696D, // 業, #166 + 0x697D, // 楽, #172 + 0x69D8, // 様, #255 + 0x6A5F, // 機, #235 + 0x6B21, // 次, #318 + 0x6B62, // 止, #475 + 0x6B63, // 正, #312 + 0x6C17, // 気, #116 + 0x6C34, // 水, #165 + 0x6C42, // 求, #465 + 0x6C7A, // 決, #370 + 0x6CBB, // 治, #505 + 0x6CC1, // 況, #462 + 0x6CD5, // 法, #227 + 0x6CE8, // 注, #372 + 0x6D3B, // 活, #303 + 0x6D41, // 流, #480 + 0x6D77, // 海, #274 + 0x6E08, // 済, #417 + 0x6F14, // 演, #504 + 0x706B, // 火, #264 + 0x70B9, // 点, #331 + 0x7121, // 無, #58 + 0x7248, // 版, #409 + 0x7269, // 物, #170 + 0x7279, // 特, #242 + 0x72B6, // 状, #458 + 0x73FE, // 現, #322 + 0x7406, // 理, #162 + 0x751F, // 生, #122 + 0x7523, // 産, #320 + 0x7528, // 用, #94 + 0x7530, // 田, #195 + 0x7537, // 男, #373 + 0x753A, // 町, #314 + 0x753B, // 画, #91 + 0x754C, // 界, #436 + 0x756A, // 番, #261 + 0x75C5, // 病, #428 + 0x767A, // 発, #194 + 0x767B, // 登, #231 + 0x767D, // 白, #419 + 0x7684, // 的, #251 + 0x76EE, // 目, #197 + 0x76F4, // 直, #497 + 0x76F8, // 相, #286 + 0x770C, // 県, #199 + 0x771F, // 真, #219 + 0x7740, // 着, #283 + 0x77E5, // 知, #185 + 0x77F3, // 石, #500 + 0x78BA, // 確, #383 + 0x793A, // 示, #241 + 0x793E, // 社, #167 + 0x795E, // 神, #315 + 0x798F, // 福, #423 + 0x79C1, // 私, #347 + 0x79D1, // 科, #420 + 0x7A0E, // 税, #368 + 0x7A2E, // 種, #455 + 0x7A3F, // 稿, #148 + 0x7A7A, // 空, #427 + 0x7ACB, // 立, #309 + 0x7B11, // 笑, #454 + 0x7B2C, // 第, #317 + 0x7B49, // 等, #457 + 0x7B54, // 答, #426 + 0x7BA1, // 管, #481 + 0x7CFB, // 系, #408 + 0x7D04, // 約, #276 + 0x7D20, // 素, #407 + 0x7D22, // 索, #214 + 0x7D30, // 細, #381 + 0x7D39, // 紹, #471 + 0x7D42, // 終, #456 + 0x7D44, // 組, #424 + 0x7D4C, // 経, #360 + 0x7D50, // 結, #291 + 0x7D9A, // 続, #357 + 0x7DCF, // 総, #467 + 0x7DDA, // 線, #338 + 0x7DE8, // 編, #453 + 0x7F8E, // 美, #204 + 0x8003, // 考, #387 + 0x8005, // 者, #151 + 0x805E, // 聞, #463 + 0x8077, // 職, #363 + 0x80B2, // 育, #433 + 0x80FD, // 能, #250 + 0x8179, // 腹, #396 + 0x81EA, // 自, #156 + 0x826F, // 良, #329 + 0x8272, // 色, #402 + 0x82B1, // 花, #440 + 0x82B8, // 芸, #413 + 0x82F1, // 英, #485 + 0x8449, // 葉, #472 + 0x884C, // 行, #128 + 0x8853, // 術, #460 + 0x8868, // 表, #209 + 0x88FD, // 製, #431 + 0x897F, // 西, #406 + 0x8981, // 要, #313 + 0x898B, // 見, #101 + 0x898F, // 規, #375 + 0x89A7, // 覧, #171 + 0x89E3, // 解, #388 + 0x8A00, // 言, #210 + 0x8A08, // 計, #343 + 0x8A18, // 記, #136 + 0x8A2D, // 設, #292 + 0x8A71, // 話, #213 + 0x8A73, // 詳, #371 + 0x8A8D, // 認, #404 + 0x8A9E, // 語, #234 + 0x8AAC, // 説, #494 + 0x8AAD, // 読, #301 + 0x8ABF, // 調, #443 + 0x8AC7, // 談, #448 + 0x8B77, // 護, #509 + 0x8C37, // 谷, #506 + 0x8CA9, // 販, #362 + 0x8CB7, // 買, #346 + 0x8CC7, // 資, #473 + 0x8CEA, // 質, #281 + 0x8CFC, // 購, #495 + 0x8EAB, // 身, #470 + 0x8ECA, // 車, #205 + 0x8EE2, // 転, #335 + 0x8F09, // 載, #342 + 0x8FBC, // 込, #229 + 0x8FD1, // 近, #304 + 0x8FD4, // 返, #461 + 0x8FFD, // 追, #379 + 0x9001, // 送, #186 + 0x901A, // 通, #182 + 0x901F, // 速, #340 + 0x9023, // 連, #244 + 0x904B, // 運, #382 + 0x904E, // 過, #498 + 0x9053, // 道, #282 + 0x9054, // 達, #450 + 0x9055, // 違, #414 + 0x9078, // 選, #288 + 0x90E8, // 部, #208 + 0x90FD, // 都, #344 + 0x914D, // 配, #389 + 0x91CD, // 重, #478 + 0x91CE, // 野, #245 + 0x91D1, // 金, #138 + 0x9332, // 録, #238 + 0x9577, // 長, #247 + 0x9580, // 門, #508 + 0x958B, // 開, #248 + 0x9593, // 間, #141 + 0x95A2, // 関, #188 + 0x962A, // 阪, #496 + 0x9650, // 限, #395 + 0x9662, // 院, #449 + 0x9664, // 除, #510 + 0x969B, // 際, #493 + 0x96C6, // 集, #196 + 0x96D1, // 雑, #442 + 0x96FB, // 電, #187 + 0x9762, // 面, #328 + 0x97F3, // 音, #325 + 0x984C, // 題, #310 + 0x985E, // 類, #491 + 0x98A8, // 風, #353 + 0x98DF, // 食, #218 + 0x9928, // 館, #464 + 0x99C5, // 駅, #316 + 0x9A13, // 験, #397 + 0x9AD8, // 高, #176 + 0xFF57, // w, #108 +}; +// the percentage of the sample covered by the above characters +static const float frequent_ja_coverage=0.880569589120162; + +// The 512 most frequently occuring characters for the ko language in a sample of the Internet. +// Ordered by codepoint, comment shows character and ranking by frequency +const uint16_t frequent_ko[] = { + 0x314B, // ㅋ, #148 + 0x314E, // ㅎ, #390 + 0x3160, // ㅠ, #354 + 0x318D, // ㆍ, #439 + 0xAC00, // 가, #6 + 0xAC01, // 각, #231 + 0xAC04, // 간, #106 + 0xAC08, // 갈, #362 + 0xAC10, // 감, #122 + 0xAC11, // 갑, #493 + 0xAC15, // 강, #155 + 0xAC19, // 같, #264 + 0xAC1C, // 개, #87 + 0xAC1D, // 객, #198 + 0xAC24, // 갤, #457 + 0xAC70, // 거, #91 + 0xAC74, // 건, #161 + 0xAC78, // 걸, #338 + 0xAC80, // 검, #184 + 0xAC83, // 것, #116 + 0xAC8C, // 게, #36 + 0xACA0, // 겠, #233 + 0xACA8, // 겨, #341 + 0xACA9, // 격, #245 + 0xACAC, // 견, #413 + 0xACB0, // 결, #202 + 0xACBD, // 경, #62 + 0xACC4, // 계, #142 + 0xACE0, // 고, #12 + 0xACE1, // 곡, #444 + 0xACE8, // 골, #379 + 0xACF3, // 곳, #388 + 0xACF5, // 공, #59 + 0xACFC, // 과, #69 + 0xAD00, // 관, #95 + 0xAD11, // 광, #235 + 0xAD50, // 교, #128 + 0xAD6C, // 구, #52 + 0xAD6D, // 국, #85 + 0xAD70, // 군, #293 + 0xAD74, // 굴, #487 + 0xAD81, // 궁, #441 + 0xAD8C, // 권, #192 + 0xADC0, // 귀, #386 + 0xADDC, // 규, #367 + 0xADF8, // 그, #30 + 0xADF9, // 극, #424 + 0xADFC, // 근, #241 + 0xAE00, // 글, #61 + 0xAE08, // 금, #138 + 0xAE09, // 급, #269 + 0xAE30, // 기, #3 + 0xAE34, // 긴, #465 + 0xAE38, // 길, #297 + 0xAE40, // 김, #205 + 0xAE4C, // 까, #171 + 0xAED8, // 께, #273 + 0xAF43, // 꽃, #475 + 0xB05D, // 끝, #505 + 0xB07C, // 끼, #490 + 0xB098, // 나, #39 + 0xB09C, // 난, #274 + 0xB0A0, // 날, #292 + 0xB0A8, // 남, #139 + 0xB0B4, // 내, #56 + 0xB108, // 너, #272 + 0xB110, // 널, #476 + 0xB118, // 넘, #492 + 0xB124, // 네, #100 + 0xB137, // 넷, #329 + 0xB140, // 녀, #288 + 0xB144, // 년, #151 + 0xB178, // 노, #149 + 0xB17C, // 논, #491 + 0xB180, // 놀, #464 + 0xB18D, // 농, #442 + 0xB204, // 누, #319 + 0xB208, // 눈, #383 + 0xB274, // 뉴, #173 + 0xB290, // 느, #368 + 0xB294, // 는, #5 + 0xB298, // 늘, #322 + 0xB2A5, // 능, #190 + 0xB2C8, // 니, #16 + 0xB2D8, // 님, #153 + 0xB2E4, // 다, #2 + 0xB2E8, // 단, #134 + 0xB2EB, // 닫, #195 + 0xB2EC, // 달, #243 + 0xB2F4, // 담, #254 + 0xB2F5, // 답, #287 + 0xB2F9, // 당, #159 + 0xB300, // 대, #33 + 0xB313, // 댓, #303 + 0xB354, // 더, #140 + 0xB358, // 던, #252 + 0xB367, // 덧, #463 + 0xB370, // 데, #104 + 0xB378, // 델, #429 + 0xB3C4, // 도, #25 + 0xB3C5, // 독, #301 + 0xB3CC, // 돌, #309 + 0xB3D9, // 동, #58 + 0xB418, // 되, #82 + 0xB41C, // 된, #189 + 0xB420, // 될, #408 + 0xB429, // 됩, #332 + 0xB450, // 두, #199 + 0xB4A4, // 뒤, #496 + 0xB4DC, // 드, #40 + 0xB4E0, // 든, #283 + 0xB4E4, // 들, #54 + 0xB4EF, // 듯, #478 + 0xB4F1, // 등, #90 + 0xB514, // 디, #133 + 0xB529, // 딩, #462 + 0xB530, // 따, #333 + 0xB54C, // 때, #240 + 0xB610, // 또, #313 + 0xB77C, // 라, #42 + 0xB77D, // 락, #355 + 0xB780, // 란, #290 + 0xB78C, // 람, #246 + 0xB78D, // 랍, #420 + 0xB791, // 랑, #270 + 0xB798, // 래, #174 + 0xB799, // 랙, #381 + 0xB79C, // 랜, #357 + 0xB7A8, // 램, #359 + 0xB7A9, // 랩, #402 + 0xB7C9, // 량, #346 + 0xB7EC, // 러, #130 + 0xB7F0, // 런, #312 + 0xB7FC, // 럼, #327 + 0xB7FD, // 럽, #447 + 0xB807, // 렇, #412 + 0xB808, // 레, #114 + 0xB80C, // 렌, #395 + 0xB824, // 려, #158 + 0xB825, // 력, #194 + 0xB828, // 련, #326 + 0xB839, // 령, #389 + 0xB85C, // 로, #4 + 0xB85D, // 록, #84 + 0xB860, // 론, #366 + 0xB8CC, // 료, #154 + 0xB8E8, // 루, #236 + 0xB958, // 류, #265 + 0xB974, // 르, #212 + 0xB978, // 른, #250 + 0xB97C, // 를, #35 + 0xB984, // 름, #276 + 0xB9AC, // 리, #19 + 0xB9AD, // 릭, #394 + 0xB9B0, // 린, #259 + 0xB9B4, // 릴, #485 + 0xB9BC, // 림, #305 + 0xB9BD, // 립, #217 + 0xB9C1, // 링, #351 + 0xB9C8, // 마, #67 + 0xB9C9, // 막, #310 + 0xB9CC, // 만, #65 + 0xB9CE, // 많, #257 + 0xB9D0, // 말, #188 + 0xB9DB, // 맛, #397 + 0xB9DD, // 망, #370 + 0xB9DE, // 맞, #399 + 0xB9E4, // 매, #125 + 0xB9E8, // 맨, #422 + 0xBA38, // 머, #311 + 0xBA39, // 먹, #377 + 0xBA3C, // 먼, #469 + 0xBA54, // 메, #147 + 0xBA70, // 며, #191 + 0xBA74, // 면, #72 + 0xBA85, // 명, #131 + 0xBAA8, // 모, #73 + 0xBAA9, // 목, #157 + 0xBAB0, // 몰, #401 + 0xBAB8, // 몸, #437 + 0xBABB, // 못, #336 + 0xBB34, // 무, #80 + 0xBB38, // 문, #57 + 0xBB3C, // 물, #94 + 0xBBA4, // 뮤, #431 + 0xBBF8, // 미, #76 + 0xBBFC, // 민, #200 + 0xBC00, // 밀, #308 + 0xBC0F, // 및, #249 + 0xBC14, // 바, #89 + 0xBC15, // 박, #226 + 0xBC18, // 반, #175 + 0xBC1B, // 받, #248 + 0xBC1C, // 발, #164 + 0xBC29, // 방, #92 + 0xBC30, // 배, #162 + 0xBC31, // 백, #256 + 0xBC84, // 버, #111 + 0xBC88, // 번, #167 + 0xBC8C, // 벌, #423 + 0xBC94, // 범, #427 + 0xBC95, // 법, #207 + 0xBCA0, // 베, #281 + 0xBCA4, // 벤, #378 + 0xBCA8, // 벨, #387 + 0xBCC0, // 변, #253 + 0xBCC4, // 별, #262 + 0xBCD1, // 병, #340 + 0xBCF4, // 보, #20 + 0xBCF5, // 복, #204 + 0xBCF8, // 본, #182 + 0xBCFC, // 볼, #385 + 0xBD09, // 봉, #405 + 0xBD80, // 부, #46 + 0xBD81, // 북, #261 + 0xBD84, // 분, #105 + 0xBD88, // 불, #225 + 0xBDF0, // 뷰, #350 + 0xBE0C, // 브, #214 + 0xBE14, // 블, #99 + 0xBE44, // 비, #55 + 0xBE4C, // 빌, #510 + 0xBE60, // 빠, #398 + 0xC0AC, // 사, #14 + 0xC0AD, // 삭, #342 + 0xC0B0, // 산, #121 + 0xC0B4, // 살, #279 + 0xC0BC, // 삼, #348 + 0xC0C1, // 상, #41 + 0xC0C8, // 새, #282 + 0xC0C9, // 색, #181 + 0xC0DD, // 생, #109 + 0xC11C, // 서, #21 + 0xC11D, // 석, #234 + 0xC120, // 선, #107 + 0xC124, // 설, #170 + 0xC131, // 성, #50 + 0xC138, // 세, #60 + 0xC139, // 섹, #456 + 0xC13C, // 센, #267 + 0xC154, // 셔, #455 + 0xC158, // 션, #237 + 0xC15C, // 셜, #448 + 0xC168, // 셨, #421 + 0xC18C, // 소, #51 + 0xC18D, // 속, #219 + 0xC190, // 손, #323 + 0xC1A1, // 송, #203 + 0xC1C4, // 쇄, #501 + 0xC1FC, // 쇼, #364 + 0xC218, // 수, #27 + 0xC219, // 숙, #467 + 0xC21C, // 순, #258 + 0xC220, // 술, #302 + 0xC26C, // 쉬, #511 + 0xC288, // 슈, #384 + 0xC2A4, // 스, #11 + 0xC2AC, // 슬, #438 + 0xC2B4, // 슴, #504 + 0xC2B5, // 습, #77 + 0xC2B9, // 승, #299 + 0xC2DC, // 시, #13 + 0xC2DD, // 식, #137 + 0xC2E0, // 신, #47 + 0xC2E4, // 실, #132 + 0xC2EC, // 심, #196 + 0xC2ED, // 십, #482 + 0xC2F6, // 싶, #352 + 0xC2F8, // 싸, #419 + 0xC4F0, // 쓰, #278 + 0xC528, // 씨, #360 + 0xC544, // 아, #23 + 0xC545, // 악, #296 + 0xC548, // 안, #71 + 0xC54A, // 않, #209 + 0xC54C, // 알, #222 + 0xC554, // 암, #460 + 0xC558, // 았, #349 + 0xC559, // 앙, #473 + 0xC55E, // 앞, #434 + 0xC560, // 애, #271 + 0xC561, // 액, #415 + 0xC571, // 앱, #477 + 0xC57C, // 야, #124 + 0xC57D, // 약, #229 + 0xC591, // 양, #177 + 0xC5B4, // 어, #24 + 0xC5B5, // 억, #407 + 0xC5B8, // 언, #294 + 0xC5BC, // 얼, #356 + 0xC5C4, // 엄, #426 + 0xC5C5, // 업, #118 + 0xC5C6, // 없, #178 + 0xC5C8, // 었, #165 + 0xC5D0, // 에, #9 + 0xC5D4, // 엔, #375 + 0xC5D8, // 엘, #506 + 0xC5EC, // 여, #66 + 0xC5ED, // 역, #186 + 0xC5EE, // 엮, #488 + 0xC5F0, // 연, #96 + 0xC5F4, // 열, #266 + 0xC5FC, // 염, #449 + 0xC600, // 였, #374 + 0xC601, // 영, #83 + 0xC608, // 예, #168 + 0xC624, // 오, #75 + 0xC628, // 온, #300 + 0xC62C, // 올, #306 + 0xC640, // 와, #119 + 0xC644, // 완, #361 + 0xC654, // 왔, #489 + 0xC655, // 왕, #418 + 0xC678, // 외, #218 + 0xC694, // 요, #43 + 0xC695, // 욕, #479 + 0xC6A9, // 용, #48 + 0xC6B0, // 우, #64 + 0xC6B1, // 욱, #503 + 0xC6B4, // 운, #108 + 0xC6B8, // 울, #223 + 0xC6C0, // 움, #317 + 0xC6C3, // 웃, #404 + 0xC6CC, // 워, #280 + 0xC6D0, // 원, #45 + 0xC6D4, // 월, #150 + 0xC6E8, // 웨, #446 + 0xC6F9, // 웹, #500 + 0xC704, // 위, #78 + 0xC720, // 유, #81 + 0xC721, // 육, #321 + 0xC724, // 윤, #416 + 0xC73C, // 으, #49 + 0xC740, // 은, #31 + 0xC744, // 을, #17 + 0xC74C, // 음, #112 + 0xC751, // 응, #461 + 0xC758, // 의, #8 + 0xC774, // 이, #1 + 0xC775, // 익, #403 + 0xC778, // 인, #18 + 0xC77C, // 일, #28 + 0xC784, // 임, #160 + 0xC785, // 입, #93 + 0xC788, // 있, #44 + 0xC790, // 자, #22 + 0xC791, // 작, #88 + 0xC798, // 잘, #347 + 0xC7A1, // 잡, #372 + 0xC7A5, // 장, #53 + 0xC7AC, // 재, #120 + 0xC7C1, // 쟁, #483 + 0xC800, // 저, #98 + 0xC801, // 적, #97 + 0xC804, // 전, #34 + 0xC808, // 절, #320 + 0xC810, // 점, #201 + 0xC811, // 접, #331 + 0xC815, // 정, #26 + 0xC81C, // 제, #29 + 0xC838, // 져, #414 + 0xC870, // 조, #86 + 0xC871, // 족, #373 + 0xC874, // 존, #432 + 0xC880, // 좀, #470 + 0xC885, // 종, #208 + 0xC88B, // 좋, #239 + 0xC8E0, // 죠, #451 + 0xC8FC, // 주, #38 + 0xC8FD, // 죽, #471 + 0xC900, // 준, #286 + 0xC904, // 줄, #392 + 0xC911, // 중, #103 + 0xC988, // 즈, #255 + 0xC98C, // 즌, #507 + 0xC990, // 즐, #371 + 0xC99D, // 증, #260 + 0xC9C0, // 지, #10 + 0xC9C1, // 직, #216 + 0xC9C4, // 진, #79 + 0xC9C8, // 질, #238 + 0xC9D1, // 집, #206 + 0xC9DC, // 짜, #411 + 0xC9F8, // 째, #494 + 0xCABD, // 쪽, #435 + 0xCC28, // 차, #146 + 0xCC29, // 착, #443 + 0xCC2C, // 찬, #481 + 0xCC30, // 찰, #440 + 0xCC38, // 참, #343 + 0xCC3D, // 창, #304 + 0xCC3E, // 찾, #335 + 0xCC44, // 채, #284 + 0xCC45, // 책, #298 + 0xCC98, // 처, #242 + 0xCC9C, // 천, #143 + 0xCCA0, // 철, #380 + 0xCCA8, // 첨, #452 + 0xCCAB, // 첫, #484 + 0xCCAD, // 청, #197 + 0xCCB4, // 체, #126 + 0xCCD0, // 쳐, #472 + 0xCD08, // 초, #220 + 0xCD1D, // 총, #406 + 0xCD5C, // 최, #179 + 0xCD94, // 추, #136 + 0xCD95, // 축, #337 + 0xCD9C, // 출, #166 + 0xCDA9, // 충, #369 + 0xCDE8, // 취, #210 + 0xCE20, // 츠, #215 + 0xCE21, // 측, #468 + 0xCE35, // 층, #512 + 0xCE58, // 치, #102 + 0xCE5C, // 친, #325 + 0xCE68, // 침, #263 + 0xCE74, // 카, #115 + 0xCE7C, // 칼, #466 + 0xCE90, // 캐, #454 + 0xCEE4, // 커, #285 + 0xCEE8, // 컨, #328 + 0xCEF4, // 컴, #417 + 0xCF00, // 케, #339 + 0xCF13, // 켓, #509 + 0xCF1C, // 켜, #508 + 0xCF54, // 코, #193 + 0xCF58, // 콘, #391 + 0xCFE0, // 쿠, #393 + 0xD035, // 퀵, #453 + 0xD06C, // 크, #101 + 0xD070, // 큰, #495 + 0xD074, // 클, #289 + 0xD0A4, // 키, #230 + 0xD0C0, // 타, #127 + 0xD0C1, // 탁, #314 + 0xD0C4, // 탄, #450 + 0xD0C8, // 탈, #436 + 0xD0DC, // 태, #221 + 0xD0DD, // 택, #275 + 0xD130, // 터, #70 + 0xD14C, // 테, #213 + 0xD150, // 텐, #324 + 0xD154, // 텔, #430 + 0xD15C, // 템, #382 + 0xD1A0, // 토, #145 + 0xD1B5, // 통, #156 + 0xD22C, // 투, #227 + 0xD2B8, // 트, #37 + 0xD2B9, // 특, #247 + 0xD2F0, // 티, #187 + 0xD305, // 팅, #410 + 0xD30C, // 파, #141 + 0xD310, // 판, #163 + 0xD314, // 팔, #499 + 0xD328, // 패, #307 + 0xD32C, // 팬, #459 + 0xD338, // 팸, #433 + 0xD37C, // 퍼, #344 + 0xD398, // 페, #172 + 0xD3B8, // 편, #251 + 0xD3C9, // 평, #291 + 0xD3EC, // 포, #68 + 0xD3ED, // 폭, #445 + 0xD3F0, // 폰, #318 + 0xD45C, // 표, #232 + 0xD480, // 풀, #497 + 0xD488, // 품, #113 + 0xD48D, // 풍, #425 + 0xD504, // 프, #110 + 0xD508, // 픈, #498 + 0xD50C, // 플, #211 + 0xD53C, // 피, #169 + 0xD544, // 필, #295 + 0xD551, // 핑, #376 + 0xD558, // 하, #7 + 0xD559, // 학, #129 + 0xD55C, // 한, #15 + 0xD560, // 할, #144 + 0xD568, // 함, #152 + 0xD569, // 합, #123 + 0xD56D, // 항, #268 + 0xD574, // 해, #32 + 0xD588, // 했, #180 + 0xD589, // 행, #135 + 0xD5A5, // 향, #345 + 0xD5C8, // 허, #396 + 0xD5D8, // 험, #316 + 0xD5E4, // 헤, #474 + 0xD604, // 현, #185 + 0xD611, // 협, #315 + 0xD615, // 형, #244 + 0xD61C, // 혜, #428 + 0xD638, // 호, #117 + 0xD63C, // 혼, #358 + 0xD648, // 홈, #330 + 0xD64D, // 홍, #363 + 0xD654, // 화, #63 + 0xD655, // 확, #183 + 0xD658, // 환, #224 + 0xD65C, // 활, #277 + 0xD669, // 황, #353 + 0xD68C, // 회, #74 + 0xD68D, // 획, #458 + 0xD69F, // 횟, #409 + 0xD6A8, // 효, #400 + 0xD6C4, // 후, #176 + 0xD6C8, // 훈, #486 + 0xD734, // 휴, #365 + 0xD754, // 흔, #480 + 0xD76C, // 희, #334 + 0xD788, // 히, #228 + 0xD798, // 힘, #502 +}; +// the percentage of the sample covered by the above characters +static const float frequent_ko_coverage=0.948157021464184; + diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp index 93a4a4c..1661f04 100644 --- a/media/libmedia/MediaScannerClient.cpp +++ b/media/libmedia/MediaScannerClient.cpp @@ -14,217 +14,57 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "MediaScannerClient" +#include + #include +#include "CharacterEncodingDetector.h" #include "StringArray.h" -#include "autodetect.h" -#include "unicode/ucnv.h" -#include "unicode/ustring.h" - namespace android { MediaScannerClient::MediaScannerClient() - : mNames(NULL), - mValues(NULL), - mLocaleEncoding(kEncodingNone) + : mEncodingDetector(NULL) { } MediaScannerClient::~MediaScannerClient() { - delete mNames; - delete mValues; + delete mEncodingDetector; } void MediaScannerClient::setLocale(const char* locale) { - if (!locale) return; - - if (!strncmp(locale, "ja", 2)) - mLocaleEncoding = kEncodingShiftJIS; - else if (!strncmp(locale, "ko", 2)) - mLocaleEncoding = kEncodingEUCKR; - else if (!strncmp(locale, "zh", 2)) { - if (!strcmp(locale, "zh_CN")) { - // simplified chinese for mainland China - mLocaleEncoding = kEncodingGBK; - } else { - // assume traditional for non-mainland Chinese locales (Taiwan, Hong Kong, Singapore) - mLocaleEncoding = kEncodingBig5; - } - } + mLocale = locale; // not currently used } void MediaScannerClient::beginFile() { - mNames = new StringArray; - mValues = new StringArray; + delete mEncodingDetector; + mEncodingDetector = new CharacterEncodingDetector(); } status_t MediaScannerClient::addStringTag(const char* name, const char* value) { - if (mLocaleEncoding != kEncodingNone) { - // don't bother caching strings that are all ASCII. - // call handleStringTag directly instead. - // check to see if value (which should be utf8) has any non-ASCII characters - bool nonAscii = false; - const char* chp = value; - char ch; - while ((ch = *chp++)) { - if (ch & 0x80) { - nonAscii = true; - break; - } - } - - if (nonAscii) { - // save the strings for later so they can be used for native encoding detection - mNames->push_back(name); - mValues->push_back(value); - return OK; - } - // else fall through - } - - // autodetection is not necessary, so no need to cache the values - // pass directly to the client instead - return handleStringTag(name, value); -} - -static uint32_t possibleEncodings(const char* s) -{ - uint32_t result = kEncodingAll; - // if s contains a native encoding, then it was mistakenly encoded in utf8 as if it were latin-1 - // so we need to reverse the latin-1 -> utf8 conversion to get the native chars back - uint8_t ch1, ch2; - uint8_t* chp = (uint8_t *)s; - - while ((ch1 = *chp++)) { - if (ch1 & 0x80) { - ch2 = *chp++; - ch1 = ((ch1 << 6) & 0xC0) | (ch2 & 0x3F); - // ch1 is now the first byte of the potential native char - - ch2 = *chp++; - if (ch2 & 0x80) - ch2 = ((ch2 << 6) & 0xC0) | (*chp++ & 0x3F); - // ch2 is now the second byte of the potential native char - int ch = (int)ch1 << 8 | (int)ch2; - result &= findPossibleEncodings(ch); - } - // else ASCII character, which could be anything - } - - return result; -} - -void MediaScannerClient::convertValues(uint32_t encoding) -{ - const char* enc = NULL; - switch (encoding) { - case kEncodingShiftJIS: - enc = "shift-jis"; - break; - case kEncodingGBK: - enc = "gbk"; - break; - case kEncodingBig5: - enc = "Big5"; - break; - case kEncodingEUCKR: - enc = "EUC-KR"; - break; - } - - if (enc) { - UErrorCode status = U_ZERO_ERROR; - - UConverter *conv = ucnv_open(enc, &status); - if (U_FAILURE(status)) { - ALOGE("could not create UConverter for %s", enc); - return; - } - UConverter *utf8Conv = ucnv_open("UTF-8", &status); - if (U_FAILURE(status)) { - ALOGE("could not create UConverter for UTF-8"); - ucnv_close(conv); - return; - } - - // for each value string, convert from native encoding to UTF-8 - for (int i = 0; i < mNames->size(); i++) { - // first we need to untangle the utf8 and convert it back to the original bytes - // since we are reducing the length of the string, we can do this in place - uint8_t* src = (uint8_t *)mValues->getEntry(i); - int len = strlen((char *)src); - uint8_t* dest = src; - - uint8_t uch; - while ((uch = *src++)) { - if (uch & 0x80) - *dest++ = ((uch << 6) & 0xC0) | (*src++ & 0x3F); - else - *dest++ = uch; - } - *dest = 0; - - // now convert from native encoding to UTF-8 - const char* source = mValues->getEntry(i); - int targetLength = len * 3 + 1; - char* buffer = new char[targetLength]; - // don't normally check for NULL, but in this case targetLength may be large - if (!buffer) - break; - char* target = buffer; - - ucnv_convertEx(utf8Conv, conv, &target, target + targetLength, - &source, (const char *)dest, NULL, NULL, NULL, NULL, TRUE, TRUE, &status); - if (U_FAILURE(status)) { - ALOGE("ucnv_convertEx failed: %d", status); - mValues->setEntry(i, "???"); - } else { - // zero terminate - *target = 0; - mValues->setEntry(i, buffer); - } - - delete[] buffer; - } - - ucnv_close(conv); - ucnv_close(utf8Conv); - } + mEncodingDetector->addTag(name, value); + return OK; } void MediaScannerClient::endFile() { - if (mLocaleEncoding != kEncodingNone) { - int size = mNames->size(); - uint32_t encoding = kEncodingAll; - - // compute a bit mask containing all possible encodings - for (int i = 0; i < mNames->size(); i++) - encoding &= possibleEncodings(mValues->getEntry(i)); - - // if the locale encoding matches, then assume we have a native encoding. - if (encoding & mLocaleEncoding) - convertValues(mLocaleEncoding); - - // finally, push all name/value pairs to the client - for (int i = 0; i < mNames->size(); i++) { - status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i)); - if (status) { - break; - } + mEncodingDetector->detectAndConvert(); + + int size = mEncodingDetector->size(); + if (size) { + for (int i = 0; i < size; i++) { + const char *name; + const char *value; + mEncodingDetector->getTag(i, &name, &value); + handleStringTag(name, value); } } - // else addStringTag() has done all the work so we have nothing to do - - delete mNames; - delete mValues; - mNames = NULL; - mValues = NULL; } } // namespace android diff --git a/media/libmedia/autodetect.cpp b/media/libmedia/autodetect.cpp deleted file mode 100644 index be5c3b2..0000000 --- a/media/libmedia/autodetect.cpp +++ /dev/null @@ -1,885 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "autodetect.h" - -struct CharRange { - uint16_t first; - uint16_t last; -}; - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) - -// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT -static const CharRange kShiftJISRanges[] = { - { 0x8140, 0x817E }, - { 0x8180, 0x81AC }, - { 0x81B8, 0x81BF }, - { 0x81C8, 0x81CE }, - { 0x81DA, 0x81E8 }, - { 0x81F0, 0x81F7 }, - { 0x81FC, 0x81FC }, - { 0x824F, 0x8258 }, - { 0x8260, 0x8279 }, - { 0x8281, 0x829A }, - { 0x829F, 0x82F1 }, - { 0x8340, 0x837E }, - { 0x8380, 0x8396 }, - { 0x839F, 0x83B6 }, - { 0x83BF, 0x83D6 }, - { 0x8440, 0x8460 }, - { 0x8470, 0x847E }, - { 0x8480, 0x8491 }, - { 0x849F, 0x84BE }, - { 0x8740, 0x875D }, - { 0x875F, 0x8775 }, - { 0x877E, 0x877E }, - { 0x8780, 0x879C }, - { 0x889F, 0x88FC }, - { 0x8940, 0x897E }, - { 0x8980, 0x89FC }, - { 0x8A40, 0x8A7E }, - { 0x8A80, 0x8AFC }, - { 0x8B40, 0x8B7E }, - { 0x8B80, 0x8BFC }, - { 0x8C40, 0x8C7E }, - { 0x8C80, 0x8CFC }, - { 0x8D40, 0x8D7E }, - { 0x8D80, 0x8DFC }, - { 0x8E40, 0x8E7E }, - { 0x8E80, 0x8EFC }, - { 0x8F40, 0x8F7E }, - { 0x8F80, 0x8FFC }, - { 0x9040, 0x907E }, - { 0x9080, 0x90FC }, - { 0x9140, 0x917E }, - { 0x9180, 0x91FC }, - { 0x9240, 0x927E }, - { 0x9280, 0x92FC }, - { 0x9340, 0x937E }, - { 0x9380, 0x93FC }, - { 0x9440, 0x947E }, - { 0x9480, 0x94FC }, - { 0x9540, 0x957E }, - { 0x9580, 0x95FC }, - { 0x9640, 0x967E }, - { 0x9680, 0x96FC }, - { 0x9740, 0x977E }, - { 0x9780, 0x97FC }, - { 0x9840, 0x9872 }, - { 0x989F, 0x98FC }, - { 0x9940, 0x997E }, - { 0x9980, 0x99FC }, - { 0x9A40, 0x9A7E }, - { 0x9A80, 0x9AFC }, - { 0x9B40, 0x9B7E }, - { 0x9B80, 0x9BFC }, - { 0x9C40, 0x9C7E }, - { 0x9C80, 0x9CFC }, - { 0x9D40, 0x9D7E }, - { 0x9D80, 0x9DFC }, - { 0x9E40, 0x9E7E }, - { 0x9E80, 0x9EFC }, - { 0x9F40, 0x9F7E }, - { 0x9F80, 0x9FFC }, - { 0xE040, 0xE07E }, - { 0xE080, 0xE0FC }, - { 0xE140, 0xE17E }, - { 0xE180, 0xE1FC }, - { 0xE240, 0xE27E }, - { 0xE280, 0xE2FC }, - { 0xE340, 0xE37E }, - { 0xE380, 0xE3FC }, - { 0xE440, 0xE47E }, - { 0xE480, 0xE4FC }, - { 0xE540, 0xE57E }, - { 0xE580, 0xE5FC }, - { 0xE640, 0xE67E }, - { 0xE680, 0xE6FC }, - { 0xE740, 0xE77E }, - { 0xE780, 0xE7FC }, - { 0xE840, 0xE87E }, - { 0xE880, 0xE8FC }, - { 0xE940, 0xE97E }, - { 0xE980, 0xE9FC }, - { 0xEA40, 0xEA7E }, - { 0xEA80, 0xEAA4 }, - { 0xED40, 0xED7E }, - { 0xED80, 0xEDFC }, - { 0xEE40, 0xEE7E }, - { 0xEE80, 0xEEEC }, - { 0xEEEF, 0xEEFC }, - { 0xFA40, 0xFA7E }, - { 0xFA80, 0xFAFC }, - { 0xFB40, 0xFB7E }, - { 0xFB80, 0xFBFC }, - { 0xFC40, 0xFC4B }, -}; - -// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT -static const CharRange kGBKRanges[] = { - { 0x8140, 0x817E }, - { 0x8180, 0x81FE }, - { 0x8240, 0x827E }, - { 0x8280, 0x82FE }, - { 0x8340, 0x837E }, - { 0x8380, 0x83FE }, - { 0x8440, 0x847E }, - { 0x8480, 0x84FE }, - { 0x8540, 0x857E }, - { 0x8580, 0x85FE }, - { 0x8640, 0x867E }, - { 0x8680, 0x86FE }, - { 0x8740, 0x877E }, - { 0x8780, 0x87FE }, - { 0x8840, 0x887E }, - { 0x8880, 0x88FE }, - { 0x8940, 0x897E }, - { 0x8980, 0x89FE }, - { 0x8A40, 0x8A7E }, - { 0x8A80, 0x8AFE }, - { 0x8B40, 0x8B7E }, - { 0x8B80, 0x8BFE }, - { 0x8C40, 0x8C7E }, - { 0x8C80, 0x8CFE }, - { 0x8D40, 0x8D7E }, - { 0x8D80, 0x8DFE }, - { 0x8E40, 0x8E7E }, - { 0x8E80, 0x8EFE }, - { 0x8F40, 0x8F7E }, - { 0x8F80, 0x8FFE }, - { 0x9040, 0x907E }, - { 0x9080, 0x90FE }, - { 0x9140, 0x917E }, - { 0x9180, 0x91FE }, - { 0x9240, 0x927E }, - { 0x9280, 0x92FE }, - { 0x9340, 0x937E }, - { 0x9380, 0x93FE }, - { 0x9440, 0x947E }, - { 0x9480, 0x94FE }, - { 0x9540, 0x957E }, - { 0x9580, 0x95FE }, - { 0x9640, 0x967E }, - { 0x9680, 0x96FE }, - { 0x9740, 0x977E }, - { 0x9780, 0x97FE }, - { 0x9840, 0x987E }, - { 0x9880, 0x98FE }, - { 0x9940, 0x997E }, - { 0x9980, 0x99FE }, - { 0x9A40, 0x9A7E }, - { 0x9A80, 0x9AFE }, - { 0x9B40, 0x9B7E }, - { 0x9B80, 0x9BFE }, - { 0x9C40, 0x9C7E }, - { 0x9C80, 0x9CFE }, - { 0x9D40, 0x9D7E }, - { 0x9D80, 0x9DFE }, - { 0x9E40, 0x9E7E }, - { 0x9E80, 0x9EFE }, - { 0x9F40, 0x9F7E }, - { 0x9F80, 0x9FFE }, - { 0xA040, 0xA07E }, - { 0xA080, 0xA0FE }, - { 0xA1A1, 0xA1FE }, - { 0xA2A1, 0xA2AA }, - { 0xA2B1, 0xA2E2 }, - { 0xA2E5, 0xA2EE }, - { 0xA2F1, 0xA2FC }, - { 0xA3A1, 0xA3FE }, - { 0xA4A1, 0xA4F3 }, - { 0xA5A1, 0xA5F6 }, - { 0xA6A1, 0xA6B8 }, - { 0xA6C1, 0xA6D8 }, - { 0xA6E0, 0xA6EB }, - { 0xA6EE, 0xA6F2 }, - { 0xA6F4, 0xA6F5 }, - { 0xA7A1, 0xA7C1 }, - { 0xA7D1, 0xA7F1 }, - { 0xA840, 0xA87E }, - { 0xA880, 0xA895 }, - { 0xA8A1, 0xA8BB }, - { 0xA8BD, 0xA8BE }, - { 0xA8C0, 0xA8C0 }, - { 0xA8C5, 0xA8E9 }, - { 0xA940, 0xA957 }, - { 0xA959, 0xA95A }, - { 0xA95C, 0xA95C }, - { 0xA960, 0xA97E }, - { 0xA980, 0xA988 }, - { 0xA996, 0xA996 }, - { 0xA9A4, 0xA9EF }, - { 0xAA40, 0xAA7E }, - { 0xAA80, 0xAAA0 }, - { 0xAB40, 0xAB7E }, - { 0xAB80, 0xABA0 }, - { 0xAC40, 0xAC7E }, - { 0xAC80, 0xACA0 }, - { 0xAD40, 0xAD7E }, - { 0xAD80, 0xADA0 }, - { 0xAE40, 0xAE7E }, - { 0xAE80, 0xAEA0 }, - { 0xAF40, 0xAF7E }, - { 0xAF80, 0xAFA0 }, - { 0xB040, 0xB07E }, - { 0xB080, 0xB0FE }, - { 0xB140, 0xB17E }, - { 0xB180, 0xB1FE }, - { 0xB240, 0xB27E }, - { 0xB280, 0xB2FE }, - { 0xB340, 0xB37E }, - { 0xB380, 0xB3FE }, - { 0xB440, 0xB47E }, - { 0xB480, 0xB4FE }, - { 0xB540, 0xB57E }, - { 0xB580, 0xB5FE }, - { 0xB640, 0xB67E }, - { 0xB680, 0xB6FE }, - { 0xB740, 0xB77E }, - { 0xB780, 0xB7FE }, - { 0xB840, 0xB87E }, - { 0xB880, 0xB8FE }, - { 0xB940, 0xB97E }, - { 0xB980, 0xB9FE }, - { 0xBA40, 0xBA7E }, - { 0xBA80, 0xBAFE }, - { 0xBB40, 0xBB7E }, - { 0xBB80, 0xBBFE }, - { 0xBC40, 0xBC7E }, - { 0xBC80, 0xBCFE }, - { 0xBD40, 0xBD7E }, - { 0xBD80, 0xBDFE }, - { 0xBE40, 0xBE7E }, - { 0xBE80, 0xBEFE }, - { 0xBF40, 0xBF7E }, - { 0xBF80, 0xBFFE }, - { 0xC040, 0xC07E }, - { 0xC080, 0xC0FE }, - { 0xC140, 0xC17E }, - { 0xC180, 0xC1FE }, - { 0xC240, 0xC27E }, - { 0xC280, 0xC2FE }, - { 0xC340, 0xC37E }, - { 0xC380, 0xC3FE }, - { 0xC440, 0xC47E }, - { 0xC480, 0xC4FE }, - { 0xC540, 0xC57E }, - { 0xC580, 0xC5FE }, - { 0xC640, 0xC67E }, - { 0xC680, 0xC6FE }, - { 0xC740, 0xC77E }, - { 0xC780, 0xC7FE }, - { 0xC840, 0xC87E }, - { 0xC880, 0xC8FE }, - { 0xC940, 0xC97E }, - { 0xC980, 0xC9FE }, - { 0xCA40, 0xCA7E }, - { 0xCA80, 0xCAFE }, - { 0xCB40, 0xCB7E }, - { 0xCB80, 0xCBFE }, - { 0xCC40, 0xCC7E }, - { 0xCC80, 0xCCFE }, - { 0xCD40, 0xCD7E }, - { 0xCD80, 0xCDFE }, - { 0xCE40, 0xCE7E }, - { 0xCE80, 0xCEFE }, - { 0xCF40, 0xCF7E }, - { 0xCF80, 0xCFFE }, - { 0xD040, 0xD07E }, - { 0xD080, 0xD0FE }, - { 0xD140, 0xD17E }, - { 0xD180, 0xD1FE }, - { 0xD240, 0xD27E }, - { 0xD280, 0xD2FE }, - { 0xD340, 0xD37E }, - { 0xD380, 0xD3FE }, - { 0xD440, 0xD47E }, - { 0xD480, 0xD4FE }, - { 0xD540, 0xD57E }, - { 0xD580, 0xD5FE }, - { 0xD640, 0xD67E }, - { 0xD680, 0xD6FE }, - { 0xD740, 0xD77E }, - { 0xD780, 0xD7F9 }, - { 0xD840, 0xD87E }, - { 0xD880, 0xD8FE }, - { 0xD940, 0xD97E }, - { 0xD980, 0xD9FE }, - { 0xDA40, 0xDA7E }, - { 0xDA80, 0xDAFE }, - { 0xDB40, 0xDB7E }, - { 0xDB80, 0xDBFE }, - { 0xDC40, 0xDC7E }, - { 0xDC80, 0xDCFE }, - { 0xDD40, 0xDD7E }, - { 0xDD80, 0xDDFE }, - { 0xDE40, 0xDE7E }, - { 0xDE80, 0xDEFE }, - { 0xDF40, 0xDF7E }, - { 0xDF80, 0xDFFE }, - { 0xE040, 0xE07E }, - { 0xE080, 0xE0FE }, - { 0xE140, 0xE17E }, - { 0xE180, 0xE1FE }, - { 0xE240, 0xE27E }, - { 0xE280, 0xE2FE }, - { 0xE340, 0xE37E }, - { 0xE380, 0xE3FE }, - { 0xE440, 0xE47E }, - { 0xE480, 0xE4FE }, - { 0xE540, 0xE57E }, - { 0xE580, 0xE5FE }, - { 0xE640, 0xE67E }, - { 0xE680, 0xE6FE }, - { 0xE740, 0xE77E }, - { 0xE780, 0xE7FE }, - { 0xE840, 0xE87E }, - { 0xE880, 0xE8FE }, - { 0xE940, 0xE97E }, - { 0xE980, 0xE9FE }, - { 0xEA40, 0xEA7E }, - { 0xEA80, 0xEAFE }, - { 0xEB40, 0xEB7E }, - { 0xEB80, 0xEBFE }, - { 0xEC40, 0xEC7E }, - { 0xEC80, 0xECFE }, - { 0xED40, 0xED7E }, - { 0xED80, 0xEDFE }, - { 0xEE40, 0xEE7E }, - { 0xEE80, 0xEEFE }, - { 0xEF40, 0xEF7E }, - { 0xEF80, 0xEFFE }, - { 0xF040, 0xF07E }, - { 0xF080, 0xF0FE }, - { 0xF140, 0xF17E }, - { 0xF180, 0xF1FE }, - { 0xF240, 0xF27E }, - { 0xF280, 0xF2FE }, - { 0xF340, 0xF37E }, - { 0xF380, 0xF3FE }, - { 0xF440, 0xF47E }, - { 0xF480, 0xF4FE }, - { 0xF540, 0xF57E }, - { 0xF580, 0xF5FE }, - { 0xF640, 0xF67E }, - { 0xF680, 0xF6FE }, - { 0xF740, 0xF77E }, - { 0xF780, 0xF7FE }, - { 0xF840, 0xF87E }, - { 0xF880, 0xF8A0 }, - { 0xF940, 0xF97E }, - { 0xF980, 0xF9A0 }, - { 0xFA40, 0xFA7E }, - { 0xFA80, 0xFAA0 }, - { 0xFB40, 0xFB7E }, - { 0xFB80, 0xFBA0 }, - { 0xFC40, 0xFC7E }, - { 0xFC80, 0xFCA0 }, - { 0xFD40, 0xFD7E }, - { 0xFD80, 0xFDA0 }, - { 0xFE40, 0xFE4F }, -}; - -// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT -static const CharRange kEUCKRRanges[] = { - { 0x8141, 0x815A }, - { 0x8161, 0x817A }, - { 0x8181, 0x81FE }, - { 0x8241, 0x825A }, - { 0x8261, 0x827A }, - { 0x8281, 0x82FE }, - { 0x8341, 0x835A }, - { 0x8361, 0x837A }, - { 0x8381, 0x83FE }, - { 0x8441, 0x845A }, - { 0x8461, 0x847A }, - { 0x8481, 0x84FE }, - { 0x8541, 0x855A }, - { 0x8561, 0x857A }, - { 0x8581, 0x85FE }, - { 0x8641, 0x865A }, - { 0x8661, 0x867A }, - { 0x8681, 0x86FE }, - { 0x8741, 0x875A }, - { 0x8761, 0x877A }, - { 0x8781, 0x87FE }, - { 0x8841, 0x885A }, - { 0x8861, 0x887A }, - { 0x8881, 0x88FE }, - { 0x8941, 0x895A }, - { 0x8961, 0x897A }, - { 0x8981, 0x89FE }, - { 0x8A41, 0x8A5A }, - { 0x8A61, 0x8A7A }, - { 0x8A81, 0x8AFE }, - { 0x8B41, 0x8B5A }, - { 0x8B61, 0x8B7A }, - { 0x8B81, 0x8BFE }, - { 0x8C41, 0x8C5A }, - { 0x8C61, 0x8C7A }, - { 0x8C81, 0x8CFE }, - { 0x8D41, 0x8D5A }, - { 0x8D61, 0x8D7A }, - { 0x8D81, 0x8DFE }, - { 0x8E41, 0x8E5A }, - { 0x8E61, 0x8E7A }, - { 0x8E81, 0x8EFE }, - { 0x8F41, 0x8F5A }, - { 0x8F61, 0x8F7A }, - { 0x8F81, 0x8FFE }, - { 0x9041, 0x905A }, - { 0x9061, 0x907A }, - { 0x9081, 0x90FE }, - { 0x9141, 0x915A }, - { 0x9161, 0x917A }, - { 0x9181, 0x91FE }, - { 0x9241, 0x925A }, - { 0x9261, 0x927A }, - { 0x9281, 0x92FE }, - { 0x9341, 0x935A }, - { 0x9361, 0x937A }, - { 0x9381, 0x93FE }, - { 0x9441, 0x945A }, - { 0x9461, 0x947A }, - { 0x9481, 0x94FE }, - { 0x9541, 0x955A }, - { 0x9561, 0x957A }, - { 0x9581, 0x95FE }, - { 0x9641, 0x965A }, - { 0x9661, 0x967A }, - { 0x9681, 0x96FE }, - { 0x9741, 0x975A }, - { 0x9761, 0x977A }, - { 0x9781, 0x97FE }, - { 0x9841, 0x985A }, - { 0x9861, 0x987A }, - { 0x9881, 0x98FE }, - { 0x9941, 0x995A }, - { 0x9961, 0x997A }, - { 0x9981, 0x99FE }, - { 0x9A41, 0x9A5A }, - { 0x9A61, 0x9A7A }, - { 0x9A81, 0x9AFE }, - { 0x9B41, 0x9B5A }, - { 0x9B61, 0x9B7A }, - { 0x9B81, 0x9BFE }, - { 0x9C41, 0x9C5A }, - { 0x9C61, 0x9C7A }, - { 0x9C81, 0x9CFE }, - { 0x9D41, 0x9D5A }, - { 0x9D61, 0x9D7A }, - { 0x9D81, 0x9DFE }, - { 0x9E41, 0x9E5A }, - { 0x9E61, 0x9E7A }, - { 0x9E81, 0x9EFE }, - { 0x9F41, 0x9F5A }, - { 0x9F61, 0x9F7A }, - { 0x9F81, 0x9FFE }, - { 0xA041, 0xA05A }, - { 0xA061, 0xA07A }, - { 0xA081, 0xA0FE }, - { 0xA141, 0xA15A }, - { 0xA161, 0xA17A }, - { 0xA181, 0xA1FE }, - { 0xA241, 0xA25A }, - { 0xA261, 0xA27A }, - { 0xA281, 0xA2E7 }, - { 0xA341, 0xA35A }, - { 0xA361, 0xA37A }, - { 0xA381, 0xA3FE }, - { 0xA441, 0xA45A }, - { 0xA461, 0xA47A }, - { 0xA481, 0xA4FE }, - { 0xA541, 0xA55A }, - { 0xA561, 0xA57A }, - { 0xA581, 0xA5AA }, - { 0xA5B0, 0xA5B9 }, - { 0xA5C1, 0xA5D8 }, - { 0xA5E1, 0xA5F8 }, - { 0xA641, 0xA65A }, - { 0xA661, 0xA67A }, - { 0xA681, 0xA6E4 }, - { 0xA741, 0xA75A }, - { 0xA761, 0xA77A }, - { 0xA781, 0xA7EF }, - { 0xA841, 0xA85A }, - { 0xA861, 0xA87A }, - { 0xA881, 0xA8A4 }, - { 0xA8A6, 0xA8A6 }, - { 0xA8A8, 0xA8AF }, - { 0xA8B1, 0xA8FE }, - { 0xA941, 0xA95A }, - { 0xA961, 0xA97A }, - { 0xA981, 0xA9FE }, - { 0xAA41, 0xAA5A }, - { 0xAA61, 0xAA7A }, - { 0xAA81, 0xAAF3 }, - { 0xAB41, 0xAB5A }, - { 0xAB61, 0xAB7A }, - { 0xAB81, 0xABF6 }, - { 0xAC41, 0xAC5A }, - { 0xAC61, 0xAC7A }, - { 0xAC81, 0xACC1 }, - { 0xACD1, 0xACF1 }, - { 0xAD41, 0xAD5A }, - { 0xAD61, 0xAD7A }, - { 0xAD81, 0xADA0 }, - { 0xAE41, 0xAE5A }, - { 0xAE61, 0xAE7A }, - { 0xAE81, 0xAEA0 }, - { 0xAF41, 0xAF5A }, - { 0xAF61, 0xAF7A }, - { 0xAF81, 0xAFA0 }, - { 0xB041, 0xB05A }, - { 0xB061, 0xB07A }, - { 0xB081, 0xB0FE }, - { 0xB141, 0xB15A }, - { 0xB161, 0xB17A }, - { 0xB181, 0xB1FE }, - { 0xB241, 0xB25A }, - { 0xB261, 0xB27A }, - { 0xB281, 0xB2FE }, - { 0xB341, 0xB35A }, - { 0xB361, 0xB37A }, - { 0xB381, 0xB3FE }, - { 0xB441, 0xB45A }, - { 0xB461, 0xB47A }, - { 0xB481, 0xB4FE }, - { 0xB541, 0xB55A }, - { 0xB561, 0xB57A }, - { 0xB581, 0xB5FE }, - { 0xB641, 0xB65A }, - { 0xB661, 0xB67A }, - { 0xB681, 0xB6FE }, - { 0xB741, 0xB75A }, - { 0xB761, 0xB77A }, - { 0xB781, 0xB7FE }, - { 0xB841, 0xB85A }, - { 0xB861, 0xB87A }, - { 0xB881, 0xB8FE }, - { 0xB941, 0xB95A }, - { 0xB961, 0xB97A }, - { 0xB981, 0xB9FE }, - { 0xBA41, 0xBA5A }, - { 0xBA61, 0xBA7A }, - { 0xBA81, 0xBAFE }, - { 0xBB41, 0xBB5A }, - { 0xBB61, 0xBB7A }, - { 0xBB81, 0xBBFE }, - { 0xBC41, 0xBC5A }, - { 0xBC61, 0xBC7A }, - { 0xBC81, 0xBCFE }, - { 0xBD41, 0xBD5A }, - { 0xBD61, 0xBD7A }, - { 0xBD81, 0xBDFE }, - { 0xBE41, 0xBE5A }, - { 0xBE61, 0xBE7A }, - { 0xBE81, 0xBEFE }, - { 0xBF41, 0xBF5A }, - { 0xBF61, 0xBF7A }, - { 0xBF81, 0xBFFE }, - { 0xC041, 0xC05A }, - { 0xC061, 0xC07A }, - { 0xC081, 0xC0FE }, - { 0xC141, 0xC15A }, - { 0xC161, 0xC17A }, - { 0xC181, 0xC1FE }, - { 0xC241, 0xC25A }, - { 0xC261, 0xC27A }, - { 0xC281, 0xC2FE }, - { 0xC341, 0xC35A }, - { 0xC361, 0xC37A }, - { 0xC381, 0xC3FE }, - { 0xC441, 0xC45A }, - { 0xC461, 0xC47A }, - { 0xC481, 0xC4FE }, - { 0xC541, 0xC55A }, - { 0xC561, 0xC57A }, - { 0xC581, 0xC5FE }, - { 0xC641, 0xC652 }, - { 0xC6A1, 0xC6FE }, - { 0xC7A1, 0xC7FE }, - { 0xC8A1, 0xC8FE }, - { 0xCAA1, 0xCAFE }, - { 0xCBA1, 0xCBFE }, - { 0xCCA1, 0xCCFE }, - { 0xCDA1, 0xCDFE }, - { 0xCEA1, 0xCEFE }, - { 0xCFA1, 0xCFFE }, - { 0xD0A1, 0xD0FE }, - { 0xD1A1, 0xD1FE }, - { 0xD2A1, 0xD2FE }, - { 0xD3A1, 0xD3FE }, - { 0xD4A1, 0xD4FE }, - { 0xD5A1, 0xD5FE }, - { 0xD6A1, 0xD6FE }, - { 0xD7A1, 0xD7FE }, - { 0xD8A1, 0xD8FE }, - { 0xD9A1, 0xD9FE }, - { 0xDAA1, 0xDAFE }, - { 0xDBA1, 0xDBFE }, - { 0xDCA1, 0xDCFE }, - { 0xDDA1, 0xDDFE }, - { 0xDEA1, 0xDEFE }, - { 0xDFA1, 0xDFFE }, - { 0xE0A1, 0xE0FE }, - { 0xE1A1, 0xE1FE }, - { 0xE2A1, 0xE2FE }, - { 0xE3A1, 0xE3FE }, - { 0xE4A1, 0xE4FE }, - { 0xE5A1, 0xE5FE }, - { 0xE6A1, 0xE6FE }, - { 0xE7A1, 0xE7FE }, - { 0xE8A1, 0xE8FE }, - { 0xE9A1, 0xE9FE }, - { 0xEAA1, 0xEAFE }, - { 0xEBA1, 0xEBFE }, - { 0xECA1, 0xECFE }, - { 0xEDA1, 0xEDFE }, - { 0xEEA1, 0xEEFE }, - { 0xEFA1, 0xEFFE }, - { 0xF0A1, 0xF0FE }, - { 0xF1A1, 0xF1FE }, - { 0xF2A1, 0xF2FE }, - { 0xF3A1, 0xF3FE }, - { 0xF4A1, 0xF4FE }, - { 0xF5A1, 0xF5FE }, - { 0xF6A1, 0xF6FE }, - { 0xF7A1, 0xF7FE }, - { 0xF8A1, 0xF8FE }, - { 0xF9A1, 0xF9FE }, - { 0xFAA1, 0xFAFE }, - { 0xFBA1, 0xFBFE }, - { 0xFCA1, 0xFCFE }, - { 0xFDA1, 0xFDFE }, -}; - -// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT -static const CharRange kBig5Ranges[] = { - { 0xA140, 0xA17E }, - { 0xA1A1, 0xA1FE }, - { 0xA240, 0xA27E }, - { 0xA2A1, 0xA2FE }, - { 0xA340, 0xA37E }, - { 0xA3A1, 0xA3BF }, - { 0xA3E1, 0xA3E1 }, - { 0xA440, 0xA47E }, - { 0xA4A1, 0xA4FE }, - { 0xA540, 0xA57E }, - { 0xA5A1, 0xA5FE }, - { 0xA640, 0xA67E }, - { 0xA6A1, 0xA6FE }, - { 0xA740, 0xA77E }, - { 0xA7A1, 0xA7FE }, - { 0xA840, 0xA87E }, - { 0xA8A1, 0xA8FE }, - { 0xA940, 0xA97E }, - { 0xA9A1, 0xA9FE }, - { 0xAA40, 0xAA7E }, - { 0xAAA1, 0xAAFE }, - { 0xAB40, 0xAB7E }, - { 0xABA1, 0xABFE }, - { 0xAC40, 0xAC7E }, - { 0xACA1, 0xACFE }, - { 0xAD40, 0xAD7E }, - { 0xADA1, 0xADFE }, - { 0xAE40, 0xAE7E }, - { 0xAEA1, 0xAEFE }, - { 0xAF40, 0xAF7E }, - { 0xAFA1, 0xAFFE }, - { 0xB040, 0xB07E }, - { 0xB0A1, 0xB0FE }, - { 0xB140, 0xB17E }, - { 0xB1A1, 0xB1FE }, - { 0xB240, 0xB27E }, - { 0xB2A1, 0xB2FE }, - { 0xB340, 0xB37E }, - { 0xB3A1, 0xB3FE }, - { 0xB440, 0xB47E }, - { 0xB4A1, 0xB4FE }, - { 0xB540, 0xB57E }, - { 0xB5A1, 0xB5FE }, - { 0xB640, 0xB67E }, - { 0xB6A1, 0xB6FE }, - { 0xB740, 0xB77E }, - { 0xB7A1, 0xB7FE }, - { 0xB840, 0xB87E }, - { 0xB8A1, 0xB8FE }, - { 0xB940, 0xB97E }, - { 0xB9A1, 0xB9FE }, - { 0xBA40, 0xBA7E }, - { 0xBAA1, 0xBAFE }, - { 0xBB40, 0xBB7E }, - { 0xBBA1, 0xBBFE }, - { 0xBC40, 0xBC7E }, - { 0xBCA1, 0xBCFE }, - { 0xBD40, 0xBD7E }, - { 0xBDA1, 0xBDFE }, - { 0xBE40, 0xBE7E }, - { 0xBEA1, 0xBEFE }, - { 0xBF40, 0xBF7E }, - { 0xBFA1, 0xBFFE }, - { 0xC040, 0xC07E }, - { 0xC0A1, 0xC0FE }, - { 0xC140, 0xC17E }, - { 0xC1A1, 0xC1FE }, - { 0xC240, 0xC27E }, - { 0xC2A1, 0xC2FE }, - { 0xC340, 0xC37E }, - { 0xC3A1, 0xC3FE }, - { 0xC440, 0xC47E }, - { 0xC4A1, 0xC4FE }, - { 0xC540, 0xC57E }, - { 0xC5A1, 0xC5FE }, - { 0xC640, 0xC67E }, - { 0xC940, 0xC97E }, - { 0xC9A1, 0xC9FE }, - { 0xCA40, 0xCA7E }, - { 0xCAA1, 0xCAFE }, - { 0xCB40, 0xCB7E }, - { 0xCBA1, 0xCBFE }, - { 0xCC40, 0xCC7E }, - { 0xCCA1, 0xCCFE }, - { 0xCD40, 0xCD7E }, - { 0xCDA1, 0xCDFE }, - { 0xCE40, 0xCE7E }, - { 0xCEA1, 0xCEFE }, - { 0xCF40, 0xCF7E }, - { 0xCFA1, 0xCFFE }, - { 0xD040, 0xD07E }, - { 0xD0A1, 0xD0FE }, - { 0xD140, 0xD17E }, - { 0xD1A1, 0xD1FE }, - { 0xD240, 0xD27E }, - { 0xD2A1, 0xD2FE }, - { 0xD340, 0xD37E }, - { 0xD3A1, 0xD3FE }, - { 0xD440, 0xD47E }, - { 0xD4A1, 0xD4FE }, - { 0xD540, 0xD57E }, - { 0xD5A1, 0xD5FE }, - { 0xD640, 0xD67E }, - { 0xD6A1, 0xD6FE }, - { 0xD740, 0xD77E }, - { 0xD7A1, 0xD7FE }, - { 0xD840, 0xD87E }, - { 0xD8A1, 0xD8FE }, - { 0xD940, 0xD97E }, - { 0xD9A1, 0xD9FE }, - { 0xDA40, 0xDA7E }, - { 0xDAA1, 0xDAFE }, - { 0xDB40, 0xDB7E }, - { 0xDBA1, 0xDBFE }, - { 0xDC40, 0xDC7E }, - { 0xDCA1, 0xDCFE }, - { 0xDD40, 0xDD7E }, - { 0xDDA1, 0xDDFE }, - { 0xDE40, 0xDE7E }, - { 0xDEA1, 0xDEFE }, - { 0xDF40, 0xDF7E }, - { 0xDFA1, 0xDFFE }, - { 0xE040, 0xE07E }, - { 0xE0A1, 0xE0FE }, - { 0xE140, 0xE17E }, - { 0xE1A1, 0xE1FE }, - { 0xE240, 0xE27E }, - { 0xE2A1, 0xE2FE }, - { 0xE340, 0xE37E }, - { 0xE3A1, 0xE3FE }, - { 0xE440, 0xE47E }, - { 0xE4A1, 0xE4FE }, - { 0xE540, 0xE57E }, - { 0xE5A1, 0xE5FE }, - { 0xE640, 0xE67E }, - { 0xE6A1, 0xE6FE }, - { 0xE740, 0xE77E }, - { 0xE7A1, 0xE7FE }, - { 0xE840, 0xE87E }, - { 0xE8A1, 0xE8FE }, - { 0xE940, 0xE97E }, - { 0xE9A1, 0xE9FE }, - { 0xEA40, 0xEA7E }, - { 0xEAA1, 0xEAFE }, - { 0xEB40, 0xEB7E }, - { 0xEBA1, 0xEBFE }, - { 0xEC40, 0xEC7E }, - { 0xECA1, 0xECFE }, - { 0xED40, 0xED7E }, - { 0xEDA1, 0xEDFE }, - { 0xEE40, 0xEE7E }, - { 0xEEA1, 0xEEFE }, - { 0xEF40, 0xEF7E }, - { 0xEFA1, 0xEFFE }, - { 0xF040, 0xF07E }, - { 0xF0A1, 0xF0FE }, - { 0xF140, 0xF17E }, - { 0xF1A1, 0xF1FE }, - { 0xF240, 0xF27E }, - { 0xF2A1, 0xF2FE }, - { 0xF340, 0xF37E }, - { 0xF3A1, 0xF3FE }, - { 0xF440, 0xF47E }, - { 0xF4A1, 0xF4FE }, - { 0xF540, 0xF57E }, - { 0xF5A1, 0xF5FE }, - { 0xF640, 0xF67E }, - { 0xF6A1, 0xF6FE }, - { 0xF740, 0xF77E }, - { 0xF7A1, 0xF7FE }, - { 0xF840, 0xF87E }, - { 0xF8A1, 0xF8FE }, - { 0xF940, 0xF97E }, - { 0xF9A1, 0xF9FE }, -}; - -static bool charMatchesEncoding(int ch, const CharRange* encodingRanges, int rangeCount) { - // Use binary search to see if the character is contained in the encoding - int low = 0; - int high = rangeCount; - - while (low < high) { - int i = (low + high) / 2; - const CharRange* range = &encodingRanges[i]; - if (ch >= range->first && ch <= range->last) - return true; - if (ch > range->last) - low = i + 1; - else - high = i; - } - - return false; -} - -extern uint32_t findPossibleEncodings(int ch) -{ - // ASCII matches everything - if (ch < 256) return kEncodingAll; - - int result = kEncodingNone; - - if (charMatchesEncoding(ch, kShiftJISRanges, ARRAY_SIZE(kShiftJISRanges))) - result |= kEncodingShiftJIS; - if (charMatchesEncoding(ch, kGBKRanges, ARRAY_SIZE(kGBKRanges))) - result |= kEncodingGBK; - if (charMatchesEncoding(ch, kBig5Ranges, ARRAY_SIZE(kBig5Ranges))) - result |= kEncodingBig5; - if (charMatchesEncoding(ch, kEUCKRRanges, ARRAY_SIZE(kEUCKRRanges))) - result |= kEncodingEUCKR; - - return result; -} diff --git a/media/libmedia/autodetect.h b/media/libmedia/autodetect.h deleted file mode 100644 index 9675db3..0000000 --- a/media/libmedia/autodetect.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef AUTODETECT_H -#define AUTODETECT_H - -#include - -// flags used for native encoding detection -enum { - kEncodingNone = 0, - kEncodingShiftJIS = (1 << 0), - kEncodingGBK = (1 << 1), - kEncodingBig5 = (1 << 2), - kEncodingEUCKR = (1 << 3), - - kEncodingAll = (kEncodingShiftJIS | kEncodingGBK | kEncodingBig5 | kEncodingEUCKR), -}; - - -// returns a bitfield containing the possible native encodings for the given character -extern uint32_t findPossibleEncodings(int ch); - -#endif // AUTODETECT_H -- cgit v1.1 From be08f6a6688f3b1ae6914fbe800953c9bfb13c45 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 19 Dec 2013 09:09:33 -0800 Subject: Fix compile warning / incomplete initialization Change-Id: Ib4accf99be800988e081f96222e1ee73538221ec --- media/libmedia/mediaplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 0f6d897..7a6f31d 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -654,7 +654,7 @@ status_t MediaPlayer::setRetransmitEndpoint(const char* addrString, return BAD_VALUE; } - memset(&mRetransmitEndpoint, 0, sizeof(&mRetransmitEndpoint)); + memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint)); mRetransmitEndpoint.sin_family = AF_INET; mRetransmitEndpoint.sin_addr = saddr; mRetransmitEndpoint.sin_port = htons(port); -- cgit v1.1 From c23885ebb142b9da31543789ecc3f7cf7111bc67 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 19 Dec 2013 16:35:18 -0800 Subject: Add versions of get/SetParameters without I/O handle This is a step towards hiding I/O handles from application level, as much as possible. Change-Id: I30f4171d5dcf77f8e8eb332ce2e9245b30f5f2e1 --- media/libmedia/AudioSystem.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 8033c2c..18f0f46 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -190,6 +190,16 @@ String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& ke return result; } +status_t AudioSystem::setParameters(const String8& keyValuePairs) +{ + return setParameters((audio_io_handle_t) 0, keyValuePairs); +} + +String8 AudioSystem::getParameters(const String8& keys) +{ + return getParameters((audio_io_handle_t) 0, keys); +} + // convert volume steps to natural log scale // change this value to change volume scaling -- cgit v1.1 From 7c7be1e05634d96d08210efb4bdeb012ffba440d Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 19 Dec 2013 16:34:04 -0800 Subject: Fix some (but not all) unused parameter warnings Change-Id: Ia99e23a0b46db3f3e6aa46f9018e63c14f4af369 --- media/libmedia/AudioRecord.cpp | 6 +++--- media/libmedia/AudioSystem.cpp | 4 ++-- media/libmedia/AudioTrack.cpp | 8 ++++---- media/libmedia/AudioTrackShared.cpp | 4 ++-- media/libmedia/IMediaDeathNotifier.cpp | 2 +- media/libmedia/SoundPool.cpp | 4 ++-- media/libmedia/mediametadataretriever.cpp | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 666fafa..6ec8ed2 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -692,7 +692,7 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize) // ------------------------------------------------------------------------- -nsecs_t AudioRecord::processAudioBuffer(const sp& thread) +nsecs_t AudioRecord::processAudioBuffer() { mLock.lock(); if (mAwaitBoost) { @@ -954,7 +954,7 @@ status_t AudioRecord::restoreRecord_l(const char *from) // ========================================================================= -void AudioRecord::DeathNotifier::binderDied(const wp& who) +void AudioRecord::DeathNotifier::binderDied(const wp& who __unused) { sp audioRecord = mAudioRecord.promote(); if (audioRecord != 0) { @@ -993,7 +993,7 @@ bool AudioRecord::AudioRecordThread::threadLoop() return true; } } - nsecs_t ns = mReceiver.processAudioBuffer(this); + nsecs_t ns = mReceiver.processAudioBuffer(); switch (ns) { case 0: return true; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 8033c2c..9b0ad22 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -419,7 +419,7 @@ void AudioSystem::releaseAudioSessionId(int audioSession) { // --------------------------------------------------------------------------- -void AudioSystem::AudioFlingerClient::binderDied(const wp& who) { +void AudioSystem::AudioFlingerClient::binderDied(const wp& who __unused) { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); @@ -804,7 +804,7 @@ bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info) // --------------------------------------------------------------------------- -void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who) { +void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioPolicyService.clear(); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index b48cb1f..ddd4612 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1341,7 +1341,7 @@ status_t TimedAudioTrack::setMediaTimeTransform(const LinearTransform& xform, // ------------------------------------------------------------------------- -nsecs_t AudioTrack::processAudioBuffer(const sp& thread) +nsecs_t AudioTrack::processAudioBuffer() { // Currently the AudioTrack thread is not created if there are no callbacks. // Would it ever make sense to run the thread, even without callbacks? @@ -1767,7 +1767,7 @@ String8 AudioTrack::getParameters(const String8& keys) } } -status_t AudioTrack::dump(int fd, const Vector& args) const +status_t AudioTrack::dump(int fd, const Vector& args __unused) const { const size_t SIZE = 256; @@ -1797,7 +1797,7 @@ uint32_t AudioTrack::getUnderrunFrames() const // ========================================================================= -void AudioTrack::DeathNotifier::binderDied(const wp& who) +void AudioTrack::DeathNotifier::binderDied(const wp& who __unused) { sp audioTrack = mAudioTrack.promote(); if (audioTrack != 0) { @@ -1841,7 +1841,7 @@ bool AudioTrack::AudioTrackThread::threadLoop() return true; } } - nsecs_t ns = mReceiver.processAudioBuffer(this); + nsecs_t ns = mReceiver.processAudioBuffer(); switch (ns) { case 0: return true; diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index caa7900..7a1e207 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -765,7 +765,7 @@ ssize_t StaticAudioTrackServerProxy::pollPosition() return (ssize_t) position; } -status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) +status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush __unused) { if (mIsShutdown) { buffer->mFrameCount = 0; @@ -847,7 +847,7 @@ void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) buffer->mNonContig = 0; } -void StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount) +void StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount __unused) { // Unlike AudioTrackServerProxy::tallyUnderrunFrames() used for streaming tracks, // we don't have a location to count underrun frames. The underrun frame counter diff --git a/media/libmedia/IMediaDeathNotifier.cpp b/media/libmedia/IMediaDeathNotifier.cpp index 9db5b1b..10b4934 100644 --- a/media/libmedia/IMediaDeathNotifier.cpp +++ b/media/libmedia/IMediaDeathNotifier.cpp @@ -75,7 +75,7 @@ IMediaDeathNotifier::removeObitRecipient(const wp& recipien } void -IMediaDeathNotifier::DeathNotifier::binderDied(const wp& who) { +IMediaDeathNotifier::DeathNotifier::binderDied(const wp& who __unused) { ALOGW("media server died"); // Need to do this with the lock held diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index b420c95..98acd1f 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -199,7 +199,7 @@ SoundChannel* SoundPool::findNextChannel(int channelID) return NULL; } -int SoundPool::load(const char* path, int priority) +int SoundPool::load(const char* path, int priority __unused) { ALOGV("load: path=%s, priority=%d", path, priority); Mutex::Autolock lock(&mLock); @@ -209,7 +209,7 @@ int SoundPool::load(const char* path, int priority) return sample->sampleID(); } -int SoundPool::load(int fd, int64_t offset, int64_t length, int priority) +int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused) { ALOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d", fd, offset, length, priority); diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp index 110b94c..bad2494 100644 --- a/media/libmedia/mediametadataretriever.cpp +++ b/media/libmedia/mediametadataretriever.cpp @@ -157,7 +157,7 @@ sp MediaMetadataRetriever::extractAlbumArt() return mRetriever->extractAlbumArt(); } -void MediaMetadataRetriever::DeathNotifier::binderDied(const wp& who) { +void MediaMetadataRetriever::DeathNotifier::binderDied(const wp& who __unused) { Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); MediaMetadataRetriever::sService.clear(); ALOGW("MediaMetadataRetriever server died!"); -- cgit v1.1 From 74935e44734c1ec235c2b6677db3e0dbefa5ddb8 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 19 Dec 2013 08:56:45 -0800 Subject: Replace control block frameCount_ by explicit in/out parameter in IAudioFlinger::createTrack and IAudioFlinger::openRecord Change-Id: I09c644c80e92c8e744b1b99055988a2588b2a83d --- media/libmedia/AudioRecord.cpp | 13 +++++++++---- media/libmedia/AudioTrack.cpp | 6 ++++-- media/libmedia/AudioTrackShared.cpp | 2 +- media/libmedia/IAudioFlinger.cpp | 20 ++++++++++++++++---- 4 files changed, 30 insertions(+), 11 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 666fafa..13c9f60 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -255,9 +255,6 @@ status_t AudioRecord::set( mStatus = NO_ERROR; - // Update buffer size in case it has been limited by AudioFlinger during track creation - mFrameCount = mCblk->frameCount_; - mActive = false; mCbf = cbf; mRefreshRemaining = true; @@ -462,11 +459,13 @@ status_t AudioRecord::openRecord_l(size_t epoch) return BAD_VALUE; } + size_t temp = mFrameCount; // temp may be replaced by a revised value of frameCount, + // but we will still need the original value also int originalSessionId = mSessionId; sp record = audioFlinger->openRecord(input, mSampleRate, mFormat, mChannelMask, - mFrameCount, + &temp, &trackFlags, tid, &mSessionId, @@ -498,6 +497,12 @@ status_t AudioRecord::openRecord_l(size_t epoch) mCblkMemory = iMem; audio_track_cblk_t* cblk = static_cast(iMemPointer); mCblk = cblk; + // note that temp is the (possibly revised) value of mFrameCount + if (temp < mFrameCount || (mFrameCount == 0 && temp == 0)) { + ALOGW("Requested frameCount %u but received frameCount %u", mFrameCount, temp); + } + mFrameCount = temp; + // FIXME missing fast track frameCount logic mAwaitBoost = false; if (mFlags & AUDIO_INPUT_FLAG_FAST) { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index b48cb1f..74bb7a6 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -969,13 +969,15 @@ status_t AudioTrack::createTrack_l( trackFlags |= IAudioFlinger::TRACK_OFFLOAD; } + size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, + // but we will still need the original value also sp track = audioFlinger->createTrack(streamType, sampleRate, // AudioFlinger only sees 16-bit PCM format == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : format, mChannelMask, - frameCount, + &temp, &trackFlags, sharedBuffer, output, @@ -1003,7 +1005,7 @@ status_t AudioTrack::createTrack_l( mCblkMemory = iMem; audio_track_cblk_t* cblk = static_cast(iMem->pointer()); mCblk = cblk; - size_t temp = cblk->frameCount_; + // note that temp is the (possibly revised) value of frameCount if (temp < frameCount || (frameCount == 0 && temp == 0)) { // In current design, AudioTrack client checks and ensures frame count validity before // passing it to AudioFlinger so AudioFlinger should not return a different value except diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index caa7900..11f5d58 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -26,7 +26,7 @@ extern "C" { namespace android { audio_track_cblk_t::audio_track_cblk_t() - : mServer(0), frameCount_(0), mFutex(0), mMinimum(0), + : mServer(0), mFutex(0), mMinimum(0), mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mFlags(0) { memset(&u, 0, sizeof(u)); diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 9df10f0..c33cb13 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -89,7 +89,7 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - size_t frameCount, + size_t *pFrameCount, track_flags_t *flags, const sp& sharedBuffer, audio_io_handle_t output, @@ -106,6 +106,7 @@ public: data.writeInt32(sampleRate); data.writeInt32(format); data.writeInt32(channelMask); + size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0; data.writeInt32(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); @@ -127,6 +128,10 @@ public: if (lStatus != NO_ERROR) { ALOGE("createTrack error: %s", strerror(-lStatus)); } else { + frameCount = reply.readInt32(); + if (pFrameCount != NULL) { + *pFrameCount = frameCount; + } lFlags = reply.readInt32(); if (flags != NULL) { *flags = lFlags; @@ -150,7 +155,7 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - size_t frameCount, + size_t *pFrameCount, track_flags_t *flags, pid_t tid, int *sessionId, @@ -163,6 +168,7 @@ public: data.writeInt32(sampleRate); data.writeInt32(format); data.writeInt32(channelMask); + size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0; data.writeInt32(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); @@ -176,6 +182,10 @@ public: if (lStatus != NO_ERROR) { ALOGE("openRecord error: %s", strerror(-lStatus)); } else { + frameCount = reply.readInt32(); + if (pFrameCount != NULL) { + *pFrameCount = frameCount; + } lFlags = reply.readInt32(); if (flags != NULL) { *flags = lFlags; @@ -793,9 +803,10 @@ status_t BnAudioFlinger::onTransact( } else { track = createTrack( (audio_stream_type_t) streamType, sampleRate, format, - channelMask, frameCount, &flags, buffer, output, tid, + channelMask, &frameCount, &flags, buffer, output, tid, &sessionId, name, clientUid, &status); } + reply->writeInt32(frameCount); reply->writeInt32(flags); reply->writeInt32(sessionId); reply->writeString8(name); @@ -815,8 +826,9 @@ status_t BnAudioFlinger::onTransact( int sessionId = data.readInt32(); status_t status; sp record = openRecord(input, - sampleRate, format, channelMask, frameCount, &flags, tid, &sessionId, &status); + sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, &status); LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR)); + reply->writeInt32(frameCount); reply->writeInt32(flags); reply->writeInt32(sessionId); reply->writeInt32(status); -- cgit v1.1 From aea7ea06394bcb155972d82055d4ea59962e4051 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 26 Jun 2013 09:25:47 -0700 Subject: Use AUDIO_SESSION_ALLOCATE instead of 0 Also fix a couple of places where we were using AUDIO_SESSION_OUTPUT_MIX, which happens to also be equal to 0, but has a different meaning. Change-Id: I90e39be3b89f5021a96d9e3b8d10929013ca977f --- media/libmedia/AudioRecord.cpp | 8 ++++---- media/libmedia/IAudioFlinger.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 666fafa..df99147 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -71,7 +71,7 @@ status_t AudioRecord::getMinFrameCount( // --------------------------------------------------------------------------- AudioRecord::AudioRecord() - : mStatus(NO_INIT), mSessionId(0), + : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) { } @@ -88,7 +88,7 @@ AudioRecord::AudioRecord( int sessionId, transfer_type transferType, audio_input_flags_t flags) - : mStatus(NO_INIT), mSessionId(0), + : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL) @@ -233,7 +233,7 @@ status_t AudioRecord::set( mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; - if (sessionId == 0 ) { + if (sessionId == AUDIO_SESSION_ALLOCATE) { mSessionId = AudioSystem::newAudioSessionId(); } else { mSessionId = sessionId; @@ -471,7 +471,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) tid, &mSessionId, &status); - ALOGE_IF(originalSessionId != 0 && mSessionId != originalSessionId, + ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId, "session ID changed from %d to %d", originalSessionId, mSessionId); if (record == 0 || status != NO_ERROR) { diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 9df10f0..c9c8d58 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -117,7 +117,7 @@ public: } data.writeInt32((int32_t) output); data.writeInt32((int32_t) tid); - int lSessionId = 0; + int lSessionId = AUDIO_SESSION_ALLOCATE; if (sessionId != NULL) { lSessionId = *sessionId; } @@ -167,7 +167,7 @@ public: track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); data.writeInt32((int32_t) tid); - int lSessionId = 0; + int lSessionId = AUDIO_SESSION_ALLOCATE; if (sessionId != NULL) { lSessionId = *sessionId; } -- cgit v1.1 From 5446e541367061b53f45f3fd4600f9060680bca3 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 8 Jan 2014 08:58:53 -0800 Subject: Cleanup AudioSystem::getInputBufferSize error handling and caching Previously, if the IAudioFlinger::getInputBufferSize failed, it would return NO_ERROR but a zero buffer size value, which could confuse the caller. Now it returns BAD_VALUE in this case. Also it would still cache the zero buffer size. Now it does not cache on failure. Removed over-initialization of the cache globals. Change-Id: I6835fcb56fe52535e018fc8c0c242115221b5d85 --- media/libmedia/AudioSystem.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 9a76111..de3beb5 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -40,10 +40,10 @@ audio_error_callback AudioSystem::gAudioErrorCallback = NULL; DefaultKeyedVector AudioSystem::gOutputs(0); // Cached values for recording queries, all protected by gLock -uint32_t AudioSystem::gPrevInSamplingRate = 16000; -audio_format_t AudioSystem::gPrevInFormat = AUDIO_FORMAT_PCM_16_BIT; -audio_channel_mask_t AudioSystem::gPrevInChannelMask = AUDIO_CHANNEL_IN_MONO; -size_t AudioSystem::gInBuffSize = 0; +uint32_t AudioSystem::gPrevInSamplingRate; +audio_format_t AudioSystem::gPrevInFormat; +audio_channel_mask_t AudioSystem::gPrevInChannelMask; +size_t AudioSystem::gInBuffSize = 0; // zero indicates cache is invalid // establish binder interface to AudioFlinger service @@ -359,6 +359,12 @@ status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t for return PERMISSION_DENIED; } inBuffSize = af->getInputBufferSize(sampleRate, format, channelMask); + if (inBuffSize == 0) { + ALOGE("AudioSystem::getInputBufferSize failed sampleRate %d format %x channelMask %x", + sampleRate, format, channelMask); + return BAD_VALUE; + } + // A benign race is possible here: we could overwrite a fresher cache entry gLock.lock(); // save the request params gPrevInSamplingRate = sampleRate; -- cgit v1.1 From f94006ca0f30c27868c284e553f57bf467ae92bc Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 8 Jan 2014 08:56:06 -0800 Subject: Cleanup error handling in AudioSystem get methods Don't return zero sample rate or frame count without an error. Change-Id: I052d841080ed33e4f081ae9825a2f33dff444fb9 --- media/libmedia/AudioSystem.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 9a76111..e37888b 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -259,6 +259,11 @@ status_t AudioSystem::getSamplingRate(audio_io_handle_t output, *samplingRate = outputDesc->samplingRate; gLock.unlock(); } + if (*samplingRate == 0) { + ALOGE("AudioSystem::getSamplingRate failed for output %d stream type %d", + output, streamType); + return BAD_VALUE; + } ALOGV("getSamplingRate() streamType %d, output %d, sampling rate %u", streamType, output, *samplingRate); @@ -299,6 +304,11 @@ status_t AudioSystem::getFrameCount(audio_io_handle_t output, *frameCount = outputDesc->frameCount; gLock.unlock(); } + if (*frameCount == 0) { + ALOGE("AudioSystem::getFrameCount failed for output %d stream type %d", + output, streamType); + return BAD_VALUE; + } ALOGV("getFrameCount() streamType %d, output %d, frameCount %d", streamType, output, *frameCount); -- cgit v1.1 From 66a0467fdddada4caabd0f0a999fbb367fea7bee Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 8 Jan 2014 08:53:44 -0800 Subject: Cleanup AudioTrack::getMinFrameCount error handling Guarantee to return a non-zero frameCount for return status NO_ERROR; Return the correct specific status_t if any of the AudioSystem APIs fail, instead of the generic NO_INIT. API change: getMinFramCount no longer defaults to zero on error, so callers _must_ check the return status. This change makes getMinFrameCount more like other APIs. All known callers were reviewed, and they do check the return status. Change-Id: I4a8342a75ee89a068c23c84b8380ed9d1b968507 --- media/libmedia/AudioTrack.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index ddd4612..a6ffc62 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -44,9 +44,6 @@ status_t AudioTrack::getMinFrameCount( return BAD_VALUE; } - // default to 0 in case of error - *frameCount = 0; - // FIXME merge with similar code in createTrack_l(), except we're missing // some information here that is available in createTrack_l(): // audio_io_handle_t output @@ -54,16 +51,20 @@ status_t AudioTrack::getMinFrameCount( // audio_channel_mask_t channelMask // audio_output_flags_t flags uint32_t afSampleRate; - if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { - return NO_INIT; + status_t status; + status = AudioSystem::getOutputSamplingRate(&afSampleRate, streamType); + if (status != NO_ERROR) { + return status; } size_t afFrameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { - return NO_INIT; + status = AudioSystem::getOutputFrameCount(&afFrameCount, streamType); + if (status != NO_ERROR) { + return status; } uint32_t afLatency; - if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { - return NO_INIT; + status = AudioSystem::getOutputLatency(&afLatency, streamType); + if (status != NO_ERROR) { + return status; } // Ensure that buffer depth covers at least audio hardware latency @@ -74,6 +75,13 @@ status_t AudioTrack::getMinFrameCount( *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount : afFrameCount * minBufCount * sampleRate / afSampleRate; + // The formula above should always produce a non-zero value, but return an error + // in the unlikely event that it does not, as that's part of the API contract. + if (*frameCount == 0) { + ALOGE("AudioTrack::getMinFrameCount failed for streamType %d, sampleRate %d", + streamType, sampleRate); + return BAD_VALUE; + } ALOGV("getMinFrameCount=%d: afFrameCount=%d, minBufCount=%d, afSampleRate=%d, afLatency=%d", *frameCount, afFrameCount, minBufCount, afSampleRate, afLatency); return NO_ERROR; -- cgit v1.1 From efa6ea97022780b68e595e5326e30dbe2a799202 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 8 Jan 2014 09:10:43 -0800 Subject: Fix error handling in AudioSystem::getOutputForEffect and AudioPolicyService::getOutputForEffect. The conventional error value for audio_io_handle_t is 0, not a status_t cast to audio_io_handle_t. Change-Id: I34b3fd1a50f3fa1cbf39f32eea1911112a4e094a --- media/libmedia/AudioSystem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 9a76111..cf7dfef 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -719,7 +719,8 @@ audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream) audio_io_handle_t AudioSystem::getOutputForEffect(const effect_descriptor_t *desc) { const sp& aps = AudioSystem::get_audio_policy_service(); - if (aps == 0) return PERMISSION_DENIED; + // FIXME change return type to status_t, and return PERMISSION_DENIED here + if (aps == 0) return 0; return aps->getOutputForEffect(desc); } -- cgit v1.1 From 396fabdb6efcdac5aea3d9f559d1beedf6a4cedc Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 8 Jan 2014 08:54:23 -0800 Subject: Document AudioTrack mFrameCount and mReqFrameCount better and remove unnecessary initialization of mFrameCount in set(). Change-Id: I9effeb0a6dd035ca02fe77f6992c55d9515b4df6 --- media/libmedia/AudioTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a6ffc62..7f6fd7a 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -318,7 +318,7 @@ status_t AudioTrack::set( mVolume[LEFT] = 1.0f; mVolume[RIGHT] = 1.0f; mSendLevel = 0.0f; - mFrameCount = frameCount; + // mFrameCount is initialized in createTrack_l mReqFrameCount = frameCount; mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; -- cgit v1.1 From 2c6c5294388e251ebc1e00d6c8785190561c27fc Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 10:29:08 -0800 Subject: Fix race in AudioTrack::getParameters() mOutput is protected by mLock. Change-Id: Id02e627062855ca60f28bd8961b1d5f44939c727 --- media/libmedia/AudioTrack.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a6ffc62..1d56788 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1768,8 +1768,9 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) String8 AudioTrack::getParameters(const String8& keys) { - if (mOutput) { - return AudioSystem::getParameters(mOutput, keys); + audio_io_handle_t output = getOutput(); + if (output != 0) { + return AudioSystem::getParameters(output, keys); } else { return String8::empty(); } -- cgit v1.1 From b1bef51fec06e8bceec914d1b48b411d3ff2adff Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 10:25:53 -0800 Subject: Improve error logging for getOutputSamplingRate Change-Id: I3b52402a663b27efe1d7c6a4f684521f33f3ff8f --- media/libmedia/AudioTrack.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a6ffc62..f9d335f 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -245,12 +245,14 @@ status_t AudioTrack::set( streamType = AUDIO_STREAM_MUSIC; } + status_t status; if (sampleRate == 0) { - uint32_t afSampleRate; - if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { - return NO_INIT; + status = AudioSystem::getOutputSamplingRate(&sampleRate, streamType); + if (status != NO_ERROR) { + ALOGE("Could not get output sample rate for stream type %d; status %d", + streamType, status); + return status; } - sampleRate = afSampleRate; } mSampleRate = sampleRate; @@ -338,7 +340,7 @@ status_t AudioTrack::set( } // create the IAudioTrack - status_t status = createTrack_l(streamType, + status = createTrack_l(streamType, sampleRate, format, frameCount, -- cgit v1.1 From 41721bb796da589f8a669d1db7687a0da8f88761 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 09:59:51 -0800 Subject: Fix race condition in AudioRecord::pause followed by start Bug: 11148722 Change-Id: Ia1e14133d73ac301fe06a047e70a573911822630 --- media/libmedia/AudioRecord.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 6ec8ed2..4328593 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -966,7 +966,8 @@ void AudioRecord::DeathNotifier::binderDied(const wp& who __unused) // ========================================================================= AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava) - : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL) + : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL), + mIgnoreNextPausedInt(false) { } @@ -983,6 +984,10 @@ bool AudioRecord::AudioRecordThread::threadLoop() // caller will check for exitPending() return true; } + if (mIgnoreNextPausedInt) { + mIgnoreNextPausedInt = false; + mPausedInt = false; + } if (mPausedInt) { if (mPausedNs > 0) { (void) mMyCond.waitRelative(mMyLock, mPausedNs); @@ -1017,12 +1022,7 @@ void AudioRecord::AudioRecordThread::requestExit() { // must be in this order to avoid a race condition Thread::requestExit(); - AutoMutex _l(mMyLock); - if (mPaused || mPausedInt) { - mPaused = false; - mPausedInt = false; - mMyCond.signal(); - } + resume(); } void AudioRecord::AudioRecordThread::pause() @@ -1034,6 +1034,7 @@ void AudioRecord::AudioRecordThread::pause() void AudioRecord::AudioRecordThread::resume() { AutoMutex _l(mMyLock); + mIgnoreNextPausedInt = true; if (mPaused || mPausedInt) { mPaused = false; mPausedInt = false; -- cgit v1.1 From 23a7545c4de71e989c2d8ebf1d5b9dcf463c36a9 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 10:37:17 -0800 Subject: Document locking rules for mFlags, and fix discrepancies Change-Id: Id45ba544cc84133ed5e578fb4fd8a11b62211dc1 --- media/libmedia/AudioTrack.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 50e394b..8954d9f 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -457,7 +457,7 @@ void AudioTrack::stop() return; } - if (isOffloaded()) { + if (isOffloaded_l()) { mState = STATE_STOPPING; } else { mState = STATE_STOPPED; @@ -479,7 +479,7 @@ void AudioTrack::stop() sp t = mAudioTrackThread; if (t != 0) { - if (!isOffloaded()) { + if (!isOffloaded_l()) { t->pause(); } } else { @@ -517,7 +517,7 @@ void AudioTrack::flush_l() mRefreshRemaining = true; mState = STATE_FLUSHED; - if (isOffloaded()) { + if (isOffloaded_l()) { mProxy->interrupt(); } mProxy->flush(); @@ -550,7 +550,7 @@ status_t AudioTrack::setVolume(float left, float right) mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); - if (isOffloaded()) { + if (isOffloaded_l()) { mAudioTrack->signal(); } return NO_ERROR; @@ -614,7 +614,7 @@ uint32_t AudioTrack::getSampleRate() const // sample rate can be updated during playback by the offloaded decoder so we need to // query the HAL and update if needed. // FIXME use Proxy return channel to update the rate from server and avoid polling here - if (isOffloaded()) { + if (isOffloaded_l()) { if (mOutput != 0) { uint32_t sampleRate = 0; status_t status = AudioSystem::getSamplingRate(mOutput, mStreamType, &sampleRate); @@ -751,7 +751,7 @@ status_t AudioTrack::getPosition(uint32_t *position) const } AutoMutex lock(mLock); - if (isOffloaded()) { + if (isOffloaded_l()) { uint32_t dspFrames = 0; if (mOutput != 0) { @@ -1389,7 +1389,7 @@ nsecs_t AudioTrack::processAudioBuffer() // for offloaded tracks restoreTrack_l() will just update the sequence and clear // AudioSystem cache. We should not exit here but after calling the callback so // that the upper layers can recreate the track - if (!isOffloaded() || (mSequence == mObservedSequence)) { + if (!isOffloaded_l() || (mSequence == mObservedSequence)) { status_t status = restoreTrack_l("processAudioBuffer"); mLock.unlock(); // Run again immediately, but with a new IAudioTrack @@ -1676,7 +1676,7 @@ nsecs_t AudioTrack::processAudioBuffer() status_t AudioTrack::restoreTrack_l(const char *from) { ALOGW("dead IAudioTrack, %s, creating a new one from %s()", - isOffloaded() ? "Offloaded" : "PCM", from); + isOffloaded_l() ? "Offloaded" : "PCM", from); ++mSequence; status_t result; @@ -1684,7 +1684,8 @@ status_t AudioTrack::restoreTrack_l(const char *from) // output parameters in getOutput_l() and createTrack_l() AudioSystem::clearAudioConfigCache(); - if (isOffloaded()) { + if (isOffloaded_l()) { + // FIXME re-creation of offloaded tracks is not yet implemented return DEAD_OBJECT; } @@ -1778,6 +1779,12 @@ String8 AudioTrack::getParameters(const String8& keys) } } +bool AudioTrack::isOffloaded() const +{ + AutoMutex lock(mLock); + return isOffloaded_l(); +} + status_t AudioTrack::dump(int fd, const Vector& args __unused) const { -- cgit v1.1 From 2b2165c75790050810460c8de3f414876bce4c0e Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 08:53:36 -0800 Subject: Unify comments between AudioTrack and AudioRecord Change-Id: I00a1025e2891a1c96218b3c2187eaddda6614ebc --- media/libmedia/AudioRecord.cpp | 8 +++++--- media/libmedia/AudioTrack.cpp | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 4328593..d2a81e1 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -352,6 +352,7 @@ bool AudioRecord::stopped() const status_t AudioRecord::setMarkerPosition(uint32_t marker) { + // The only purpose of setting marker position is to get a callback if (mCbf == NULL) { return INVALID_OPERATION; } @@ -377,6 +378,7 @@ status_t AudioRecord::getMarkerPosition(uint32_t *marker) const status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) { + // The only purpose of setting position update period is to get a callback if (mCbf == NULL) { return INVALID_OPERATION; } @@ -770,7 +772,7 @@ nsecs_t AudioRecord::processAudioBuffer() int32_t sequence = mSequence; // These fields don't need to be cached, because they are assigned only by set(): - // mTransfer, mCbf, mUserData, mSampleRate + // mTransfer, mCbf, mUserData, mSampleRate, mFrameSize mLock.unlock(); @@ -844,8 +846,8 @@ nsecs_t AudioRecord::processAudioBuffer() "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount); requested = &ClientProxy::kNonBlocking; size_t avail = audioBuffer.frameCount + nonContig; - ALOGV("obtainBuffer(%u) returned %u = %u + %u", - mRemainingFrames, avail, audioBuffer.frameCount, nonContig); + ALOGV("obtainBuffer(%u) returned %u = %u + %u err %d", + mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err); if (err != NO_ERROR) { if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) { break; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 8954d9f..8aa0126 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -355,7 +355,7 @@ status_t AudioTrack::set( mAudioTrackThread->requestExitAndWait(); mAudioTrackThread.clear(); } - //Use of direct and offloaded output streams is ref counted by audio policy manager. + // Use of direct and offloaded output streams is ref counted by audio policy manager. // As getOutput was called above and resulted in an output stream to be opened, // we need to release it. AudioSystem::releaseOutput(output); @@ -698,6 +698,7 @@ status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) AutoMutex lock(mLock); mNewPosition = mProxy->getPosition() + updatePeriod; mUpdatePeriod = updatePeriod; + return NO_ERROR; } @@ -1735,7 +1736,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) } } if (result != NO_ERROR) { - //Use of direct and offloaded output streams is ref counted by audio policy manager. + // Use of direct and offloaded output streams is ref counted by audio policy manager. // As getOutput was called above and resulted in an output stream to be opened, // we need to release it. AudioSystem::releaseOutput(output); -- cgit v1.1 From 5f972c031d4061f4f037c9fda1ea4bd9b6a756cd Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 09:59:31 -0800 Subject: AudioRecord::getInputFramesLost() cleanup Fixed bug that if the binder call failed (for example if the IAudioFlinger binder is dead), then getInputFramesLost was returning garbage. Now it correctly returns zero, which is the error value for this method. The type declarations for getInputFramesLost were inconsistent: a mixture of unsigned int, size_t, and uint32_t. Now it returns uint32_t everywhere, which is what the underlying HAL API returns. Added a FIXME about the side effect behavior. This will need review for multi-client. Change-Id: Ifa2e117a87dbd0c1f2c892a31d1c3dd919bf1a0a --- media/libmedia/AudioRecord.cpp | 2 +- media/libmedia/AudioSystem.cpp | 4 ++-- media/libmedia/IAudioFlinger.cpp | 11 +++++++---- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index e39a475..0a728a8 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -412,7 +412,7 @@ status_t AudioRecord::getPosition(uint32_t *position) const return NO_ERROR; } -unsigned int AudioRecord::getInputFramesLost() const +uint32_t AudioRecord::getInputFramesLost() const { // no need to check mActive, because if inactive this will return 0, which is what we want return AudioSystem::getInputFramesLost(getInput()); diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 4580030..2188cac 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -413,9 +413,9 @@ status_t AudioSystem::getRenderPosition(audio_io_handle_t output, size_t *halFra return af->getRenderPosition(halFrames, dspFrames, output); } -size_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) { +uint32_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) { const sp& af = AudioSystem::get_audio_flinger(); - unsigned int result = 0; + uint32_t result = 0; if (af == 0) return result; if (ioHandle == 0) return result; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index c9c8d58..3aaff88 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -564,13 +564,16 @@ public: return status; } - virtual size_t getInputFramesLost(audio_io_handle_t ioHandle) const + virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32((int32_t) ioHandle); - remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply); - return reply.readInt32(); + status_t status = remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply); + if (status != NO_ERROR) { + return 0; + } + return (uint32_t) reply.readInt32(); } virtual int newAudioSessionId() @@ -1044,7 +1047,7 @@ status_t BnAudioFlinger::onTransact( case GET_INPUT_FRAMES_LOST: { CHECK_INTERFACE(IAudioFlinger, data, reply); audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32(); - reply->writeInt32(getInputFramesLost(ioHandle)); + reply->writeInt32((int32_t) getInputFramesLost(ioHandle)); return NO_ERROR; } break; case NEW_AUDIO_SESSION_ID: { -- cgit v1.1 From 8ff50e7526d24aca11713006933b8dcb64ef6be9 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 14 Jan 2014 15:44:30 -0800 Subject: Use uint32_t sequence numbers for IAudioRecord This makes it the same as for IAudioTrack. Previously we had a mix of int, int32_t and uint32_t, which could cause comparisons to fail. Change-Id: Ic72ef650ee81f65db11e42ed16d818fdf3e310f4 --- media/libmedia/AudioRecord.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index e39a475..076404b 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -767,7 +767,7 @@ nsecs_t AudioRecord::processAudioBuffer() mRetryOnPartialBuffer = false; } size_t misalignment = mProxy->getMisalignment(); - int32_t sequence = mSequence; + uint32_t sequence = mSequence; // These fields don't need to be cached, because they are assigned only by set(): // mTransfer, mCbf, mUserData, mSampleRate -- cgit v1.1 From 7103d9671ded507fd3f6938297019a32f71ea5a0 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 14 Jan 2014 15:47:52 -0800 Subject: Remove dead code in AudioTrack::processAudioBuffer Change-Id: I0baefe9dc08bb5ec45d34698fc764caa160789d2 --- media/libmedia/AudioTrack.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d5e3e67..3794c84 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1610,7 +1610,6 @@ nsecs_t AudioTrack::processAudioBuffer() size_t reqSize = audioBuffer.size; mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); size_t writtenSize = audioBuffer.size; - size_t writtenFrames = writtenSize / mFrameSize; // Sanity check on returned size if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) { -- cgit v1.1 From 70c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03a Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 14 Jan 2014 15:47:01 -0800 Subject: Improve logs in AudioTrack::getMinFrameCount Change-Id: I8b478e6abdded26a43f32c131931939e9ae36fd7 --- media/libmedia/AudioTrack.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d5e3e67..a8f91ab 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -54,16 +54,22 @@ status_t AudioTrack::getMinFrameCount( status_t status; status = AudioSystem::getOutputSamplingRate(&afSampleRate, streamType); if (status != NO_ERROR) { + ALOGE("Unable to query output sample rate for stream type %d; status %d", + streamType, status); return status; } size_t afFrameCount; status = AudioSystem::getOutputFrameCount(&afFrameCount, streamType); if (status != NO_ERROR) { + ALOGE("Unable to query output frame count for stream type %d; status %d", + streamType, status); return status; } uint32_t afLatency; status = AudioSystem::getOutputLatency(&afLatency, streamType); if (status != NO_ERROR) { + ALOGE("Unable to query output latency for stream type %d; status %d", + streamType, status); return status; } -- cgit v1.1 From d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bb Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 14 Jan 2014 15:46:38 -0800 Subject: Cleanup loop termination logic in AudioRecord::obtainBuffer() Apply the same change to AudioRecord, that was already done for AudioTrack in this CL: > Change-Id: I0fc48117946364cb255afd653195498891f622bd If the proxy->obtainBuffer at the end of the "do" loop fails with status DEAD_OBJECT, and the restoreRecord_l during the next trip of the "do" loop also fails, then the value of the buffer fields will be based on the previous proxy->obtainBuffer that returned DEAD_OBJECT. This will have cleared the buffer, but it's tricky. So instead explicitly clear the buffer after restoreRecord_l, before breaking out of the loop. Change-Id: Ifc97f2ab7b8195d6b149502bb5d765d2983b07be --- media/libmedia/AudioRecord.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index e39a475..f332313 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -591,6 +591,9 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r if (newSequence == oldSequence) { status = restoreRecord_l("obtainBuffer"); if (status != NO_ERROR) { + buffer.mFrameCount = 0; + buffer.mRaw = NULL; + buffer.mNonContig = 0; break; } } -- cgit v1.1 From 5e1f79baa5c7355effbd2c9183787d6604487908 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 14 Jan 2014 15:45:21 -0800 Subject: AudioRecord: fix unwanted overrun when restarting Apply the same fix to AudioRecord as this CL did for AudioTrack: > Change-Id: Id703f8dc092a6f07c905eee194054b4a978f979d Details: When restarting an AudioRecord from stopped state, it is necessary to force refresh of mRemainingFrames by processAudioBuffer() as the last read before stop() could be partial. No doing so will lead into unnecessary sleep before filling the non contiguous part of the buffer returned by obtainBuffer() when processAudioBuffer() is executed for the first time after start(). Change-Id: I0ff04648e990e97bad5ea3db5be0c4151250d5e1 --- media/libmedia/AudioRecord.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index e39a475..3a0f222 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -289,6 +289,9 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) // reset current position as seen by client to 0 mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); + // force refresh of remaining frames by processAudioBuffer() as last + // read before stop could be partial. + mRefreshRemaining = true; mNewPosition = mProxy->getPosition() + mUpdatePeriod; int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); -- cgit v1.1 From 0cde076ddb283c84c3801a2df4cc3df99bd1577f Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 16 Jan 2014 15:06:36 -0800 Subject: Cleanup createTrack error handling Similar to cleanup done earlier for openRecord in this CL: > Change-Id: I84897dd7d30b370640b54e928f230604b873cb68 Bug: 10888816 Change-Id: I804a47f898e0319a60a9bd58906bbb037e45cc25 --- media/libmedia/AudioTrack.cpp | 7 ++++++- media/libmedia/IAudioFlinger.cpp | 12 ++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d5e3e67..a113f77 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1004,6 +1004,11 @@ status_t AudioTrack::createTrack_l( ALOGE("Could not get control block"); return NO_INIT; } + void *iMemPointer = iMem->pointer(); + if (iMemPointer == NULL) { + ALOGE("Could not get control block pointer"); + return NO_INIT; + } // invariant that mAudioTrack != 0 is true only after set() returns successfully if (mAudioTrack != 0) { mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this); @@ -1011,7 +1016,7 @@ status_t AudioTrack::createTrack_l( } mAudioTrack = track; mCblkMemory = iMem; - audio_track_cblk_t* cblk = static_cast(iMem->pointer()); + audio_track_cblk_t* cblk = static_cast(iMemPointer); mCblk = cblk; size_t temp = cblk->frameCount_; if (temp < frameCount || (frameCount == 0 && temp == 0)) { diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index c9c8d58..ecbb5bf 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -138,6 +138,17 @@ public: name = reply.readString8(); lStatus = reply.readInt32(); track = interface_cast(reply.readStrongBinder()); + if (lStatus == NO_ERROR) { + if (track == 0) { + ALOGE("createTrack should have returned an IAudioTrack"); + lStatus = UNKNOWN_ERROR; + } + } else { + if (track != 0) { + ALOGE("createTrack returned an IAudioTrack but with status %d", lStatus); + track.clear(); + } + } } if (status != NULL) { *status = lStatus; @@ -795,6 +806,7 @@ status_t BnAudioFlinger::onTransact( (audio_stream_type_t) streamType, sampleRate, format, channelMask, frameCount, &flags, buffer, output, tid, &sessionId, name, clientUid, &status); + LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR)); } reply->writeInt32(flags); reply->writeInt32(sessionId); -- cgit v1.1 From dd5f4c8c4059f890e81b28b026a688febb4e1dd9 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 10:26:32 -0800 Subject: Move up initialization of mFormat, mStreamType, and mSharedBuffer earlier This will allow removal of most of the parameter list to createTrack_l. Also check for valid stream type at client so we can log a better error message. Change-Id: Ia7176896d47fbb49106119fca26d9de8e7efe859 --- media/libmedia/AudioTrack.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a113f77..eeaab44 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -216,6 +216,7 @@ status_t AudioTrack::set( ALOGE("Invalid transfer type %d", transferType); return BAD_VALUE; } + mSharedBuffer = sharedBuffer; mTransfer = transferType; // FIXME "int" here is legacy and will be replaced by size_t later @@ -244,6 +245,11 @@ status_t AudioTrack::set( if (streamType == AUDIO_STREAM_DEFAULT) { streamType = AUDIO_STREAM_MUSIC; } + if (uint32_t(streamType) >= AUDIO_STREAM_CNT) { + ALOGE("Invalid stream type %d", streamType); + return BAD_VALUE; + } + mStreamType = streamType; status_t status; if (sampleRate == 0) { @@ -266,6 +272,7 @@ status_t AudioTrack::set( ALOGE("Invalid format %d", format); return BAD_VALUE; } + mFormat = format; if (!audio_is_output_channel(channelMask)) { ALOGE("Invalid channel mask %#x", channelMask); @@ -363,9 +370,6 @@ status_t AudioTrack::set( } mStatus = NO_ERROR; - mStreamType = streamType; - mFormat = format; - mSharedBuffer = sharedBuffer; mState = STATE_STOPPED; mUserData = user; mLoopPeriod = 0; -- cgit v1.1 From b5ccb2d99b2af400c70777a6452f090ac14f5a96 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 14:42:43 -0800 Subject: Make copy of audio_offload_info_t for future use Change-Id: I515970aa0660418d5d1640fb1bf477e112c89bdd --- media/libmedia/AudioTrack.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index eeaab44..2cb3459 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -324,6 +324,16 @@ status_t AudioTrack::set( return BAD_VALUE; } + // Make copy of input parameter offloadInfo so that in the future: + // (a) createTrack_l doesn't need it as an input parameter + // (b) we can support re-creation of offloaded tracks + if (offloadInfo != NULL) { + mOffloadInfoCopy = *offloadInfo; + mOffloadInfo = &mOffloadInfoCopy; + } else { + mOffloadInfo = NULL; + } + mVolume[LEFT] = 1.0f; mVolume[RIGHT] = 1.0f; mSendLevel = 0.0f; -- cgit v1.1 From 38e905b3cbba4da443d799b16999989781afc6d8 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 13 Jan 2014 10:21:48 -0800 Subject: Refactor code related to I/O handles to reduce chance for leaks The AudioRecord input handle code was refactored earlier to fix a potential handle leak, and to simplify the code: > Change-Id: I124dce344b1d11c2dd66ca5e2c9aec0c52c230e2 This changelist refactors AudioTrack similarly, and adds further cleanup of both AudioTrack and AudioRecord. We attempt to implement the rules for referencing counting I/O handles, but there is still the possibility of a handle leak if the client process dies after allocating the handle reference but before releasing it. That issue is being tracked separately. Details: - AudioSystem::getOutput() is now called within createTrack_l - restoreTrack_l was missing offload info now it has the info available, but is not yet being called for offloaded tracks - AudioTrack::getOutput() is now const - Remove getOutput_l() Change-Id: I44a0a623d24fc5847bcac0939c276400568adbca --- media/libmedia/AudioRecord.cpp | 21 ++++++++-- media/libmedia/AudioTrack.cpp | 91 +++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 45 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 0673079..a999e7e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -244,7 +244,7 @@ status_t AudioRecord::set( // create the IAudioRecord status = openRecord_l(0 /*epoch*/); - if (status) { + if (status != NO_ERROR) { return status; } @@ -463,6 +463,9 @@ status_t AudioRecord::openRecord_l(size_t epoch) ALOGE("Could not get audio input for record source %d", mInputSource); return BAD_VALUE; } + { + // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, + // we must release it ourselves if anything goes wrong. size_t temp = mFrameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also @@ -480,9 +483,11 @@ status_t AudioRecord::openRecord_l(size_t epoch) if (record == 0 || status != NO_ERROR) { ALOGE("AudioFlinger could not create record track, status: %d", status); - AudioSystem::releaseInput(input); - return status; + goto release; } + // AudioFlinger now owns the reference to the I/O handle, + // so we are no longer responsible for releasing it. + sp iMem = record->getCblk(); if (iMem == 0) { ALOGE("Could not get control block"); @@ -497,6 +502,8 @@ status_t AudioRecord::openRecord_l(size_t epoch) mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); mDeathNotifier.clear(); } + + // We retain a copy of the I/O handle, but don't own the reference mInput = input; mAudioRecord = record; mCblkMemory = iMem; @@ -540,6 +547,14 @@ status_t AudioRecord::openRecord_l(size_t epoch) mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this); return NO_ERROR; + } + +release: + AudioSystem::releaseInput(input); + if (status == NO_ERROR) { + status = NO_INIT; + } + return status; } status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index c8dc38b..8e91f12 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -245,8 +245,6 @@ status_t AudioTrack::set( return INVALID_OPERATION; } - mOutput = 0; - // handle default values first. if (streamType == AUDIO_STREAM_DEFAULT) { streamType = AUDIO_STREAM_MUSIC; @@ -319,17 +317,6 @@ status_t AudioTrack::set( mFrameSizeAF = sizeof(uint8_t); } - audio_io_handle_t output = AudioSystem::getOutput( - streamType, - sampleRate, format, channelMask, - flags, - offloadInfo); - - if (output == 0) { - ALOGE("Could not get audio output for stream type %d", streamType); - return BAD_VALUE; - } - // Make copy of input parameter offloadInfo so that in the future: // (a) createTrack_l doesn't need it as an input parameter // (b) we can support re-creation of offloaded tracks @@ -369,7 +356,6 @@ status_t AudioTrack::set( frameCount, flags, sharedBuffer, - output, 0 /*epoch*/); if (status != NO_ERROR) { @@ -379,9 +365,15 @@ status_t AudioTrack::set( mAudioTrackThread.clear(); } // Use of direct and offloaded output streams is ref counted by audio policy manager. +#if 0 // FIXME This should no longer be needed + //Use of direct and offloaded output streams is ref counted by audio policy manager. // As getOutput was called above and resulted in an output stream to be opened, // we need to release it. - AudioSystem::releaseOutput(output); + if (mOutput != 0) { + AudioSystem::releaseOutput(mOutput); + mOutput = 0; + } +#endif return status; } @@ -397,7 +389,6 @@ status_t AudioTrack::set( mSequence = 1; mObservedSequence = mSequence; mInUnderrun = false; - mOutput = output; return NO_ERROR; } @@ -821,23 +812,12 @@ status_t AudioTrack::reload() return NO_ERROR; } -audio_io_handle_t AudioTrack::getOutput() +audio_io_handle_t AudioTrack::getOutput() const { AutoMutex lock(mLock); return mOutput; } -// must be called with mLock held -audio_io_handle_t AudioTrack::getOutput_l() -{ - if (mOutput) { - return mOutput; - } else { - return AudioSystem::getOutput(mStreamType, - mSampleRate, mFormat, mChannelMask, mFlags); - } -} - status_t AudioTrack::attachAuxEffect(int effectId) { AutoMutex lock(mLock); @@ -858,7 +838,6 @@ status_t AudioTrack::createTrack_l( size_t frameCount, audio_output_flags_t flags, const sp& sharedBuffer, - audio_io_handle_t output, size_t epoch) { status_t status; @@ -868,27 +847,39 @@ status_t AudioTrack::createTrack_l( return NO_INIT; } + audio_io_handle_t output = AudioSystem::getOutput(mStreamType, mSampleRate, mFormat, + mChannelMask, mFlags, mOffloadInfo); + if (output == 0) { + ALOGE("Could not get audio output for stream type %d, sample rate %u, format %#x, " + "channel mask %#x, flags %#x", + mStreamType, mSampleRate, mFormat, mChannelMask, mFlags); + return BAD_VALUE; + } + { + // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, + // we must release it ourselves if anything goes wrong. + // Not all of these values are needed under all conditions, but it is easier to get them all uint32_t afLatency; status = AudioSystem::getLatency(output, streamType, &afLatency); if (status != NO_ERROR) { ALOGE("getLatency(%d) failed status %d", output, status); - return NO_INIT; + goto release; } size_t afFrameCount; status = AudioSystem::getFrameCount(output, streamType, &afFrameCount); if (status != NO_ERROR) { ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status); - return NO_INIT; + goto release; } uint32_t afSampleRate; status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate); if (status != NO_ERROR) { ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType, status); - return NO_INIT; + goto release; } // Client decides whether the track is TIMED (see below), but can only express a preference @@ -940,7 +931,8 @@ status_t AudioTrack::createTrack_l( if (((size_t)sharedBuffer->pointer() & (alignment - 1)) != 0) { ALOGE("Invalid buffer alignment: address %p, channel count %u", sharedBuffer->pointer(), mChannelCount); - return BAD_VALUE; + status = BAD_VALUE; + goto release; } // When initializing a shared buffer AudioTrack via constructors, @@ -1020,8 +1012,11 @@ status_t AudioTrack::createTrack_l( if (track == 0) { ALOGE("AudioFlinger could not create track, status: %d", status); - return status; + goto release; } + // AudioFlinger now owns the reference to the I/O handle, + // so we are no longer responsible for releasing it. + sp iMem = track->getCblk(); if (iMem == 0) { ALOGE("Could not get control block"); @@ -1081,10 +1076,13 @@ status_t AudioTrack::createTrack_l( ALOGW("AUDIO_OUTPUT_FLAG_OFFLOAD denied by server"); flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); mFlags = flags; - return NO_INIT; + // FIXME This is a warning, not an error, so don't return error status + //return NO_INIT; } } + // We retain a copy of the I/O handle, but don't own the reference + mOutput = output; mRefreshRemaining = true; // Starting address of buffers in shared memory. If there is a shared buffer, buffers @@ -1127,6 +1125,14 @@ status_t AudioTrack::createTrack_l( mAudioTrack->asBinder()->linkToDeath(mDeathNotifier, this); return NO_ERROR; + } + +release: + AudioSystem::releaseOutput(output); + if (status == NO_ERROR) { + status = NO_INIT; + } + return status; } status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) @@ -1708,7 +1714,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) status_t result; // refresh the audio configuration cache in this process to make sure we get new - // output parameters in getOutput_l() and createTrack_l() + // output parameters in createTrack_l() AudioSystem::clearAudioConfigCache(); if (isOffloaded_l()) { @@ -1716,10 +1722,6 @@ status_t AudioTrack::restoreTrack_l(const char *from) return DEAD_OBJECT; } - // force new output query from audio policy manager; - mOutput = 0; - audio_io_handle_t output = getOutput_l(); - // if the new IAudioTrack is created, createTrack_l() will modify the // following member variables: mAudioTrack, mCblkMemory and mCblk. // It will also delete the strong references on previous IAudioTrack and IMemory @@ -1733,7 +1735,6 @@ status_t AudioTrack::restoreTrack_l(const char *from) mReqFrameCount, // so that frame count never goes down mFlags, mSharedBuffer, - output, position /*epoch*/); if (result == NO_ERROR) { @@ -1763,9 +1764,15 @@ status_t AudioTrack::restoreTrack_l(const char *from) } if (result != NO_ERROR) { // Use of direct and offloaded output streams is ref counted by audio policy manager. +#if 0 // FIXME This should no longer be needed + //Use of direct and offloaded output streams is ref counted by audio policy manager. // As getOutput was called above and resulted in an output stream to be opened, // we need to release it. - AudioSystem::releaseOutput(output); + if (mOutput != 0) { + AudioSystem::releaseOutput(mOutput); + mOutput = 0; + } +#endif ALOGW("restoreTrack_l() failed status %d", result); mState = STATE_STOPPED; } -- cgit v1.1 From 363fb75db26698cbb50065506e0c80b61d1fbf92 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 15 Jan 2014 12:27:31 -0800 Subject: Remove the redundant parameters from createTrack_l() AudioRecord::openRecord_l() code was refactored earlier to remove the redundant parameters: > Change-Id: I124dce344b1d11c2dd66ca5e2c9aec0c52c230e2 This changelist refactors AudioTrack similarly. Change-Id: Iefd2bd662870ea81d04eff7b7c26f9c8b0dadd26 --- media/libmedia/AudioTrack.cpp | 103 +++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 62 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 8e91f12..f61a265 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -350,13 +350,7 @@ status_t AudioTrack::set( } // create the IAudioTrack - status = createTrack_l(streamType, - sampleRate, - format, - frameCount, - flags, - sharedBuffer, - 0 /*epoch*/); + status = createTrack_l(0 /*epoch*/); if (status != NO_ERROR) { if (mAudioTrackThread != 0) { @@ -831,14 +825,7 @@ status_t AudioTrack::attachAuxEffect(int effectId) // ------------------------------------------------------------------------- // must be called with mLock held -status_t AudioTrack::createTrack_l( - audio_stream_type_t streamType, - uint32_t sampleRate, - audio_format_t format, - size_t frameCount, - audio_output_flags_t flags, - const sp& sharedBuffer, - size_t epoch) +status_t AudioTrack::createTrack_l(size_t epoch) { status_t status; const sp& audioFlinger = AudioSystem::get_audio_flinger(); @@ -862,38 +849,37 @@ status_t AudioTrack::createTrack_l( // Not all of these values are needed under all conditions, but it is easier to get them all uint32_t afLatency; - status = AudioSystem::getLatency(output, streamType, &afLatency); + status = AudioSystem::getLatency(output, mStreamType, &afLatency); if (status != NO_ERROR) { ALOGE("getLatency(%d) failed status %d", output, status); goto release; } size_t afFrameCount; - status = AudioSystem::getFrameCount(output, streamType, &afFrameCount); + status = AudioSystem::getFrameCount(output, mStreamType, &afFrameCount); if (status != NO_ERROR) { - ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status); + ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, mStreamType, status); goto release; } uint32_t afSampleRate; - status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate); + status = AudioSystem::getSamplingRate(output, mStreamType, &afSampleRate); if (status != NO_ERROR) { - ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType, status); + ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, mStreamType, status); goto release; } // Client decides whether the track is TIMED (see below), but can only express a preference // for FAST. Server will perform additional tests. - if ((flags & AUDIO_OUTPUT_FLAG_FAST) && !( + if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) && !( // either of these use cases: // use case 1: shared buffer - (sharedBuffer != 0) || + (mSharedBuffer != 0) || // use case 2: callback handler (mCbf != NULL))) { ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client"); // once denied, do not request again if IAudioTrack is re-created - flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); - mFlags = flags; + mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST); } ALOGV("createTrack_l() output %d afLatency %d", output, afLatency); @@ -904,33 +890,34 @@ status_t AudioTrack::createTrack_l( // n = 3 normal track, with sample rate conversion // (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering) // n > 3 very high latency or very small notification interval; nBuffering is ignored - const uint32_t nBuffering = (sampleRate == afSampleRate) ? 2 : 3; + const uint32_t nBuffering = (mSampleRate == afSampleRate) ? 2 : 3; mNotificationFramesAct = mNotificationFramesReq; - if (!audio_is_linear_pcm(format)) { + size_t frameCount = mReqFrameCount; + if (!audio_is_linear_pcm(mFormat)) { - if (sharedBuffer != 0) { + if (mSharedBuffer != 0) { // Same comment as below about ignoring frameCount parameter for set() - frameCount = sharedBuffer->size(); + frameCount = mSharedBuffer->size(); } else if (frameCount == 0) { frameCount = afFrameCount; } if (mNotificationFramesAct != frameCount) { mNotificationFramesAct = frameCount; } - } else if (sharedBuffer != 0) { + } else if (mSharedBuffer != 0) { // Ensure that buffer alignment matches channel count // 8-bit data in shared memory is not currently supported by AudioFlinger - size_t alignment = /* format == AUDIO_FORMAT_PCM_8_BIT ? 1 : */ 2; + size_t alignment = /* mFormat == AUDIO_FORMAT_PCM_8_BIT ? 1 : */ 2; if (mChannelCount > 1) { // More than 2 channels does not require stronger alignment than stereo alignment <<= 1; } - if (((size_t)sharedBuffer->pointer() & (alignment - 1)) != 0) { + if (((size_t)mSharedBuffer->pointer() & (alignment - 1)) != 0) { ALOGE("Invalid buffer alignment: address %p, channel count %u", - sharedBuffer->pointer(), mChannelCount); + mSharedBuffer->pointer(), mChannelCount); status = BAD_VALUE; goto release; } @@ -939,9 +926,9 @@ status_t AudioTrack::createTrack_l( // there's no frameCount parameter. // But when initializing a shared buffer AudioTrack via set(), // there _is_ a frameCount parameter. We silently ignore it. - frameCount = sharedBuffer->size()/mChannelCount/sizeof(int16_t); + frameCount = mSharedBuffer->size()/mChannelCount/sizeof(int16_t); - } else if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) { + } else if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) { // FIXME move these calculations and associated checks to server @@ -953,10 +940,10 @@ status_t AudioTrack::createTrack_l( minBufCount = nBuffering; } - size_t minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; + size_t minFrameCount = (afFrameCount*mSampleRate*minBufCount)/afSampleRate; ALOGV("minFrameCount: %u, afFrameCount=%d, minBufCount=%d, sampleRate=%u, afSampleRate=%u" ", afLatency=%d", - minFrameCount, afFrameCount, minBufCount, sampleRate, afSampleRate, afLatency); + minFrameCount, afFrameCount, minBufCount, mSampleRate, afSampleRate, afLatency); if (frameCount == 0) { frameCount = minFrameCount; @@ -981,28 +968,28 @@ status_t AudioTrack::createTrack_l( } pid_t tid = -1; - if (flags & AUDIO_OUTPUT_FLAG_FAST) { + if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { trackFlags |= IAudioFlinger::TRACK_FAST; if (mAudioTrackThread != 0) { tid = mAudioTrackThread->getTid(); } } - if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { + if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { trackFlags |= IAudioFlinger::TRACK_OFFLOAD; } size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also - sp track = audioFlinger->createTrack(streamType, - sampleRate, + sp track = audioFlinger->createTrack(mStreamType, + mSampleRate, // AudioFlinger only sees 16-bit PCM - format == AUDIO_FORMAT_PCM_8_BIT ? - AUDIO_FORMAT_PCM_16_BIT : format, + mFormat == AUDIO_FORMAT_PCM_8_BIT ? + AUDIO_FORMAT_PCM_16_BIT : mFormat, mChannelMask, &temp, &trackFlags, - sharedBuffer, + mSharedBuffer, output, tid, &mSessionId, @@ -1045,11 +1032,11 @@ status_t AudioTrack::createTrack_l( } frameCount = temp; mAwaitBoost = false; - if (flags & AUDIO_OUTPUT_FLAG_FAST) { + if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { if (trackFlags & IAudioFlinger::TRACK_FAST) { ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount); mAwaitBoost = true; - if (sharedBuffer == 0) { + if (mSharedBuffer == 0) { // Theoretically double-buffering is not required for fast tracks, // due to tighter scheduling. But in practice, to accommodate kernels with // scheduling jitter, and apps with computation jitter, we use double-buffering. @@ -1060,22 +1047,20 @@ status_t AudioTrack::createTrack_l( } else { ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", frameCount); // once denied, do not request again if IAudioTrack is re-created - flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); - mFlags = flags; - if (sharedBuffer == 0) { + mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST); + if (mSharedBuffer == 0) { if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { mNotificationFramesAct = frameCount/nBuffering; } } } } - if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { + if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { if (trackFlags & IAudioFlinger::TRACK_OFFLOAD) { ALOGV("AUDIO_OUTPUT_FLAG_OFFLOAD successful"); } else { ALOGW("AUDIO_OUTPUT_FLAG_OFFLOAD denied by server"); - flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); - mFlags = flags; + mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); // FIXME This is a warning, not an error, so don't return error status //return NO_INIT; } @@ -1090,15 +1075,15 @@ status_t AudioTrack::createTrack_l( // immediately after the control block. This address is for the mapping within client // address space. AudioFlinger::TrackBase::mBuffer is for the server address space. void* buffers; - if (sharedBuffer == 0) { + if (mSharedBuffer == 0) { buffers = (char*)cblk + sizeof(audio_track_cblk_t); } else { - buffers = sharedBuffer->pointer(); + buffers = mSharedBuffer->pointer(); } mAudioTrack->attachAuxEffect(mAuxEffectId); // FIXME don't believe this lie - mLatency = afLatency + (1000*frameCount) / sampleRate; + mLatency = afLatency + (1000*frameCount) / mSampleRate; mFrameCount = frameCount; // If IAudioTrack is re-created, don't let the requested frameCount // decrease. This can confuse clients that cache frameCount(). @@ -1107,7 +1092,7 @@ status_t AudioTrack::createTrack_l( } // update proxy - if (sharedBuffer == 0) { + if (mSharedBuffer == 0) { mStaticProxy.clear(); mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF); } else { @@ -1729,13 +1714,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) // take the frames that will be lost by track recreation into account in saved position size_t position = mProxy->getPosition() + mProxy->getFramesFilled(); size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0; - result = createTrack_l(mStreamType, - mSampleRate, - mFormat, - mReqFrameCount, // so that frame count never goes down - mFlags, - mSharedBuffer, - position /*epoch*/); + result = createTrack_l(position /*epoch*/); if (result == NO_ERROR) { // continue playback from last known position, but -- cgit v1.1 From df576995a5aad3428aeeef765387d650945c161d Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Mon, 27 Jan 2014 18:13:39 -0800 Subject: AudioTrack: fix obtainBuffer timeout calculation AudioTrack::obtainBuffer() passes a pointer to a timeout variable that has gone out of scope when calling ClientProxy::obtainBuffer(). Same fix for AudioRecord. Bug: 11968591. Change-Id: I22af8f94fa2f8cc54ab5c25c89167c805e754317 --- media/libmedia/AudioRecord.cpp | 2 +- media/libmedia/AudioTrack.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a999e7e..b69e3ae 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -570,13 +570,13 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) } const struct timespec *requested; + struct timespec timeout; if (waitCount == -1) { requested = &ClientProxy::kForever; } else if (waitCount == 0) { requested = &ClientProxy::kNonBlocking; } else if (waitCount > 0) { long long ms = WAIT_PERIOD_MS * (long long) waitCount; - struct timespec timeout; timeout.tv_sec = ms / 1000; timeout.tv_nsec = (int) (ms % 1000) * 1000000; requested = &timeout; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index f61a265..cfd79bc 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1133,13 +1133,13 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) } const struct timespec *requested; + struct timespec timeout; if (waitCount == -1) { requested = &ClientProxy::kForever; } else if (waitCount == 0) { requested = &ClientProxy::kNonBlocking; } else if (waitCount > 0) { long long ms = WAIT_PERIOD_MS * (long long) waitCount; - struct timespec timeout; timeout.tv_sec = ms / 1000; timeout.tv_nsec = (int) (ms % 1000) * 1000000; requested = &timeout; -- cgit v1.1 From fdac7c00f9201bb3a9862069145f01d37e39755b Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 28 Jan 2014 11:03:28 -0800 Subject: Replace size_t in shared memory by uint32_t Eventually we may want to use uint64_t, but will need to confirm atomicity. Bug: 12381724 Change-Id: Ia2c591d262d22b47b6f7dab4b9d9faa14b86d865 --- media/libmedia/AudioTrackShared.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 21018a0..fdd1a12 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -475,9 +475,14 @@ void StaticAudioTrackClientProxy::flush() void StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount) { + // This can only happen on a 64-bit client + if (loopStart > UINT32_MAX || loopEnd > UINT32_MAX) { + // FIXME Should return an error status + return; + } StaticAudioTrackState newState; - newState.mLoopStart = loopStart; - newState.mLoopEnd = loopEnd; + newState.mLoopStart = (uint32_t) loopStart; + newState.mLoopEnd = (uint32_t) loopEnd; newState.mLoopCount = loopCount; mBufferPosition = loopStart; (void) mMutator.push(newState); @@ -487,7 +492,7 @@ size_t StaticAudioTrackClientProxy::getBufferPosition() { size_t bufferPosition; if (mMutator.ack()) { - bufferPosition = mCblk->u.mStatic.mBufferPosition; + bufferPosition = (size_t) mCblk->u.mStatic.mBufferPosition; if (bufferPosition > mFrameCount) { bufferPosition = mFrameCount; } @@ -622,7 +627,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer) if (half == 0) { half = 1; } - size_t minimum = cblk->mMinimum; + size_t minimum = (size_t) cblk->mMinimum; if (minimum == 0) { minimum = mIsOut ? half : 1; } else if (minimum > half) { @@ -760,7 +765,8 @@ ssize_t StaticAudioTrackServerProxy::pollPosition() mIsShutdown = true; return (ssize_t) NO_INIT; } - mCblk->u.mStatic.mBufferPosition = position; + // This may overflow, but client is not supposed to rely on it + mCblk->u.mStatic.mBufferPosition = (uint32_t) position; } return (ssize_t) position; } @@ -836,7 +842,8 @@ void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) mPosition = newPosition; cblk->mServer += stepCount; - cblk->u.mStatic.mBufferPosition = newPosition; + // This may overflow, but client is not supposed to rely on it + cblk->u.mStatic.mBufferPosition = (uint32_t) newPosition; if (setFlags != 0) { (void) android_atomic_or(setFlags, &cblk->mFlags); // this would be a good place to wake a futex -- cgit v1.1 From 0f11b51a57bc9062c4fe8af73747319cedabc5d6 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 31 Jan 2014 16:18:54 -0800 Subject: Fix unused parameter warnings in audio Change-Id: I665ba3358dd9502f0adec70d486e7bf8a2e1b0fe --- media/libmedia/AudioEffect.cpp | 4 ++-- media/libmedia/AudioRecord.cpp | 2 +- media/libmedia/AudioSystem.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 8dfffb3..35f6557 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -380,9 +380,9 @@ void AudioEffect::enableStatusChanged(bool enabled) } void AudioEffect::commandExecuted(uint32_t cmdCode, - uint32_t cmdSize, + uint32_t cmdSize __unused, void *cmdData, - uint32_t replySize, + uint32_t replySize __unused, void *replyData) { if (cmdData == NULL || replyData == NULL) { diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index b69e3ae..286096e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -87,7 +87,7 @@ AudioRecord::AudioRecord( int notificationFrames, int sessionId, transfer_type transferType, - audio_input_flags_t flags) + audio_input_flags_t flags __unused) : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index dcb72f8..1ab94fa 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -333,7 +333,7 @@ status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t st } status_t AudioSystem::getLatency(audio_io_handle_t output, - audio_stream_type_t streamType, + audio_stream_type_t streamType __unused, uint32_t* latency) { OutputDescriptor *outputDesc; -- cgit v1.1 From 1b86fe063badb5f28c467ade39be0f4008688947 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Wed, 29 Jan 2014 11:13:26 -0800 Subject: FINAL ATTEMPT: HTTP services are now provided from JAVA and made available to media code Change-Id: I9f74a86e70422187c9cf0ca1318a29019700192d --- media/libmedia/Android.mk | 2 + media/libmedia/IMediaHTTPConnection.cpp | 158 +++++++++++++++++++++++++++++ media/libmedia/IMediaHTTPService.cpp | 58 +++++++++++ media/libmedia/IMediaMetadataRetriever.cpp | 19 +++- media/libmedia/IMediaPlayer.cpp | 19 +++- media/libmedia/IMediaPlayerService.cpp | 30 +++++- media/libmedia/SoundPool.cpp | 10 +- media/libmedia/mediametadataretriever.cpp | 7 +- media/libmedia/mediaplayer.cpp | 16 ++- 9 files changed, 303 insertions(+), 16 deletions(-) create mode 100644 media/libmedia/IMediaHTTPConnection.cpp create mode 100644 media/libmedia/IMediaHTTPService.cpp (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 8aa54dc..fc4b2a5 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -25,6 +25,8 @@ LOCAL_SRC_FILES:= \ AudioRecord.cpp \ AudioSystem.cpp \ mediaplayer.cpp \ + IMediaHTTPConnection.cpp \ + IMediaHTTPService.cpp \ IMediaLogService.cpp \ IMediaPlayerService.cpp \ IMediaPlayerClient.cpp \ diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp new file mode 100644 index 0000000..622d9cf --- /dev/null +++ b/media/libmedia/IMediaHTTPConnection.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "IMediaHTTPConnection" +#include + +#include + +#include +#include +#include +#include + +namespace android { + +enum { + CONNECT = IBinder::FIRST_CALL_TRANSACTION, + DISCONNECT, + READ_AT, + GET_SIZE, + GET_MIME_TYPE, +}; + +struct BpMediaHTTPConnection : public BpInterface { + BpMediaHTTPConnection(const sp &impl) + : BpInterface(impl) { + } + + virtual bool connect( + const char *uri, const KeyedVector *headers) { + Parcel data, reply; + data.writeInterfaceToken( + IMediaHTTPConnection::getInterfaceDescriptor()); + + String16 tmp(uri); + data.writeString16(tmp); + + tmp = String16(""); + if (headers != NULL) { + for (size_t i = 0; i < headers->size(); ++i) { + String16 key(headers->keyAt(i).string()); + String16 val(headers->valueAt(i).string()); + + tmp.append(key); + tmp.append(String16(": ")); + tmp.append(val); + tmp.append(String16("\r\n")); + } + } + data.writeString16(tmp); + + remote()->transact(CONNECT, data, &reply); + + int32_t exceptionCode = reply.readExceptionCode(); + + if (exceptionCode) { + return UNKNOWN_ERROR; + } + + sp binder = reply.readStrongBinder(); + mMemory = interface_cast(binder); + + return mMemory != NULL; + } + + virtual void disconnect() { + Parcel data, reply; + data.writeInterfaceToken( + IMediaHTTPConnection::getInterfaceDescriptor()); + + remote()->transact(DISCONNECT, data, &reply); + } + + virtual ssize_t readAt(off64_t offset, void *buffer, size_t size) { + Parcel data, reply; + data.writeInterfaceToken( + IMediaHTTPConnection::getInterfaceDescriptor()); + + data.writeInt64(offset); + data.writeInt32(size); + + status_t err = remote()->transact(READ_AT, data, &reply); + CHECK_EQ(err, (status_t)OK); + + int32_t exceptionCode = reply.readExceptionCode(); + + if (exceptionCode) { + return UNKNOWN_ERROR; + } + + int32_t len = reply.readInt32(); + + if (len > 0) { + memcpy(buffer, mMemory->pointer(), len); + } + + return len; + } + + virtual off64_t getSize() { + Parcel data, reply; + data.writeInterfaceToken( + IMediaHTTPConnection::getInterfaceDescriptor()); + + remote()->transact(GET_SIZE, data, &reply); + + int32_t exceptionCode = reply.readExceptionCode(); + + if (exceptionCode) { + return UNKNOWN_ERROR; + } + + return reply.readInt64(); + } + + virtual status_t getMIMEType(String8 *mimeType) { + *mimeType = String8(""); + + Parcel data, reply; + data.writeInterfaceToken( + IMediaHTTPConnection::getInterfaceDescriptor()); + + remote()->transact(GET_MIME_TYPE, data, &reply); + + int32_t exceptionCode = reply.readExceptionCode(); + + if (exceptionCode) { + return UNKNOWN_ERROR; + } + + *mimeType = String8(reply.readString16()); + + return OK; + } + +private: + sp mMemory; +}; + +IMPLEMENT_META_INTERFACE( + MediaHTTPConnection, "android.media.IMediaHTTPConnection"); + +} // namespace android + diff --git a/media/libmedia/IMediaHTTPService.cpp b/media/libmedia/IMediaHTTPService.cpp new file mode 100644 index 0000000..1260582 --- /dev/null +++ b/media/libmedia/IMediaHTTPService.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "IMediaHTTPService" +#include + +#include + +#include +#include + +namespace android { + +enum { + MAKE_HTTP = IBinder::FIRST_CALL_TRANSACTION, +}; + +struct BpMediaHTTPService : public BpInterface { + BpMediaHTTPService(const sp &impl) + : BpInterface(impl) { + } + + virtual sp makeHTTPConnection() { + Parcel data, reply; + data.writeInterfaceToken( + IMediaHTTPService::getInterfaceDescriptor()); + + remote()->transact(MAKE_HTTP, data, &reply); + + status_t err = reply.readInt32(); + + if (err != OK) { + return NULL; + } + + return interface_cast(reply.readStrongBinder()); + } +}; + +IMPLEMENT_META_INTERFACE( + MediaHTTPService, "android.media.IMediaHTTPService"); + +} // namespace android + diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp index bb066a0..c7d9d51 100644 --- a/media/libmedia/IMediaMetadataRetriever.cpp +++ b/media/libmedia/IMediaMetadataRetriever.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -84,10 +85,16 @@ public: } status_t setDataSource( - const char *srcUrl, const KeyedVector *headers) + const sp &httpService, + const char *srcUrl, + const KeyedVector *headers) { Parcel data, reply; data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + data.writeInt32(httpService != NULL); + if (httpService != NULL) { + data.writeStrongBinder(httpService->asBinder()); + } data.writeCString(srcUrl); if (headers == NULL) { @@ -195,6 +202,13 @@ status_t BnMediaMetadataRetriever::onTransact( } break; case SET_DATA_SOURCE_URL: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + + sp httpService; + if (data.readInt32()) { + httpService = + interface_cast(data.readStrongBinder()); + } + const char* srcUrl = data.readCString(); KeyedVector headers; @@ -206,7 +220,8 @@ status_t BnMediaMetadataRetriever::onTransact( } reply->writeInt32( - setDataSource(srcUrl, numHeaders > 0 ? &headers : NULL)); + setDataSource( + httpService, srcUrl, numHeaders > 0 ? &headers : NULL)); return NO_ERROR; } break; diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index e79bcd2..d778d05 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -75,11 +76,17 @@ public: remote()->transact(DISCONNECT, data, &reply); } - status_t setDataSource(const char* url, + status_t setDataSource( + const sp &httpService, + const char* url, const KeyedVector* headers) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + data.writeInt32(httpService != NULL); + if (httpService != NULL) { + data.writeStrongBinder(httpService->asBinder()); + } data.writeCString(url); if (headers == NULL) { data.writeInt32(0); @@ -355,6 +362,13 @@ status_t BnMediaPlayer::onTransact( } break; case SET_DATA_SOURCE_URL: { CHECK_INTERFACE(IMediaPlayer, data, reply); + + sp httpService; + if (data.readInt32()) { + httpService = + interface_cast(data.readStrongBinder()); + } + const char* url = data.readCString(); KeyedVector headers; int32_t numHeaders = data.readInt32(); @@ -363,7 +377,8 @@ status_t BnMediaPlayer::onTransact( String8 value = data.readString8(); headers.add(key, value); } - reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL)); + reply->writeInt32(setDataSource( + httpService, url, numHeaders > 0 ? &headers : NULL)); return NO_ERROR; } break; case SET_DATA_SOURCE_FD: { diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index 3c22b4c..190adf2 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -86,12 +87,21 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual status_t decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, - audio_format_t* pFormat, - const sp& heap, size_t *pSize) + virtual status_t decode( + const sp &httpService, + const char* url, + uint32_t *pSampleRate, + int* pNumChannels, + audio_format_t* pFormat, + const sp& heap, + size_t *pSize) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(httpService != NULL); + if (httpService != NULL) { + data.writeStrongBinder(httpService->asBinder()); + } data.writeCString(url); data.writeStrongBinder(heap->asBinder()); status_t status = remote()->transact(DECODE_URL, data, &reply); @@ -222,13 +232,25 @@ status_t BnMediaPlayerService::onTransact( } break; case DECODE_URL: { CHECK_INTERFACE(IMediaPlayerService, data, reply); + sp httpService; + if (data.readInt32()) { + httpService = + interface_cast(data.readStrongBinder()); + } const char* url = data.readCString(); sp heap = interface_cast(data.readStrongBinder()); uint32_t sampleRate; int numChannels; audio_format_t format; size_t size; - status_t status = decode(url, &sampleRate, &numChannels, &format, heap, &size); + status_t status = + decode(httpService, + url, + &sampleRate, + &numChannels, + &format, + heap, + &size); reply->writeInt32(status); if (status == NO_ERROR) { reply->writeInt32(sampleRate); diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 98acd1f..9ed010d 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -21,6 +21,7 @@ #define USE_SHARED_MEM_BUFFER #include +#include #include #include #include "SoundPoolThread.h" @@ -496,7 +497,14 @@ status_t Sample::doLoad() ALOGV("Start decode"); if (mUrl) { - status = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format, mHeap, &mSize); + status = MediaPlayer::decode( + NULL /* httpService */, + mUrl, + &sampleRate, + &numChannels, + &format, + mHeap, + &mSize); } else { status = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format, mHeap, &mSize); diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp index bad2494..1d6bb6f 100644 --- a/media/libmedia/mediametadataretriever.cpp +++ b/media/libmedia/mediametadataretriever.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -93,7 +94,9 @@ void MediaMetadataRetriever::disconnect() } status_t MediaMetadataRetriever::setDataSource( - const char *srcUrl, const KeyedVector *headers) + const sp &httpService, + const char *srcUrl, + const KeyedVector *headers) { ALOGV("setDataSource"); Mutex::Autolock _l(mLock); @@ -106,7 +109,7 @@ status_t MediaMetadataRetriever::setDataSource( return UNKNOWN_ERROR; } ALOGV("data source (%s)", srcUrl); - return mRetriever->setDataSource(srcUrl, headers); + return mRetriever->setDataSource(httpService, srcUrl, headers); } status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 7a6f31d..a4d4b1a 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -136,6 +136,7 @@ status_t MediaPlayer::attachNewPlayer(const sp& player) } status_t MediaPlayer::setDataSource( + const sp &httpService, const char *url, const KeyedVector *headers) { ALOGV("setDataSource(%s)", url); @@ -145,7 +146,7 @@ status_t MediaPlayer::setDataSource( if (service != 0) { sp player(service->create(this, mAudioSessionId)); if ((NO_ERROR != doSetRetransmitEndpoint(player)) || - (NO_ERROR != player->setDataSource(url, headers))) { + (NO_ERROR != player->setDataSource(httpService, url, headers))) { player.clear(); } err = attachNewPlayer(player); @@ -776,15 +777,20 @@ void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) } } -/*static*/ status_t MediaPlayer::decode(const char* url, uint32_t *pSampleRate, - int* pNumChannels, audio_format_t* pFormat, - const sp& heap, size_t *pSize) +/*static*/ status_t MediaPlayer::decode( + const sp &httpService, + const char* url, + uint32_t *pSampleRate, + int* pNumChannels, + audio_format_t* pFormat, + const sp& heap, + size_t *pSize) { ALOGV("decode(%s)", url); status_t status; const sp& service = getMediaPlayerService(); if (service != 0) { - status = service->decode(url, pSampleRate, pNumChannels, pFormat, heap, pSize); + status = service->decode(httpService, url, pSampleRate, pNumChannels, pFormat, heap, pSize); } else { ALOGE("Unable to locate media service"); status = DEAD_OBJECT; -- cgit v1.1 From b3b2e23fcf7e050710d23b82a6682c0f3d869b69 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 5 Feb 2014 11:10:26 -0800 Subject: Add AudioRecord::mReqFrameCount similar to AudioTrack Change-Id: I62d6534a9581e84ae20c2422f7ad9aeda9b7c4df --- media/libmedia/AudioRecord.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 286096e..a9ba154 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -228,7 +228,8 @@ status_t AudioRecord::set( ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount); return BAD_VALUE; } - mFrameCount = frameCount; + // mFrameCount is initialized in openRecord_l + mReqFrameCount = frameCount; mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; @@ -449,11 +450,12 @@ status_t AudioRecord::openRecord_l(size_t epoch) } mNotificationFramesAct = mNotificationFramesReq; + size_t frameCount = mReqFrameCount; if (!(mFlags & AUDIO_INPUT_FLAG_FAST)) { // Make sure that application is notified with sufficient margin before overrun - if (mNotificationFramesAct == 0 || mNotificationFramesAct > mFrameCount/2) { - mNotificationFramesAct = mFrameCount/2; + if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) { + mNotificationFramesAct = frameCount/2; } } @@ -467,7 +469,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, // we must release it ourselves if anything goes wrong. - size_t temp = mFrameCount; // temp may be replaced by a revised value of frameCount, + size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also int originalSessionId = mSessionId; sp record = audioFlinger->openRecord(input, @@ -510,10 +512,15 @@ status_t AudioRecord::openRecord_l(size_t epoch) audio_track_cblk_t* cblk = static_cast(iMemPointer); mCblk = cblk; // note that temp is the (possibly revised) value of mFrameCount - if (temp < mFrameCount || (mFrameCount == 0 && temp == 0)) { - ALOGW("Requested frameCount %u but received frameCount %u", mFrameCount, temp); + if (temp < frameCount || (frameCount == 0 && temp == 0)) { + ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp); + } + frameCount = temp; + // If IAudioRecord is re-created, don't let the requested frameCount + // decrease. This can confuse clients that cache frameCount(). + if (frameCount > mReqFrameCount) { + mReqFrameCount = frameCount; } - mFrameCount = temp; // FIXME missing fast track frameCount logic mAwaitBoost = false; @@ -538,6 +545,8 @@ status_t AudioRecord::openRecord_l(size_t epoch) // starting address of buffers in shared memory void *buffers = (char*)cblk + sizeof(audio_track_cblk_t); + mFrameCount = frameCount; + // update proxy mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize); mProxy->setEpoch(epoch); -- cgit v1.1 From 81e68448f3361eaf8618930471fdc3c21bdf5cbc Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Wed, 5 Feb 2014 11:52:33 -0800 Subject: Remove no longer needed http proxy handling code, it's obsolete now since we started to use java's HTTPConnection instead of the native implementation. Also remove other remnants of the previous http implementation, such as accounting for the http user's uid. Change-Id: I60bfd31381ea40d2220db587ec5c433093b60034 --- media/libmedia/IMediaPlayerService.cpp | 38 ---------------------------------- media/libmedia/mediaplayer.cpp | 11 ---------- 2 files changed, 49 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index 190adf2..d116b14 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -49,7 +49,6 @@ enum { ADD_BATTERY_DATA, PULL_BATTERY_DATA, LISTEN_FOR_REMOTE_DISPLAY, - UPDATE_PROXY_CONFIG, }; class BpMediaPlayerService: public BpInterface @@ -192,25 +191,6 @@ public: remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply); return interface_cast(reply.readStrongBinder()); } - - virtual status_t updateProxyConfig( - const char *host, int32_t port, const char *exclusionList) { - Parcel data, reply; - - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - if (host == NULL) { - data.writeInt32(0); - } else { - data.writeInt32(1); - data.writeCString(host); - data.writeInt32(port); - data.writeCString(exclusionList); - } - - remote()->transact(UPDATE_PROXY_CONFIG, data, &reply); - - return reply.readInt32(); - } }; IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService"); @@ -338,24 +318,6 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(display->asBinder()); return NO_ERROR; } break; - case UPDATE_PROXY_CONFIG: - { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - - const char *host = NULL; - int32_t port = 0; - const char *exclusionList = NULL; - - if (data.readInt32()) { - host = data.readCString(); - port = data.readInt32(); - exclusionList = data.readCString(); - } - - reply->writeInt32(updateProxyConfig(host, port, exclusionList)); - - return OK; - } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index a4d4b1a..24663ad 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -838,15 +838,4 @@ status_t MediaPlayer::setNextMediaPlayer(const sp& next) { return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer); } -status_t MediaPlayer::updateProxyConfig( - const char *host, int32_t port, const char *exclusionList) { - const sp& service = getMediaPlayerService(); - - if (service != NULL) { - return service->updateProxyConfig(host, port, exclusionList); - } - - return INVALID_OPERATION; -} - }; // namespace android -- cgit v1.1 From 80520381d0bdf3451bd17c9ddef73d3fe71c58c2 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 31 Jan 2014 16:49:31 -0800 Subject: Fix warnings about unused parameters Change-Id: I27dc108e2c1f7ffd414bb7ff3d4c349651da6c26 --- media/libmedia/MediaProfiles.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 8319cd7..1074da9 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -81,8 +81,14 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA}, }; +#if LOG_NDEBUG +#define UNUSED __unused +#else +#define UNUSED +#endif + /*static*/ void -MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec) +MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec UNUSED) { ALOGV("video codec:"); ALOGV("codec = %d", codec.mCodec); @@ -93,7 +99,7 @@ MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec) } /*static*/ void -MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec) +MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec UNUSED) { ALOGV("audio codec:"); ALOGV("codec = %d", codec.mCodec); @@ -103,7 +109,7 @@ MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec) } /*static*/ void -MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap) +MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap UNUSED) { ALOGV("video encoder cap:"); ALOGV("codec = %d", cap.mCodec); @@ -114,7 +120,7 @@ MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap) } /*static*/ void -MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap) +MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap UNUSED) { ALOGV("audio encoder cap:"); ALOGV("codec = %d", cap.mCodec); @@ -124,21 +130,21 @@ MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap) } /*static*/ void -MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap) +MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap UNUSED) { ALOGV("video decoder cap:"); ALOGV("codec = %d", cap.mCodec); } /*static*/ void -MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap) +MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap UNUSED) { ALOGV("audio codec cap:"); ALOGV("codec = %d", cap.mCodec); } /*static*/ void -MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap) +MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap UNUSED) { ALOGV("videoeditor cap:"); ALOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth); -- cgit v1.1 From cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 7 Feb 2014 09:47:14 -0800 Subject: Use printf format %#x for audio_format_t in logs Change-Id: I1c611d1037685d52ccc84efe0fccd6413ec938e9 --- media/libmedia/AudioRecord.cpp | 6 +++--- media/libmedia/AudioSystem.cpp | 6 +++--- media/libmedia/AudioTrack.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a9ba154..541cb51 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -52,7 +52,7 @@ status_t AudioRecord::getMinFrameCount( } if (size == 0) { - ALOGE("Unsupported configuration: sampleRate %u, format %d, channelMask %#x", + ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x", sampleRate, format, channelMask); return BAD_VALUE; } @@ -191,12 +191,12 @@ status_t AudioRecord::set( // validate parameters if (!audio_is_valid_format(format)) { - ALOGE("Invalid format %d", format); + ALOGE("Invalid format %#x", format); return BAD_VALUE; } // Temporary restriction: AudioFlinger currently supports 16-bit PCM only if (format != AUDIO_FORMAT_PCM_16_BIT) { - ALOGE("Format %d is not supported", format); + ALOGE("Format %#x is not supported", format); return BAD_VALUE; } mFormat = format; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 1ab94fa..51dba7b 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -370,7 +370,7 @@ status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t for } inBuffSize = af->getInputBufferSize(sampleRate, format, channelMask); if (inBuffSize == 0) { - ALOGE("AudioSystem::getInputBufferSize failed sampleRate %d format %x channelMask %x", + ALOGE("AudioSystem::getInputBufferSize failed sampleRate %d format %#x channelMask %x", sampleRate, format, channelMask); return BAD_VALUE; } @@ -481,7 +481,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle OutputDescriptor *outputDesc = new OutputDescriptor(*desc); gOutputs.add(ioHandle, outputDesc); - ALOGV("ioConfigChanged() new output samplingRate %u, format %d channel mask %#x frameCount %u " + ALOGV("ioConfigChanged() new output samplingRate %u, format %#x channel mask %#x frameCount %u " "latency %d", outputDesc->samplingRate, outputDesc->format, outputDesc->channelMask, outputDesc->frameCount, outputDesc->latency); @@ -505,7 +505,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle if (param2 == NULL) break; desc = (const OutputDescriptor *)param2; - ALOGV("ioConfigChanged() new config for output %d samplingRate %u, format %d channel mask %#x " + ALOGV("ioConfigChanged() new config for output %d samplingRate %u, format %#x channel mask %#x " "frameCount %d latency %d", ioHandle, desc->samplingRate, desc->format, desc->channelMask, desc->frameCount, desc->latency); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index cfd79bc..41b4845 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -273,7 +273,7 @@ status_t AudioTrack::set( // validate parameters if (!audio_is_valid_format(format)) { - ALOGE("Invalid format %d", format); + ALOGE("Invalid format %#x", format); return BAD_VALUE; } mFormat = format; -- cgit v1.1 From 4944acb7355b3aa25748fd25945a363a69d65444 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 19 Aug 2013 08:39:20 -0700 Subject: Fix whitespace Change-Id: I9add0872030a26933f6b6dad1be299154611cc56 --- media/libmedia/AudioSystem.cpp | 36 ++++++++++++++++++++++++------------ media/libmedia/SoundPool.cpp | 3 ++- 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 1ab94fa..e224d20 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -84,13 +84,15 @@ const sp& AudioSystem::get_audio_flinger() return DEAD_OBJECT; } -status_t AudioSystem::muteMicrophone(bool state) { +status_t AudioSystem::muteMicrophone(bool state) +{ const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; return af->setMicMute(state); } -status_t AudioSystem::isMicrophoneMuted(bool* state) { +status_t AudioSystem::isMicrophoneMuted(bool* state) +{ const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; *state = af->getMicMute(); @@ -175,13 +177,15 @@ status_t AudioSystem::setMode(audio_mode_t mode) return af->setMode(mode); } -status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) { +status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) +{ const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; return af->setParameters(ioHandle, keyValuePairs); } -String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys) { +String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys) +{ const sp& af = AudioSystem::get_audio_flinger(); String8 result = String8(""); if (af == 0) return result; @@ -413,7 +417,8 @@ status_t AudioSystem::getRenderPosition(audio_io_handle_t output, size_t *halFra return af->getRenderPosition(halFrames, dspFrames, output); } -uint32_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) { +uint32_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) +{ const sp& af = AudioSystem::get_audio_flinger(); uint32_t result = 0; if (af == 0) return result; @@ -423,20 +428,23 @@ uint32_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) { return result; } -int AudioSystem::newAudioSessionId() { +int AudioSystem::newAudioSessionId() +{ const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return 0; return af->newAudioSessionId(); } -void AudioSystem::acquireAudioSessionId(int audioSession) { +void AudioSystem::acquireAudioSessionId(int audioSession) +{ const sp& af = AudioSystem::get_audio_flinger(); if (af != 0) { af->acquireAudioSessionId(audioSession); } } -void AudioSystem::releaseAudioSessionId(int audioSession) { +void AudioSystem::releaseAudioSessionId(int audioSession) +{ const sp& af = AudioSystem::get_audio_flinger(); if (af != 0) { af->releaseAudioSessionId(audioSession); @@ -445,7 +453,8 @@ void AudioSystem::releaseAudioSessionId(int audioSession) { // --------------------------------------------------------------------------- -void AudioSystem::AudioFlingerClient::binderDied(const wp& who __unused) { +void AudioSystem::AudioFlingerClient::binderDied(const wp& who __unused) +{ Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); @@ -522,12 +531,14 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle } } -void AudioSystem::setErrorCallback(audio_error_callback cb) { +void AudioSystem::setErrorCallback(audio_error_callback cb) +{ Mutex::Autolock _l(gLock); gAudioErrorCallback = cb; } -bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType) { +bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType) +{ switch (streamType) { case AUDIO_STREAM_MUSIC: case AUDIO_STREAM_VOICE_CALL: @@ -831,7 +842,8 @@ bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info) // --------------------------------------------------------------------------- -void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) { +void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) +{ Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioPolicyService.clear(); diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 9ed010d..4885b4f 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -737,7 +737,8 @@ void SoundChannel::process(int event, void *info, unsigned long toggle) count = b->size; } memcpy(q, p, count); -// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count); +// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, +// count); } else if (mPos < mAudioBufferSize) { count = mAudioBufferSize - mPos; if (count > b->size) { -- cgit v1.1 From 43bdc1de363a3c72c7dcf9c9a898bac109dc7cb5 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 10 Feb 2014 09:53:55 -0800 Subject: Fix build after merge from AOSP Change-Id: I1cd3432c02db1600e49ade67e6a89e39e7a8d3ed --- media/libmedia/AudioTrack.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index fa56dc2..37ae70f 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -871,24 +871,20 @@ status_t AudioTrack::createTrack_l(size_t epoch) // Client decides whether the track is TIMED (see below), but can only express a preference // for FAST. Server will perform additional tests. - if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) && !( + if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) && !(( // either of these use cases: // use case 1: shared buffer (mSharedBuffer != 0) || // use case 2: callback handler - (mCbf != NULL))) { + (mCbf != NULL)) && + // matching sample rate + (mSampleRate == afSampleRate))) { ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client"); // once denied, do not request again if IAudioTrack is re-created mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST); } ALOGV("createTrack_l() output %d afLatency %d", output, afLatency); - if ((flags & AUDIO_OUTPUT_FLAG_FAST) && sampleRate != afSampleRate) { - ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client due to mismatching sample rate (%d vs %d)", - sampleRate, afSampleRate); - flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); - } - // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where // n = 1 fast track with single buffering; nBuffering is ignored // n = 2 fast track with double buffering -- cgit v1.1 From d457c970c8d08519cd77280a90b61ae1e342cfe3 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Tue, 11 Feb 2014 08:47:07 -0800 Subject: Track pid for each session so they can be properly freed. Change-Id: I6f389035bc29e74e7c367c1c6d0252b180f666b3 --- media/libmedia/AudioRecord.cpp | 4 ++-- media/libmedia/AudioSystem.cpp | 8 ++++---- media/libmedia/AudioTrack.cpp | 29 +++++++++++++++++++++-------- media/libmedia/IAudioFlinger.cpp | 12 ++++++++---- media/libmedia/mediaplayer.cpp | 8 ++++---- 5 files changed, 39 insertions(+), 22 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 541cb51..6ca499b 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -115,7 +115,7 @@ AudioRecord::~AudioRecord() mAudioRecord.clear(); } IPCThreadState::self()->flushCommands(); - AudioSystem::releaseAudioSessionId(mSessionId); + AudioSystem::releaseAudioSessionId(mSessionId, -1); } } @@ -266,7 +266,7 @@ status_t AudioRecord::set( mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; - AudioSystem::acquireAudioSessionId(mSessionId); + AudioSystem::acquireAudioSessionId(mSessionId, -1); mSequence = 1; mObservedSequence = mSequence; mInOverrun = false; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 87f4b4c..140fb66 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -435,19 +435,19 @@ int AudioSystem::newAudioSessionId() return af->newAudioSessionId(); } -void AudioSystem::acquireAudioSessionId(int audioSession) +void AudioSystem::acquireAudioSessionId(int audioSession, pid_t pid) { const sp& af = AudioSystem::get_audio_flinger(); if (af != 0) { - af->acquireAudioSessionId(audioSession); + af->acquireAudioSessionId(audioSession, pid); } } -void AudioSystem::releaseAudioSessionId(int audioSession) +void AudioSystem::releaseAudioSessionId(int audioSession, pid_t pid) { const sp& af = AudioSystem::get_audio_flinger(); if (af != 0) { - af->releaseAudioSessionId(audioSession); + af->releaseAudioSessionId(audioSession, pid); } } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 63eaf1a..5c62260 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -116,7 +116,8 @@ AudioTrack::AudioTrack( int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, - int uid) + int uid, + pid_t pid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -125,7 +126,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, - offloadInfo, uid); + offloadInfo, uid, pid); } AudioTrack::AudioTrack( @@ -141,7 +142,8 @@ AudioTrack::AudioTrack( int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, - int uid) + int uid, + pid_t pid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -149,7 +151,8 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, - sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, uid); + sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, + uid, pid); } AudioTrack::~AudioTrack() @@ -168,7 +171,9 @@ AudioTrack::~AudioTrack() mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); IPCThreadState::self()->flushCommands(); - AudioSystem::releaseAudioSessionId(mSessionId); + ALOGV("~AudioTrack, releasing session id from %d on behalf of %d", + IPCThreadState::self()->getCallingPid(), mClientPid); + AudioSystem::releaseAudioSessionId(mSessionId, mClientPid); } } @@ -187,7 +192,8 @@ status_t AudioTrack::set( int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, - int uid) + int uid, + pid_t pid) { switch (transferType) { case TRANSFER_DEFAULT: @@ -335,11 +341,18 @@ status_t AudioTrack::set( mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; mSessionId = sessionId; - if (uid == -1 || (IPCThreadState::self()->getCallingPid() != getpid())) { + int callingpid = IPCThreadState::self()->getCallingPid(); + int mypid = getpid(); + if (uid == -1 || (callingpid != mypid)) { mClientUid = IPCThreadState::self()->getCallingUid(); } else { mClientUid = uid; } + if (pid == -1 || (callingpid != mypid)) { + mClientPid = callingpid; + } else { + mClientPid = pid; + } mAuxEffectId = 0; mFlags = flags; mCbf = cbf; @@ -379,7 +392,7 @@ status_t AudioTrack::set( mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; - AudioSystem::acquireAudioSessionId(mSessionId); + AudioSystem::acquireAudioSessionId(mSessionId, mClientPid); mSequence = 1; mObservedSequence = mSequence; mInUnderrun = false; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index eef6a3d..7b15e68 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -609,19 +609,21 @@ public: return id; } - virtual void acquireAudioSessionId(int audioSession) + virtual void acquireAudioSessionId(int audioSession, int pid) { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(audioSession); + data.writeInt32(pid); remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply); } - virtual void releaseAudioSessionId(int audioSession) + virtual void releaseAudioSessionId(int audioSession, int pid) { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(audioSession); + data.writeInt32(pid); remote()->transact(RELEASE_AUDIO_SESSION_ID, data, &reply); } @@ -1082,13 +1084,15 @@ status_t BnAudioFlinger::onTransact( case ACQUIRE_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); int audioSession = data.readInt32(); - acquireAudioSessionId(audioSession); + int pid = data.readInt32(); + acquireAudioSessionId(audioSession, pid); return NO_ERROR; } break; case RELEASE_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); int audioSession = data.readInt32(); - releaseAudioSessionId(audioSession); + int pid = data.readInt32(); + releaseAudioSessionId(audioSession, pid); return NO_ERROR; } break; case QUERY_NUM_EFFECTS: { diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 24663ad..d94c7c5 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -58,7 +58,7 @@ MediaPlayer::MediaPlayer() mVideoWidth = mVideoHeight = 0; mLockThreadId = 0; mAudioSessionId = AudioSystem::newAudioSessionId(); - AudioSystem::acquireAudioSessionId(mAudioSessionId); + AudioSystem::acquireAudioSessionId(mAudioSessionId, -1); mSendLevel = 0; mRetransmitEndpointValid = false; } @@ -66,7 +66,7 @@ MediaPlayer::MediaPlayer() MediaPlayer::~MediaPlayer() { ALOGV("destructor"); - AudioSystem::releaseAudioSessionId(mAudioSessionId); + AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); disconnect(); IPCThreadState::self()->flushCommands(); } @@ -576,8 +576,8 @@ status_t MediaPlayer::setAudioSessionId(int sessionId) return BAD_VALUE; } if (sessionId != mAudioSessionId) { - AudioSystem::acquireAudioSessionId(sessionId); - AudioSystem::releaseAudioSessionId(mAudioSessionId); + AudioSystem::acquireAudioSessionId(sessionId, -1); + AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); mAudioSessionId = sessionId; } return NO_ERROR; -- cgit v1.1 From 7074296c72b3be919ebc9dfd504f4572a188d2e7 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 18 Feb 2014 08:00:47 -0800 Subject: Fix warning due to incorrect log format Change-Id: I58ff399ace74965ebf8e5690c20637385f9425ad --- media/libmedia/IAudioFlinger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 7b15e68..e696323 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -988,7 +988,7 @@ status_t BnAudioFlinger::onTransact( &latency, flags, hasOffloadInfo ? &offloadInfo : NULL); - ALOGV("OPEN_OUTPUT output, %p", output); + ALOGV("OPEN_OUTPUT output, %d", output); reply->writeInt32((int32_t) output); reply->writeInt32(devices); reply->writeInt32(samplingRate); -- cgit v1.1 From 3e8027a04c20a4b7028f1615538b36219386c9e5 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 15 Oct 2013 09:24:38 -0700 Subject: Move StateQueueInstantiations to libinstantssq This removes a circular dependency between libmedia and libnbaio Change-Id: I3692cbbe2b76028a953b36606b62cdda70c8c26f --- media/libmedia/Android.mk | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index fc4b2a5..26d94b0 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -60,16 +60,13 @@ LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES += ../libnbaio/roundup.c -# for -LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0) -LOCAL_SRC_FILES += SingleStateQueue.cpp -LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"' -# Consider a separate a library for SingleStateQueueInstantiations. - LOCAL_SHARED_LIBRARIES := \ libui liblog libcutils libutils libbinder libsonivox libicuuc libicui18n libexpat \ libcamera_client libstagefright_foundation \ libgui libdl libaudioutils +LOCAL_SHARED_LIBRARIES += libnbaio + +LOCAL_STATIC_LIBRARIES += libinstantssq LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper @@ -84,3 +81,16 @@ LOCAL_C_INCLUDES := \ $(call include-path-for, audio-utils) include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +# for +LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0) +LOCAL_SRC_FILES += SingleStateQueue.cpp +LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"' +# Consider a separate a library for SingleStateQueueInstantiations. + +LOCAL_MODULE := libinstantssq +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) -- cgit v1.1 From ee3759090c2194eaeca4944a01104771ff1c91d2 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 18 Feb 2014 12:43:37 -0800 Subject: Simplify and remove old comment Change-Id: Iee41641252f65cea9ce0ea0ec1ea4229608f7c64 --- media/libmedia/Android.mk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 26d94b0..e0acae6 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -63,8 +63,7 @@ LOCAL_SRC_FILES += ../libnbaio/roundup.c LOCAL_SHARED_LIBRARIES := \ libui liblog libcutils libutils libbinder libsonivox libicuuc libicui18n libexpat \ libcamera_client libstagefright_foundation \ - libgui libdl libaudioutils -LOCAL_SHARED_LIBRARIES += libnbaio + libgui libdl libaudioutils libnbaio LOCAL_STATIC_LIBRARIES += libinstantssq @@ -88,7 +87,6 @@ include $(CLEAR_VARS) LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0) LOCAL_SRC_FILES += SingleStateQueue.cpp LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"' -# Consider a separate a library for SingleStateQueueInstantiations. LOCAL_MODULE := libinstantssq LOCAL_MODULE_TAGS := optional -- cgit v1.1 From 6dd62fb91d82dedcfa3ab38c02eb0940b4ba932a Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 5 Dec 2013 16:35:58 -0800 Subject: Multi-client recording Supports multiple clients both at native sample rate and with resampling. Change-Id: Icea55b4fd30751761b7debaa3ce016c79e712d8d --- media/libmedia/AudioRecord.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 6ca499b..700718d 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -462,7 +462,9 @@ status_t AudioRecord::openRecord_l(size_t epoch) audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId); if (input == 0) { - ALOGE("Could not get audio input for record source %d", mInputSource); + ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " + "channel mask %#x, session %d", + mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId); return BAD_VALUE; } { -- cgit v1.1 From c9c7e25a4b1c34439fb365f6cfbef063884566cc Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Fri, 21 Feb 2014 12:01:23 -0800 Subject: Add method to get redirected Uri Change-Id: Id8aac1077c3de1bb1f58bfcfcca93d685abe9b79 --- media/libmedia/IMediaHTTPConnection.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp index 622d9cf..22c470a 100644 --- a/media/libmedia/IMediaHTTPConnection.cpp +++ b/media/libmedia/IMediaHTTPConnection.cpp @@ -33,6 +33,7 @@ enum { READ_AT, GET_SIZE, GET_MIME_TYPE, + GET_URI }; struct BpMediaHTTPConnection : public BpInterface { @@ -147,6 +148,26 @@ struct BpMediaHTTPConnection : public BpInterface { return OK; } + virtual status_t getUri(String8 *uri) { + *uri = String8(""); + + Parcel data, reply; + data.writeInterfaceToken( + IMediaHTTPConnection::getInterfaceDescriptor()); + + remote()->transact(GET_URI, data, &reply); + + int32_t exceptionCode = reply.readExceptionCode(); + + if (exceptionCode) { + return UNKNOWN_ERROR; + } + + *uri = String8(reply.readString16()); + + return OK; + } + private: sp mMemory; }; -- cgit v1.1 From 86f04663032ddaa25110149d709bbf896ad83b02 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 15:13:05 -0800 Subject: Add log at entry to set() in AudioTrack and AudioRecord Change-Id: Ife23b88474c1d62c0cf682c1a310d951f2c0f54a --- media/libmedia/AudioRecord.cpp | 8 +++++--- media/libmedia/AudioTrack.cpp | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 700718d..b6b6d14 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -133,6 +133,11 @@ status_t AudioRecord::set( transfer_type transferType, audio_input_flags_t flags) { + ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %d, " + "notificationFrames %d, sessionId %d, transferType %d, flags %#x", + inputSource, sampleRate, format, channelMask, frameCountInt, notificationFrames, + sessionId, transferType, flags); + switch (transferType) { case TRANSFER_DEFAULT: if (cbf == NULL || threadCanCallJava) { @@ -163,9 +168,6 @@ status_t AudioRecord::set( } size_t frameCount = frameCountInt; - ALOGV("set(): sampleRate %u, channelMask %#x, frameCount %u", sampleRate, channelMask, - frameCount); - AutoMutex lock(mLock); if (mAudioRecord != 0) { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 5c62260..46025c0 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -195,6 +195,11 @@ status_t AudioTrack::set( int uid, pid_t pid) { + ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %d, " + "flags #%x, notificationFrames %d, sessionId %d, transferType %d", + streamType, sampleRate, format, channelMask, frameCountInt, flags, notificationFrames, + sessionId, transferType); + switch (transferType) { case TRANSFER_DEFAULT: if (sharedBuffer != 0) { -- cgit v1.1 From c85df82b1e8b05714268926a8bb3deb9c65f9a22 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 15:13:40 -0800 Subject: Permit AudioRecord to support non-linear formats in future But still restricted to 16-bit PCM currently Change-Id: I5df0e5033da9144ca73e44addf14a63d31406034 --- media/libmedia/AudioRecord.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index b6b6d14..e18819c 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -211,8 +211,11 @@ status_t AudioRecord::set( uint32_t channelCount = popcount(channelMask); mChannelCount = channelCount; - // Assumes audio_is_linear_pcm(format), else sizeof(uint8_t) - mFrameSize = channelCount * audio_bytes_per_sample(format); + if (audio_is_linear_pcm(format)) { + mFrameSize = channelCount * audio_bytes_per_sample(format); + } else { + mFrameSize = sizeof(uint8_t); + } // validate framecount size_t minFrameCount = 0; -- cgit v1.1 From 11cb175005db0090345f44bfa049b52fd8c809b8 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 15:16:59 -0800 Subject: Update mReqFrameCount at same point in AudioTrack and AudioRecord Change-Id: I12369dfbb9e75389f2cab015a706decdaf310a0d --- media/libmedia/AudioRecord.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index e18819c..bb0d196 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -523,11 +523,6 @@ status_t AudioRecord::openRecord_l(size_t epoch) ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp); } frameCount = temp; - // If IAudioRecord is re-created, don't let the requested frameCount - // decrease. This can confuse clients that cache frameCount(). - if (frameCount > mReqFrameCount) { - mReqFrameCount = frameCount; - } // FIXME missing fast track frameCount logic mAwaitBoost = false; @@ -553,6 +548,11 @@ status_t AudioRecord::openRecord_l(size_t epoch) void *buffers = (char*)cblk + sizeof(audio_track_cblk_t); mFrameCount = frameCount; + // If IAudioRecord is re-created, don't let the requested frameCount + // decrease. This can confuse clients that cache frameCount(). + if (frameCount > mReqFrameCount) { + mReqFrameCount = frameCount; + } // update proxy mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize); -- cgit v1.1 From e3247bf8dd4f8fa8dfa3a108260241ae4a967569 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 15:19:07 -0800 Subject: Update channel fields at same place in AudioTrack and AudioRecord Change-Id: I4b649feeef47e7968a9fa3a460217017ca9b05fe --- media/libmedia/AudioTrack.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 46025c0..0eb0915 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -293,6 +293,9 @@ status_t AudioTrack::set( ALOGE("Invalid channel mask %#x", channelMask); return BAD_VALUE; } + mChannelMask = channelMask; + uint32_t channelCount = popcount(channelMask); + mChannelCount = channelCount; // AudioFlinger does not currently support 8-bit data in shared memory if (format == AUDIO_FORMAT_PCM_8_BIT && sharedBuffer != 0) { @@ -316,10 +319,6 @@ status_t AudioTrack::set( flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); } - mChannelMask = channelMask; - uint32_t channelCount = popcount(channelMask); - mChannelCount = channelCount; - if (audio_is_linear_pcm(format)) { mFrameSize = channelCount * audio_bytes_per_sample(format); mFrameSizeAF = channelCount * sizeof(int16_t); -- cgit v1.1 From 5f631515d098c29603cda88f7a7e7580a2d55b57 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 15:16:07 -0800 Subject: Unify comments and whitespace between AudioTrack and AudioRecord Change-Id: I5320a6b2d7f7077cb12d7da4f2ca30a940100bf2 --- media/libmedia/AudioRecord.cpp | 3 ++- media/libmedia/AudioTrack.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index bb0d196..bb66b4c 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -175,6 +175,7 @@ status_t AudioRecord::set( return INVALID_OPERATION; } + // handle default values first. if (inputSource == AUDIO_SOURCE_DEFAULT) { inputSource = AUDIO_SOURCE_MIC; } @@ -518,7 +519,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) mCblkMemory = iMem; audio_track_cblk_t* cblk = static_cast(iMemPointer); mCblk = cblk; - // note that temp is the (possibly revised) value of mFrameCount + // note that temp is the (possibly revised) value of frameCount if (temp < frameCount || (frameCount == 0 && temp == 0)) { ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp); } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 0eb0915..eed7a0b 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1039,6 +1039,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) mDeathNotifier.clear(); } mAudioTrack = track; + mCblkMemory = iMem; audio_track_cblk_t* cblk = static_cast(iMemPointer); mCblk = cblk; @@ -1050,6 +1051,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp); } frameCount = temp; + mAwaitBoost = false; if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { if (trackFlags & IAudioFlinger::TRACK_FAST) { @@ -1103,6 +1105,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) mAudioTrack->attachAuxEffect(mAuxEffectId); // FIXME don't believe this lie mLatency = afLatency + (1000*frameCount) / mSampleRate; + mFrameCount = frameCount; // If IAudioTrack is re-created, don't let the requested frameCount // decrease. This can confuse clients that cache frameCount(). -- cgit v1.1 From 089e87201522c8979ac8f00fa729e907f54c790b Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 15:12:48 -0800 Subject: mAudioRecord is always non-0 if set() is successful Change-Id: I0c2483210903c922f06f097ada373a37b9a90a02 --- media/libmedia/AudioRecord.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index bb66b4c..ad9e996 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -110,10 +110,8 @@ AudioRecord::~AudioRecord() mAudioRecordThread->requestExitAndWait(); mAudioRecordThread.clear(); } - if (mAudioRecord != 0) { - mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); - mAudioRecord.clear(); - } + mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); + mAudioRecord.clear(); IPCThreadState::self()->flushCommands(); AudioSystem::releaseAudioSessionId(mSessionId, -1); } @@ -170,6 +168,7 @@ status_t AudioRecord::set( AutoMutex lock(mLock); + // invariant that mAudioRecord != 0 is true only after set() returns successfully if (mAudioRecord != 0) { ALOGE("Track already in use"); return INVALID_OPERATION; @@ -508,6 +507,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) ALOGE("Could not get control block pointer"); return NO_INIT; } + // invariant that mAudioRecord != 0 is true only after set() returns successfully if (mAudioRecord != 0) { mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); mDeathNotifier.clear(); -- cgit v1.1 From b42f318d9733f88c7eb9bedfd33b086b8ea5dff5 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 13:42:58 -0800 Subject: Simplify and cleanup error handling in AudioRecord::getMinFrameCount Change-Id: I8721ecedfb429c4e233453d1e768ddf69ecabbe4 --- media/libmedia/AudioRecord.cpp | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 700718d..10aafed 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -41,30 +41,22 @@ status_t AudioRecord::getMinFrameCount( return BAD_VALUE; } - // default to 0 in case of error - *frameCount = 0; - - size_t size = 0; + size_t size; status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size); if (status != NO_ERROR) { - ALOGE("AudioSystem could not query the input buffer size; status %d", status); - return NO_INIT; + ALOGE("AudioSystem could not query the input buffer size for sampleRate %u, format %#x, " + "channelMask %#x; status %d", sampleRate, format, channelMask, status); + return status; } - if (size == 0) { + // We double the size of input buffer for ping pong use of record buffer. + // Assumes audio_is_linear_pcm(format) + if ((*frameCount = (size * 2) / (popcount(channelMask) * audio_bytes_per_sample(format))) == 0) { ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x", sampleRate, format, channelMask); return BAD_VALUE; } - // We double the size of input buffer for ping pong use of record buffer. - size <<= 1; - - // Assumes audio_is_linear_pcm(format) - uint32_t channelCount = popcount(channelMask); - size /= channelCount * audio_bytes_per_sample(format); - - *frameCount = size; return NO_ERROR; } @@ -213,11 +205,12 @@ status_t AudioRecord::set( mFrameSize = channelCount * audio_bytes_per_sample(format); // validate framecount - size_t minFrameCount = 0; + size_t minFrameCount; status_t status = AudioRecord::getMinFrameCount(&minFrameCount, sampleRate, format, channelMask); if (status != NO_ERROR) { - ALOGE("getMinFrameCount() failed; status %d", status); + ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; status %d", + sampleRate, format, channelMask, status); return status; } ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); -- cgit v1.1 From a5ed48d3476df7dd1e10b380a68e3333f2b646fd Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 25 Feb 2014 15:13:37 -0800 Subject: Move initialization of mRefreshRemaining to match AudioTrack This also fixes a bug where, for a re-created IAudioRecord, mRefreshRemaining was not being reset correctly. Change-Id: I9f721a4edf92aab859cf3f247ab7f65562d14fb0 --- media/libmedia/AudioRecord.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 99f2fe5..123834b 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -256,7 +256,6 @@ status_t AudioRecord::set( mActive = false; mCbf = cbf; - mRefreshRemaining = true; mUserData = user; // TODO: add audio hardware input latency here mLatency = (1000*mFrameCount) / sampleRate; @@ -538,6 +537,8 @@ status_t AudioRecord::openRecord_l(size_t epoch) } } + mRefreshRemaining = true; + // starting address of buffers in shared memory void *buffers = (char*)cblk + sizeof(audio_track_cblk_t); -- cgit v1.1 From f7cc3631c5c264e13ce8c6bc15bd829b2ff9b036 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 25 Feb 2014 15:14:45 -0800 Subject: Update comments to match AudioTrack Change-Id: I7dd14eabd78c9130a157da2063a1d65ec4f9c65a --- media/libmedia/AudioRecord.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 123834b..83e9ea8 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -539,7 +539,9 @@ status_t AudioRecord::openRecord_l(size_t epoch) mRefreshRemaining = true; - // starting address of buffers in shared memory + // Starting address of buffers in shared memory, immediately after the control block. This + // address is for the mapping within client address space. AudioFlinger::TrackBase::mBuffer + // is for the server address space. void *buffers = (char*)cblk + sizeof(audio_track_cblk_t); mFrameCount = frameCount; -- cgit v1.1 From 045e739161f5ae00321a6cfba20935abb791005b Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 25 Feb 2014 15:15:53 -0800 Subject: Move initialize of mInput to match AudioTrack Change-Id: I4dc977f22f51cd618dc83d800b4b8756929a4612 --- media/libmedia/AudioRecord.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 83e9ea8..7f86032 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -504,10 +504,8 @@ status_t AudioRecord::openRecord_l(size_t epoch) mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); mDeathNotifier.clear(); } - - // We retain a copy of the I/O handle, but don't own the reference - mInput = input; mAudioRecord = record; + mCblkMemory = iMem; audio_track_cblk_t* cblk = static_cast(iMemPointer); mCblk = cblk; @@ -537,6 +535,8 @@ status_t AudioRecord::openRecord_l(size_t epoch) } } + // We retain a copy of the I/O handle, but don't own the reference + mInput = input; mRefreshRemaining = true; // Starting address of buffers in shared memory, immediately after the control block. This -- cgit v1.1 From c08d20b6a37122ebf116262c9372509ed060d4c1 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 24 Feb 2014 15:21:10 -0800 Subject: Simplify error handling after track creation IAudioFlinger::createTrack and IAudioFlinger::openRecord both guarantee that (status == OK) == (sp<> != 0). Change-Id: I91cb4f7e843019efb65cace7ba146f7da7aa5b59 --- media/libmedia/AudioRecord.cpp | 4 +++- media/libmedia/AudioTrack.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 7f86032..4438dfd 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -482,10 +482,12 @@ status_t AudioRecord::openRecord_l(size_t epoch) ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId, "session ID changed from %d to %d", originalSessionId, mSessionId); - if (record == 0 || status != NO_ERROR) { + if (status != NO_ERROR) { ALOGE("AudioFlinger could not create record track, status: %d", status); goto release; } + ALOG_ASSERT(record != 0); + // AudioFlinger now owns the reference to the I/O handle, // so we are no longer responsible for releasing it. diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index eed7a0b..adf3847 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1016,10 +1016,12 @@ status_t AudioTrack::createTrack_l(size_t epoch) mClientUid, &status); - if (track == 0) { + if (status != NO_ERROR) { ALOGE("AudioFlinger could not create track, status: %d", status); goto release; } + ALOG_ASSERT(track != 0); + // AudioFlinger now owns the reference to the I/O handle, // so we are no longer responsible for releasing it. -- cgit v1.1 From e27e2d9bcabc1a367cb56b4599665c931a1d22ec Mon Sep 17 00:00:00 2001 From: Derek Sollenberger Date: Thu, 27 Feb 2014 14:29:56 -0500 Subject: Fix includes to no longer pull in Skia includes directories. bug:13225538 Change-Id: I4fccc414923f7e62cd46d691c67cb44b9692c225 --- media/libmedia/Android.mk | 1 - 1 file changed, 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index e0acae6..f3770e4 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -72,7 +72,6 @@ LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper LOCAL_MODULE:= libmedia LOCAL_C_INCLUDES := \ - $(call include-path-for, graphics corecg) \ $(TOP)/frameworks/native/include/media/openmax \ external/icu4c/common \ external/icu4c/i18n \ -- cgit v1.1 From 19a9fef6d2970a615f4f33025f9141e44b7c9f34 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Thu, 27 Feb 2014 13:20:07 -0800 Subject: Don't crash on remote read error, just return Change-Id: I35a2af255f55e008d64142ed0eceb6e83473d630 --- media/libmedia/IMediaHTTPConnection.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp index 22c470a..7e26ee6 100644 --- a/media/libmedia/IMediaHTTPConnection.cpp +++ b/media/libmedia/IMediaHTTPConnection.cpp @@ -95,7 +95,10 @@ struct BpMediaHTTPConnection : public BpInterface { data.writeInt32(size); status_t err = remote()->transact(READ_AT, data, &reply); - CHECK_EQ(err, (status_t)OK); + if (err != OK) { + ALOGE("remote readAt failed"); + return UNKNOWN_ERROR; + } int32_t exceptionCode = reply.readExceptionCode(); -- cgit v1.1 From c6ba823a397abf865b02f4f48fe18231f94d8e87 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 27 Feb 2014 13:34:29 -0800 Subject: Make openRecord_l more like createTrack_l for fast tracks: part 1 Use the transfer mode to distinguish use cases, as the presence of a callback handler is not sufficient. For example, the track could be configured for synchronous transfer with write() or read(), and also have a callback handler for position updates. But that does not mean the track can operate in fast track mode. Change-Id: I2a7f1f0ca98e68efe180b524496985109d8ce291 --- media/libmedia/AudioRecord.cpp | 30 +++++++++++++++++++++--------- media/libmedia/AudioTrack.cpp | 4 ++-- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 4438dfd..28daf16 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -430,18 +430,30 @@ status_t AudioRecord::openRecord_l(size_t epoch) return NO_INIT; } - IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; - pid_t tid = -1; + // Fast tracks must be at the primary _output_ [sic] sampling rate, + // because there is currently no concept of a primary input sampling rate + uint32_t afSampleRate = AudioSystem::getPrimaryOutputSamplingRate(); + if (afSampleRate == 0) { + ALOGW("getPrimaryOutputSamplingRate failed"); + } // Client can only express a preference for FAST. Server will perform additional tests. - // The only supported use case for FAST is callback transfer mode. + if ((mFlags & AUDIO_INPUT_FLAG_FAST) && !( + // use case: callback transfer mode + (mTransfer == TRANSFER_CALLBACK) && + // matching sample rate + (mSampleRate == afSampleRate))) { + ALOGW("AUDIO_INPUT_FLAG_FAST denied by client"); + // once denied, do not request again if IAudioRecord is re-created + mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); + } + + IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; + + pid_t tid = -1; if (mFlags & AUDIO_INPUT_FLAG_FAST) { - if ((mTransfer != TRANSFER_CALLBACK) || (mAudioRecordThread == 0)) { - ALOGW("AUDIO_INPUT_FLAG_FAST denied by client"); - // once denied, do not request again if IAudioRecord is re-created - mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); - } else { - trackFlags |= IAudioFlinger::TRACK_FAST; + trackFlags |= IAudioFlinger::TRACK_FAST; + if (mAudioRecordThread != 0) { tid = mAudioRecordThread->getTid(); } } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index adf3847..c79b2c8 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -892,8 +892,8 @@ status_t AudioTrack::createTrack_l(size_t epoch) // either of these use cases: // use case 1: shared buffer (mSharedBuffer != 0) || - // use case 2: callback handler - (mCbf != NULL)) && + // use case 2: callback transfer mode + (mTransfer == TRANSFER_CALLBACK)) && // matching sample rate (mSampleRate == afSampleRate))) { ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client"); -- cgit v1.1 From 838b3d8bafa4a781e277870dee4e0390165cff52 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 27 Feb 2014 15:30:41 -0800 Subject: Fix type of AudioTrack/AudioRecord parameter notificationFrames It's uint32_t consistently Change-Id: If8298c7e9aeea2b951fe47b675adbdf48d104846 --- media/libmedia/AudioRecord.cpp | 8 ++++---- media/libmedia/AudioTrack.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 4438dfd..f372da6 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -76,7 +76,7 @@ AudioRecord::AudioRecord( int frameCount, callback_t cbf, void* user, - int notificationFrames, + uint32_t notificationFrames, int sessionId, transfer_type transferType, audio_input_flags_t flags __unused) @@ -117,14 +117,14 @@ status_t AudioRecord::set( int frameCountInt, callback_t cbf, void* user, - int notificationFrames, + uint32_t notificationFrames, bool threadCanCallJava, int sessionId, transfer_type transferType, audio_input_flags_t flags) { ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %d, " - "notificationFrames %d, sessionId %d, transferType %d, flags %#x", + "notificationFrames %u, sessionId %d, transferType %d, flags %#x", inputSource, sampleRate, format, channelMask, frameCountInt, notificationFrames, sessionId, transferType, flags); @@ -803,7 +803,7 @@ nsecs_t AudioRecord::processAudioBuffer() } // Cache other fields that will be needed soon - size_t notificationFrames = mNotificationFramesAct; + uint32_t notificationFrames = mNotificationFramesAct; if (mRefreshRemaining) { mRefreshRemaining = false; mRemainingFrames = notificationFrames; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index adf3847..aea164b 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -112,7 +112,7 @@ AudioTrack::AudioTrack( audio_output_flags_t flags, callback_t cbf, void* user, - int notificationFrames, + uint32_t notificationFrames, int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, @@ -138,7 +138,7 @@ AudioTrack::AudioTrack( audio_output_flags_t flags, callback_t cbf, void* user, - int notificationFrames, + uint32_t notificationFrames, int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, @@ -186,7 +186,7 @@ status_t AudioTrack::set( audio_output_flags_t flags, callback_t cbf, void* user, - int notificationFrames, + uint32_t notificationFrames, const sp& sharedBuffer, bool threadCanCallJava, int sessionId, @@ -196,7 +196,7 @@ status_t AudioTrack::set( pid_t pid) { ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %d, " - "flags #%x, notificationFrames %d, sessionId %d, transferType %d", + "flags #%x, notificationFrames %u, sessionId %d, transferType %d", streamType, sampleRate, format, channelMask, frameCountInt, flags, notificationFrames, sessionId, transferType); @@ -1487,7 +1487,7 @@ nsecs_t AudioTrack::processAudioBuffer() // Cache other fields that will be needed soon uint32_t loopPeriod = mLoopPeriod; uint32_t sampleRate = mSampleRate; - size_t notificationFrames = mNotificationFramesAct; + uint32_t notificationFrames = mNotificationFramesAct; if (mRefreshRemaining) { mRefreshRemaining = false; mRemainingFrames = notificationFrames; -- cgit v1.1 From bce50bfc3846ab008bafa75c5d3f29fd7b5395f7 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 27 Feb 2014 15:29:51 -0800 Subject: Fix type of AudioTrack/AudioRecord parameter frameCount It's size_t consistently Change-Id: I29638ef59ac773218025f2403a3508a307b487e0 --- media/libmedia/AudioRecord.cpp | 15 ++++----------- media/libmedia/AudioTrack.cpp | 15 ++++----------- media/libmedia/JetPlayer.cpp | 2 +- media/libmedia/SoundPool.cpp | 2 +- 4 files changed, 10 insertions(+), 24 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index f372da6..a3cb538 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -73,7 +73,7 @@ AudioRecord::AudioRecord( uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - int frameCount, + size_t frameCount, callback_t cbf, void* user, uint32_t notificationFrames, @@ -114,7 +114,7 @@ status_t AudioRecord::set( uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - int frameCountInt, + size_t frameCount, callback_t cbf, void* user, uint32_t notificationFrames, @@ -123,9 +123,9 @@ status_t AudioRecord::set( transfer_type transferType, audio_input_flags_t flags) { - ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %d, " + ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "notificationFrames %u, sessionId %d, transferType %d, flags %#x", - inputSource, sampleRate, format, channelMask, frameCountInt, notificationFrames, + inputSource, sampleRate, format, channelMask, frameCount, notificationFrames, sessionId, transferType, flags); switch (transferType) { @@ -151,13 +151,6 @@ status_t AudioRecord::set( } mTransfer = transferType; - // FIXME "int" here is legacy and will be replaced by size_t later - if (frameCountInt < 0) { - ALOGE("Invalid frame count %d", frameCountInt); - return BAD_VALUE; - } - size_t frameCount = frameCountInt; - AutoMutex lock(mLock); // invariant that mAudioRecord != 0 is true only after set() returns successfully diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index aea164b..f85b0ce 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -108,7 +108,7 @@ AudioTrack::AudioTrack( uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - int frameCount, + size_t frameCount, audio_output_flags_t flags, callback_t cbf, void* user, @@ -182,7 +182,7 @@ status_t AudioTrack::set( uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - int frameCountInt, + size_t frameCount, audio_output_flags_t flags, callback_t cbf, void* user, @@ -195,9 +195,9 @@ status_t AudioTrack::set( int uid, pid_t pid) { - ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %d, " + ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "flags #%x, notificationFrames %u, sessionId %d, transferType %d", - streamType, sampleRate, format, channelMask, frameCountInt, flags, notificationFrames, + streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames, sessionId, transferType); switch (transferType) { @@ -236,13 +236,6 @@ status_t AudioTrack::set( mSharedBuffer = sharedBuffer; mTransfer = transferType; - // FIXME "int" here is legacy and will be replaced by size_t later - if (frameCountInt < 0) { - ALOGE("Invalid frame count %d", frameCountInt); - return BAD_VALUE; - } - size_t frameCount = frameCountInt; - ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp index e914b34..f0f1832 100644 --- a/media/libmedia/JetPlayer.cpp +++ b/media/libmedia/JetPlayer.cpp @@ -90,7 +90,7 @@ int JetPlayer::init() pLibConfig->sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_out_mask_from_count(pLibConfig->numChannels), - mTrackBufferSize, + (size_t) mTrackBufferSize, AUDIO_OUTPUT_FLAG_NONE); // create render and playback thread diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 4885b4f..a55e09c 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -587,7 +587,7 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate; uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount; - uint32_t frameCount = 0; + size_t frameCount = 0; if (loop) { frameCount = sample->size()/numChannels/ -- cgit v1.1 From d2304db2fcb5112292105a0949a55986a4c9875f Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 3 Feb 2014 07:40:31 -0800 Subject: Rename setStreamOutput to invalidateStream And simplify by removing the unused I/O handle parameter 'output'. Change-Id: Ie9c4df17a7378066312d4ed8790fda7a9125c95e --- media/libmedia/IAudioFlinger.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index e696323..a9a9f1a 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -58,7 +58,7 @@ enum { RESTORE_OUTPUT, OPEN_INPUT, CLOSE_INPUT, - SET_STREAM_OUTPUT, + INVALIDATE_STREAM, SET_VOICE_VOLUME, GET_RENDER_POSITION, GET_INPUT_FRAMES_LOST, @@ -545,13 +545,12 @@ public: return reply.readInt32(); } - virtual status_t setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output) + virtual status_t invalidateStream(audio_stream_type_t stream) { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32((int32_t) stream); - data.writeInt32((int32_t) output); - remote()->transact(SET_STREAM_OUTPUT, data, &reply); + remote()->transact(INVALIDATE_STREAM, data, &reply); return reply.readInt32(); } @@ -1044,11 +1043,10 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32(closeInput((audio_io_handle_t) data.readInt32())); return NO_ERROR; } break; - case SET_STREAM_OUTPUT: { + case INVALIDATE_STREAM: { CHECK_INTERFACE(IAudioFlinger, data, reply); - uint32_t stream = data.readInt32(); - audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); - reply->writeInt32(setStreamOutput((audio_stream_type_t) stream, output)); + audio_stream_type_t stream = (audio_stream_type_t) data.readInt32(); + reply->writeInt32(invalidateStream(stream)); return NO_ERROR; } break; case SET_VOICE_VOLUME: { -- cgit v1.1 From 2c48f27be6b3ae58e451d9b56c1dfd00e606f345 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 27 Feb 2014 13:35:06 -0800 Subject: Make openRecord_l more like createTrack_l for fast tracks: part 2 Assume double-buffering because we don't know the true HAL sample rate, and for fast tracks we must accomodate kernel scheduling and app computation jitter. Change-Id: I983d6048a8b4814cfa5bf789397cdd9f1572256c --- media/libmedia/AudioRecord.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 8b92669..a8e1f5d 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -451,6 +451,9 @@ status_t AudioRecord::openRecord_l(size_t epoch) } } + // FIXME Assume double buffering, because we don't know the true HAL sample rate + const uint32_t nBuffering = 2; + mNotificationFramesAct = mNotificationFramesReq; size_t frameCount = mReqFrameCount; @@ -522,23 +525,21 @@ status_t AudioRecord::openRecord_l(size_t epoch) } frameCount = temp; - // FIXME missing fast track frameCount logic mAwaitBoost = false; if (mFlags & AUDIO_INPUT_FLAG_FAST) { if (trackFlags & IAudioFlinger::TRACK_FAST) { - ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %u", mFrameCount); + ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %u", frameCount); mAwaitBoost = true; - // double-buffering is not required for fast tracks, due to tighter scheduling - if (mNotificationFramesAct == 0 || mNotificationFramesAct > mFrameCount) { - mNotificationFramesAct = mFrameCount; - } } else { - ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %u", mFrameCount); + ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %u", frameCount); // once denied, do not request again if IAudioRecord is re-created mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); - if (mNotificationFramesAct == 0 || mNotificationFramesAct > mFrameCount/2) { - mNotificationFramesAct = mFrameCount/2; - } + } + // Theoretically double-buffering is not required for fast tracks, + // due to tighter scheduling. But in practice, to accomodate kernels with + // scheduling jitter, and apps with computation jitter, we use double-buffering. + if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { + mNotificationFramesAct = frameCount/nBuffering; } } -- cgit v1.1 From 879707057cde0a83b5f6143c918c66b8f4a97581 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 27 Feb 2014 15:31:39 -0800 Subject: Make openRecord_l more like createTrack_l for fast tracks: part 3 Create the callback thread earlier, before creating the IAudioRecord, so that the thread's tid is available as a parameter to openRecord(). Also move initialization of mCbf to same point as in AudioTrack.cpp. Change-Id: I61ea4c5e2724ccfc691aaf51bc02a7c10d5a7495 --- media/libmedia/AudioRecord.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a8e1f5d..961b0a2 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -233,22 +233,27 @@ status_t AudioRecord::set( ALOGV("set(): mSessionId %d", mSessionId); mFlags = flags; + mCbf = cbf; + + if (cbf != NULL) { + mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); + mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); + } // create the IAudioRecord status = openRecord_l(0 /*epoch*/); + if (status != NO_ERROR) { + if (mAudioRecordThread != 0) { + mAudioRecordThread->requestExit(); // see comment in AudioRecord.h + mAudioRecordThread->requestExitAndWait(); + mAudioRecordThread.clear(); + } return status; } - if (cbf != NULL) { - mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); - mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); - } - mStatus = NO_ERROR; - mActive = false; - mCbf = cbf; mUserData = user; // TODO: add audio hardware input latency here mLatency = (1000*mFrameCount) / sampleRate; -- cgit v1.1 From 720ad9ddb2ac6b55b0dfbfcd2d8360151d8ac427 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 4 Feb 2014 11:00:59 -0800 Subject: AudioTrack non-blocking write Bug 7531968 Change-Id: I6d0e79fa8cab5b6eb36bcc34977f4cf0d7eec8ea --- media/libmedia/AudioTrack.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 5c62260..3184902 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1270,7 +1270,7 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) // ------------------------------------------------------------------------- -ssize_t AudioTrack::write(const void* buffer, size_t userSize) +ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking) { if (mTransfer != TRANSFER_SYNC || mIsTimed) { return INVALID_OPERATION; @@ -1289,7 +1289,8 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) while (userSize >= mFrameSize) { audioBuffer.frameCount = userSize / mFrameSize; - status_t err = obtainBuffer(&audioBuffer, &ClientProxy::kForever); + status_t err = obtainBuffer(&audioBuffer, + blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking); if (err < 0) { if (written > 0) { break; -- cgit v1.1 From ebcb254adb7402ab89ae97c4d9d16d886790dcb3 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 5 Mar 2014 18:30:08 -0800 Subject: audio policy service: clean up type casting. Change-Id: If16d6495c16e0d61a221f81bfd49e7d14bbfdc12 --- media/libmedia/IAudioPolicyService.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 4be3c09..1a027a6 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -476,10 +476,11 @@ status_t BnAudioPolicyService::onTransact( case START_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t output = static_cast (data.readInt32()); - uint32_t stream = data.readInt32(); + audio_stream_type_t stream = + static_cast (data.readInt32()); int session = data.readInt32(); reply->writeInt32(static_cast (startOutput(output, - (audio_stream_type_t)stream, + stream, session))); return NO_ERROR; } break; @@ -487,10 +488,11 @@ status_t BnAudioPolicyService::onTransact( case STOP_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t output = static_cast (data.readInt32()); - uint32_t stream = data.readInt32(); + audio_stream_type_t stream = + static_cast (data.readInt32()); int session = data.readInt32(); reply->writeInt32(static_cast (stopOutput(output, - (audio_stream_type_t)stream, + stream, session))); return NO_ERROR; } break; @@ -633,7 +635,7 @@ status_t BnAudioPolicyService::onTransact( CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = (audio_stream_type_t) data.readInt32(); uint32_t inPastMs = (uint32_t)data.readInt32(); - reply->writeInt32( isStreamActive((audio_stream_type_t) stream, inPastMs) ); + reply->writeInt32( isStreamActive(stream, inPastMs) ); return NO_ERROR; } break; @@ -641,7 +643,7 @@ status_t BnAudioPolicyService::onTransact( CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = (audio_stream_type_t) data.readInt32(); uint32_t inPastMs = (uint32_t)data.readInt32(); - reply->writeInt32( isStreamActiveRemotely((audio_stream_type_t) stream, inPastMs) ); + reply->writeInt32( isStreamActiveRemotely(stream, inPastMs) ); return NO_ERROR; } break; -- cgit v1.1 From 7064fd2dcdfeafea53cd5a992bb78c413542f29f Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Wed, 8 Jan 2014 13:59:53 -0800 Subject: AudioTrack: When paused, return cached playback position An offload output can be re-used between two audio tracks having the same configuration. A timestamp query for a paused track while the other is running would return an incorrect time. To fix this, cache the playback position on a pause() and return this time when requested until the track is resumed. Bug: 12826612. Change-Id: I324112ea9827e52fff53ef44cd8513c8d85a0bc4 --- media/libmedia/AudioTrack.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d25c40b..f353fac 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -99,7 +99,8 @@ AudioTrack::AudioTrack() : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { } @@ -121,7 +122,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, @@ -147,7 +149,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, @@ -551,6 +554,16 @@ void AudioTrack::pause() } mProxy->interrupt(); mAudioTrack->pause(); + + if (isOffloaded()) { + if (mOutput != 0) { + uint32_t halFrames; + // OffloadThread sends HAL pause in its threadLoop.. time saved + // here can be slightly off + AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition); + ALOGV("AudioTrack::pause for offload, cache current position %u", mPausedPosition); + } + } } status_t AudioTrack::setVolume(float left, float right) @@ -770,6 +783,12 @@ status_t AudioTrack::getPosition(uint32_t *position) const if (isOffloaded_l()) { uint32_t dspFrames = 0; + if ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING)) { + ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition); + *position = mPausedPosition; + return NO_ERROR; + } + if (mOutput != 0) { uint32_t halFrames; AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames); -- cgit v1.1 From 3a90f2849d49bf65f2d6257fd6da30ae46d745fa Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Mon, 10 Mar 2014 11:21:43 -0700 Subject: Fix freeze on pause isOffloaded() tries to lock mLock again. We should be calling isOffloaded_l() b/13394633 Change-Id: I155be6fee937f894d8e6c974e593223ab6014ade --- media/libmedia/AudioTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 3217171..ae47201 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -555,7 +555,7 @@ void AudioTrack::pause() mProxy->interrupt(); mAudioTrack->pause(); - if (isOffloaded()) { + if (isOffloaded_l()) { if (mOutput != 0) { uint32_t halFrames; // OffloadThread sends HAL pause in its threadLoop.. time saved -- cgit v1.1 From c5a17425986b4ce3384e6956762c86018b49c4a0 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 13 Mar 2014 14:59:59 -0700 Subject: Remove name output parameter from createTrack It was only used for one log. A better solution will be a per-track unique ID. Change-Id: Ia440e02ae4a5a4019a9a2d08970e1ee93ac4c3a3 --- media/libmedia/AudioTrack.cpp | 4 +--- media/libmedia/IAudioFlinger.cpp | 6 +----- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 60ed626..20c1cdb 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1024,7 +1024,6 @@ status_t AudioTrack::createTrack_l(size_t epoch) output, tid, &mSessionId, - mName, mClientUid, &status); @@ -1281,8 +1280,7 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) if (mState == STATE_ACTIVE) { audio_track_cblk_t* cblk = mCblk; if (android_atomic_and(~CBLK_DISABLED, &cblk->mFlags) & CBLK_DISABLED) { - ALOGW("releaseBuffer() track %p name=%s disabled due to previous underrun, restarting", - this, mName.string()); + ALOGW("releaseBuffer() track %p disabled due to previous underrun, restarting", this); // FIXME ignoring status mAudioTrack->start(); } diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index a9a9f1a..762681e 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -95,7 +95,6 @@ public: audio_io_handle_t output, pid_t tid, int *sessionId, - String8& name, int clientUid, status_t *status) { @@ -140,7 +139,6 @@ public: if (sessionId != NULL) { *sessionId = lSessionId; } - name = reply.readString8(); lStatus = reply.readInt32(); track = interface_cast(reply.readStrongBinder()); if (lStatus == NO_ERROR) { @@ -808,7 +806,6 @@ status_t BnAudioFlinger::onTransact( pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); int clientUid = data.readInt32(); - String8 name; status_t status; sp track; if ((haveSharedBuffer && (buffer == 0)) || @@ -819,13 +816,12 @@ status_t BnAudioFlinger::onTransact( track = createTrack( (audio_stream_type_t) streamType, sampleRate, format, channelMask, &frameCount, &flags, buffer, output, tid, - &sessionId, name, clientUid, &status); + &sessionId, clientUid, &status); LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR)); } reply->writeInt32(frameCount); reply->writeInt32(flags); reply->writeInt32(sessionId); - reply->writeString8(name); reply->writeInt32(status); reply->writeStrongBinder(track->asBinder()); return NO_ERROR; -- cgit v1.1 From bfd55f243feb3f04e26ad07aae035475768ada8a Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Tue, 18 Mar 2014 14:00:39 -0700 Subject: Use more tags to help the ICU detector. The detector only gave non-ascii data to ICU. In some cases that could result in very short data, for which ICU would issue a low confidence level for the actual encoding. By padding the data with additional (ascii) tags, we improve accuracy for such files. Becauses this can reduce accuracy in other cases, only do this when the initial confidence is low. b/13473604 Change-Id: I63d932043155c310b0e358cdf2d37787961e94b7 --- media/libmedia/CharacterEncodingDetector.cpp | 115 ++++++++++++++++++++++----- media/libmedia/CharacterEncodingDetector.h | 4 +- 2 files changed, 99 insertions(+), 20 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp index eb091ac..5a3bf9d 100644 --- a/media/libmedia/CharacterEncodingDetector.cpp +++ b/media/libmedia/CharacterEncodingDetector.cpp @@ -90,6 +90,7 @@ void CharacterEncodingDetector::detectAndConvert() { char buf[1024]; buf[0] = 0; int idx; + bool allprintable = true; for (int i = 0; i < size; i++) { const char *name = mNames.getEntry(i); const char *value = mValues.getEntry(i); @@ -103,18 +104,60 @@ void CharacterEncodingDetector::detectAndConvert() { strlcat(buf, value, sizeof(buf)); // separate tags by space so ICU's ngram detector can do its job strlcat(buf, " ", sizeof(buf)); + allprintable = false; } } - ucsdet_setText(csd, buf, strlen(buf), &status); - int32_t matches; - const UCharsetMatch** ucma = ucsdet_detectAll(csd, &matches, &status); - const char *combinedenc = "???"; - - const UCharsetMatch* bestCombinedMatch = getPreferred(buf, strlen(buf), ucma, matches); + const char *combinedenc = "UTF-8"; + if (allprintable) { + // since 'buf' is empty, ICU would return a UTF-8 matcher with low confidence, so + // no need to even call it + ALOGV("all tags are printable, assuming ascii (%d)", strlen(buf)); + } else { + ucsdet_setText(csd, buf, strlen(buf), &status); + int32_t matches; + const UCharsetMatch** ucma = ucsdet_detectAll(csd, &matches, &status); + bool goodmatch = true; + const UCharsetMatch* bestCombinedMatch = getPreferred(buf, strlen(buf), + ucma, matches, &goodmatch); + + if (!goodmatch && strlen(buf) < 20) { + ALOGV("not a good match, trying with more data"); + // This string might be too short for ICU to do anything useful with. + // (real world example: "Björk" in ISO-8859-1 might be detected as GB18030, because + // the ISO detector reports a confidence of 0, while the GB18030 detector reports + // a confidence of 10 with no invalid characters) + // Append artist, album and title if they were previously omitted because they + // were printable ascii. + bool added = false; + for (int i = 0; i < size; i++) { + const char *name = mNames.getEntry(i); + const char *value = mValues.getEntry(i); + if (isPrintableAscii(value, strlen(value)) && ( + !strcmp(name, "artist") || + !strcmp(name, "album") || + !strcmp(name, "title"))) { + strlcat(buf, value, sizeof(buf)); + strlcat(buf, " ", sizeof(buf)); + added = true; + } + } + if (added) { + ucsdet_setText(csd, buf, strlen(buf), &status); + ucma = ucsdet_detectAll(csd, &matches, &status); + bestCombinedMatch = getPreferred(buf, strlen(buf), + ucma, matches, &goodmatch); + if (!goodmatch) { + ALOGV("still not a good match after adding printable tags"); + } + } else { + ALOGV("no printable tags to add"); + } + } - if (bestCombinedMatch != NULL) { - combinedenc = ucsdet_getName(bestCombinedMatch, &status); + if (bestCombinedMatch != NULL) { + combinedenc = ucsdet_getName(bestCombinedMatch, &status); + } } for (int i = 0; i < size; i++) { @@ -128,7 +171,7 @@ void CharacterEncodingDetector::detectAndConvert() { int32_t inputLength = strlen(s); const char *enc; - if (!strcmp(name, "artist") || + if (!allprintable && !strcmp(name, "artist") || !strcmp(name, "albumartist") || !strcmp(name, "composer") || !strcmp(name, "genre") || @@ -137,15 +180,20 @@ void CharacterEncodingDetector::detectAndConvert() { // use encoding determined from the combination of artist/album/title etc. enc = combinedenc; } else { - ucsdet_setText(csd, s, inputLength, &status); - ucm = ucsdet_detect(csd, &status); - if (!ucm) { - mValues.setEntry(i, "???"); - continue; + if (isPrintableAscii(s, inputLength)) { + enc = "UTF-8"; + ALOGV("@@@@ %s is ascii", mNames.getEntry(i)); + } else { + ucsdet_setText(csd, s, inputLength, &status); + ucm = ucsdet_detect(csd, &status); + if (!ucm) { + mValues.setEntry(i, "???"); + continue; + } + enc = ucsdet_getName(ucm, &status); + ALOGV("@@@@ recognized charset: %s for %s confidence %d", + enc, mNames.getEntry(i), ucsdet_getConfidence(ucm, &status)); } - enc = ucsdet_getName(ucm, &status); - ALOGV("@@@@ recognized charset: %s for %s confidence %d", - enc, mNames.getEntry(i), ucsdet_getConfidence(ucm, &status)); } if (strcmp(enc,"UTF-8") != 0) { @@ -207,10 +255,15 @@ void CharacterEncodingDetector::detectAndConvert() { * algorithm and larger frequent character lists than ICU * - devalue encoding where the conversion contains unlikely characters (symbols, reserved, etc) * - pick the highest match + * - signal to the caller whether this match is considered good: confidence > 15, and confidence + * delta with the next runner up > 15 */ const UCharsetMatch *CharacterEncodingDetector::getPreferred( - const char *input, size_t len, const UCharsetMatch** ucma, size_t nummatches) { + const char *input, size_t len, + const UCharsetMatch** ucma, size_t nummatches, + bool *goodmatch) { + *goodmatch = false; Vector matches; UErrorCode status = U_ZERO_ERROR; @@ -227,6 +280,10 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( return NULL; } if (num == 1) { + int confidence = ucsdet_getConfidence(matches[0], &status); + if (confidence > 15) { + *goodmatch = true; + } return matches[0]; } @@ -326,15 +383,35 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( // find match with highest confidence after adjusting for unlikely characters int highest = newconfidence[0]; size_t highestidx = 0; + int runnerup = -10000; + int runnerupidx = -10000; num = newconfidence.size(); for (size_t i = 1; i < num; i++) { if (newconfidence[i] > highest) { + runnerup = highest; + runnerupidx = highestidx; highest = newconfidence[i]; highestidx = i; + } else if (newconfidence[i] > runnerup){ + runnerup = newconfidence[i]; + runnerupidx = i; } } status = U_ZERO_ERROR; - ALOGV("selecting '%s' w/ %d confidence", ucsdet_getName(matches[highestidx], &status), highest); + ALOGV("selecting: '%s' w/ %d confidence", + ucsdet_getName(matches[highestidx], &status), highest); + if (runnerupidx < 0) { + ALOGV("no runner up"); + if (highest > 15) { + *goodmatch = true; + } + } else { + ALOGV("runner up: '%s' w/ %d confidence", + ucsdet_getName(matches[runnerupidx], &status), runnerup); + if ((highest - runnerup) > 15) { + *goodmatch = true; + } + } return matches[highestidx]; } diff --git a/media/libmedia/CharacterEncodingDetector.h b/media/libmedia/CharacterEncodingDetector.h index 3655a91..7b5ed86 100644 --- a/media/libmedia/CharacterEncodingDetector.h +++ b/media/libmedia/CharacterEncodingDetector.h @@ -41,7 +41,9 @@ class CharacterEncodingDetector { private: const UCharsetMatch *getPreferred( - const char *input, size_t len, const UCharsetMatch** ucma, size_t matches); + const char *input, size_t len, + const UCharsetMatch** ucma, size_t matches, + bool *goodmatch); bool isFrequent(const uint16_t *values, uint32_t c); -- cgit v1.1 From de9453fb5cbc9cd69fd1ea45d577851e3aa3b8c9 Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Wed, 19 Mar 2014 13:05:45 -0400 Subject: Add MediaPlayer::getAudioStreamType. Change-Id: I9cd8a718d2873543609aa651fd85749478f4f89f --- media/libmedia/mediaplayer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index d94c7c5..0be01a9 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -531,6 +531,14 @@ status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type) return OK; } +status_t MediaPlayer::getAudioStreamType(audio_stream_type_t *type) +{ + ALOGV("getAudioStreamType"); + Mutex::Autolock _l(mLock); + *type = mStreamType; + return OK; +} + status_t MediaPlayer::setLooping(int loop) { ALOGV("MediaPlayer::setLooping"); -- cgit v1.1 From 1392eb3d1802e9f894f87d7a7387207d1b6faca1 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 25 Mar 2014 11:49:08 -0700 Subject: Fix operator precedence Change-Id: I164708a5b76a341a185467b008ecbec98d58a6df --- media/libmedia/CharacterEncodingDetector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp index 5a3bf9d..4992798 100644 --- a/media/libmedia/CharacterEncodingDetector.cpp +++ b/media/libmedia/CharacterEncodingDetector.cpp @@ -171,12 +171,12 @@ void CharacterEncodingDetector::detectAndConvert() { int32_t inputLength = strlen(s); const char *enc; - if (!allprintable && !strcmp(name, "artist") || + if (!allprintable && (!strcmp(name, "artist") || !strcmp(name, "albumartist") || !strcmp(name, "composer") || !strcmp(name, "genre") || !strcmp(name, "album") || - !strcmp(name, "title")) { + !strcmp(name, "title"))) { // use encoding determined from the combination of artist/album/title etc. enc = combinedenc; } else { -- cgit v1.1 From 85d109a4b0eddd76a8c5cee170bc2bcc99d00118 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 17 Jan 2014 10:25:08 -0800 Subject: Document AudioSystem::newAudioSessionId() failures Change-Id: Iaa168722f362c36bdfa87fe20dc0a59b43cf1ca3 --- media/libmedia/AudioSystem.cpp | 2 +- media/libmedia/IAudioFlinger.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 140fb66..c418466 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -431,7 +431,7 @@ uint32_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) int AudioSystem::newAudioSessionId() { const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return 0; + if (af == 0) return AUDIO_SESSION_ALLOCATE; return af->newAudioSessionId(); } diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 762681e..f28b82d 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -599,7 +599,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply); - int id = 0; + int id = AUDIO_SESSION_ALLOCATE; if (status == NO_ERROR) { id = reply.readInt32(); } -- cgit v1.1 From 9ea65d0f4a564478343b1a722fae4ce5883670c3 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 17 Jan 2014 10:21:24 -0800 Subject: Fix uses of KeyedVector Constructor for AudioFlinger::mAudioHwDevs was missing, and so AudioFlinger::findSuitableHwDev_l() could return an undefined pointer if a non-0 module wasn't found. A KeyedVector of Plain Old Data (POD) element type must specify the default value in the constructor, or else the default will be undefined. Minor: - Parameter had wrong type in constructor for AudioSystem::gOutputs. - Remove obsolete AudioSystem::gStreamOutputMap. Change-Id: I9841493e018440e559d8b8b0e4e748ba2b2d365b --- media/libmedia/AudioSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 140fb66..193e488 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -37,7 +37,7 @@ sp AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; // Cached values -DefaultKeyedVector AudioSystem::gOutputs(0); +DefaultKeyedVector AudioSystem::gOutputs(NULL); // Cached values for recording queries, all protected by gLock uint32_t AudioSystem::gPrevInSamplingRate; -- cgit v1.1 From 66e4635cb09fadcaccf912f37c387396c428378a Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 16 Jan 2014 17:44:23 -0800 Subject: Use symbolic constants from AUDIO_INTERLEAVE_* AUDIO_STREAM_MIN AUDIO_SESSION_ALLOCATE Change-Id: I31dd6f327204685e50716079ce21c4ba206dff11 --- media/libmedia/AudioTrack.cpp | 12 ++++++------ media/libmedia/ToneGenerator.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 20c1cdb..74c1800 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -333,8 +333,8 @@ status_t AudioTrack::set( mOffloadInfo = NULL; } - mVolume[LEFT] = 1.0f; - mVolume[RIGHT] = 1.0f; + mVolume[AUDIO_INTERLEAVE_LEFT] = 1.0f; + mVolume[AUDIO_INTERLEAVE_RIGHT] = 1.0f; mSendLevel = 0.0f; // mFrameCount is initialized in createTrack_l mReqFrameCount = frameCount; @@ -573,8 +573,8 @@ status_t AudioTrack::setVolume(float left, float right) } AutoMutex lock(mLock); - mVolume[LEFT] = left; - mVolume[RIGHT] = right; + mVolume[AUDIO_INTERLEAVE_LEFT] = left; + mVolume[AUDIO_INTERLEAVE_RIGHT] = right; mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); @@ -1134,8 +1134,8 @@ status_t AudioTrack::createTrack_l(size_t epoch) mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF); mProxy = mStaticProxy; } - mProxy->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | - uint16_t(mVolume[LEFT] * 0x1000)); + mProxy->setVolumeLR((uint32_t(uint16_t(mVolume[AUDIO_INTERLEAVE_RIGHT] * 0x1000)) << 16) | + uint16_t(mVolume[AUDIO_INTERLEAVE_LEFT] * 0x1000)); mProxy->setSendLevel(mSendLevel); mProxy->setSampleRate(mSampleRate); mProxy->setEpoch(epoch); diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp index adef3be..61b6d36 100644 --- a/media/libmedia/ToneGenerator.cpp +++ b/media/libmedia/ToneGenerator.cpp @@ -1057,7 +1057,7 @@ bool ToneGenerator::initAudioTrack() { 0, // notificationFrames 0, // sharedBuffer mThreadCanCallJava, - 0, // sessionId + AUDIO_SESSION_ALLOCATE, AudioTrack::TRANSFER_CALLBACK); if (mpAudioTrack->initCheck() != NO_ERROR) { -- cgit v1.1 From 45faf7e02791993a487d6e038d16ff46395f1975 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 17 Jan 2014 10:23:01 -0800 Subject: Use symbol AUDIO_DEVICE_NONE from Change-Id: I61f882c5e7c949bf00d3bfc745ebf3b5e1c42a58 --- media/libmedia/AudioSystem.cpp | 2 +- media/libmedia/IAudioFlinger.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 140fb66..dafccd6 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -739,7 +739,7 @@ uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream) audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream) { const sp& aps = AudioSystem::get_audio_policy_service(); - if (aps == 0) return (audio_devices_t)0; + if (aps == 0) return AUDIO_DEVICE_NONE; return aps->getDevicesForStream(stream); } diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 762681e..67564ee 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -410,7 +410,7 @@ public: const audio_offload_info_t *offloadInfo) { Parcel data, reply; - audio_devices_t devices = pDevices != NULL ? *pDevices : (audio_devices_t)0; + audio_devices_t devices = pDevices != NULL ? *pDevices : AUDIO_DEVICE_NONE; uint32_t samplingRate = pSamplingRate != NULL ? *pSamplingRate : 0; audio_format_t format = pFormat != NULL ? *pFormat : AUDIO_FORMAT_DEFAULT; audio_channel_mask_t channelMask = pChannelMask != NULL ? @@ -501,7 +501,7 @@ public: audio_channel_mask_t *pChannelMask) { Parcel data, reply; - audio_devices_t devices = pDevices != NULL ? *pDevices : (audio_devices_t)0; + audio_devices_t devices = pDevices != NULL ? *pDevices : AUDIO_DEVICE_NONE; uint32_t samplingRate = pSamplingRate != NULL ? *pSamplingRate : 0; audio_format_t format = pFormat != NULL ? *pFormat : AUDIO_FORMAT_DEFAULT; audio_channel_mask_t channelMask = pChannelMask != NULL ? -- cgit v1.1 From 241618f1b286f9e7e02fe61e96d9194e2e1e8a7a Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 25 Mar 2014 17:48:57 -0700 Subject: Remove streamType parameter from AudioSystem::getLatency() Change-Id: Ie7346e93436ddc215cad7d16be555dcb6c277d54 --- media/libmedia/AudioSystem.cpp | 5 ++--- media/libmedia/AudioTrack.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 140fb66..758e660 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -333,11 +333,10 @@ status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t st return PERMISSION_DENIED; } - return getLatency(output, streamType, latency); + return getLatency(output, latency); } status_t AudioSystem::getLatency(audio_io_handle_t output, - audio_stream_type_t streamType __unused, uint32_t* latency) { OutputDescriptor *outputDesc; @@ -354,7 +353,7 @@ status_t AudioSystem::getLatency(audio_io_handle_t output, gLock.unlock(); } - ALOGV("getLatency() streamType %d, output %d, latency %d", streamType, output, *latency); + ALOGV("getLatency() output %d, latency %d", output, *latency); return NO_ERROR; } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 20c1cdb..fa7249b 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -878,7 +878,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) // Not all of these values are needed under all conditions, but it is easier to get them all uint32_t afLatency; - status = AudioSystem::getLatency(output, mStreamType, &afLatency); + status = AudioSystem::getLatency(output, &afLatency); if (status != NO_ERROR) { ALOGE("getLatency(%d) failed status %d", output, status); goto release; -- cgit v1.1 From ebb80e4f9873cc1a5ee3f766323f622bb0c07ae5 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 26 Mar 2014 08:21:17 -0700 Subject: Remove dead code Change-Id: I0878d11451c7bbbf96b59f5fe0cd97ba1f033aa9 --- media/libmedia/AudioTrack.cpp | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 20c1cdb..62fd7b9 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -371,16 +371,6 @@ status_t AudioTrack::set( mAudioTrackThread->requestExitAndWait(); mAudioTrackThread.clear(); } - // Use of direct and offloaded output streams is ref counted by audio policy manager. -#if 0 // FIXME This should no longer be needed - //Use of direct and offloaded output streams is ref counted by audio policy manager. - // As getOutput was called above and resulted in an output stream to be opened, - // we need to release it. - if (mOutput != 0) { - AudioSystem::releaseOutput(mOutput); - mOutput = 0; - } -#endif return status; } @@ -1775,16 +1765,6 @@ status_t AudioTrack::restoreTrack_l(const char *from) } } if (result != NO_ERROR) { - // Use of direct and offloaded output streams is ref counted by audio policy manager. -#if 0 // FIXME This should no longer be needed - //Use of direct and offloaded output streams is ref counted by audio policy manager. - // As getOutput was called above and resulted in an output stream to be opened, - // we need to release it. - if (mOutput != 0) { - AudioSystem::releaseOutput(mOutput); - mOutput = 0; - } -#endif ALOGW("restoreTrack_l() failed status %d", result); mState = STATE_STOPPED; } -- cgit v1.1 From 0ed19594452c901c3c8665d06610fffe46895d06 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 26 Mar 2014 07:50:05 -0700 Subject: Remove stream type from AudioSystem::getRenderPosition() The I/O handle is never equal to AUDIO_IO_HANDLE_NONE, so the stream type is not needed. Change-Id: I1ab134a2fa379d6dd0b6167345a856a192d478f9 --- media/libmedia/AudioSystem.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 140fb66..ac93a3a 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -401,19 +401,11 @@ status_t AudioSystem::setVoiceVolume(float value) } status_t AudioSystem::getRenderPosition(audio_io_handle_t output, uint32_t *halFrames, - uint32_t *dspFrames, audio_stream_type_t stream) + uint32_t *dspFrames) { const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; - if (stream == AUDIO_STREAM_DEFAULT) { - stream = AUDIO_STREAM_MUSIC; - } - - if (output == 0) { - output = getOutput(stream); - } - return af->getRenderPosition(halFrames, dspFrames, output); } -- cgit v1.1 From adad3d7d935da176ff24941b4ae9edf7340e9b96 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 21 Feb 2014 14:51:43 -0800 Subject: Use LOG_ALWAYS_FATAL instead of LOG_FATAL LOG_FATAL is compiled out in most builds, so the assertion checks were not being performed. Change-Id: I774f0985ab9c5ccecd8989a0f1c940386b73fc35 --- media/libmedia/AudioTrackShared.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index fdd1a12..58c9fc1 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -200,7 +200,7 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques ts = &remaining; break; default: - LOG_FATAL("obtainBuffer() timeout=%d", timeout); + LOG_ALWAYS_FATAL("obtainBuffer() timeout=%d", timeout); ts = NULL; break; } @@ -429,7 +429,7 @@ status_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *request ts = &remaining; break; default: - LOG_FATAL("waitStreamEndDone() timeout=%d", timeout); + LOG_ALWAYS_FATAL("waitStreamEndDone() timeout=%d", timeout); ts = NULL; break; } @@ -470,7 +470,7 @@ StaticAudioTrackClientProxy::StaticAudioTrackClientProxy(audio_track_cblk_t* cbl void StaticAudioTrackClientProxy::flush() { - LOG_FATAL("static flush"); + LOG_ALWAYS_FATAL("static flush"); } void StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount) -- cgit v1.1 From 2301acc6a9c7a3af4ad01f3d1d0f76f13eca7350 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 17 Jan 2014 10:21:00 -0800 Subject: Update comments Change-Id: I5776313b9b49072cd666d28880f0d07cc73f827b --- media/libmedia/AudioSystem.cpp | 2 +- media/libmedia/IAudioFlinger.cpp | 2 ++ media/libmedia/IAudioPolicyService.cpp | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 8542404..a2cb619 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -35,8 +35,8 @@ Mutex AudioSystem::gLock; sp AudioSystem::gAudioFlinger; sp AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; -// Cached values +// Cached values for output handles DefaultKeyedVector AudioSystem::gOutputs(NULL); // Cached values for recording queries, all protected by gLock diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 2cb0c5c..eb813bd 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -109,6 +109,7 @@ public: data.writeInt32(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); + // haveSharedBuffer if (sharedBuffer != 0) { data.writeInt32(true); data.writeStrongBinder(sharedBuffer->asBinder()); @@ -424,6 +425,7 @@ public: data.writeInt32(channelMask); data.writeInt32(latency); data.writeInt32((int32_t) flags); + // hasOffloadInfo if (offloadInfo == NULL) { data.writeInt32(0); } else { diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 1a027a6..9bb4a49 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -137,6 +137,7 @@ public: data.writeInt32(static_cast (format)); data.writeInt32(channelMask); data.writeInt32(static_cast (flags)); + // hasOffloadInfo if (offloadInfo == NULL) { data.writeInt32(0); } else { -- cgit v1.1 From 142f519aa1acd5804d111e60d100f170fed28405 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 25 Mar 2014 17:44:59 -0700 Subject: Use symbol AUDIO_IO_HANDLE_NONE from Change-Id: Id6b1aa17558eb73e17f22b8eab6cd02e00a96dff --- media/libmedia/AudioRecord.cpp | 2 +- media/libmedia/AudioSystem.cpp | 14 +++++++------- media/libmedia/AudioTrack.cpp | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 961b0a2..a7bf380 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -471,7 +471,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId); - if (input == 0) { + if (input == AUDIO_IO_HANDLE_NONE) { ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " "channel mask %#x, session %d", mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId); diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 8542404..301c7d6 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -196,12 +196,12 @@ String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& ke status_t AudioSystem::setParameters(const String8& keyValuePairs) { - return setParameters((audio_io_handle_t) 0, keyValuePairs); + return setParameters(AUDIO_IO_HANDLE_NONE, keyValuePairs); } String8 AudioSystem::getParameters(const String8& keys) { - return getParameters((audio_io_handle_t) 0, keys); + return getParameters(AUDIO_IO_HANDLE_NONE, keys); } // convert volume steps to natural log scale @@ -284,7 +284,7 @@ status_t AudioSystem::getOutputFrameCount(size_t* frameCount, audio_stream_type_ } output = getOutput(streamType); - if (output == 0) { + if (output == AUDIO_IO_HANDLE_NONE) { return PERMISSION_DENIED; } @@ -329,7 +329,7 @@ status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t st } output = getOutput(streamType); - if (output == 0) { + if (output == AUDIO_IO_HANDLE_NONE) { return PERMISSION_DENIED; } @@ -413,7 +413,7 @@ uint32_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) const sp& af = AudioSystem::get_audio_flinger(); uint32_t result = 0; if (af == 0) return result; - if (ioHandle == 0) return result; + if (ioHandle == AUDIO_IO_HANDLE_NONE) return result; result = af->getInputFramesLost(ioHandle); return result; @@ -464,7 +464,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle const OutputDescriptor *desc; audio_stream_type_t stream; - if (ioHandle == 0) return; + if (ioHandle == AUDIO_IO_HANDLE_NONE) return; Mutex::Autolock _l(AudioSystem::gLock); @@ -738,7 +738,7 @@ audio_io_handle_t AudioSystem::getOutputForEffect(const effect_descriptor_t *des { const sp& aps = AudioSystem::get_audio_policy_service(); // FIXME change return type to status_t, and return PERMISSION_DENIED here - if (aps == 0) return 0; + if (aps == 0) return AUDIO_IO_HANDLE_NONE; return aps->getOutputForEffect(desc); } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 22760d9..fbfd3da 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -546,7 +546,7 @@ void AudioTrack::pause() mAudioTrack->pause(); if (isOffloaded_l()) { - if (mOutput != 0) { + if (mOutput != AUDIO_IO_HANDLE_NONE) { uint32_t halFrames; // OffloadThread sends HAL pause in its threadLoop.. time saved // here can be slightly off @@ -633,7 +633,7 @@ uint32_t AudioTrack::getSampleRate() const // query the HAL and update if needed. // FIXME use Proxy return channel to update the rate from server and avoid polling here if (isOffloaded_l()) { - if (mOutput != 0) { + if (mOutput != AUDIO_IO_HANDLE_NONE) { uint32_t sampleRate = 0; status_t status = AudioSystem::getSamplingRate(mOutput, mStreamType, &sampleRate); if (status == NO_ERROR) { @@ -779,7 +779,7 @@ status_t AudioTrack::getPosition(uint32_t *position) const return NO_ERROR; } - if (mOutput != 0) { + if (mOutput != AUDIO_IO_HANDLE_NONE) { uint32_t halFrames; AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames); } @@ -855,7 +855,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) audio_io_handle_t output = AudioSystem::getOutput(mStreamType, mSampleRate, mFormat, mChannelMask, mFlags, mOffloadInfo); - if (output == 0) { + if (output == AUDIO_IO_HANDLE_NONE) { ALOGE("Could not get audio output for stream type %d, sample rate %u, format %#x, " "channel mask %#x, flags %#x", mStreamType, mSampleRate, mFormat, mChannelMask, mFlags); @@ -1798,7 +1798,7 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) String8 AudioTrack::getParameters(const String8& keys) { audio_io_handle_t output = getOutput(); - if (output != 0) { + if (output != AUDIO_IO_HANDLE_NONE) { return AudioSystem::getParameters(output, keys); } else { return String8::empty(); -- cgit v1.1 From 68d9d71a792deed75d32fe13febc07c9c12c8449 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Tue, 4 Mar 2014 13:21:31 -0800 Subject: Support CAST V2 Authentication in MediaDrm Java API version Update frameworks to enable support for CAST V2 Authentication in the DRM Plugin. Change-Id: I9066ada0edf8e0d777c503897d8c7fc7f76f2861 related-to-bug: 12702350 --- media/libmedia/IDrm.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp index f7a9a75..f1a6a9f 100644 --- a/media/libmedia/IDrm.cpp +++ b/media/libmedia/IDrm.cpp @@ -51,6 +51,7 @@ enum { ENCRYPT, DECRYPT, SIGN, + SIGN_RSA, VERIFY, SET_LISTENER }; @@ -196,11 +197,15 @@ struct BpDrm : public BpInterface { return reply.readInt32(); } - virtual status_t getProvisionRequest(Vector &request, + virtual status_t getProvisionRequest(String8 const &certType, + String8 const &certAuthority, + Vector &request, String8 &defaultUrl) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + data.writeString8(certType); + data.writeString8(certAuthority); remote()->transact(GET_PROVISION_REQUEST, data, &reply); readVector(reply, request); @@ -209,13 +214,18 @@ struct BpDrm : public BpInterface { return reply.readInt32(); } - virtual status_t provideProvisionResponse(Vector const &response) { + virtual status_t provideProvisionResponse(Vector const &response, + Vector &certificate, + Vector &wrappedKey) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, response); remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply); + readVector(reply, certificate); + readVector(reply, wrappedKey); + return reply.readInt32(); } @@ -386,6 +396,25 @@ struct BpDrm : public BpInterface { return reply.readInt32(); } + virtual status_t signRSA(Vector const &sessionId, + String8 const &algorithm, + Vector const &message, + Vector const &wrappedKey, + Vector &signature) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, sessionId); + data.writeString8(algorithm); + writeVector(data, message); + writeVector(data, wrappedKey); + + remote()->transact(SIGN_RSA, data, &reply); + readVector(reply, signature); + + return reply.readInt32(); + } + virtual status_t setListener(const sp& listener) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); @@ -563,9 +592,13 @@ status_t BnDrm::onTransact( case GET_PROVISION_REQUEST: { CHECK_INTERFACE(IDrm, data, reply); + String8 certType = data.readString8(); + String8 certAuthority = data.readString8(); + Vector request; String8 defaultUrl; - status_t result = getProvisionRequest(request, defaultUrl); + status_t result = getProvisionRequest(certType, certAuthority, + request, defaultUrl); writeVector(reply, request); reply->writeString8(defaultUrl); reply->writeInt32(result); @@ -576,8 +609,13 @@ status_t BnDrm::onTransact( { CHECK_INTERFACE(IDrm, data, reply); Vector response; + Vector certificate; + Vector wrappedKey; readVector(data, response); - reply->writeInt32(provideProvisionResponse(response)); + status_t result = provideProvisionResponse(response, certificate, wrappedKey); + writeVector(reply, certificate); + writeVector(reply, wrappedKey); + reply->writeInt32(result); return OK; } @@ -725,6 +763,20 @@ status_t BnDrm::onTransact( return OK; } + case SIGN_RSA: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector sessionId, message, wrappedKey, signature; + readVector(data, sessionId); + String8 algorithm = data.readString8(); + readVector(data, message); + readVector(data, wrappedKey); + uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature); + writeVector(reply, signature); + reply->writeInt32(result); + return OK; + } + case SET_LISTENER: { CHECK_INTERFACE(IDrm, data, reply); sp listener = -- cgit v1.1 From 877a0ac7e8677fa1cbd0e8565ad9d38ba0db5fc0 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 30 Apr 2014 17:04:13 -0700 Subject: Use AUDIO_INTERLEAVE_* constants Change-Id: I6609fa75c9a57fc4ca3887d626a2f4fb8b6593a1 --- media/libmedia/AudioTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index fbfd3da..8daf08b 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1820,7 +1820,7 @@ status_t AudioTrack::dump(int fd, const Vector& args __unused) const result.append(" AudioTrack::dump\n"); snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, - mVolume[0], mVolume[1]); + mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]); result.append(buffer); snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%zu)\n", mFormat, mChannelCount, mFrameCount); -- cgit v1.1 From c4b88a8d0f524666bf0f390075c334d047a104f2 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 30 Apr 2014 16:54:30 -0700 Subject: Fix bug for direct track with PCM != 16-bit The AUDIO_FORMAT_PCM_8_BIT format was being converted to AUDIO_FORMAT_PCM_16_BIT on client side even for direct tracks. That conversion was incorrect; it should only be done for mixed tracks. Also remove checks for specific PCM formats in the generic part of server side of createTrack. Those format checks should only be done by the thread. This will allow direct tracks for PCM 8-bit, PCM 24-bit, etc. Change-Id: If5b9fd79f8642ed93e2aeabcaf4809b2ed798978 --- media/libmedia/AudioTrack.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 8daf08b..dc4f90e 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1005,7 +1005,8 @@ status_t AudioTrack::createTrack_l(size_t epoch) sp track = audioFlinger->createTrack(mStreamType, mSampleRate, // AudioFlinger only sees 16-bit PCM - mFormat == AUDIO_FORMAT_PCM_8_BIT ? + mFormat == AUDIO_FORMAT_PCM_8_BIT && + !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT) ? AUDIO_FORMAT_PCM_16_BIT : mFormat, mChannelMask, &temp, -- cgit v1.1 From 828f883a43f66f77d776a75d0ea2b87c7c826071 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 7 May 2014 11:17:52 -0700 Subject: Fix a couple of fast capture typo bugs AudioRecord constructor was not passing flags through to set(). Server-side check was using wrong kind of channel mask. Change-Id: Ifaa880ec323771e9fd168262be05f3e539f53390 --- media/libmedia/AudioRecord.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a7bf380..2c8605c 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -79,14 +79,14 @@ AudioRecord::AudioRecord( uint32_t notificationFrames, int sessionId, transfer_type transferType, - audio_input_flags_t flags __unused) + audio_input_flags_t flags) : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL) { mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, - notificationFrames, false /*threadCanCallJava*/, sessionId, transferType); + notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags); } AudioRecord::~AudioRecord() -- cgit v1.1 From b773038277ba328696832b690b91ce6e95bd1a6c Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 30 Apr 2014 15:50:31 -0700 Subject: Add client side support for more AUDIO_FORMAT_PCM_* As much as possible, the checks for specific formats are done on server side. The only exception is 8-bit, which needs a client side workaround. Change-Id: I52fe086c039460c8dac009de03b67eb54c56a836 --- media/libmedia/AudioTrack.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index dc4f90e..aaaa3f1 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -315,12 +315,20 @@ status_t AudioTrack::set( flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); } - if (audio_is_linear_pcm(format)) { - mFrameSize = channelCount * audio_bytes_per_sample(format); - mFrameSizeAF = channelCount * sizeof(int16_t); + if (flags & AUDIO_OUTPUT_FLAG_DIRECT) { + if (audio_is_linear_pcm(format)) { + mFrameSize = channelCount * audio_bytes_per_sample(format); + } else { + mFrameSize = sizeof(uint8_t); + } + mFrameSizeAF = mFrameSize; } else { - mFrameSize = sizeof(uint8_t); - mFrameSizeAF = sizeof(uint8_t); + ALOG_ASSERT(audio_is_linear_pcm(format)); + mFrameSize = channelCount * audio_bytes_per_sample(format); + mFrameSizeAF = channelCount * audio_bytes_per_sample( + format == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : format); + // createTrack will return an error if PCM format is not supported by server, + // so no need to check for specific PCM formats here } // Make copy of input parameter offloadInfo so that in the future: @@ -931,7 +939,11 @@ status_t AudioTrack::createTrack_l(size_t epoch) // Ensure that buffer alignment matches channel count // 8-bit data in shared memory is not currently supported by AudioFlinger - size_t alignment = /* mFormat == AUDIO_FORMAT_PCM_8_BIT ? 1 : */ 2; + size_t alignment = audio_bytes_per_sample( + mFormat == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : mFormat); + if (alignment & 1) { + alignment = 1; + } if (mChannelCount > 1) { // More than 2 channels does not require stronger alignment than stereo alignment <<= 1; @@ -947,7 +959,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) // there's no frameCount parameter. // But when initializing a shared buffer AudioTrack via set(), // there _is_ a frameCount parameter. We silently ignore it. - frameCount = mSharedBuffer->size()/mChannelCount/sizeof(int16_t); + frameCount = mSharedBuffer->size() / mFrameSizeAF; } else if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) { -- cgit v1.1 From d776ac63ce9c013c9626226e43f7db606e035838 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 7 May 2014 09:16:09 -0700 Subject: IAudioFlinger::openRecord returns IMemory(s) openRecord() now explicitly returns the control block and data buffer as separate IMemory references. If the IMemory for data buffer is 0, this means it immediately follows the control block. Change-Id: Ic098f88f0e037f8fbe30006689e18cacacf09d06 --- media/libmedia/AudioRecord.cpp | 32 ++++++++++++++++++++++++-------- media/libmedia/IAudioFlinger.cpp | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 12 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 2c8605c..97ab8f8 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -484,6 +484,8 @@ status_t AudioRecord::openRecord_l(size_t epoch) size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also int originalSessionId = mSessionId; + sp iMem; // for cblk + sp bufferMem; sp record = audioFlinger->openRecord(input, mSampleRate, mFormat, mChannelMask, @@ -491,6 +493,8 @@ status_t AudioRecord::openRecord_l(size_t epoch) &trackFlags, tid, &mSessionId, + iMem, + bufferMem, &status); ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId, "session ID changed from %d to %d", originalSessionId, mSessionId); @@ -504,7 +508,6 @@ status_t AudioRecord::openRecord_l(size_t epoch) // AudioFlinger now owns the reference to the I/O handle, // so we are no longer responsible for releasing it. - sp iMem = record->getCblk(); if (iMem == 0) { ALOGE("Could not get control block"); return NO_INIT; @@ -514,6 +517,22 @@ status_t AudioRecord::openRecord_l(size_t epoch) ALOGE("Could not get control block pointer"); return NO_INIT; } + audio_track_cblk_t* cblk = static_cast(iMemPointer); + + // Starting address of buffers in shared memory. + // The buffers are either immediately after the control block, + // or in a separate area at discretion of server. + void *buffers; + if (bufferMem == 0) { + buffers = cblk + 1; + } else { + buffers = bufferMem->pointer(); + if (buffers == NULL) { + ALOGE("Could not get buffer pointer"); + return NO_INIT; + } + } + // invariant that mAudioRecord != 0 is true only after set() returns successfully if (mAudioRecord != 0) { mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); @@ -522,7 +541,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) mAudioRecord = record; mCblkMemory = iMem; - audio_track_cblk_t* cblk = static_cast(iMemPointer); + mBufferMemory = bufferMem; mCblk = cblk; // note that temp is the (possibly revised) value of frameCount if (temp < frameCount || (frameCount == 0 && temp == 0)) { @@ -552,11 +571,6 @@ status_t AudioRecord::openRecord_l(size_t epoch) mInput = input; mRefreshRemaining = true; - // Starting address of buffers in shared memory, immediately after the control block. This - // address is for the mapping within client address space. AudioFlinger::TrackBase::mBuffer - // is for the server address space. - void *buffers = (char*)cblk + sizeof(audio_track_cblk_t); - mFrameCount = frameCount; // If IAudioRecord is re-created, don't let the requested frameCount // decrease. This can confuse clients that cache frameCount(). @@ -631,6 +645,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r // keep them from going away if another thread re-creates the track during obtainBuffer() sp proxy; sp iMem; + sp bufferMem; { // start of lock scope AutoMutex lock(mLock); @@ -654,6 +669,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r // Keep the extra references proxy = mProxy; iMem = mCblkMemory; + bufferMem = mBufferMemory; // Non-blocking if track is stopped if (!mActive) { @@ -986,7 +1002,7 @@ status_t AudioRecord::restoreRecord_l(const char *from) status_t result; // if the new IAudioRecord is created, openRecord_l() will modify the - // following member variables: mAudioRecord, mCblkMemory and mCblk. + // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory. // It will also delete the strong references on previous IAudioRecord and IMemory size_t position = mProxy->getPosition(); mNewPosition = position + mUpdatePeriod; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 1940fe7..0e2463e 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -169,6 +169,8 @@ public: track_flags_t *flags, pid_t tid, int *sessionId, + sp& cblk, + sp& buffers, status_t *status) { Parcel data, reply; @@ -188,6 +190,8 @@ public: lSessionId = *sessionId; } data.writeInt32(lSessionId); + cblk.clear(); + buffers.clear(); status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply); if (lStatus != NO_ERROR) { ALOGE("openRecord error: %s", strerror(-lStatus)); @@ -206,17 +210,34 @@ public: } lStatus = reply.readInt32(); record = interface_cast(reply.readStrongBinder()); + cblk = interface_cast(reply.readStrongBinder()); + if (cblk != 0 && cblk->pointer() == NULL) { + cblk.clear(); + } + buffers = interface_cast(reply.readStrongBinder()); + if (buffers != 0 && buffers->pointer() == NULL) { + buffers.clear(); + } if (lStatus == NO_ERROR) { if (record == 0) { ALOGE("openRecord should have returned an IAudioRecord"); lStatus = UNKNOWN_ERROR; + } else if (cblk == 0) { + ALOGE("openRecord should have returned a cblk"); + lStatus = NO_MEMORY; } + // buffers is permitted to be 0 } else { - if (record != 0) { - ALOGE("openRecord returned an IAudioRecord but with status %d", lStatus); - record.clear(); + if (record != 0 || cblk != 0 || buffers != 0) { + ALOGE("openRecord returned an IAudioRecord, cblk, " + "or buffers but with status %d", lStatus); } } + if (lStatus != NO_ERROR) { + record.clear(); + cblk.clear(); + buffers.clear(); + } } if (status != NULL) { *status = lStatus; @@ -838,15 +859,20 @@ status_t BnAudioFlinger::onTransact( track_flags_t flags = (track_flags_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); + sp cblk; + sp buffers; status_t status; sp record = openRecord(input, - sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, &status); + sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, + cblk, buffers, &status); LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR)); reply->writeInt64(frameCount); reply->writeInt32(flags); reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(record->asBinder()); + reply->writeStrongBinder(cblk->asBinder()); + reply->writeStrongBinder(buffers->asBinder()); return NO_ERROR; } break; case SAMPLE_RATE: { -- cgit v1.1 From fe9570c7b937b49d3603ccb394aed732b79bc6be Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 7 May 2014 08:42:25 -0700 Subject: Remove obsolete IAudioRecord::getCblk() Change-Id: Id20b5efd765b9796b0e391610e06dc928a829ebf --- media/libmedia/IAudioRecord.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp index 9866d70..8a4a383 100644 --- a/media/libmedia/IAudioRecord.cpp +++ b/media/libmedia/IAudioRecord.cpp @@ -29,7 +29,7 @@ namespace android { enum { - GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, + UNUSED_WAS_GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, START, STOP }; @@ -42,21 +42,6 @@ public: { } - virtual sp getCblk() const - { - Parcel data, reply; - sp cblk; - data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); - status_t status = remote()->transact(GET_CBLK, data, &reply); - if (status == NO_ERROR) { - cblk = interface_cast(reply.readStrongBinder()); - if (cblk != 0 && cblk->pointer() == NULL) { - cblk.clear(); - } - } - return cblk; - } - virtual status_t start(int /*AudioSystem::sync_event_t*/ event, int triggerSession) { Parcel data, reply; @@ -89,11 +74,6 @@ status_t BnAudioRecord::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { - case GET_CBLK: { - CHECK_INTERFACE(IAudioRecord, data, reply); - reply->writeStrongBinder(getCblk()->asBinder()); - return NO_ERROR; - } break; case START: { CHECK_INTERFACE(IAudioRecord, data, reply); int /*AudioSystem::sync_event_t*/ event = data.readInt32(); -- cgit v1.1 From 844f88ccfcca95687e774bccb5e9065da61d33f8 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 9 May 2014 13:38:09 -0700 Subject: Cache mCblk in local variable cblk This is the style used throughout the rest of AudioTrackShared. Change-Id: I959a6be3064e087bb19eba41173fd130dfcb4a9a --- media/libmedia/AudioTrackShared.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 58c9fc1..323b675 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -621,7 +621,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer) android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear); } - mCblk->mServer += stepCount; + cblk->mServer += stepCount; size_t half = mFrameCount / 2; if (half == 0) { @@ -679,10 +679,11 @@ size_t AudioTrackServerProxy::framesReady() } bool AudioTrackServerProxy::setStreamEndDone() { + audio_track_cblk_t* cblk = mCblk; bool old = - (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; + (android_atomic_or(CBLK_STREAM_END_DONE, &cblk->mFlags) & CBLK_STREAM_END_DONE) != 0; if (!old) { - (void) __futex_syscall3(&mCblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, + (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } return old; @@ -690,10 +691,11 @@ bool AudioTrackServerProxy::setStreamEndDone() { void AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount) { - mCblk->u.mStreaming.mUnderrunFrames += frameCount; + audio_track_cblk_t* cblk = mCblk; + cblk->u.mStreaming.mUnderrunFrames += frameCount; // FIXME also wake futex so that underrun is noticed more quickly - (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags); + (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags); } // --------------------------------------------------------------------------- -- cgit v1.1 From 609b815a3131d22da38b2f452faa9f89daad4039 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Fri, 2 May 2014 11:05:04 -0700 Subject: Update OMX messages for 64 bit Change node_id and buffer_id to uint32_t. Ensure IOMX messages are fixed size. Remove 64 bit compile warnings in associated files. Change-Id: Icdbef00aca575e5dc502ebb52e3ce7d0d7883203 Signed-off-by: Andy Hung --- media/libmedia/IOMX.cpp | 132 +++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 64 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 9c13848..5df232f 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -65,7 +65,7 @@ public: virtual bool livesLocally(node_id node, pid_t pid) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(pid); remote()->transact(LIVES_LOCALLY, data, &reply); @@ -104,7 +104,7 @@ public: status_t err = reply.readInt32(); if (err == OK) { - *node = (void*)reply.readIntPtr(); + *node = (node_id)reply.readInt32(); } else { *node = 0; } @@ -115,7 +115,7 @@ public: virtual status_t freeNode(node_id node) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); remote()->transact(FREE_NODE, data, &reply); return reply.readInt32(); @@ -125,7 +125,7 @@ public: node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(cmd); data.writeInt32(param); remote()->transact(SEND_COMMAND, data, &reply); @@ -138,7 +138,7 @@ public: void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); data.writeInt64(size); data.write(params, size); @@ -159,7 +159,7 @@ public: const void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); data.writeInt64(size); data.write(params, size); @@ -173,7 +173,7 @@ public: void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); data.writeInt64(size); data.write(params, size); @@ -194,7 +194,7 @@ public: const void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); data.writeInt64(size); data.write(params, size); @@ -207,7 +207,7 @@ public: node_id node, OMX_STATETYPE* state) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); remote()->transact(GET_STATE, data, &reply); *state = static_cast(reply.readInt32()); @@ -218,7 +218,7 @@ public: node_id node, OMX_U32 port_index, OMX_BOOL enable) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt32((uint32_t)enable); remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply); @@ -231,7 +231,7 @@ public: node_id node, OMX_U32 port_index, OMX_U32* usage) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply); @@ -245,7 +245,7 @@ public: buffer_id *buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeStrongBinder(params->asBinder()); remote()->transact(USE_BUFFER, data, &reply); @@ -257,7 +257,7 @@ public: return err; } - *buffer = (void*)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); return err; } @@ -268,7 +268,7 @@ public: const sp &graphicBuffer, buffer_id *buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.write(*graphicBuffer); remote()->transact(USE_GRAPHIC_BUFFER, data, &reply); @@ -280,7 +280,7 @@ public: return err; } - *buffer = (void*)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); return err; } @@ -290,10 +290,10 @@ public: const sp &graphicBuffer, buffer_id buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.write(*graphicBuffer); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)buffer); remote()->transact(UPDATE_GRAPHIC_BUFFER_IN_META, data, &reply); status_t err = reply.readInt32(); @@ -306,7 +306,7 @@ public: Parcel data, reply; status_t err; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply); if (err != OK) { @@ -329,7 +329,7 @@ public: Parcel data, reply; status_t err; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply); if (err != OK) { ALOGW("binder transaction failed: %d", err); @@ -343,7 +343,7 @@ public: node_id node, OMX_U32 port_index, OMX_BOOL enable) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt32((uint32_t)enable); remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); @@ -357,7 +357,7 @@ public: OMX_U32 max_width, OMX_U32 max_height) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt32((int32_t)enable); data.writeInt32(max_width); @@ -373,7 +373,7 @@ public: buffer_id *buffer, void **buffer_data) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt64(size); remote()->transact(ALLOC_BUFFER, data, &reply); @@ -385,8 +385,8 @@ public: return err; } - *buffer = (void *)reply.readIntPtr(); - *buffer_data = (void *)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); + *buffer_data = (void *)reply.readInt64(); return err; } @@ -396,7 +396,7 @@ public: buffer_id *buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeStrongBinder(params->asBinder()); remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); @@ -408,7 +408,7 @@ public: return err; } - *buffer = (void*)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); return err; } @@ -417,9 +417,9 @@ public: node_id node, OMX_U32 port_index, buffer_id buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)buffer); remote()->transact(FREE_BUFFER, data, &reply); return reply.readInt32(); @@ -428,8 +428,8 @@ public: virtual status_t fillBuffer(node_id node, buffer_id buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)node); + data.writeInt32((int32_t)buffer); remote()->transact(FILL_BUFFER, data, &reply); return reply.readInt32(); @@ -442,8 +442,8 @@ public: OMX_U32 flags, OMX_TICKS timestamp) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)node); + data.writeInt32((int32_t)buffer); data.writeInt32(range_offset); data.writeInt32(range_length); data.writeInt32(flags); @@ -459,7 +459,7 @@ public: OMX_INDEXTYPE *index) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeCString(parameter_name); remote()->transact(GET_EXTENSION_INDEX, data, &reply); @@ -482,7 +482,7 @@ public: size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt64(size); data.write(optionData, size); @@ -509,7 +509,7 @@ status_t BnOMX::onTransact( case LIVES_LOCALLY: { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void *)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); pid_t pid = (pid_t)data.readInt32(); reply->writeInt32(livesLocally(node, pid)); @@ -553,7 +553,7 @@ status_t BnOMX::onTransact( status_t err = allocateNode(name, observer, &node); reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)node); + reply->writeInt32((int32_t)node); } return NO_ERROR; @@ -563,7 +563,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); reply->writeInt32(freeNode(node)); @@ -574,7 +574,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_COMMANDTYPE cmd = static_cast(data.readInt32()); @@ -593,7 +593,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_INDEXTYPE index = static_cast(data.readInt32()); size_t size = data.readInt64(); @@ -644,7 +644,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_STATETYPE state = OMX_StateInvalid; status_t err = getState(node, &state); @@ -658,7 +658,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); @@ -672,7 +672,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_U32 usage = 0; @@ -687,7 +687,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp params = interface_cast(data.readStrongBinder()); @@ -697,7 +697,7 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); + reply->writeInt32((int32_t)buffer); } return NO_ERROR; @@ -707,7 +707,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp graphicBuffer = new GraphicBuffer(); data.read(*graphicBuffer); @@ -718,7 +718,7 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); + reply->writeInt32((int32_t)buffer); } return NO_ERROR; @@ -728,11 +728,11 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp graphicBuffer = new GraphicBuffer(); data.read(*graphicBuffer); - buffer_id buffer = (void*)data.readIntPtr(); + buffer_id buffer = (buffer_id)data.readInt32(); status_t err = updateGraphicBufferInMeta( node, port_index, graphicBuffer, buffer); @@ -745,7 +745,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp bufferProducer; @@ -765,7 +765,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); status_t err = signalEndOfInputStream(node); reply->writeInt32(err); @@ -777,7 +777,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); @@ -791,7 +791,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); OMX_U32 max_width = data.readInt32(); @@ -808,7 +808,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); size_t size = data.readInt64(); @@ -819,8 +819,8 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); - reply->writeIntPtr((intptr_t)buffer_data); + reply->writeInt32((int32_t)buffer); + reply->writeInt64((uintptr_t)buffer_data); } return NO_ERROR; @@ -830,7 +830,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp params = interface_cast(data.readStrongBinder()); @@ -842,7 +842,7 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); + reply->writeInt32((int32_t)buffer); } return NO_ERROR; @@ -852,9 +852,9 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); - buffer_id buffer = (void*)data.readIntPtr(); + buffer_id buffer = (buffer_id)data.readInt32(); reply->writeInt32(freeBuffer(node, port_index, buffer)); return NO_ERROR; @@ -864,8 +864,8 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); - buffer_id buffer = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); + buffer_id buffer = (buffer_id)data.readInt32(); reply->writeInt32(fillBuffer(node, buffer)); return NO_ERROR; @@ -875,8 +875,8 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); - buffer_id buffer = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); + buffer_id buffer = (buffer_id)data.readInt32(); OMX_U32 range_offset = data.readInt32(); OMX_U32 range_length = data.readInt32(); OMX_U32 flags = data.readInt32(); @@ -894,7 +894,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); const char *parameter_name = data.readCString(); OMX_INDEXTYPE index; @@ -927,6 +927,8 @@ public: data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); data.write(&msg, sizeof(msg)); + ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg)); + remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); } }; @@ -943,6 +945,8 @@ status_t BnOMXObserver::onTransact( omx_message msg; data.read(&msg, sizeof(msg)); + ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg)); + // XXX Could use readInplace maybe? onMessage(msg); -- cgit v1.1 From e541269be94f3a1072932d51537905b120ef4733 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Fri, 16 May 2014 11:25:07 -0700 Subject: Use new channel count functions for audio masks Change-Id: Ia658ab4b6320d19fdb50f123c930918724ff0ef3 Signed-off-by: Andy Hung --- media/libmedia/AudioRecord.cpp | 5 +++-- media/libmedia/AudioTrack.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 97ab8f8..1c808d0 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -51,7 +51,8 @@ status_t AudioRecord::getMinFrameCount( // We double the size of input buffer for ping pong use of record buffer. // Assumes audio_is_linear_pcm(format) - if ((*frameCount = (size * 2) / (popcount(channelMask) * audio_bytes_per_sample(format))) == 0) { + if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) * + audio_bytes_per_sample(format))) == 0) { ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x", sampleRate, format, channelMask); return BAD_VALUE; @@ -193,7 +194,7 @@ status_t AudioRecord::set( return BAD_VALUE; } mChannelMask = channelMask; - uint32_t channelCount = popcount(channelMask); + uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); mChannelCount = channelCount; if (audio_is_linear_pcm(format)) { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index aaaa3f1..b4d6d76 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -290,7 +290,7 @@ status_t AudioTrack::set( return BAD_VALUE; } mChannelMask = channelMask; - uint32_t channelCount = popcount(channelMask); + uint32_t channelCount = audio_channel_count_from_out_mask(channelMask); mChannelCount = channelCount; // AudioFlinger does not currently support 8-bit data in shared memory -- cgit v1.1 From c56f3426099a3cf2d07ccff8886050c7fbce140f Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 21 Mar 2014 17:53:17 -0700 Subject: Pass stereo gains as packed minifloat This will allow (eventually) a greater dynamic range for gains. However there are still a few remaining places in effects and mixer that will also need to be changed in order to get the full benefit. Also fixes a minor bug: was not checking for NaN in AudioTrack C++. Change-Id: I63bce9e82e0a61546d8ff475fb94bcb700d99c96 --- media/libmedia/AudioTrack.cpp | 13 ++++++++----- media/libmedia/AudioTrackShared.cpp | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index aaaa3f1..120b28e 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -19,6 +19,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "AudioTrack" +#include #include #include #include @@ -566,7 +567,9 @@ void AudioTrack::pause() status_t AudioTrack::setVolume(float left, float right) { - if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) { + // This duplicates a test by AudioTrack JNI, but that is not the only caller + if (isnanf(left) || left < GAIN_FLOAT_ZERO || left > GAIN_FLOAT_UNITY || + isnanf(right) || right < GAIN_FLOAT_ZERO || right > GAIN_FLOAT_UNITY) { return BAD_VALUE; } @@ -574,7 +577,7 @@ status_t AudioTrack::setVolume(float left, float right) mVolume[AUDIO_INTERLEAVE_LEFT] = left; mVolume[AUDIO_INTERLEAVE_RIGHT] = right; - mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); + mProxy->setVolumeLR(gain_minifloat_pack(gain_from_float(left), gain_from_float(right))); if (isOffloaded_l()) { mAudioTrack->signal(); @@ -589,7 +592,8 @@ status_t AudioTrack::setVolume(float volume) status_t AudioTrack::setAuxEffectSendLevel(float level) { - if (level < 0.0f || level > 1.0f) { + // This duplicates a test by AudioTrack JNI, but that is not the only caller + if (isnanf(level) || level < GAIN_FLOAT_ZERO || level > GAIN_FLOAT_UNITY) { return BAD_VALUE; } @@ -1137,8 +1141,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF); mProxy = mStaticProxy; } - mProxy->setVolumeLR((uint32_t(uint16_t(mVolume[AUDIO_INTERLEAVE_RIGHT] * 0x1000)) << 16) | - uint16_t(mVolume[AUDIO_INTERLEAVE_LEFT] * 0x1000)); + mProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY); mProxy->setSendLevel(mSendLevel); mProxy->setSampleRate(mSampleRate); mProxy->setEpoch(epoch); diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 323b675..27a3718 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -27,7 +27,7 @@ namespace android { audio_track_cblk_t::audio_track_cblk_t() : mServer(0), mFutex(0), mMinimum(0), - mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mFlags(0) + mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0), mFlags(0) { memset(&u, 0, sizeof(u)); } -- cgit v1.1 From 29b703eec27b305e7b5b2343bf257643e38f6b68 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Mon, 12 May 2014 11:06:26 -0700 Subject: Move validation of frameCount from set to openRecord_l This move is needed because frameCount is validated on server side for fast tracks (as should be done for normal tracks too). Change-Id: I6d99e80869fd90fab373cf60ef348c01f075fbca --- media/libmedia/AudioRecord.cpp | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 1c808d0..db61e85 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -203,23 +203,6 @@ status_t AudioRecord::set( mFrameSize = sizeof(uint8_t); } - // validate framecount - size_t minFrameCount; - status_t status = AudioRecord::getMinFrameCount(&minFrameCount, - sampleRate, format, channelMask); - if (status != NO_ERROR) { - ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; status %d", - sampleRate, format, channelMask, status); - return status; - } - ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); - - if (frameCount == 0) { - frameCount = minFrameCount; - } else if (frameCount < minFrameCount) { - ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount); - return BAD_VALUE; - } // mFrameCount is initialized in openRecord_l mReqFrameCount = frameCount; @@ -242,7 +225,7 @@ status_t AudioRecord::set( } // create the IAudioRecord - status = openRecord_l(0 /*epoch*/); + status_t status = openRecord_l(0 /*epoch*/); if (status != NO_ERROR) { if (mAudioRecordThread != 0) { @@ -464,6 +447,29 @@ status_t AudioRecord::openRecord_l(size_t epoch) size_t frameCount = mReqFrameCount; if (!(mFlags & AUDIO_INPUT_FLAG_FAST)) { + // validate framecount + // If fast track was not requested, this preserves + // the old behavior of validating on client side. + // FIXME Eventually the validation should be done on server side + // regardless of whether it's a fast or normal track. It's debatable + // whether to account for the input latency to provision buffers appropriately. + size_t minFrameCount; + status = AudioRecord::getMinFrameCount(&minFrameCount, + mSampleRate, mFormat, mChannelMask); + if (status != NO_ERROR) { + ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; " + "status %d", + mSampleRate, mFormat, mChannelMask, status); + return status; + } + + if (frameCount == 0) { + frameCount = minFrameCount; + } else if (frameCount < minFrameCount) { + ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount); + return BAD_VALUE; + } + // Make sure that application is notified with sufficient margin before overrun if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) { mNotificationFramesAct = frameCount/2; -- cgit v1.1 From 4b123406c10c17852734a1b691bb9ce2a4cb7caf Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 11 Apr 2014 09:22:20 -0700 Subject: IAudioFlinger interface extension for patch panel Change-Id: Iaabe0a7e315d5725e00a74a6ed40339b98f20330 --- media/libmedia/IAudioFlinger.cpp | 172 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 171 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 0e2463e..687fa76 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -74,6 +74,12 @@ enum { GET_PRIMARY_OUTPUT_SAMPLING_RATE, GET_PRIMARY_OUTPUT_FRAME_COUNT, SET_LOW_RAM_DEVICE, + LIST_AUDIO_PORTS, + GET_AUDIO_PORT, + CREATE_AUDIO_PATCH, + RELEASE_AUDIO_PATCH, + LIST_AUDIO_PATCHES, + SET_AUDIO_PORT_CONFIG }; class BpAudioFlinger : public BpInterface @@ -801,7 +807,101 @@ public: remote()->transact(SET_LOW_RAM_DEVICE, data, &reply); return reply.readInt32(); } - + virtual status_t listAudioPorts(unsigned int *num_ports, + struct audio_port *ports) + { + if (num_ports == NULL || *num_ports == 0 || ports == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(*num_ports); + status_t status = remote()->transact(LIST_AUDIO_PORTS, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + *num_ports = (unsigned int)reply.readInt32(); + reply.read(ports, *num_ports * sizeof(struct audio_port)); + return status; + } + virtual status_t getAudioPort(struct audio_port *port) + { + if (port == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(port, sizeof(struct audio_port)); + status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(port, sizeof(struct audio_port)); + return status; + } + virtual status_t createAudioPatch(const struct audio_patch *patch, + audio_patch_handle_t *handle) + { + if (patch == NULL || handle == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(patch, sizeof(struct audio_patch)); + data.write(handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(CREATE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(handle, sizeof(audio_patch_handle_t)); + return status; + } + virtual status_t releaseAudioPatch(audio_patch_handle_t handle) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(&handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(RELEASE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + virtual status_t listAudioPatches(unsigned int *num_patches, + struct audio_patch *patches) + { + if (num_patches == NULL || *num_patches == 0 || patches == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(*num_patches); + status_t status = remote()->transact(LIST_AUDIO_PATCHES, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + *num_patches = (unsigned int)reply.readInt32(); + reply.read(patches, *num_patches * sizeof(struct audio_patch)); + return status; + } + virtual status_t setAudioPortConfig(const struct audio_port_config *config) + { + if (config == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(config, sizeof(struct audio_port_config)); + status_t status = remote()->transact(SET_AUDIO_PORT_CONFIG, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -1199,6 +1299,76 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32(setLowRamDevice(isLowRamDevice)); return NO_ERROR; } break; + case LIST_AUDIO_PORTS: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + unsigned int num_ports = data.readInt32(); + struct audio_port *ports = + (struct audio_port *)calloc(num_ports, + sizeof(struct audio_port)); + status_t status = listAudioPorts(&num_ports, ports); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(num_ports); + reply->write(&ports, num_ports * sizeof(struct audio_port)); + } + free(ports); + return NO_ERROR; + } break; + case GET_AUDIO_PORT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + struct audio_port port; + data.read(&port, sizeof(struct audio_port)); + status_t status = getAudioPort(&port); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&port, sizeof(struct audio_port)); + } + return NO_ERROR; + } break; + case CREATE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + struct audio_patch patch; + data.read(&patch, sizeof(struct audio_patch)); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = createAudioPatch(&patch, &handle); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&handle, sizeof(audio_patch_handle_t)); + } + return NO_ERROR; + } break; + case RELEASE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = releaseAudioPatch(handle); + reply->writeInt32(status); + return NO_ERROR; + } break; + case LIST_AUDIO_PATCHES: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + unsigned int num_patches = data.readInt32(); + struct audio_patch *patches = + (struct audio_patch *)calloc(num_patches, + sizeof(struct audio_patch)); + status_t status = listAudioPatches(&num_patches, patches); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(num_patches); + reply->write(&patches, num_patches * sizeof(struct audio_patch)); + } + free(patches); + return NO_ERROR; + } break; + case SET_AUDIO_PORT_CONFIG: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + struct audio_port_config config; + data.read(&config, sizeof(struct audio_port_config)); + status_t status = setAudioPortConfig(&config); + reply->writeInt32(status); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 8670c31fddbeadcf9627aa970c69a823f13939ff Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 1 Apr 2014 10:34:16 -0700 Subject: IAudioPolicyService interface extension for patch panel Change-Id: I0a62e5416edc41c3a0e816275085ab18a23066f1 --- media/libmedia/AudioSystem.cpp | 49 +++++++ media/libmedia/IAudioPolicyService.cpp | 228 ++++++++++++++++++++++++++++++++- 2 files changed, 275 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 2f16444..845ee20 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -831,6 +831,55 @@ bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info) return aps->isOffloadSupported(info); } +status_t AudioSystem::listAudioPorts(audio_port_role_t role, + audio_port_type_t type, + unsigned int *num_ports, + struct audio_port *ports, + unsigned int *generation) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->listAudioPorts(role, type, num_ports, ports, generation); +} + +status_t AudioSystem::getAudioPort(struct audio_port *port) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->getAudioPort(port); +} + +status_t AudioSystem::createAudioPatch(const struct audio_patch *patch, + audio_patch_handle_t *handle) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->createAudioPatch(patch, handle); +} + +status_t AudioSystem::releaseAudioPatch(audio_patch_handle_t handle) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->releaseAudioPatch(handle); +} + +status_t AudioSystem::listAudioPatches(unsigned int *num_patches, + struct audio_patch *patches, + unsigned int *generation) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->listAudioPatches(num_patches, patches, generation); +} + +status_t AudioSystem::setAudioPortConfig(const struct audio_port_config *config) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->setAudioPortConfig(config); +} + // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 9bb4a49..ad2d4eb 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -57,7 +57,13 @@ enum { QUERY_DEFAULT_PRE_PROCESSING, SET_EFFECT_ENABLED, IS_STREAM_ACTIVE_REMOTELY, - IS_OFFLOAD_SUPPORTED + IS_OFFLOAD_SUPPORTED, + LIST_AUDIO_PORTS, + GET_AUDIO_PORT, + CREATE_AUDIO_PATCH, + RELEASE_AUDIO_PATCH, + LIST_AUDIO_PATCHES, + SET_AUDIO_PORT_CONFIG }; class BpAudioPolicyService : public BpInterface @@ -390,7 +396,134 @@ public: data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.write(&info, sizeof(audio_offload_info_t)); remote()->transact(IS_OFFLOAD_SUPPORTED, data, &reply); - return reply.readInt32(); } + return reply.readInt32(); + } + + virtual status_t listAudioPorts(audio_port_role_t role, + audio_port_type_t type, + unsigned int *num_ports, + struct audio_port *ports, + unsigned int *generation) + { + if (num_ports == NULL || (*num_ports != 0 && ports == NULL) || + generation == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + unsigned int numPortsReq = (ports == NULL) ? 0 : *num_ports; + data.writeInt32(role); + data.writeInt32(type); + data.writeInt32(numPortsReq); + status_t status = remote()->transact(LIST_AUDIO_PORTS, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + *num_ports = (unsigned int)reply.readInt32(); + } + ALOGI("listAudioPorts() status %d got *num_ports %d", status, *num_ports); + if (status == NO_ERROR) { + if (numPortsReq > *num_ports) { + numPortsReq = *num_ports; + } + if (numPortsReq > 0) { + reply.read(ports, numPortsReq * sizeof(struct audio_port)); + } + *generation = reply.readInt32(); + } + return status; + } + + virtual status_t getAudioPort(struct audio_port *port) + { + if (port == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(port, sizeof(struct audio_port)); + status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(port, sizeof(struct audio_port)); + return status; + } + + virtual status_t createAudioPatch(const struct audio_patch *patch, + audio_patch_handle_t *handle) + { + if (patch == NULL || handle == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(patch, sizeof(struct audio_patch)); + data.write(handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(CREATE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(handle, sizeof(audio_patch_handle_t)); + return status; + } + + virtual status_t releaseAudioPatch(audio_patch_handle_t handle) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(&handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(RELEASE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t listAudioPatches(unsigned int *num_patches, + struct audio_patch *patches, + unsigned int *generation) + { + if (num_patches == NULL || (*num_patches != 0 && patches == NULL) || + generation == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + unsigned int numPatchesReq = (patches == NULL) ? 0 : *num_patches; + data.writeInt32(numPatchesReq); + status_t status = remote()->transact(LIST_AUDIO_PATCHES, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + *num_patches = (unsigned int)reply.readInt32(); + } + if (status == NO_ERROR) { + if (numPatchesReq > *num_patches) { + numPatchesReq = *num_patches; + } + if (numPatchesReq > 0) { + reply.read(patches, numPatchesReq * sizeof(struct audio_patch)); + } + *generation = reply.readInt32(); + } + return status; + } + + virtual status_t setAudioPortConfig(const struct audio_port_config *config) + { + if (config == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(config, sizeof(struct audio_port_config)); + status_t status = remote()->transact(SET_AUDIO_PORT_CONFIG, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -687,6 +820,97 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } + case LIST_AUDIO_PORTS: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_port_role_t role = (audio_port_role_t)data.readInt32(); + audio_port_type_t type = (audio_port_type_t)data.readInt32(); + unsigned int numPortsReq = data.readInt32(); + unsigned int numPorts = numPortsReq; + unsigned int generation; + struct audio_port *ports = + (struct audio_port *)calloc(numPortsReq, sizeof(struct audio_port)); + status_t status = listAudioPorts(role, type, &numPorts, ports, &generation); + reply->writeInt32(status); + reply->writeInt32(numPorts); + ALOGI("LIST_AUDIO_PORTS status %d got numPorts %d", status, numPorts); + + if (status == NO_ERROR) { + if (numPortsReq > numPorts) { + numPortsReq = numPorts; + } + reply->write(ports, numPortsReq * sizeof(struct audio_port)); + reply->writeInt32(generation); + } + free(ports); + return NO_ERROR; + } + + case GET_AUDIO_PORT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + struct audio_port port; + data.read(&port, sizeof(struct audio_port)); + status_t status = getAudioPort(&port); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&port, sizeof(struct audio_port)); + } + return NO_ERROR; + } + + case CREATE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + struct audio_patch patch; + data.read(&patch, sizeof(struct audio_patch)); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = createAudioPatch(&patch, &handle); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&handle, sizeof(audio_patch_handle_t)); + } + return NO_ERROR; + } + + case RELEASE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = releaseAudioPatch(handle); + reply->writeInt32(status); + return NO_ERROR; + } + + case LIST_AUDIO_PATCHES: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + unsigned int numPatchesReq = data.readInt32(); + unsigned int numPatches = numPatchesReq; + unsigned int generation; + struct audio_patch *patches = + (struct audio_patch *)calloc(numPatchesReq, + sizeof(struct audio_patch)); + status_t status = listAudioPatches(&numPatches, patches, &generation); + reply->writeInt32(status); + reply->writeInt32(numPatches); + if (status == NO_ERROR) { + if (numPatchesReq > numPatches) { + numPatchesReq = numPatches; + } + reply->write(patches, numPatchesReq * sizeof(struct audio_patch)); + reply->writeInt32(generation); + } + free(patches); + return NO_ERROR; + } + + case SET_AUDIO_PORT_CONFIG: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + struct audio_port_config config; + data.read(&config, sizeof(struct audio_port_config)); + status_t status = setAudioPortConfig(&config); + reply->writeInt32(status); + return NO_ERROR; + } + default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 1cda6afaf6207a41303e653a6ecd7909d73186eb Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 11 Apr 2014 09:22:20 -0700 Subject: DO NOT MERGE - IAudioFlinger interface extension for patch panel Change-Id: Iaabe0a7e315d5725e00a74a6ed40339b98f20330 --- media/libmedia/IAudioFlinger.cpp | 172 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 171 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 0e2463e..687fa76 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -74,6 +74,12 @@ enum { GET_PRIMARY_OUTPUT_SAMPLING_RATE, GET_PRIMARY_OUTPUT_FRAME_COUNT, SET_LOW_RAM_DEVICE, + LIST_AUDIO_PORTS, + GET_AUDIO_PORT, + CREATE_AUDIO_PATCH, + RELEASE_AUDIO_PATCH, + LIST_AUDIO_PATCHES, + SET_AUDIO_PORT_CONFIG }; class BpAudioFlinger : public BpInterface @@ -801,7 +807,101 @@ public: remote()->transact(SET_LOW_RAM_DEVICE, data, &reply); return reply.readInt32(); } - + virtual status_t listAudioPorts(unsigned int *num_ports, + struct audio_port *ports) + { + if (num_ports == NULL || *num_ports == 0 || ports == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(*num_ports); + status_t status = remote()->transact(LIST_AUDIO_PORTS, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + *num_ports = (unsigned int)reply.readInt32(); + reply.read(ports, *num_ports * sizeof(struct audio_port)); + return status; + } + virtual status_t getAudioPort(struct audio_port *port) + { + if (port == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(port, sizeof(struct audio_port)); + status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(port, sizeof(struct audio_port)); + return status; + } + virtual status_t createAudioPatch(const struct audio_patch *patch, + audio_patch_handle_t *handle) + { + if (patch == NULL || handle == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(patch, sizeof(struct audio_patch)); + data.write(handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(CREATE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(handle, sizeof(audio_patch_handle_t)); + return status; + } + virtual status_t releaseAudioPatch(audio_patch_handle_t handle) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(&handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(RELEASE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + virtual status_t listAudioPatches(unsigned int *num_patches, + struct audio_patch *patches) + { + if (num_patches == NULL || *num_patches == 0 || patches == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(*num_patches); + status_t status = remote()->transact(LIST_AUDIO_PATCHES, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + *num_patches = (unsigned int)reply.readInt32(); + reply.read(patches, *num_patches * sizeof(struct audio_patch)); + return status; + } + virtual status_t setAudioPortConfig(const struct audio_port_config *config) + { + if (config == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(config, sizeof(struct audio_port_config)); + status_t status = remote()->transact(SET_AUDIO_PORT_CONFIG, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -1199,6 +1299,76 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32(setLowRamDevice(isLowRamDevice)); return NO_ERROR; } break; + case LIST_AUDIO_PORTS: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + unsigned int num_ports = data.readInt32(); + struct audio_port *ports = + (struct audio_port *)calloc(num_ports, + sizeof(struct audio_port)); + status_t status = listAudioPorts(&num_ports, ports); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(num_ports); + reply->write(&ports, num_ports * sizeof(struct audio_port)); + } + free(ports); + return NO_ERROR; + } break; + case GET_AUDIO_PORT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + struct audio_port port; + data.read(&port, sizeof(struct audio_port)); + status_t status = getAudioPort(&port); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&port, sizeof(struct audio_port)); + } + return NO_ERROR; + } break; + case CREATE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + struct audio_patch patch; + data.read(&patch, sizeof(struct audio_patch)); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = createAudioPatch(&patch, &handle); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&handle, sizeof(audio_patch_handle_t)); + } + return NO_ERROR; + } break; + case RELEASE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = releaseAudioPatch(handle); + reply->writeInt32(status); + return NO_ERROR; + } break; + case LIST_AUDIO_PATCHES: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + unsigned int num_patches = data.readInt32(); + struct audio_patch *patches = + (struct audio_patch *)calloc(num_patches, + sizeof(struct audio_patch)); + status_t status = listAudioPatches(&num_patches, patches); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(num_patches); + reply->write(&patches, num_patches * sizeof(struct audio_patch)); + } + free(patches); + return NO_ERROR; + } break; + case SET_AUDIO_PORT_CONFIG: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + struct audio_port_config config; + data.read(&config, sizeof(struct audio_port_config)); + status_t status = setAudioPortConfig(&config); + reply->writeInt32(status); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 203b1a18a806e2c56c701aac49cda963bccfad5b Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 1 Apr 2014 10:34:16 -0700 Subject: DO NOT MERGE - IAudioPolicyService interface extension for patch panel Change-Id: I0a62e5416edc41c3a0e816275085ab18a23066f1 --- media/libmedia/AudioSystem.cpp | 49 +++++++ media/libmedia/IAudioPolicyService.cpp | 228 ++++++++++++++++++++++++++++++++- 2 files changed, 275 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 2f16444..845ee20 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -831,6 +831,55 @@ bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info) return aps->isOffloadSupported(info); } +status_t AudioSystem::listAudioPorts(audio_port_role_t role, + audio_port_type_t type, + unsigned int *num_ports, + struct audio_port *ports, + unsigned int *generation) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->listAudioPorts(role, type, num_ports, ports, generation); +} + +status_t AudioSystem::getAudioPort(struct audio_port *port) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->getAudioPort(port); +} + +status_t AudioSystem::createAudioPatch(const struct audio_patch *patch, + audio_patch_handle_t *handle) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->createAudioPatch(patch, handle); +} + +status_t AudioSystem::releaseAudioPatch(audio_patch_handle_t handle) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->releaseAudioPatch(handle); +} + +status_t AudioSystem::listAudioPatches(unsigned int *num_patches, + struct audio_patch *patches, + unsigned int *generation) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->listAudioPatches(num_patches, patches, generation); +} + +status_t AudioSystem::setAudioPortConfig(const struct audio_port_config *config) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->setAudioPortConfig(config); +} + // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 9bb4a49..ad2d4eb 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -57,7 +57,13 @@ enum { QUERY_DEFAULT_PRE_PROCESSING, SET_EFFECT_ENABLED, IS_STREAM_ACTIVE_REMOTELY, - IS_OFFLOAD_SUPPORTED + IS_OFFLOAD_SUPPORTED, + LIST_AUDIO_PORTS, + GET_AUDIO_PORT, + CREATE_AUDIO_PATCH, + RELEASE_AUDIO_PATCH, + LIST_AUDIO_PATCHES, + SET_AUDIO_PORT_CONFIG }; class BpAudioPolicyService : public BpInterface @@ -390,7 +396,134 @@ public: data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.write(&info, sizeof(audio_offload_info_t)); remote()->transact(IS_OFFLOAD_SUPPORTED, data, &reply); - return reply.readInt32(); } + return reply.readInt32(); + } + + virtual status_t listAudioPorts(audio_port_role_t role, + audio_port_type_t type, + unsigned int *num_ports, + struct audio_port *ports, + unsigned int *generation) + { + if (num_ports == NULL || (*num_ports != 0 && ports == NULL) || + generation == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + unsigned int numPortsReq = (ports == NULL) ? 0 : *num_ports; + data.writeInt32(role); + data.writeInt32(type); + data.writeInt32(numPortsReq); + status_t status = remote()->transact(LIST_AUDIO_PORTS, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + *num_ports = (unsigned int)reply.readInt32(); + } + ALOGI("listAudioPorts() status %d got *num_ports %d", status, *num_ports); + if (status == NO_ERROR) { + if (numPortsReq > *num_ports) { + numPortsReq = *num_ports; + } + if (numPortsReq > 0) { + reply.read(ports, numPortsReq * sizeof(struct audio_port)); + } + *generation = reply.readInt32(); + } + return status; + } + + virtual status_t getAudioPort(struct audio_port *port) + { + if (port == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(port, sizeof(struct audio_port)); + status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(port, sizeof(struct audio_port)); + return status; + } + + virtual status_t createAudioPatch(const struct audio_patch *patch, + audio_patch_handle_t *handle) + { + if (patch == NULL || handle == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(patch, sizeof(struct audio_patch)); + data.write(handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(CREATE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR || + (status = (status_t)reply.readInt32()) != NO_ERROR) { + return status; + } + reply.read(handle, sizeof(audio_patch_handle_t)); + return status; + } + + virtual status_t releaseAudioPatch(audio_patch_handle_t handle) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(&handle, sizeof(audio_patch_handle_t)); + status_t status = remote()->transact(RELEASE_AUDIO_PATCH, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t listAudioPatches(unsigned int *num_patches, + struct audio_patch *patches, + unsigned int *generation) + { + if (num_patches == NULL || (*num_patches != 0 && patches == NULL) || + generation == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + unsigned int numPatchesReq = (patches == NULL) ? 0 : *num_patches; + data.writeInt32(numPatchesReq); + status_t status = remote()->transact(LIST_AUDIO_PATCHES, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + *num_patches = (unsigned int)reply.readInt32(); + } + if (status == NO_ERROR) { + if (numPatchesReq > *num_patches) { + numPatchesReq = *num_patches; + } + if (numPatchesReq > 0) { + reply.read(patches, numPatchesReq * sizeof(struct audio_patch)); + } + *generation = reply.readInt32(); + } + return status; + } + + virtual status_t setAudioPortConfig(const struct audio_port_config *config) + { + if (config == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(config, sizeof(struct audio_port_config)); + status_t status = remote()->transact(SET_AUDIO_PORT_CONFIG, data, &reply); + if (status != NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -687,6 +820,97 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } + case LIST_AUDIO_PORTS: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_port_role_t role = (audio_port_role_t)data.readInt32(); + audio_port_type_t type = (audio_port_type_t)data.readInt32(); + unsigned int numPortsReq = data.readInt32(); + unsigned int numPorts = numPortsReq; + unsigned int generation; + struct audio_port *ports = + (struct audio_port *)calloc(numPortsReq, sizeof(struct audio_port)); + status_t status = listAudioPorts(role, type, &numPorts, ports, &generation); + reply->writeInt32(status); + reply->writeInt32(numPorts); + ALOGI("LIST_AUDIO_PORTS status %d got numPorts %d", status, numPorts); + + if (status == NO_ERROR) { + if (numPortsReq > numPorts) { + numPortsReq = numPorts; + } + reply->write(ports, numPortsReq * sizeof(struct audio_port)); + reply->writeInt32(generation); + } + free(ports); + return NO_ERROR; + } + + case GET_AUDIO_PORT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + struct audio_port port; + data.read(&port, sizeof(struct audio_port)); + status_t status = getAudioPort(&port); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&port, sizeof(struct audio_port)); + } + return NO_ERROR; + } + + case CREATE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + struct audio_patch patch; + data.read(&patch, sizeof(struct audio_patch)); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = createAudioPatch(&patch, &handle); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&handle, sizeof(audio_patch_handle_t)); + } + return NO_ERROR; + } + + case RELEASE_AUDIO_PATCH: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_patch_handle_t handle; + data.read(&handle, sizeof(audio_patch_handle_t)); + status_t status = releaseAudioPatch(handle); + reply->writeInt32(status); + return NO_ERROR; + } + + case LIST_AUDIO_PATCHES: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + unsigned int numPatchesReq = data.readInt32(); + unsigned int numPatches = numPatchesReq; + unsigned int generation; + struct audio_patch *patches = + (struct audio_patch *)calloc(numPatchesReq, + sizeof(struct audio_patch)); + status_t status = listAudioPatches(&numPatches, patches, &generation); + reply->writeInt32(status); + reply->writeInt32(numPatches); + if (status == NO_ERROR) { + if (numPatchesReq > numPatches) { + numPatchesReq = numPatches; + } + reply->write(patches, numPatchesReq * sizeof(struct audio_patch)); + reply->writeInt32(generation); + } + free(patches); + return NO_ERROR; + } + + case SET_AUDIO_PORT_CONFIG: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + struct audio_port_config config; + data.read(&config, sizeof(struct audio_port_config)); + status_t status = setAudioPortConfig(&config); + reply->writeInt32(status); + return NO_ERROR; + } + default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From b52c152d553556b2d227ffc943489de0c60b4b02 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 20 May 2014 11:27:36 -0700 Subject: audio policy: add routing update client interface Added IAudioPolicyServiceClient client binder interface for client process to receive notifications from AudioPolicyService when audio ports are added/removed or audio patches created/released. The audio patches owned by a given client are automatically released when this client binder dies. Bug: 14815883. Change-Id: I6013f6aec03b50565cffb1ad2cd1f0f8852032c5 --- media/libmedia/Android.mk | 1 + media/libmedia/AudioSystem.cpp | 30 +++++++++- media/libmedia/IAudioPolicyService.cpp | 17 +++++- media/libmedia/IAudioPolicyServiceClient.cpp | 83 ++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 media/libmedia/IAudioPolicyServiceClient.cpp (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index f3770e4..69eead3 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -44,6 +44,7 @@ LOCAL_SRC_FILES:= \ JetPlayer.cpp \ IOMX.cpp \ IAudioPolicyService.cpp \ + IAudioPolicyServiceClient.cpp \ MediaScanner.cpp \ MediaScannerClient.cpp \ CharacterEncodingDetector.cpp \ diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 845ee20..eafb3ad 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -45,6 +45,7 @@ audio_format_t AudioSystem::gPrevInFormat; audio_channel_mask_t AudioSystem::gPrevInChannelMask; size_t AudioSystem::gInBuffSize = 0; // zero indicates cache is invalid +sp AudioSystem::gAudioPortCallback; // establish binder interface to AudioFlinger service const sp& AudioSystem::get_audio_flinger() @@ -528,6 +529,7 @@ void AudioSystem::setErrorCallback(audio_error_callback cb) gAudioErrorCallback = cb; } + bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType) { switch (streamType) { @@ -566,6 +568,7 @@ const sp& AudioSystem::get_audio_policy_service() } binder->linkToDeath(gAudioPolicyServiceClient); gAudioPolicyService = interface_cast(binder); + gAudioPolicyService->registerClient(gAudioPolicyServiceClient); gLock.unlock(); } else { gLock.unlock(); @@ -880,14 +883,39 @@ status_t AudioSystem::setAudioPortConfig(const struct audio_port_config *config) return aps->setAudioPortConfig(config); } +void AudioSystem::setAudioPortCallback(sp callBack) +{ + Mutex::Autolock _l(gLock); + gAudioPortCallback = callBack; +} + // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) { - Mutex::Autolock _l(AudioSystem::gLock); + Mutex::Autolock _l(gLock); + if (gAudioPortCallback != 0) { + gAudioPortCallback->onServiceDied(); + } AudioSystem::gAudioPolicyService.clear(); ALOGW("AudioPolicyService server died!"); } +void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate() +{ + Mutex::Autolock _l(gLock); + if (gAudioPortCallback != 0) { + gAudioPortCallback->onAudioPortListUpdate(); + } +} + +void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate() +{ + Mutex::Autolock _l(gLock); + if (gAudioPortCallback != 0) { + gAudioPortCallback->onAudioPatchListUpdate(); + } +} + }; // namespace android diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index ad2d4eb..eee72c5 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -63,7 +63,8 @@ enum { CREATE_AUDIO_PATCH, RELEASE_AUDIO_PATCH, LIST_AUDIO_PATCHES, - SET_AUDIO_PORT_CONFIG + SET_AUDIO_PORT_CONFIG, + REGISTER_CLIENT }; class BpAudioPolicyService : public BpInterface @@ -524,6 +525,13 @@ public: } return status; } + virtual void registerClient(const sp& client) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeStrongBinder(client->asBinder()); + remote()->transact(REGISTER_CLIENT, data, &reply); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -910,6 +918,13 @@ status_t BnAudioPolicyService::onTransact( reply->writeInt32(status); return NO_ERROR; } + case REGISTER_CLIENT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + sp client = interface_cast( + data.readStrongBinder()); + registerClient(client); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp new file mode 100644 index 0000000..e802277 --- /dev/null +++ b/media/libmedia/IAudioPolicyServiceClient.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "IAudioPolicyServiceClient" +#include + +#include +#include + +#include + +#include +#include + +namespace android { + +enum { + PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION, + PATCH_LIST_UPDATE +}; + +class BpAudioPolicyServiceClient : public BpInterface +{ +public: + BpAudioPolicyServiceClient(const sp& impl) + : BpInterface(impl) + { + } + + void onAudioPortListUpdate() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); + remote()->transact(PORT_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); + } + + void onAudioPatchListUpdate() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); + remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient"); + +// ---------------------------------------------------------------------- + +status_t BnAudioPolicyServiceClient::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case PORT_LIST_UPDATE: { + CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); + onAudioPortListUpdate(); + return NO_ERROR; + } break; + case PATCH_LIST_UPDATE: { + CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); + onAudioPatchListUpdate(); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android -- cgit v1.1 From 6dbb5e3336cfff1ad51d429fcb847307c06efd61 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 13 May 2014 10:38:42 -0700 Subject: Use of fast capture by normal capture Will only configure fast capture path if the input buffer size is less than 10 ms and the input sample rate is same as the primary output sample rate. Change-Id: I4a7cdc6069d750845412c626d27e83f72a1ab397 --- media/libmedia/AudioTrackShared.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 219dbfd..0dbfa62 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -134,10 +134,17 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques ssize_t filled = rear - front; // pipe should not be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { - ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); - mIsShutdown = true; - status = NO_INIT; - goto end; + if (mIsOut) { + ALOGE("Shared memory control block is corrupt (filled=%d, mFrameCount=%u); " + "shutting down", filled, mFrameCount); + mIsShutdown = true; + status = NO_INIT; + goto end; + } + // for input, sync up on overrun + filled = 0; + cblk->u.mStreaming.mFront = rear; + (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); } // don't allow filling pipe beyond the nominal size size_t avail = mIsOut ? mFrameCount - filled : filled; -- cgit v1.1 From a121f90f388343dc48793cbc7eb899aba42e7664 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 3 Jun 2014 13:32:54 -0700 Subject: audio policy: new setAudioPortConfig implementation Rewrite setAudioPortConfig() to take advantage of the new AudioPortConfig class. The configuration is now checked against AudioPort capabilities and stored in the AudioPortConfig. Fix a bug where the config mask was not set properly when calling setAudioPortConfig at the PatchPanel interface. Remove debug log in IAudioPolicyService. Bug: 14815883. Change-Id: I7eb7683a96e049581c13f2a212486507883d008d --- media/libmedia/IAudioPolicyService.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index eee72c5..77d131b 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -421,7 +421,6 @@ public: status = (status_t)reply.readInt32(); *num_ports = (unsigned int)reply.readInt32(); } - ALOGI("listAudioPorts() status %d got *num_ports %d", status, *num_ports); if (status == NO_ERROR) { if (numPortsReq > *num_ports) { numPortsReq = *num_ports; @@ -840,7 +839,6 @@ status_t BnAudioPolicyService::onTransact( status_t status = listAudioPorts(role, type, &numPorts, ports, &generation); reply->writeInt32(status); reply->writeInt32(numPorts); - ALOGI("LIST_AUDIO_PORTS status %d got numPorts %d", status, numPorts); if (status == NO_ERROR) { if (numPortsReq > numPorts) { -- cgit v1.1 From c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 4 Jun 2014 20:31:46 -0700 Subject: Squashed commit of the following: commit 9128d6ffec43731d723f9b394f243d940f4c7e41 Author: Glenn Kasten Date: Tue May 13 10:38:42 2014 -0700 Use of fast capture by normal capture Will only configure fast capture path if the input buffer size is less than 10 ms and the input sample rate is same as the primary output sample rate. Change-Id: I4a7cdc6069d750845412c626d27e83f72a1ab397 commit 2e5e0806a5abe7499848358ef5fde5c26405000d Author: Glenn Kasten Date: Mon Jun 2 08:29:22 2014 -0700 Add mPrimaryOutputSampleRate Change-Id: I46b527fc3f2b5a5720a74b4f0b9a8f2e0d570b09 commit baf1d73467923996d1b1f2a9237260cc5697e050 Author: Andy Hung Date: Fri May 30 10:42:03 2014 -0700 Change parameter type for volume to float in AudioMixer Change-Id: I4da1505ce852505f86f8e5b87f60e8edceeb30e0 commit 40fe20fa9760cd03c69778c2021cf7a490d75ece Author: Andy Hung Date: Fri May 30 10:35:47 2014 -0700 Rename UNITY_GAIN to UNITY_GAIN_INT in AudioMixer Change-Id: Ic040311305026f0b4c4280a5b3bef7a447ac1da3 commit 37c9a2b49f876abc5ff537a9ec036d7f0a423775 Author: Andy Hung Date: Thu May 29 21:33:13 2014 -0700 Refactor setVolumeRampVariables in AudioMixer Change-Id: I8fcf3101bcea292de7c65433fa578f1c9cdd0974 commit 397070eca31f121d5d3993de1bfea99aaea5d4f3 Author: Andy Hung Date: Thu May 29 18:52:38 2014 -0700 Fix floating point output from mixer A buffer pointer was being erroneously reset to buffer start, potentially causing an audio glitch. The floating point output mode is not enabled at this time, but will be in the future. Change-Id: If8b6414d232f064f3a2e2c5a6da889a91b27fb24 commit 2e61aa5b33b2247bbc5d4eaa0b519df9accd4bbc Author: Andy Hung Date: Fri May 23 21:22:17 2014 -0700 Add multiple format capability to FastMixer Floating point data from MixerThread into FastMixer. Multiple output format capability from FastMixer to Sink. Change-Id: I0da17810ee71381a39a006c46faec71108d22c26 commit b9ea653c702a785bbd23a66c5e588d40b4192c4e Author: Andy Hung Date: Thu May 29 15:53:09 2014 -0700 Avoid resetting BufferProviders in mixer unnecessarily Change-Id: Iad85c4dfd21be1dbf89dc11906106b34219376f8 commit 7f1a6d6da21c616f80cf9ba21bea11b419ec561b Author: Andy Hung Date: Tue May 27 12:32:17 2014 -0700 Update dynamic resampler buffer fetching Make the criteria tight for fetching to avoid storing excessive frame data internal to the resampler. This should reduce jitter in frame delivery computation. Bug: 14962343 Change-Id: I7adaf714d11c272696ccdbf218bda994c7217477 commit b5e4aac07b9a02f0c803c090058602b03ac09ebb Author: Glenn Kasten Date: Tue May 27 12:30:54 2014 -0700 Allow kFastTrackMultiplier to be specified per device Change-Id: I4eaaaf038df720cec4f5d9221d1b632970f9e3dd commit b93cd97a52af31122df2da2cc0415cda888c8c73 Author: Andy Hung Date: Fri May 23 21:13:31 2014 -0700 Rename mixBuffer to mMixerBuffer in FastMixer Likewise mixBufferState becomes mMixerBufferState. This harmonizes with the naming in AF::MixerThread. Change-Id: I1255d7c07cc2c6ee925d7430925236d2bd163122 commit 8340758622b9711365a8801806cbdf934803c63f Author: Andy Hung Date: Mon May 12 16:51:41 2014 -0700 Add multiple format capability to AudioMixer Change-Id: I04ac1cafd90b6ed652f8d51888ad07576678f0bc Signed-off-by: Andy Hung commit 6b695b9d094820c232a897a3fabbe83d2b7193fe Author: Glenn Kasten Date: Thu Mar 13 14:59:31 2014 -0700 Start adding FastCapture based on FastThread WIP This version supports at most one fast capture client. Change-Id: Idf609bfc80ae22433433d66a5232c043c65506df commit e951ad05a2c388471d7e2806d91e7d51325a150a Author: Glenn Kasten Date: Mon May 12 11:06:26 2014 -0700 Move validation of frameCount from set to openRecord_l This move is needed because frameCount is validated on server side for fast tracks (as should be done for normal tracks too). Change-Id: I6d99e80869fd90fab373cf60ef348c01f075fbca commit 73e76992dbba794894837c38e5472312ea829cf3 Author: Glenn Kasten Date: Tue May 13 10:41:52 2014 -0700 Allow track buffer "allocation" to be from pipe Change-Id: Ib9ac170f8e8b7746b3588157a56cbee3b753a1cb commit 60de1d7ded05c6304037d4858b401094b1d2b4d3 Author: Andy Hung Date: Fri May 9 15:02:21 2014 -0700 Add format parameter to getTrackName() and track_t Change-Id: Ia152a839014e235fbfb656104c15d7c1b456d02e Signed-off-by: Andy Hung Change-Id: Ied0ade8b25d23e89bb03319a7e3135c238f735b9 --- media/libmedia/AudioRecord.cpp | 42 +++++++++++++++++++++---------------- media/libmedia/AudioTrackShared.cpp | 15 +++++++++---- 2 files changed, 35 insertions(+), 22 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 1c808d0..db61e85 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -203,23 +203,6 @@ status_t AudioRecord::set( mFrameSize = sizeof(uint8_t); } - // validate framecount - size_t minFrameCount; - status_t status = AudioRecord::getMinFrameCount(&minFrameCount, - sampleRate, format, channelMask); - if (status != NO_ERROR) { - ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; status %d", - sampleRate, format, channelMask, status); - return status; - } - ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); - - if (frameCount == 0) { - frameCount = minFrameCount; - } else if (frameCount < minFrameCount) { - ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount); - return BAD_VALUE; - } // mFrameCount is initialized in openRecord_l mReqFrameCount = frameCount; @@ -242,7 +225,7 @@ status_t AudioRecord::set( } // create the IAudioRecord - status = openRecord_l(0 /*epoch*/); + status_t status = openRecord_l(0 /*epoch*/); if (status != NO_ERROR) { if (mAudioRecordThread != 0) { @@ -464,6 +447,29 @@ status_t AudioRecord::openRecord_l(size_t epoch) size_t frameCount = mReqFrameCount; if (!(mFlags & AUDIO_INPUT_FLAG_FAST)) { + // validate framecount + // If fast track was not requested, this preserves + // the old behavior of validating on client side. + // FIXME Eventually the validation should be done on server side + // regardless of whether it's a fast or normal track. It's debatable + // whether to account for the input latency to provision buffers appropriately. + size_t minFrameCount; + status = AudioRecord::getMinFrameCount(&minFrameCount, + mSampleRate, mFormat, mChannelMask); + if (status != NO_ERROR) { + ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; " + "status %d", + mSampleRate, mFormat, mChannelMask, status); + return status; + } + + if (frameCount == 0) { + frameCount = minFrameCount; + } else if (frameCount < minFrameCount) { + ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount); + return BAD_VALUE; + } + // Make sure that application is notified with sufficient margin before overrun if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) { mNotificationFramesAct = frameCount/2; diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 219dbfd..0dbfa62 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -134,10 +134,17 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques ssize_t filled = rear - front; // pipe should not be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { - ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); - mIsShutdown = true; - status = NO_INIT; - goto end; + if (mIsOut) { + ALOGE("Shared memory control block is corrupt (filled=%d, mFrameCount=%u); " + "shutting down", filled, mFrameCount); + mIsShutdown = true; + status = NO_INIT; + goto end; + } + // for input, sync up on overrun + filled = 0; + cblk->u.mStreaming.mFront = rear; + (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); } // don't allow filling pipe beyond the nominal size size_t avail = mIsOut ? mFrameCount - filled : filled; -- cgit v1.1 From bcca9e072c1f288a53ce6862936f57dc36488f96 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Mon, 9 Jun 2014 15:51:38 -0700 Subject: Remove dependency on Parcel::{read,write}IntPtr bug: 15424960 bug: 15107693 Change-Id: Ic3bf37f591e620985c37f345f9a5544fd20ec4a1 --- media/libmedia/ICrypto.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp index 98b183a..0d5f990 100644 --- a/media/libmedia/ICrypto.cpp +++ b/media/libmedia/ICrypto.cpp @@ -131,7 +131,7 @@ struct BpCrypto : public BpInterface { data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); if (secure) { - data.writeIntPtr((intptr_t)dstPtr); + data.writeInt64(static_cast(reinterpret_cast(dstPtr))); } remote()->transact(DECRYPT, data, &reply); @@ -249,7 +249,7 @@ status_t BnCrypto::onTransact( void *dstPtr; if (secure) { - dstPtr = (void *)data.readIntPtr(); + dstPtr = reinterpret_cast(static_cast(data.readInt64())); } else { dstPtr = malloc(totalSize); } -- cgit v1.1 From 5f6af1a8e34381ca2ac2527fcefe220a22f49b53 Mon Sep 17 00:00:00 2001 From: Zhijun He Date: Tue, 10 Jun 2014 08:26:33 -0700 Subject: MediaProfiles: Add 4K video related constants Bug: 15287656 Change-Id: I4c49640a349afb336f52db1636902fc216bff6ad --- media/libmedia/MediaProfiles.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 1074da9..28238c4 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -69,6 +69,7 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { {"480p", CAMCORDER_QUALITY_480P}, {"720p", CAMCORDER_QUALITY_720P}, {"1080p", CAMCORDER_QUALITY_1080P}, + {"2160p", CAMCORDER_QUALITY_2160P}, {"qvga", CAMCORDER_QUALITY_QVGA}, {"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW}, @@ -78,6 +79,7 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { {"timelapse480p", CAMCORDER_QUALITY_TIME_LAPSE_480P}, {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P}, {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P}, + {"timelapse2160p", CAMCORDER_QUALITY_TIME_LAPSE_2160P}, {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA}, }; -- cgit v1.1 From b7f24b101d43139b4c747129bfbc4ecf5c468b86 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Wed, 11 Jun 2014 10:05:30 -0700 Subject: AudioSystem: remove unused stream type The audio stream type is not used in the getSampleRate() and getFrameCount() methods. Change-Id: I3d065ae272bd039204cd323cdab9b60460034f2d --- media/libmedia/AudioSystem.cpp | 18 ++++++------------ media/libmedia/AudioTrack.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 17 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index eafb3ad..15b32ff 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -242,11 +242,10 @@ status_t AudioSystem::getOutputSamplingRate(uint32_t* samplingRate, audio_stream return PERMISSION_DENIED; } - return getSamplingRate(output, streamType, samplingRate); + return getSamplingRate(output, samplingRate); } status_t AudioSystem::getSamplingRate(audio_io_handle_t output, - audio_stream_type_t streamType, uint32_t* samplingRate) { OutputDescriptor *outputDesc; @@ -265,13 +264,11 @@ status_t AudioSystem::getSamplingRate(audio_io_handle_t output, gLock.unlock(); } if (*samplingRate == 0) { - ALOGE("AudioSystem::getSamplingRate failed for output %d stream type %d", - output, streamType); + ALOGE("AudioSystem::getSamplingRate failed for output %d", output); return BAD_VALUE; } - ALOGV("getSamplingRate() streamType %d, output %d, sampling rate %u", streamType, output, - *samplingRate); + ALOGV("getSamplingRate() output %d, sampling rate %u", output, *samplingRate); return NO_ERROR; } @@ -289,11 +286,10 @@ status_t AudioSystem::getOutputFrameCount(size_t* frameCount, audio_stream_type_ return PERMISSION_DENIED; } - return getFrameCount(output, streamType, frameCount); + return getFrameCount(output, frameCount); } status_t AudioSystem::getFrameCount(audio_io_handle_t output, - audio_stream_type_t streamType, size_t* frameCount) { OutputDescriptor *outputDesc; @@ -310,13 +306,11 @@ status_t AudioSystem::getFrameCount(audio_io_handle_t output, gLock.unlock(); } if (*frameCount == 0) { - ALOGE("AudioSystem::getFrameCount failed for output %d stream type %d", - output, streamType); + ALOGE("AudioSystem::getFrameCount failed for output %d", output); return BAD_VALUE; } - ALOGV("getFrameCount() streamType %d, output %d, frameCount %d", streamType, output, - *frameCount); + ALOGV("getFrameCount() output %d, frameCount %d", output, *frameCount); return NO_ERROR; } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 7d3ecc5..6989aaf 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -647,7 +647,7 @@ uint32_t AudioTrack::getSampleRate() const if (isOffloaded_l()) { if (mOutput != AUDIO_IO_HANDLE_NONE) { uint32_t sampleRate = 0; - status_t status = AudioSystem::getSamplingRate(mOutput, mStreamType, &sampleRate); + status_t status = AudioSystem::getSamplingRate(mOutput, &sampleRate); if (status == NO_ERROR) { mSampleRate = sampleRate; } @@ -887,16 +887,16 @@ status_t AudioTrack::createTrack_l(size_t epoch) } size_t afFrameCount; - status = AudioSystem::getFrameCount(output, mStreamType, &afFrameCount); + status = AudioSystem::getFrameCount(output, &afFrameCount); if (status != NO_ERROR) { - ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, mStreamType, status); + ALOGE("getFrameCount(output=%d) status %d", output, status); goto release; } uint32_t afSampleRate; - status = AudioSystem::getSamplingRate(output, mStreamType, &afSampleRate); + status = AudioSystem::getSamplingRate(output, &afSampleRate); if (status != NO_ERROR) { - ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, mStreamType, status); + ALOGE("getSamplingRate(output=%d) status %d", output, status); goto release; } -- cgit v1.1 From 3bcffa136909c1fb6e88ee4efd12ccac18360a85 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 12 Jun 2014 18:38:45 -0700 Subject: force command flush after releasing a reference to shared memory After releasing a reference to a shared memory interface, IPCThreadState::self()->flushCommands() must be called to ensure that the corresponding reference is also cleared immediately in the remote process. Otherwise the binder implementaiton will not push the clear systematically causing the memory region not to be freed. See issues 10711502 and 2801375. Bug: 14057166. Change-Id: If55f36f00d452d6cf00cf83bd2fba1c8f3abcb57 --- media/libmedia/AudioRecord.cpp | 5 ++++- media/libmedia/AudioTrack.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index db61e85..50b444a 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -105,6 +105,8 @@ AudioRecord::~AudioRecord() } mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); + mCblkMemory.clear(); + mBufferMemory.clear(); IPCThreadState::self()->flushCommands(); AudioSystem::releaseAudioSessionId(mSessionId, -1); } @@ -546,9 +548,10 @@ status_t AudioRecord::openRecord_l(size_t epoch) mDeathNotifier.clear(); } mAudioRecord = record; - mCblkMemory = iMem; mBufferMemory = bufferMem; + IPCThreadState::self()->flushCommands(); + mCblk = cblk; // note that temp is the (possibly revised) value of frameCount if (temp < frameCount || (frameCount == 0 && temp == 0)) { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 7d3ecc5..fa8e5c3 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -174,6 +174,8 @@ AudioTrack::~AudioTrack() } mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); + mCblkMemory.clear(); + mSharedBuffer.clear(); IPCThreadState::self()->flushCommands(); ALOGV("~AudioTrack, releasing session id from %d on behalf of %d", IPCThreadState::self()->getCallingPid(), mClientPid); @@ -1059,8 +1061,9 @@ status_t AudioTrack::createTrack_l(size_t epoch) mDeathNotifier.clear(); } mAudioTrack = track; - mCblkMemory = iMem; + IPCThreadState::self()->flushCommands(); + audio_track_cblk_t* cblk = static_cast(iMemPointer); mCblk = cblk; // note that temp is the (possibly revised) value of frameCount -- cgit v1.1 From faabb51ceef13bf1e3f692219ac410c1cd75d0de Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Wed, 11 Jun 2014 16:55:06 -0700 Subject: AudioTrack construction with audio attributes Store audio attributes in AudioTrack class. When an AudioTrack is "set" with non null audio attributes, derive a stream type that reflects the attributes. When an AudioTrack is "set" without attributes, and only has a stream type, derive default audio attributes. Change-Id: I322b91fa9a7e193118960c5e78cdddd85d66f9ad --- media/libmedia/AudioTrack.cpp | 173 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 163 insertions(+), 10 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index e6827ee..000185b 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -103,6 +103,10 @@ AudioTrack::AudioTrack() mPreviousSchedulingGroup(SP_DEFAULT), mPausedPosition(0) { + mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN; + mAttributes.usage = AUDIO_USAGE_UNKNOWN; + mAttributes.flags = 0x0; + strcpy(mAttributes.tags, ""); } AudioTrack::AudioTrack( @@ -129,7 +133,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, - offloadInfo, uid, pid); + offloadInfo, uid, pid, NULL /*no audio attributes*/); } AudioTrack::AudioTrack( @@ -156,7 +160,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, - uid, pid); + uid, pid, NULL /*no audio attributes*/); } AudioTrack::~AudioTrack() @@ -199,7 +203,8 @@ status_t AudioTrack::set( transfer_type transferType, const audio_offload_info_t *offloadInfo, int uid, - pid_t pid) + pid_t pid, + audio_attributes_t* pAttributes) { ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "flags #%x, notificationFrames %u, sessionId %d, transferType %d", @@ -259,18 +264,34 @@ status_t AudioTrack::set( if (streamType == AUDIO_STREAM_DEFAULT) { streamType = AUDIO_STREAM_MUSIC; } - if (uint32_t(streamType) >= AUDIO_STREAM_CNT) { - ALOGE("Invalid stream type %d", streamType); - return BAD_VALUE; + + if (pAttributes == NULL) { + if (uint32_t(streamType) >= AUDIO_STREAM_CNT) { + ALOGE("Invalid stream type %d", streamType); + return BAD_VALUE; + } + setAttributesFromStreamType(streamType); + mStreamType = streamType; + } else { + if (!isValidAttributes(pAttributes)) { + ALOGE("Invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", + pAttributes->usage, pAttributes->content_type, pAttributes->flags, + pAttributes->tags); + } + // stream type shouldn't be looked at, this track has audio attributes + memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); + setStreamTypeFromAttributes(mAttributes); + ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]", + mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags); } - mStreamType = streamType; status_t status; if (sampleRate == 0) { - status = AudioSystem::getOutputSamplingRate(&sampleRate, streamType); + // TODO replace with new APM method with support for audio_attributes_t + status = AudioSystem::getOutputSamplingRate(&sampleRate, mStreamType); if (status != NO_ERROR) { ALOGE("Could not get output sample rate for stream type %d; status %d", - streamType, status); + mStreamType, status); return status; } } @@ -314,7 +335,7 @@ status_t AudioTrack::set( ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST); } // only allow deep buffering for music stream type - if (streamType != AUDIO_STREAM_MUSIC) { + if (mStreamType != AUDIO_STREAM_MUSIC) { flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); } @@ -620,6 +641,7 @@ status_t AudioTrack::setSampleRate(uint32_t rate) } uint32_t afSamplingRate; + // TODO replace with new APM method with support for audio_attributes_t if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) { return NO_INIT; } @@ -867,6 +889,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) return NO_INIT; } + // TODO replace with new APM method with support for audio_attributes_t audio_io_handle_t output = AudioSystem::getOutput(mStreamType, mSampleRate, mFormat, mChannelMask, mFlags, mOffloadInfo); if (output == AUDIO_IO_HANDLE_NONE) { @@ -1858,6 +1881,136 @@ uint32_t AudioTrack::getUnderrunFrames() const return mProxy->getUnderrunFrames(); } +void AudioTrack::setAttributesFromStreamType(audio_stream_type_t streamType) { + mAttributes.flags = 0x0; + + switch(streamType) { + case AUDIO_STREAM_DEFAULT: + case AUDIO_STREAM_MUSIC: + mAttributes.content_type = AUDIO_CONTENT_TYPE_MUSIC; + mAttributes.usage = AUDIO_USAGE_MEDIA; + break; + case AUDIO_STREAM_VOICE_CALL: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH; + mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION; + break; + case AUDIO_STREAM_ENFORCED_AUDIBLE: + mAttributes.flags |= AUDIO_FLAG_AUDIBILITY_ENFORCED; + // intended fall through, attributes in common with STREAM_SYSTEM + case AUDIO_STREAM_SYSTEM: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + mAttributes.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION; + break; + case AUDIO_STREAM_RING: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + mAttributes.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; + break; + case AUDIO_STREAM_ALARM: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + mAttributes.usage = AUDIO_USAGE_ALARM; + break; + case AUDIO_STREAM_NOTIFICATION: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + mAttributes.usage = AUDIO_USAGE_NOTIFICATION; + break; + case AUDIO_STREAM_BLUETOOTH_SCO: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH; + mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION; + mAttributes.flags |= AUDIO_FLAG_SCO; + break; + case AUDIO_STREAM_DTMF: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; + break; + case AUDIO_STREAM_TTS: + mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH; + mAttributes.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; + break; + default: + ALOGE("invalid stream type %d when converting to attributes", streamType); + } +} + +void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) { + // flags to stream type mapping + if ((aa.flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { + mStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE; + return; + } + if ((aa.flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) { + mStreamType = AUDIO_STREAM_BLUETOOTH_SCO; + return; + } + + // usage to stream type mapping + switch (aa.usage) { + case AUDIO_USAGE_MEDIA: + case AUDIO_USAGE_GAME: + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: + mStreamType = AUDIO_STREAM_MUSIC; + return; + case AUDIO_USAGE_ASSISTANCE_SONIFICATION: + mStreamType = AUDIO_STREAM_SYSTEM; + return; + case AUDIO_USAGE_VOICE_COMMUNICATION: + mStreamType = AUDIO_STREAM_VOICE_CALL; + return; + + case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: + mStreamType = AUDIO_STREAM_DTMF; + return; + + case AUDIO_USAGE_ALARM: + mStreamType = AUDIO_STREAM_ALARM; + return; + case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: + mStreamType = AUDIO_STREAM_RING; + return; + + case AUDIO_USAGE_NOTIFICATION: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: + case AUDIO_USAGE_NOTIFICATION_EVENT: + mStreamType = AUDIO_STREAM_NOTIFICATION; + return; + + case AUDIO_USAGE_UNKNOWN: + default: + mStreamType = AUDIO_STREAM_MUSIC; + } +} + +bool AudioTrack::isValidAttributes(const audio_attributes_t *paa) { + // has flags that map to a strategy? + if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO)) != 0) { + return true; + } + + // has known usage? + switch (paa->usage) { + case AUDIO_USAGE_UNKNOWN: + case AUDIO_USAGE_MEDIA: + case AUDIO_USAGE_VOICE_COMMUNICATION: + case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: + case AUDIO_USAGE_ALARM: + case AUDIO_USAGE_NOTIFICATION: + case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: + case AUDIO_USAGE_NOTIFICATION_EVENT: + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: + case AUDIO_USAGE_ASSISTANCE_SONIFICATION: + case AUDIO_USAGE_GAME: + break; + default: + return false; + } + return true; +} // ========================================================================= void AudioTrack::DeathNotifier::binderDied(const wp& who __unused) -- cgit v1.1 From 5bd3f38638acab633d181359cc9ec27b80f84d43 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 13 Jun 2014 16:06:54 -0700 Subject: AudioPolicyManager: return output for audio attributes In AudioPolicyManager, support querying an output or playback strategy for audio attributes, instead of a stream type, In AudioTrack creation, use the output returned for the track's attributes. Change-Id: I0fef05845ba676404775e2e338c10e6a96237268 --- media/libmedia/AudioSystem.cpp | 26 ++++++++++++++++ media/libmedia/AudioTrack.cpp | 15 ++++----- media/libmedia/IAudioPolicyService.cpp | 57 +++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 10 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 15b32ff..f5e7a78 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -245,6 +245,19 @@ status_t AudioSystem::getOutputSamplingRate(uint32_t* samplingRate, audio_stream return getSamplingRate(output, samplingRate); } +status_t AudioSystem::getOutputSamplingRateForAttr(uint32_t* samplingRate, + const audio_attributes_t *attr) +{ + if (attr == NULL) { + return BAD_VALUE; + } + audio_io_handle_t output = getOutputForAttr(attr); + if (output == 0) { + return PERMISSION_DENIED; + } + return getSamplingRate(output, samplingRate); +} + status_t AudioSystem::getSamplingRate(audio_io_handle_t output, uint32_t* samplingRate) { @@ -633,6 +646,19 @@ audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream, return aps->getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo); } +audio_io_handle_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) +{ + if (attr == NULL) return 0; + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return 0; + return aps->getOutputForAttr(attr, samplingRate, format, channelMask, flags, offloadInfo); +} + status_t AudioSystem::startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 000185b..77419f0 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -287,8 +287,7 @@ status_t AudioTrack::set( status_t status; if (sampleRate == 0) { - // TODO replace with new APM method with support for audio_attributes_t - status = AudioSystem::getOutputSamplingRate(&sampleRate, mStreamType); + status = AudioSystem::getOutputSamplingRateForAttr(&sampleRate, &mAttributes); if (status != NO_ERROR) { ALOGE("Could not get output sample rate for stream type %d; status %d", mStreamType, status); @@ -641,8 +640,7 @@ status_t AudioTrack::setSampleRate(uint32_t rate) } uint32_t afSamplingRate; - // TODO replace with new APM method with support for audio_attributes_t - if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRateForAttr(&afSamplingRate, &mAttributes) != NO_ERROR) { return NO_INIT; } // Resampler implementation limits input sampling rate to 2 x output sampling rate. @@ -889,13 +887,12 @@ status_t AudioTrack::createTrack_l(size_t epoch) return NO_INIT; } - // TODO replace with new APM method with support for audio_attributes_t - audio_io_handle_t output = AudioSystem::getOutput(mStreamType, mSampleRate, mFormat, + audio_io_handle_t output = AudioSystem::getOutputForAttr(&mAttributes, mSampleRate, mFormat, mChannelMask, mFlags, mOffloadInfo); if (output == AUDIO_IO_HANDLE_NONE) { - ALOGE("Could not get audio output for stream type %d, sample rate %u, format %#x, " - "channel mask %#x, flags %#x", - mStreamType, mSampleRate, mFormat, mChannelMask, mFlags); + ALOGE("Could not get audio output for stream type %d, usage %d, sample rate %u, format %#x," + " channel mask %#x, flags %#x", + mStreamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags); return BAD_VALUE; } { diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 77d131b..41a9065 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -64,7 +64,8 @@ enum { RELEASE_AUDIO_PATCH, LIST_AUDIO_PATCHES, SET_AUDIO_PORT_CONFIG, - REGISTER_CLIENT + REGISTER_CLIENT, + GET_OUTPUT_FOR_ATTR }; class BpAudioPolicyService : public BpInterface @@ -155,6 +156,36 @@ public: return static_cast (reply.readInt32()); } + virtual audio_io_handle_t getOutputForAttr( + const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + if (attr == NULL) { + ALOGE("Writing NULL audio attributes - shouldn't happen"); + return (audio_io_handle_t) 0; + } + data.write(attr, sizeof(audio_attributes_t)); + data.writeInt32(samplingRate); + data.writeInt32(static_cast (format)); + data.writeInt32(channelMask); + data.writeInt32(static_cast (flags)); + // hasOffloadInfo + if (offloadInfo == NULL) { + data.writeInt32(0); + } else { + data.writeInt32(1); + data.write(offloadInfo, sizeof(audio_offload_info_t)); + } + remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply); + return static_cast (reply.readInt32()); + } + virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session) @@ -614,6 +645,30 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case GET_OUTPUT_FOR_ATTR: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_attributes_t *attr = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t)); + data.read(attr, sizeof(audio_attributes_t)); + uint32_t samplingRate = data.readInt32(); + audio_format_t format = (audio_format_t) data.readInt32(); + audio_channel_mask_t channelMask = data.readInt32(); + audio_output_flags_t flags = + static_cast (data.readInt32()); + bool hasOffloadInfo = data.readInt32() != 0; + audio_offload_info_t offloadInfo; + if (hasOffloadInfo) { + data.read(&offloadInfo, sizeof(audio_offload_info_t)); + } + audio_io_handle_t output = getOutputForAttr(attr, + samplingRate, + format, + channelMask, + flags, + hasOffloadInfo ? &offloadInfo : NULL); + reply->writeInt32(static_cast (output)); + return NO_ERROR; + } break; + case START_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t output = static_cast (data.readInt32()); -- cgit v1.1 From ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3fa Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Mon, 9 Jun 2014 17:22:27 -0700 Subject: AudioTrack: add support for compressed audio Add support for compressed audio playback by use of an AudioTrack attached to a direct output thread. Bug: 9428304. Change-Id: I4a61be9cf0e31003ca85935d6e0ee38ca8192e03 --- media/libmedia/AudioTrack.cpp | 67 +++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 15 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 77419f0..5c82cfb 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -635,7 +635,7 @@ void AudioTrack::getAuxEffectSendLevel(float* level) const status_t AudioTrack::setSampleRate(uint32_t rate) { - if (mIsTimed || isOffloaded()) { + if (mIsTimed || isOffloadedOrDirect()) { return INVALID_OPERATION; } @@ -666,7 +666,7 @@ uint32_t AudioTrack::getSampleRate() const // sample rate can be updated during playback by the offloaded decoder so we need to // query the HAL and update if needed. // FIXME use Proxy return channel to update the rate from server and avoid polling here - if (isOffloaded_l()) { + if (isOffloadedOrDirect_l()) { if (mOutput != AUDIO_IO_HANDLE_NONE) { uint32_t sampleRate = 0; status_t status = AudioSystem::getSamplingRate(mOutput, &sampleRate); @@ -680,7 +680,7 @@ uint32_t AudioTrack::getSampleRate() const status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) { - if (mSharedBuffer == 0 || mIsTimed || isOffloaded()) { + if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) { return INVALID_OPERATION; } @@ -714,7 +714,7 @@ void AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount) status_t AudioTrack::setMarkerPosition(uint32_t marker) { // The only purpose of setting marker position is to get a callback - if (mCbf == NULL || isOffloaded()) { + if (mCbf == NULL || isOffloadedOrDirect()) { return INVALID_OPERATION; } @@ -727,7 +727,7 @@ status_t AudioTrack::setMarkerPosition(uint32_t marker) status_t AudioTrack::getMarkerPosition(uint32_t *marker) const { - if (isOffloaded()) { + if (isOffloadedOrDirect()) { return INVALID_OPERATION; } if (marker == NULL) { @@ -743,7 +743,7 @@ status_t AudioTrack::getMarkerPosition(uint32_t *marker) const status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) { // The only purpose of setting position update period is to get a callback - if (mCbf == NULL || isOffloaded()) { + if (mCbf == NULL || isOffloadedOrDirect()) { return INVALID_OPERATION; } @@ -756,7 +756,7 @@ status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) const { - if (isOffloaded()) { + if (isOffloadedOrDirect()) { return INVALID_OPERATION; } if (updatePeriod == NULL) { @@ -771,7 +771,7 @@ status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) const status_t AudioTrack::setPosition(uint32_t position) { - if (mSharedBuffer == 0 || mIsTimed || isOffloaded()) { + if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) { return INVALID_OPERATION; } if (position > mFrameCount) { @@ -804,10 +804,10 @@ status_t AudioTrack::getPosition(uint32_t *position) const } AutoMutex lock(mLock); - if (isOffloaded_l()) { + if (isOffloadedOrDirect_l()) { uint32_t dspFrames = 0; - if ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING)) { + if (isOffloaded_l() && ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING))) { ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition); *position = mPausedPosition; return NO_ERROR; @@ -842,7 +842,7 @@ status_t AudioTrack::getBufferPosition(uint32_t *position) status_t AudioTrack::reload() { - if (mSharedBuffer == 0 || mIsTimed || isOffloaded()) { + if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) { return INVALID_OPERATION; } @@ -1038,6 +1038,10 @@ status_t AudioTrack::createTrack_l(size_t epoch) trackFlags |= IAudioFlinger::TRACK_OFFLOAD; } + if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { + trackFlags |= IAudioFlinger::TRACK_DIRECT; + } + size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also sp track = audioFlinger->createTrack(mStreamType, @@ -1129,6 +1133,16 @@ status_t AudioTrack::createTrack_l(size_t epoch) //return NO_INIT; } } + if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { + if (trackFlags & IAudioFlinger::TRACK_DIRECT) { + ALOGV("AUDIO_OUTPUT_FLAG_DIRECT successful"); + } else { + ALOGW("AUDIO_OUTPUT_FLAG_DIRECT denied by server"); + mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_DIRECT); + // FIXME This is a warning, not an error, so don't return error status + //return NO_INIT; + } + } // We retain a copy of the I/O handle, but don't own the reference mOutput = output; @@ -1324,6 +1338,16 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking) return INVALID_OPERATION; } + if (isDirect()) { + AutoMutex lock(mLock); + int32_t flags = android_atomic_and( + ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END), + &mCblk->mFlags); + if (flags & CBLK_INVALID) { + return DEAD_OBJECT; + } + } + if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { // Sanity-check: user is most-likely passing an error code, and it would // make the return value ambiguous (actualSize vs error). @@ -1472,7 +1496,7 @@ nsecs_t AudioTrack::processAudioBuffer() // for offloaded tracks restoreTrack_l() will just update the sequence and clear // AudioSystem cache. We should not exit here but after calling the callback so // that the upper layers can recreate the track - if (!isOffloaded_l() || (mSequence == mObservedSequence)) { + if (!isOffloadedOrDirect_l() || (mSequence == mObservedSequence)) { status_t status = restoreTrack_l("processAudioBuffer"); mLock.unlock(); // Run again immediately, but with a new IAudioTrack @@ -1598,7 +1622,7 @@ nsecs_t AudioTrack::processAudioBuffer() mObservedSequence = sequence; mCbf(EVENT_NEW_IAUDIOTRACK, mUserData, NULL); // for offloaded tracks, just wait for the upper layers to recreate the track - if (isOffloaded()) { + if (isOffloadedOrDirect()) { return NS_INACTIVE; } } @@ -1756,7 +1780,7 @@ nsecs_t AudioTrack::processAudioBuffer() status_t AudioTrack::restoreTrack_l(const char *from) { ALOGW("dead IAudioTrack, %s, creating a new one from %s()", - isOffloaded_l() ? "Offloaded" : "PCM", from); + isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from); ++mSequence; status_t result; @@ -1764,7 +1788,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) // output parameters in createTrack_l() AudioSystem::clearAudioConfigCache(); - if (isOffloaded_l()) { + if (isOffloadedOrDirect_l()) { // FIXME re-creation of offloaded tracks is not yet implemented return DEAD_OBJECT; } @@ -1850,6 +1874,19 @@ bool AudioTrack::isOffloaded() const return isOffloaded_l(); } +bool AudioTrack::isDirect() const +{ + AutoMutex lock(mLock); + return isDirect_l(); +} + +bool AudioTrack::isOffloadedOrDirect() const +{ + AutoMutex lock(mLock); + return isOffloadedOrDirect_l(); +} + + status_t AudioTrack::dump(int fd, const Vector& args __unused) const { -- cgit v1.1 From 34fb29696b0f3abf61b10f8d053b1f33d501de0a Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 18 Jun 2014 16:30:56 -0700 Subject: libmedia: 64-bit compile warnings Change-Id: I600f062fa7148c01851023c1240c39939e648002 --- media/libmedia/AudioRecord.cpp | 22 +++++++++++---------- media/libmedia/AudioSystem.cpp | 6 +++--- media/libmedia/AudioTrack.cpp | 29 ++++++++++++++-------------- media/libmedia/AudioTrackShared.cpp | 12 ++++++------ media/libmedia/CharacterEncodingDetector.cpp | 10 +++++----- media/libmedia/IMediaMetadataRetriever.cpp | 6 ++++-- media/libmedia/IMediaRecorder.cpp | 8 +++++--- media/libmedia/MediaProfiles.cpp | 6 +++--- media/libmedia/SoundPool.cpp | 10 +++++++--- media/libmedia/mediametadataretriever.cpp | 6 ++++-- media/libmedia/mediaplayer.cpp | 14 ++++++++------ media/libmedia/mediarecorder.cpp | 5 ++++- 12 files changed, 76 insertions(+), 58 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 50b444a..f865d38 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -18,7 +18,9 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "AudioRecord" +#include #include + #include #include #include @@ -468,7 +470,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) if (frameCount == 0) { frameCount = minFrameCount; } else if (frameCount < minFrameCount) { - ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount); + ALOGE("frameCount %zu < minFrameCount %zu", frameCount, minFrameCount); return BAD_VALUE; } @@ -555,17 +557,17 @@ status_t AudioRecord::openRecord_l(size_t epoch) mCblk = cblk; // note that temp is the (possibly revised) value of frameCount if (temp < frameCount || (frameCount == 0 && temp == 0)) { - ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp); + ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp); } frameCount = temp; mAwaitBoost = false; if (mFlags & AUDIO_INPUT_FLAG_FAST) { if (trackFlags & IAudioFlinger::TRACK_FAST) { - ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %u", frameCount); + ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount); mAwaitBoost = true; } else { - ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %u", frameCount); + ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount); // once denied, do not request again if IAudioRecord is re-created mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); } @@ -740,7 +742,7 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize) if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { // sanity-check. user is most-likely passing an error code, and it would // make the return value ambiguous (actualSize vs error). - ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", buffer, userSize, userSize); + ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize); return BAD_VALUE; } @@ -921,10 +923,10 @@ nsecs_t AudioRecord::processAudioBuffer() size_t nonContig; status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig); LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0), - "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount); + "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount); requested = &ClientProxy::kNonBlocking; size_t avail = audioBuffer.frameCount + nonContig; - ALOGV("obtainBuffer(%u) returned %u = %u + %u err %d", + ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d", mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err); if (err != NO_ERROR) { if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) { @@ -952,8 +954,8 @@ nsecs_t AudioRecord::processAudioBuffer() // Sanity check on returned size if (ssize_t(readSize) < 0 || readSize > reqSize) { - ALOGE("EVENT_MORE_DATA requested %u bytes but callback returned %d bytes", - reqSize, (int) readSize); + ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes", + reqSize, ssize_t(readSize)); return NS_NEVER; } @@ -1092,7 +1094,7 @@ bool AudioRecord::AudioRecordThread::threadLoop() ns = 1000000000LL; // fall through default: - LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns); + LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns); pauseInternal(ns); return true; } diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index f5e7a78..a47d45c 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -323,7 +323,7 @@ status_t AudioSystem::getFrameCount(audio_io_handle_t output, return BAD_VALUE; } - ALOGV("getFrameCount() output %d, frameCount %d", output, *frameCount); + ALOGV("getFrameCount() output %d, frameCount %zu", output, *frameCount); return NO_ERROR; } @@ -489,7 +489,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle OutputDescriptor *outputDesc = new OutputDescriptor(*desc); gOutputs.add(ioHandle, outputDesc); - ALOGV("ioConfigChanged() new output samplingRate %u, format %#x channel mask %#x frameCount %u " + ALOGV("ioConfigChanged() new output samplingRate %u, format %#x channel mask %#x frameCount %zu " "latency %d", outputDesc->samplingRate, outputDesc->format, outputDesc->channelMask, outputDesc->frameCount, outputDesc->latency); @@ -514,7 +514,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle desc = (const OutputDescriptor *)param2; ALOGV("ioConfigChanged() new config for output %d samplingRate %u, format %#x channel mask %#x " - "frameCount %d latency %d", + "frameCount %zu latency %d", ioHandle, desc->samplingRate, desc->format, desc->channelMask, desc->frameCount, desc->latency); OutputDescriptor *outputDesc = gOutputs.valueAt(index); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 5c82cfb..898d58d 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -15,12 +15,13 @@ ** limitations under the License. */ - //#define LOG_NDEBUG 0 #define LOG_TAG "AudioTrack" +#include #include #include + #include #include #include @@ -89,7 +90,7 @@ status_t AudioTrack::getMinFrameCount( streamType, sampleRate); return BAD_VALUE; } - ALOGV("getMinFrameCount=%d: afFrameCount=%d, minBufCount=%d, afSampleRate=%d, afLatency=%d", + ALOGV("getMinFrameCount=%zu: afFrameCount=%zu, minBufCount=%d, afSampleRate=%d, afLatency=%d", *frameCount, afFrameCount, minBufCount, afSampleRate, afLatency); return NO_ERROR; } @@ -250,7 +251,7 @@ status_t AudioTrack::set( ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); - ALOGV("set() streamType %d frameCount %u flags %04x", streamType, frameCount, flags); + ALOGV("set() streamType %d frameCount %zu flags %04x", streamType, frameCount, flags); AutoMutex lock(mLock); @@ -993,14 +994,14 @@ status_t AudioTrack::createTrack_l(size_t epoch) // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); - ALOGV("afFrameCount=%d, minBufCount=%d, afSampleRate=%u, afLatency=%d", + ALOGV("afFrameCount=%zu, minBufCount=%d, afSampleRate=%u, afLatency=%d", afFrameCount, minBufCount, afSampleRate, afLatency); if (minBufCount <= nBuffering) { minBufCount = nBuffering; } size_t minFrameCount = (afFrameCount*mSampleRate*minBufCount)/afSampleRate; - ALOGV("minFrameCount: %u, afFrameCount=%d, minBufCount=%d, sampleRate=%u, afSampleRate=%u" + ALOGV("minFrameCount: %zu, afFrameCount=%zu, minBufCount=%d, sampleRate=%u, afSampleRate=%u" ", afLatency=%d", minFrameCount, afFrameCount, minBufCount, mSampleRate, afSampleRate, afLatency); @@ -1008,7 +1009,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) frameCount = minFrameCount; } else if (frameCount < minFrameCount) { // not ALOGW because it happens all the time when playing key clicks over A2DP - ALOGV("Minimum buffer size corrected from %d to %d", + ALOGV("Minimum buffer size corrected from %zu to %zu", frameCount, minFrameCount); frameCount = minFrameCount; } @@ -1095,14 +1096,14 @@ status_t AudioTrack::createTrack_l(size_t epoch) // In current design, AudioTrack client checks and ensures frame count validity before // passing it to AudioFlinger so AudioFlinger should not return a different value except // for fast track as it uses a special method of assigning frame count. - ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp); + ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp); } frameCount = temp; mAwaitBoost = false; if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { if (trackFlags & IAudioFlinger::TRACK_FAST) { - ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount); + ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu", frameCount); mAwaitBoost = true; if (mSharedBuffer == 0) { // Theoretically double-buffering is not required for fast tracks, @@ -1113,7 +1114,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) } } } else { - ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", frameCount); + ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu", frameCount); // once denied, do not request again if IAudioTrack is re-created mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST); if (mSharedBuffer == 0) { @@ -1680,10 +1681,10 @@ nsecs_t AudioTrack::processAudioBuffer() size_t nonContig; status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig); LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0), - "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount); + "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount); requested = &ClientProxy::kNonBlocking; size_t avail = audioBuffer.frameCount + nonContig; - ALOGV("obtainBuffer(%u) returned %u = %u + %u err %d", + ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d", mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err); if (err != NO_ERROR) { if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR || @@ -1718,8 +1719,8 @@ nsecs_t AudioTrack::processAudioBuffer() // Sanity check on returned size if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) { - ALOGE("EVENT_MORE_DATA requested %u bytes but callback returned %d bytes", - reqSize, (int) writtenSize); + ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes", + reqSize, ssize_t(writtenSize)); return NS_NEVER; } @@ -2105,7 +2106,7 @@ bool AudioTrack::AudioTrackThread::threadLoop() ns = 1000000000LL; // fall through default: - LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns); + LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns); pauseInternal(ns); return true; } diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 0dbfa62..eec025e 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -135,7 +135,7 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques // pipe should not be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { if (mIsOut) { - ALOGE("Shared memory control block is corrupt (filled=%d, mFrameCount=%u); " + ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); " "shutting down", filled, mFrameCount); mIsShutdown = true; status = NO_INIT; @@ -338,7 +338,7 @@ size_t ClientProxy::getFramesFilled() { ssize_t filled = rear - front; // pipe should not be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { - ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); + ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled); return 0; } return (size_t)filled; @@ -555,7 +555,7 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) ssize_t filled = rear - front; // pipe should not already be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { - ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); + ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled); mIsShutdown = true; } if (mIsShutdown) { @@ -642,7 +642,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer) } // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time if (!mIsOut || (mAvailToClient + stepCount >= minimum)) { - ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum); + ALOGV("mAvailToClient=%zu stepCount=%zu minimum=%zu", mAvailToClient, stepCount, minimum); int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { (void) syscall(__NR_futex, &cblk->mFutex, @@ -675,7 +675,7 @@ size_t AudioTrackServerProxy::framesReady() ssize_t filled = rear - cblk->u.mStreaming.mFront; // pipe should not already be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { - ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); + ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled); mIsShutdown = true; return 0; } @@ -834,7 +834,7 @@ void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) size_t newPosition = position + stepCount; int32_t setFlags = 0; if (!(position <= newPosition && newPosition <= mFrameCount)) { - ALOGW("%s newPosition %u outside [%u, %u]", __func__, newPosition, position, mFrameCount); + ALOGW("%s newPosition %zu outside [%zu, %zu]", __func__, newPosition, position, mFrameCount); newPosition = mFrameCount; } else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) { if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) { diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp index 4992798..7d1ddfd 100644 --- a/media/libmedia/CharacterEncodingDetector.cpp +++ b/media/libmedia/CharacterEncodingDetector.cpp @@ -112,7 +112,7 @@ void CharacterEncodingDetector::detectAndConvert() { if (allprintable) { // since 'buf' is empty, ICU would return a UTF-8 matcher with low confidence, so // no need to even call it - ALOGV("all tags are printable, assuming ascii (%d)", strlen(buf)); + ALOGV("all tags are printable, assuming ascii (%zu)", strlen(buf)); } else { ucsdet_setText(csd, buf, strlen(buf), &status); int32_t matches; @@ -267,11 +267,11 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( Vector matches; UErrorCode status = U_ZERO_ERROR; - ALOGV("%d matches", nummatches); + ALOGV("%zu matches", nummatches); for (size_t i = 0; i < nummatches; i++) { const char *encname = ucsdet_getName(ucma[i], &status); int confidence = ucsdet_getConfidence(ucma[i], &status); - ALOGV("%d: %s %d", i, encname, confidence); + ALOGV("%zu: %s %d", i, encname, confidence); matches.push_back(ucma[i]); } @@ -287,7 +287,7 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( return matches[0]; } - ALOGV("considering %d matches", num); + ALOGV("considering %zu matches", num); // keep track of how many "special" characters result when converting the input using each // encoding @@ -315,7 +315,7 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( freqcoverage = frequent_ja_coverage; } - ALOGV("%d: %s %d", i, encname, confidence); + ALOGV("%zu: %s %d", i, encname, confidence); UConverter *conv = ucnv_open(encname, &status); const char *source = input; const char *sourceLimit = input + len; diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp index 432d890..38f717c 100644 --- a/media/libmedia/IMediaMetadataRetriever.cpp +++ b/media/libmedia/IMediaMetadataRetriever.cpp @@ -15,8 +15,10 @@ ** limitations under the License. */ +#include #include #include + #include #include #include @@ -125,7 +127,7 @@ public: sp getFrameAtTime(int64_t timeUs, int option) { - ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option); + ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option); Parcel data, reply; data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); data.writeInt64(timeUs); @@ -237,7 +239,7 @@ status_t BnMediaMetadataRetriever::onTransact( CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); int64_t timeUs = data.readInt64(); int option = data.readInt32(); - ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option); + ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index 8e58162..95af006 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -17,6 +17,10 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "IMediaRecorder" + +#include +#include + #include #include #include @@ -24,8 +28,6 @@ #include #include #include -#include - namespace android { @@ -167,7 +169,7 @@ public: } status_t setOutputFile(int fd, int64_t offset, int64_t length) { - ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); Parcel data, reply; data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); data.writeFileDescriptor(fd); diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 28238c4..e9e453b 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -475,7 +475,7 @@ static bool isTimelapseProfile(camcorder_quality quality) { } void MediaProfiles::initRequiredProfileRefs(const Vector& cameraIds) { - ALOGV("Number of camera ids: %d", cameraIds.size()); + ALOGV("Number of camera ids: %zu", cameraIds.size()); CHECK(cameraIds.size() > 0); mRequiredProfileRefs = new RequiredProfiles[cameraIds.size()]; for (size_t i = 0, n = cameraIds.size(); i < n; ++i) { @@ -602,14 +602,14 @@ void MediaProfiles::checkAndAddRequiredProfilesIfNecessary() { int index = getCamcorderProfileIndex(cameraId, profile->mQuality); if (index != -1) { - ALOGV("Profile quality %d for camera %d already exists", + ALOGV("Profile quality %d for camera %zu already exists", profile->mQuality, cameraId); CHECK(index == refIndex); continue; } // Insert the new profile - ALOGV("Add a profile: quality %d=>%d for camera %d", + ALOGV("Add a profile: quality %d=>%d for camera %zu", mCamcorderProfiles[info->mRefProfileIndex]->mQuality, profile->mQuality, cameraId); diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index a55e09c..2aa0592 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -16,6 +16,9 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "SoundPool" + +#include + #include #define USE_SHARED_MEM_BUFFER @@ -212,7 +215,7 @@ int SoundPool::load(const char* path, int priority __unused) int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused) { - ALOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d", + ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d", fd, offset, length, priority); Mutex::Autolock lock(&mLock); sp sample = new Sample(++mNextSampleID, fd, offset, length); @@ -462,7 +465,8 @@ Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length) mFd = dup(fd); mOffset = offset; mLength = length; - ALOGV("create sampleID=%d, fd=%d, offset=%lld, length=%lld", mSampleID, mFd, mLength, mOffset); + ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64, + mSampleID, mFd, mLength, mOffset); } void Sample::init() @@ -516,7 +520,7 @@ status_t Sample::doLoad() ALOGE("Unable to load sample: %s", mUrl); goto error; } - ALOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d", + ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d", mHeap->getBase(), mSize, sampleRate, numChannels); if (sampleRate > kMaxSampleRate) { diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp index 1d6bb6f..39a239d 100644 --- a/media/libmedia/mediametadataretriever.cpp +++ b/media/libmedia/mediametadataretriever.cpp @@ -18,6 +18,8 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaMetadataRetriever" +#include + #include #include #include @@ -114,7 +116,7 @@ status_t MediaMetadataRetriever::setDataSource( status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) { - ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); + ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); Mutex::Autolock _l(mLock); if (mRetriever == 0) { ALOGE("retriever is not initialized"); @@ -129,7 +131,7 @@ status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t l sp MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option) { - ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option); + ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d)", timeUs, option); Mutex::Autolock _l(mLock); if (mRetriever == 0) { ALOGE("retriever is not initialized"); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 0be01a9..406f9f2 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -17,12 +17,14 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaPlayer" -#include -#include +#include +#include #include +#include #include -#include + +#include #include #include @@ -157,7 +159,7 @@ status_t MediaPlayer::setDataSource( status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) { - ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); + ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); status_t err = UNKNOWN_ERROR; const sp& service(getMediaPlayerService()); if (service != 0) { @@ -194,7 +196,7 @@ status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply) (mCurrentState != MEDIA_PLAYER_STATE_ERROR) && ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE); if ((mPlayer != NULL) && hasBeenInitialized) { - ALOGV("invoke %d", request.dataSize()); + ALOGV("invoke %zu", request.dataSize()); return mPlayer->invoke(request, reply); } ALOGE("invoke failed: wrong state %X", mCurrentState); @@ -818,7 +820,7 @@ void MediaPlayer::died() audio_format_t* pFormat, const sp& heap, size_t *pSize) { - ALOGV("decode(%d, %lld, %lld)", fd, offset, length); + ALOGV("decode(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); status_t status; const sp& service = getMediaPlayerService(); if (service != 0) { diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 3710e46..c8192e9 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -17,6 +17,9 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaRecorder" + +#include + #include #include #include @@ -286,7 +289,7 @@ status_t MediaRecorder::setOutputFile(const char* path) status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { - ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); if (mMediaRecorder == NULL) { ALOGE("media recorder is not initialized yet"); return INVALID_OPERATION; -- cgit v1.1 From d9d7fa0873796ac661c44a7fcd6ad5ff697ff01f Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 24 Jun 2014 08:01:46 -0700 Subject: Support for audio attributes on audio output of media player Change-Id: Iae4995c98e64add1ab9e6c8ae6501515032755f5 --- media/libmedia/AudioTrack.cpp | 12 +++++++----- media/libmedia/mediaplayer.cpp | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 898d58d..b5c9125 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -124,7 +124,8 @@ AudioTrack::AudioTrack( transfer_type transferType, const audio_offload_info_t *offloadInfo, int uid, - pid_t pid) + pid_t pid, + const audio_attributes_t* pAttributes) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -134,7 +135,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, - offloadInfo, uid, pid, NULL /*no audio attributes*/); + offloadInfo, uid, pid, pAttributes); } AudioTrack::AudioTrack( @@ -151,7 +152,8 @@ AudioTrack::AudioTrack( transfer_type transferType, const audio_offload_info_t *offloadInfo, int uid, - pid_t pid) + pid_t pid, + const audio_attributes_t* pAttributes) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -161,7 +163,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, - uid, pid, NULL /*no audio attributes*/); + uid, pid, pAttributes); } AudioTrack::~AudioTrack() @@ -205,7 +207,7 @@ status_t AudioTrack::set( const audio_offload_info_t *offloadInfo, int uid, pid_t pid, - audio_attributes_t* pAttributes) + const audio_attributes_t* pAttributes) { ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "flags #%x, notificationFrames %u, sessionId %d, transferType %d", diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 406f9f2..889bd7f 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -624,10 +624,32 @@ status_t MediaPlayer::attachAuxEffect(int effectId) return mPlayer->attachAuxEffect(effectId); } +// always call with lock held +status_t MediaPlayer::checkStateForKeySet_l(int key) +{ + switch(key) { + case KEY_PARAMETER_AUDIO_ATTRIBUTES: + if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | + MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) { + // Can't change the audio attributes after prepare + ALOGE("trying to set audio attributes called in state %d", mCurrentState); + return INVALID_OPERATION; + } + break; + default: + // parameter doesn't require player state check + break; + } + return OK; +} + status_t MediaPlayer::setParameter(int key, const Parcel& request) { ALOGV("MediaPlayer::setParameter(%d)", key); Mutex::Autolock _l(mLock); + if (checkStateForKeySet_l(key) != OK) { + return INVALID_OPERATION; + } if (mPlayer != NULL) { return mPlayer->setParameter(key, request); } -- cgit v1.1 From 7df8c0b799d8f52d6386e03313286dbd7d5cdc7c Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 3 Jul 2014 12:23:29 -0700 Subject: IAudioFlinger::openRecord now suggests notificationFrames Change-Id: I08885cc381d03c522a23289e74f0e1ed46563863 --- media/libmedia/AudioRecord.cpp | 5 +++++ media/libmedia/IAudioFlinger.cpp | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index f865d38..3ee5809 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -495,6 +495,10 @@ status_t AudioRecord::openRecord_l(size_t epoch) size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also int originalSessionId = mSessionId; + + // The notification frame count is the period between callbacks, as suggested by the server. + size_t notificationFrames; + sp iMem; // for cblk sp bufferMem; sp record = audioFlinger->openRecord(input, @@ -504,6 +508,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) &trackFlags, tid, &mSessionId, + ¬ificationFrames, iMem, bufferMem, &status); diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 687fa76..5cf42f7 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -175,6 +175,7 @@ public: track_flags_t *flags, pid_t tid, int *sessionId, + size_t *notificationFrames, sp& cblk, sp& buffers, status_t *status) @@ -214,6 +215,10 @@ public: if (sessionId != NULL) { *sessionId = lSessionId; } + size_t lNotificationFrames = (size_t) reply.readInt64(); + if (notificationFrames != NULL) { + *notificationFrames = lNotificationFrames; + } lStatus = reply.readInt32(); record = interface_cast(reply.readStrongBinder()); cblk = interface_cast(reply.readStrongBinder()); @@ -959,16 +964,19 @@ status_t BnAudioFlinger::onTransact( track_flags_t flags = (track_flags_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); + size_t notificationFrames = 0; sp cblk; sp buffers; status_t status; sp record = openRecord(input, sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, + ¬ificationFrames, cblk, buffers, &status); LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR)); reply->writeInt64(frameCount); reply->writeInt32(flags); reply->writeInt32(sessionId); + reply->writeInt64(notificationFrames); reply->writeInt32(status); reply->writeStrongBinder(record->asBinder()); reply->writeStrongBinder(cblk->asBinder()); -- cgit v1.1 From ec40d284218466d8f0e832e7eb88e6ea6c479c88 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 15 Jul 2014 15:31:26 -0700 Subject: Add audio_input_flags_t to IAudioFlinger::openInput For backward compatibility, until flags are correctly calculated, we will assume that the request is for a low latency input stream. Change-Id: I76746834e870df00833dc77cbdaa2edd2ffeec95 --- media/libmedia/IAudioFlinger.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 5cf42f7..7795fdb 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -532,7 +532,8 @@ public: audio_devices_t *pDevices, uint32_t *pSamplingRate, audio_format_t *pFormat, - audio_channel_mask_t *pChannelMask) + audio_channel_mask_t *pChannelMask, + audio_input_flags_t flags) { Parcel data, reply; audio_devices_t devices = pDevices != NULL ? *pDevices : AUDIO_DEVICE_NONE; @@ -547,6 +548,7 @@ public: data.writeInt32(samplingRate); data.writeInt32(format); data.writeInt32(channelMask); + data.writeInt32(flags); remote()->transact(OPEN_INPUT, data, &reply); audio_io_handle_t input = (audio_io_handle_t) reply.readInt32(); devices = (audio_devices_t)reply.readInt32(); @@ -1157,12 +1159,14 @@ status_t BnAudioFlinger::onTransact( uint32_t samplingRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = (audio_channel_mask_t)data.readInt32(); + audio_input_flags_t flags = (audio_input_flags_t) data.readInt32(); audio_io_handle_t input = openInput(module, &devices, &samplingRate, &format, - &channelMask); + &channelMask, + flags); reply->writeInt32((int32_t) input); reply->writeInt32(devices); reply->writeInt32(samplingRate); -- cgit v1.1 From b3b1660ecb67f61f9da54efced8677fa3a6f4863 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 16 Jul 2014 08:36:31 -0700 Subject: Add audio_input_flags_t to IAudioPolicyService::getInput Change-Id: I9f37be05f8dc7b85a8827a94e76ca0f45453e170 --- media/libmedia/AudioRecord.cpp | 6 +++--- media/libmedia/AudioSystem.cpp | 5 +++-- media/libmedia/IAudioPolicyService.cpp | 8 ++++++-- 3 files changed, 12 insertions(+), 7 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 3ee5809..c474a25 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -481,11 +481,11 @@ status_t AudioRecord::openRecord_l(size_t epoch) } audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat, - mChannelMask, mSessionId); + mChannelMask, mSessionId, mFlags); if (input == AUDIO_IO_HANDLE_NONE) { ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " - "channel mask %#x, session %d", - mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId); + "channel mask %#x, session %d, flags %#x", + mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags); return BAD_VALUE; } { diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index a47d45c..fd5824b 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -688,11 +688,12 @@ audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int sessionId) + int sessionId, + audio_input_flags_t flags) { const sp& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return 0; - return aps->getInput(inputSource, samplingRate, format, channelMask, sessionId); + return aps->getInput(inputSource, samplingRate, format, channelMask, sessionId, flags); } status_t AudioSystem::startInput(audio_io_handle_t input) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 41a9065..40dfb58 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -225,7 +225,8 @@ public: uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int audioSession) + int audioSession, + audio_input_flags_t flags) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); @@ -234,6 +235,7 @@ public: data.writeInt32(static_cast (format)); data.writeInt32(channelMask); data.writeInt32(audioSession); + data.writeInt32(flags); remote()->transact(GET_INPUT, data, &reply); return static_cast (reply.readInt32()); } @@ -707,11 +709,13 @@ status_t BnAudioPolicyService::onTransact( audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); int audioSession = data.readInt32(); + audio_input_flags_t flags = (audio_input_flags_t) data.readInt32(); audio_io_handle_t input = getInput(inputSource, samplingRate, format, channelMask, - audioSession); + audioSession, + flags); reply->writeInt32(static_cast (input)); return NO_ERROR; } break; -- cgit v1.1 From 7410591dad836434c72ddee66680802708b70c10 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 3 Jul 2014 12:28:53 -0700 Subject: Move AudioRecord frame count calculations to server Buffer frame count and notification frame count are now calculated by server instead of by client. The server has more information and can do a better job. Also fix a few bugs: - If a fast track was re-created, even with same pipe depth, it would fail. Now it can correctly re-create a fast track provided the pipe depth is same. - Notification frame count for fast tracks was calculated by client as 1/2 of the total frame count, which is a large value due to the pipe. Now the notification frame count is set by server to the HAL frame count. This should reduce latency for fast tracks. - EVENT_OVERRUN were happening frequently when there was sample rate conversion, because the client didn't know about the sample rate conversion, and under-estimated the necessary buffer size. Now since server calculates the buffer sizes, EVENT_OVERRUN is unlikely. - RecordThread::createRecordTrack_l was checking for mono and stereo for fast tracks. This is not necessary, and now we can handle a multi-channel fast track. Bug: 7498763 Change-Id: I0c581618e8db33084d5ff9ed50a592990c9749e8 --- media/libmedia/AudioRecord.cpp | 53 +++++++--------------------------------- media/libmedia/IAudioFlinger.cpp | 3 ++- 2 files changed, 11 insertions(+), 45 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index c474a25..80c8c5e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -211,7 +211,7 @@ status_t AudioRecord::set( mReqFrameCount = frameCount; mNotificationFramesReq = notificationFrames; - mNotificationFramesAct = 0; + // mNotificationFramesAct is initialized in openRecord_l if (sessionId == AUDIO_SESSION_ALLOCATE) { mSessionId = AudioSystem::newAudioSessionId(); @@ -444,42 +444,6 @@ status_t AudioRecord::openRecord_l(size_t epoch) } } - // FIXME Assume double buffering, because we don't know the true HAL sample rate - const uint32_t nBuffering = 2; - - mNotificationFramesAct = mNotificationFramesReq; - size_t frameCount = mReqFrameCount; - - if (!(mFlags & AUDIO_INPUT_FLAG_FAST)) { - // validate framecount - // If fast track was not requested, this preserves - // the old behavior of validating on client side. - // FIXME Eventually the validation should be done on server side - // regardless of whether it's a fast or normal track. It's debatable - // whether to account for the input latency to provision buffers appropriately. - size_t minFrameCount; - status = AudioRecord::getMinFrameCount(&minFrameCount, - mSampleRate, mFormat, mChannelMask); - if (status != NO_ERROR) { - ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; " - "status %d", - mSampleRate, mFormat, mChannelMask, status); - return status; - } - - if (frameCount == 0) { - frameCount = minFrameCount; - } else if (frameCount < minFrameCount) { - ALOGE("frameCount %zu < minFrameCount %zu", frameCount, minFrameCount); - return BAD_VALUE; - } - - // Make sure that application is notified with sufficient margin before overrun - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) { - mNotificationFramesAct = frameCount/2; - } - } - audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags); if (input == AUDIO_IO_HANDLE_NONE) { @@ -492,12 +456,13 @@ status_t AudioRecord::openRecord_l(size_t epoch) // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, // we must release it ourselves if anything goes wrong. + size_t frameCount = mReqFrameCount; size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also int originalSessionId = mSessionId; // The notification frame count is the period between callbacks, as suggested by the server. - size_t notificationFrames; + size_t notificationFrames = mNotificationFramesReq; sp iMem; // for cblk sp bufferMem; @@ -576,14 +541,14 @@ status_t AudioRecord::openRecord_l(size_t epoch) // once denied, do not request again if IAudioRecord is re-created mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); } - // Theoretically double-buffering is not required for fast tracks, - // due to tighter scheduling. But in practice, to accomodate kernels with - // scheduling jitter, and apps with computation jitter, we use double-buffering. - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { - mNotificationFramesAct = frameCount/nBuffering; - } } + // Make sure that application is notified with sufficient margin before overrun + if (notificationFrames == 0 || notificationFrames > frameCount) { + ALOGW("Received notificationFrames %zu for frameCount %zu", notificationFrames, frameCount); + } + mNotificationFramesAct = notificationFrames; + // We retain a copy of the I/O handle, but don't own the reference mInput = input; mRefreshRemaining = true; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 7795fdb..bd7ea46 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -197,6 +197,7 @@ public: lSessionId = *sessionId; } data.writeInt32(lSessionId); + data.writeInt64(notificationFrames != NULL ? *notificationFrames : 0); cblk.clear(); buffers.clear(); status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply); @@ -966,7 +967,7 @@ status_t BnAudioFlinger::onTransact( track_flags_t flags = (track_flags_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); - size_t notificationFrames = 0; + size_t notificationFrames = data.readInt64(); sp cblk; sp buffers; status_t status; -- cgit v1.1 From df813a3ba59109ca519ce0cb00a1a9144074f40e Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Sun, 20 Jul 2014 17:58:33 -0700 Subject: audio_attributes_t for SoundPool Add support for the audio_attributes_t structure in the SoundPoool constructor. Remove SRC quality which was never implemented. Remove stream types. Add file to contain audio helper functions related to policy. Change-Id: I1720ff15e7b23ea7b713a4395fdfac26dc3fd4da --- media/libmedia/SoundPool.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 2aa0592..d2e381b 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -28,6 +28,7 @@ #include #include #include "SoundPoolThread.h" +#include namespace android { @@ -39,10 +40,10 @@ uint32_t kDefaultFrameCount = 1200; size_t kDefaultHeapSize = 1024 * 1024; // 1MB -SoundPool::SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQuality) +SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes) { - ALOGV("SoundPool constructor: maxChannels=%d, streamType=%d, srcQuality=%d", - maxChannels, streamType, srcQuality); + ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s", + maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags); // check limits mMaxChannels = maxChannels; @@ -56,8 +57,7 @@ SoundPool::SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQua mQuit = false; mDecodeThread = 0; - mStreamType = streamType; - mSrcQuality = srcQuality; + memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); mAllocated = 0; mNextSampleID = 0; mNextChannelID = 0; @@ -580,7 +580,7 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV // initialize track size_t afFrameCount; uint32_t afSampleRate; - audio_stream_type_t streamType = mSoundPool->streamType(); + audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes()); if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { afFrameCount = kDefaultFrameCount; } -- cgit v1.1 From 114819633470ebd5b346c13c2a82a0025d2d39c0 Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Wed, 9 Jul 2014 20:09:43 -0700 Subject: StagefrightRecorder: webm (video only) support Bug: 16329805 Change-Id: I8a0ecd100fca397add97a1416125bcc6aeb86364 --- media/libmedia/mediarecorder.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index c8192e9..1952b86 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -186,8 +186,11 @@ status_t MediaRecorder::setOutputFormat(int of) ALOGE("setOutputFormat called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } - if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP && of != OUTPUT_FORMAT_MPEG2TS) { //first non-video output format - ALOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); + if (mIsVideoSourceSet + && of >= OUTPUT_FORMAT_AUDIO_ONLY_START //first non-video output format + && of < OUTPUT_FORMAT_AUDIO_ONLY_END) { + ALOGE("output format (%d) is meant for audio recording only" + " and incompatible with video recording", of); return INVALID_OPERATION; } -- cgit v1.1 From d88adb96ec867ed1b629c434f87514d2fabaf5e9 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Wed, 23 Jul 2014 11:43:46 -0700 Subject: NuPlayer: save thread id in MediaPlayer::start so that when MediaPlayer::notify is called from within start, it doesn't try to lock itself again. Bug: 15323063 Change-Id: Idd77e892cd22538bbfe3e65c64c9dd2a216a0aee --- media/libmedia/mediaplayer.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 889bd7f..2b7ea97 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -283,16 +283,21 @@ status_t MediaPlayer::prepareAsync() status_t MediaPlayer::start() { ALOGV("start"); + + status_t ret = NO_ERROR; Mutex::Autolock _l(mLock); - if (mCurrentState & MEDIA_PLAYER_STARTED) - return NO_ERROR; - if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | + + mLockThreadId = getThreadId(); + + if (mCurrentState & MEDIA_PLAYER_STARTED) { + ret = NO_ERROR; + } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { mPlayer->setLooping(mLoop); mPlayer->setVolume(mLeftVolume, mRightVolume); mPlayer->setAuxEffectSendLevel(mSendLevel); mCurrentState = MEDIA_PLAYER_STARTED; - status_t ret = mPlayer->start(); + ret = mPlayer->start(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; } else { @@ -300,10 +305,14 @@ status_t MediaPlayer::start() ALOGV("playback completed immediately following start()"); } } - return ret; + } else { + ALOGE("start called in state %d", mCurrentState); + ret = INVALID_OPERATION; } - ALOGE("start called in state %d", mCurrentState); - return INVALID_OPERATION; + + mLockThreadId = 0; + + return ret; } status_t MediaPlayer::stop() @@ -706,8 +715,8 @@ void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) // running in the same process as the media server. In that case, // this will deadlock. // - // The threadId hack below works around this for the care of prepare - // and seekTo within the same process. + // The threadId hack below works around this for the care of prepare, + // seekTo and start within the same process. // FIXME: Remember, this is a hack, it's not even a hack that is applied // consistently for all use-cases, this needs to be revisited. if (mLockThreadId != getThreadId()) { -- cgit v1.1 From e07909715b44cc56df723750af93f0608210f94d Mon Sep 17 00:00:00 2001 From: Zhijun He Date: Wed, 23 Jul 2014 15:17:26 -0700 Subject: CamcorderProfiles: add high speed profile constants Change-Id: I8f783466f8c2560820db14488acc1a309d27ab0f --- media/libmedia/MediaProfiles.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index e9e453b..d2e181b 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -81,6 +81,12 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P}, {"timelapse2160p", CAMCORDER_QUALITY_TIME_LAPSE_2160P}, {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA}, + + {"highspeedlow", CAMCORDER_QUALITY_HIGH_SPEED_LOW}, + {"highspeedhigh", CAMCORDER_QUALITY_HIGH_SPEED_HIGH}, + {"highspeed480p", CAMCORDER_QUALITY_HIGH_SPEED_480P}, + {"highspeed720p", CAMCORDER_QUALITY_HIGH_SPEED_720P}, + {"highspeed1080p", CAMCORDER_QUALITY_HIGH_SPEED_1080P}, }; #if LOG_NDEBUG @@ -474,6 +480,11 @@ static bool isTimelapseProfile(camcorder_quality quality) { quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END; } +static bool isHighSpeedProfile(camcorder_quality quality) { + return quality >= CAMCORDER_QUALITY_HIGH_SPEED_LIST_START && + quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END; +} + void MediaProfiles::initRequiredProfileRefs(const Vector& cameraIds) { ALOGV("Number of camera ids: %zu", cameraIds.size()); CHECK(cameraIds.size() > 0); @@ -521,14 +532,17 @@ void MediaProfiles::checkAndAddRequiredProfilesIfNecessary() { camcorder_quality refQuality; VideoCodec *codec = NULL; - // Check high and low from either camcorder profile or timelapse profile - // but not both. Default, check camcorder profile + // Check high and low from either camcorder profile, timelapse profile + // or high speed profile, but not all of them. Default, check camcorder profile size_t j = 0; size_t o = 2; if (isTimelapseProfile(quality)) { // Check timelapse profile instead. j = 2; o = kNumRequiredProfiles; + } else if (isHighSpeedProfile(quality)) { + // Skip the check for high speed profile. + continue; } else { // Must be camcorder profile. CHECK(isCamcorderProfile(quality)); -- cgit v1.1 From cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bf Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 25 Jul 2014 16:20:43 -0700 Subject: AudioFlinger: update openInput() and openOutput() Add parameters to openInput() and openOutput(): device address, input source. Allow caller to specify a given I/O handle Group parameters in a struct audio_config. Bug: 12378680. Change-Id: I7e9af74c0d996561cc13cbee7d9012d2daf33025 --- media/libmedia/IAudioFlinger.cpp | 201 ++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 119 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index bd7ea46..0f4e632 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -434,61 +434,40 @@ public: return reply.readInt64(); } - virtual audio_io_handle_t openOutput(audio_module_handle_t module, - audio_devices_t *pDevices, - uint32_t *pSamplingRate, - audio_format_t *pFormat, - audio_channel_mask_t *pChannelMask, - uint32_t *pLatencyMs, - audio_output_flags_t flags, - const audio_offload_info_t *offloadInfo) + virtual status_t openOutput(audio_module_handle_t module, + audio_io_handle_t *output, + audio_config_t *config, + audio_devices_t *devices, + const String8& address, + uint32_t *latencyMs, + audio_output_flags_t flags) { + if (output == NULL || config == NULL || devices == NULL || latencyMs == NULL) { + return BAD_VALUE; + } Parcel data, reply; - audio_devices_t devices = pDevices != NULL ? *pDevices : AUDIO_DEVICE_NONE; - uint32_t samplingRate = pSamplingRate != NULL ? *pSamplingRate : 0; - audio_format_t format = pFormat != NULL ? *pFormat : AUDIO_FORMAT_DEFAULT; - audio_channel_mask_t channelMask = pChannelMask != NULL ? - *pChannelMask : (audio_channel_mask_t)0; - uint32_t latency = pLatencyMs != NULL ? *pLatencyMs : 0; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(module); - data.writeInt32(devices); - data.writeInt32(samplingRate); - data.writeInt32(format); - data.writeInt32(channelMask); - data.writeInt32(latency); + data.write(config, sizeof(audio_config_t)); + data.writeInt32(*devices); + data.writeString8(address); data.writeInt32((int32_t) flags); - // hasOffloadInfo - if (offloadInfo == NULL) { - data.writeInt32(0); - } else { - data.writeInt32(1); - data.write(offloadInfo, sizeof(audio_offload_info_t)); - } - remote()->transact(OPEN_OUTPUT, data, &reply); - audio_io_handle_t output = (audio_io_handle_t) reply.readInt32(); - ALOGV("openOutput() returned output, %d", output); - devices = (audio_devices_t)reply.readInt32(); - if (pDevices != NULL) { - *pDevices = devices; - } - samplingRate = reply.readInt32(); - if (pSamplingRate != NULL) { - *pSamplingRate = samplingRate; - } - format = (audio_format_t) reply.readInt32(); - if (pFormat != NULL) { - *pFormat = format; - } - channelMask = (audio_channel_mask_t)reply.readInt32(); - if (pChannelMask != NULL) { - *pChannelMask = channelMask; + status_t status = remote()->transact(OPEN_OUTPUT, data, &reply); + if (status != NO_ERROR) { + *output = AUDIO_IO_HANDLE_NONE; + return status; } - latency = reply.readInt32(); - if (pLatencyMs != NULL) { - *pLatencyMs = latency; + status = (status_t)reply.readInt32(); + if (status != NO_ERROR) { + *output = AUDIO_IO_HANDLE_NONE; + return status; } - return output; + *output = (audio_io_handle_t)reply.readInt32(); + ALOGV("openOutput() returned output, %d", *output); + reply.read(config, sizeof(audio_config_t)); + *devices = (audio_devices_t)reply.readInt32(); + *latencyMs = reply.readInt32(); + return NO_ERROR; } virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, @@ -529,46 +508,40 @@ public: return reply.readInt32(); } - virtual audio_io_handle_t openInput(audio_module_handle_t module, - audio_devices_t *pDevices, - uint32_t *pSamplingRate, - audio_format_t *pFormat, - audio_channel_mask_t *pChannelMask, - audio_input_flags_t flags) + virtual status_t openInput(audio_module_handle_t module, + audio_io_handle_t *input, + audio_config_t *config, + audio_devices_t *device, + const String8& address, + audio_source_t source, + audio_input_flags_t flags) { + if (input == NULL || config == NULL || device == NULL) { + return BAD_VALUE; + } Parcel data, reply; - audio_devices_t devices = pDevices != NULL ? *pDevices : AUDIO_DEVICE_NONE; - uint32_t samplingRate = pSamplingRate != NULL ? *pSamplingRate : 0; - audio_format_t format = pFormat != NULL ? *pFormat : AUDIO_FORMAT_DEFAULT; - audio_channel_mask_t channelMask = pChannelMask != NULL ? - *pChannelMask : (audio_channel_mask_t)0; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(module); - data.writeInt32(devices); - data.writeInt32(samplingRate); - data.writeInt32(format); - data.writeInt32(channelMask); + data.writeInt32(*input); + data.write(config, sizeof(audio_config_t)); + data.writeInt32(*device); + data.writeString8(address); + data.writeInt32(source); data.writeInt32(flags); - remote()->transact(OPEN_INPUT, data, &reply); - audio_io_handle_t input = (audio_io_handle_t) reply.readInt32(); - devices = (audio_devices_t)reply.readInt32(); - if (pDevices != NULL) { - *pDevices = devices; - } - samplingRate = reply.readInt32(); - if (pSamplingRate != NULL) { - *pSamplingRate = samplingRate; - } - format = (audio_format_t) reply.readInt32(); - if (pFormat != NULL) { - *pFormat = format; + status_t status = remote()->transact(OPEN_INPUT, data, &reply); + if (status != NO_ERROR) { + *input = AUDIO_IO_HANDLE_NONE; + return status; } - channelMask = (audio_channel_mask_t)reply.readInt32(); - if (pChannelMask != NULL) { - *pChannelMask = channelMask; + status = (status_t)reply.readInt32(); + if (status != NO_ERROR) { + *input = AUDIO_IO_HANDLE_NONE; + return status; } - return input; + *input = (audio_io_handle_t)reply.readInt32(); + reply.read(config, sizeof(audio_config_t)); + *device = (audio_devices_t)reply.readInt32(); + return NO_ERROR; } virtual status_t closeInput(int input) @@ -1103,32 +1076,23 @@ status_t BnAudioFlinger::onTransact( case OPEN_OUTPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); audio_module_handle_t module = (audio_module_handle_t)data.readInt32(); + audio_config_t config; + data.read(&config, sizeof(audio_config_t)); audio_devices_t devices = (audio_devices_t)data.readInt32(); - uint32_t samplingRate = data.readInt32(); - audio_format_t format = (audio_format_t) data.readInt32(); - audio_channel_mask_t channelMask = (audio_channel_mask_t)data.readInt32(); - uint32_t latency = data.readInt32(); + String8 address(data.readString8()); audio_output_flags_t flags = (audio_output_flags_t) data.readInt32(); - bool hasOffloadInfo = data.readInt32() != 0; - audio_offload_info_t offloadInfo; - if (hasOffloadInfo) { - data.read(&offloadInfo, sizeof(audio_offload_info_t)); - } - audio_io_handle_t output = openOutput(module, - &devices, - &samplingRate, - &format, - &channelMask, - &latency, - flags, - hasOffloadInfo ? &offloadInfo : NULL); + uint32_t latencyMs; + audio_io_handle_t output; + status_t status = openOutput(module, &output, &config, + &devices, address, &latencyMs, flags); ALOGV("OPEN_OUTPUT output, %d", output); - reply->writeInt32((int32_t) output); - reply->writeInt32(devices); - reply->writeInt32(samplingRate); - reply->writeInt32(format); - reply->writeInt32(channelMask); - reply->writeInt32(latency); + reply->writeInt32((int32_t)status); + if (status == NO_ERROR) { + reply->writeInt32((int32_t)output); + reply->write(&config, sizeof(audio_config_t)); + reply->writeInt32(devices); + reply->writeInt32(latencyMs); + } return NO_ERROR; } break; case OPEN_DUPLICATE_OUTPUT: { @@ -1156,23 +1120,22 @@ status_t BnAudioFlinger::onTransact( case OPEN_INPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); audio_module_handle_t module = (audio_module_handle_t)data.readInt32(); - audio_devices_t devices = (audio_devices_t)data.readInt32(); - uint32_t samplingRate = data.readInt32(); - audio_format_t format = (audio_format_t) data.readInt32(); - audio_channel_mask_t channelMask = (audio_channel_mask_t)data.readInt32(); + audio_io_handle_t input = (audio_io_handle_t)data.readInt32(); + audio_config_t config; + data.read(&config, sizeof(audio_config_t)); + audio_devices_t device = (audio_devices_t)data.readInt32(); + String8 address(data.readString8()); + audio_source_t source = (audio_source_t)data.readInt32(); audio_input_flags_t flags = (audio_input_flags_t) data.readInt32(); - audio_io_handle_t input = openInput(module, - &devices, - &samplingRate, - &format, - &channelMask, - flags); - reply->writeInt32((int32_t) input); - reply->writeInt32(devices); - reply->writeInt32(samplingRate); - reply->writeInt32(format); - reply->writeInt32(channelMask); + status_t status = openInput(module, &input, &config, + &device, address, source, flags); + reply->writeInt32((int32_t) status); + if (status == NO_ERROR) { + reply->writeInt32((int32_t) input); + reply->write(&config, sizeof(audio_config_t)); + reply->writeInt32(device); + } return NO_ERROR; } break; case CLOSE_INPUT: { -- cgit v1.1 From de3f8392fbf380ba6f09d009b00d7172477389a2 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Sun, 27 Jul 2014 18:38:22 -0700 Subject: rename AudioSystem::newAudioSessionId() Rename AudioSystem::newAudioSessionId() to AudioSystem::newAudioUniqueId() as it can be used also for I/O handles. Bug: 12378680. Change-Id: I611ea3b5eb57a4b0774437f477ee87dc4ccc2cc2 --- media/libmedia/AudioRecord.cpp | 2 +- media/libmedia/AudioSystem.cpp | 6 +++--- media/libmedia/IAudioFlinger.cpp | 6 +++--- media/libmedia/mediaplayer.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 80c8c5e..299a77c 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -214,7 +214,7 @@ status_t AudioRecord::set( // mNotificationFramesAct is initialized in openRecord_l if (sessionId == AUDIO_SESSION_ALLOCATE) { - mSessionId = AudioSystem::newAudioSessionId(); + mSessionId = AudioSystem::newAudioUniqueId(); } else { mSessionId = sessionId; } diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index fd5824b..0d61885 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -427,11 +427,11 @@ uint32_t AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) return result; } -int AudioSystem::newAudioSessionId() +audio_unique_id_t AudioSystem::newAudioUniqueId() { const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return AUDIO_SESSION_ALLOCATE; - return af->newAudioSessionId(); + if (af == 0) return AUDIO_UNIQUE_ID_ALLOCATE; + return af->newAudioUniqueId(); } void AudioSystem::acquireAudioSessionId(int audioSession, pid_t pid) diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 0f4e632..5331fce 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -604,12 +604,12 @@ public: return (uint32_t) reply.readInt32(); } - virtual int newAudioSessionId() + virtual audio_unique_id_t newAudioUniqueId() { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply); - int id = AUDIO_SESSION_ALLOCATE; + audio_unique_id_t id = AUDIO_SESSION_ALLOCATE; if (status == NO_ERROR) { id = reply.readInt32(); } @@ -1176,7 +1176,7 @@ status_t BnAudioFlinger::onTransact( } break; case NEW_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32(newAudioSessionId()); + reply->writeInt32(newAudioUniqueId()); return NO_ERROR; } break; case ACQUIRE_AUDIO_SESSION_ID: { diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 2b7ea97..6cd377a 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -59,7 +59,7 @@ MediaPlayer::MediaPlayer() mLeftVolume = mRightVolume = 1.0; mVideoWidth = mVideoHeight = 0; mLockThreadId = 0; - mAudioSessionId = AudioSystem::newAudioSessionId(); + mAudioSessionId = AudioSystem::newAudioUniqueId(); AudioSystem::acquireAudioSessionId(mAudioSessionId, -1); mSendLevel = 0; mRetransmitEndpointValid = false; -- cgit v1.1 From 4dc680607181e6a76f4e91a39366c4f5dfb7b03e Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Mon, 28 Jul 2014 17:26:49 -0700 Subject: audio policy: pass session ID to capture activity methods Indicate the audio session ID when calling getInput(), startInput(), stopInput(), releaseInput(). Bug: 12378680. Change-Id: I763793752f93e2f4e1445a5ab217c895af011038 --- media/libmedia/AudioRecord.cpp | 2 +- media/libmedia/AudioSystem.cpp | 15 +++++++++------ media/libmedia/IAudioPolicyService.cpp | 21 +++++++++++++++------ 3 files changed, 25 insertions(+), 13 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 299a77c..9e7ba88 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -572,7 +572,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) } release: - AudioSystem::releaseInput(input); + AudioSystem::releaseInput(input, (audio_session_t)mSessionId); if (status == NO_ERROR) { status = NO_INIT; } diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 0d61885..365a594 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -696,25 +696,28 @@ audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource, return aps->getInput(inputSource, samplingRate, format, channelMask, sessionId, flags); } -status_t AudioSystem::startInput(audio_io_handle_t input) +status_t AudioSystem::startInput(audio_io_handle_t input, + audio_session_t session) { const sp& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - return aps->startInput(input); + return aps->startInput(input, session); } -status_t AudioSystem::stopInput(audio_io_handle_t input) +status_t AudioSystem::stopInput(audio_io_handle_t input, + audio_session_t session) { const sp& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - return aps->stopInput(input); + return aps->stopInput(input, session); } -void AudioSystem::releaseInput(audio_io_handle_t input) +void AudioSystem::releaseInput(audio_io_handle_t input, + audio_session_t session) { const sp& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return; - aps->releaseInput(input); + aps->releaseInput(input, session); } status_t AudioSystem::initStreamVolume(audio_stream_type_t stream, diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 40dfb58..1593b17 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -240,29 +240,35 @@ public: return static_cast (reply.readInt32()); } - virtual status_t startInput(audio_io_handle_t input) + virtual status_t startInput(audio_io_handle_t input, + audio_session_t session) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(input); + data.writeInt32(session); remote()->transact(START_INPUT, data, &reply); return static_cast (reply.readInt32()); } - virtual status_t stopInput(audio_io_handle_t input) + virtual status_t stopInput(audio_io_handle_t input, + audio_session_t session) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(input); + data.writeInt32(session); remote()->transact(STOP_INPUT, data, &reply); return static_cast (reply.readInt32()); } - virtual void releaseInput(audio_io_handle_t input) + virtual void releaseInput(audio_io_handle_t input, + audio_session_t session) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(input); + data.writeInt32(session); remote()->transact(RELEASE_INPUT, data, &reply); } @@ -723,21 +729,24 @@ status_t BnAudioPolicyService::onTransact( case START_INPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t input = static_cast (data.readInt32()); - reply->writeInt32(static_cast (startInput(input))); + audio_session_t session = static_cast (data.readInt32()); + reply->writeInt32(static_cast (startInput(input, session))); return NO_ERROR; } break; case STOP_INPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t input = static_cast (data.readInt32()); - reply->writeInt32(static_cast (stopInput(input))); + audio_session_t session = static_cast (data.readInt32()); + reply->writeInt32(static_cast (stopInput(input, session))); return NO_ERROR; } break; case RELEASE_INPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t input = static_cast (data.readInt32()); - releaseInput(input); + audio_session_t session = static_cast (data.readInt32()); + releaseInput(input, session); return NO_ERROR; } break; -- cgit v1.1 From 68b15554f6dca3b056eac517fe5fa2fd4ee80a33 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Wed, 30 Apr 2014 10:19:03 -0700 Subject: Allow device to be unprovisioned bug: 12247651 Change-Id: I564ac8de3da2430342a028f4058e2c5ac2d85d5e --- media/libmedia/IDrm.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp index f1a6a9f..1904839 100644 --- a/media/libmedia/IDrm.cpp +++ b/media/libmedia/IDrm.cpp @@ -53,7 +53,8 @@ enum { SIGN, SIGN_RSA, VERIFY, - SET_LISTENER + SET_LISTENER, + UNPROVISION_DEVICE }; struct BpDrm : public BpInterface { @@ -229,6 +230,15 @@ struct BpDrm : public BpInterface { return reply.readInt32(); } + virtual status_t unprovisionDevice() { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + remote()->transact(UNPROVISION_DEVICE, data, &reply); + + return reply.readInt32(); + } + virtual status_t getSecureStops(List > &secureStops) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); @@ -619,6 +629,14 @@ status_t BnDrm::onTransact( return OK; } + case UNPROVISION_DEVICE: + { + CHECK_INTERFACE(IDrm, data, reply); + status_t result = unprovisionDevice(); + reply->writeInt32(result); + return OK; + } + case GET_SECURE_STOPS: { CHECK_INTERFACE(IDrm, data, reply); -- cgit v1.1 From df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Sun, 27 Jul 2014 18:39:40 -0700 Subject: Add sound trigger control by audio policy Audio policy: - Added active capture indication to sound trigger service: recognition stops if concurrent capture is not supported. - Added generation of reserved I/O handle and session ID for utterance capture. Sound trigger service - Added sound model update callback handling. - Added service state callback - Simplified callback shared memory allocation. Bug: 12378680. Change-Id: Ib0292c2733e6df90fdae480633dd9953d0016ef1 --- media/libmedia/AudioSystem.cpp | 15 ++++++++ media/libmedia/IAudioPolicyService.cpp | 67 +++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 365a594..172b056 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -913,6 +913,21 @@ void AudioSystem::setAudioPortCallback(sp callBack) gAudioPortCallback = callBack; } +status_t AudioSystem::acquireSoundTriggerSession(audio_session_t *session, + audio_io_handle_t *ioHandle, + audio_devices_t *device) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->acquireSoundTriggerSession(session, ioHandle, device); +} + +status_t AudioSystem::releaseSoundTriggerSession(audio_session_t session) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->releaseSoundTriggerSession(session); +} // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 1593b17..b57f747 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -65,7 +65,9 @@ enum { LIST_AUDIO_PATCHES, SET_AUDIO_PORT_CONFIG, REGISTER_CLIENT, - GET_OUTPUT_FOR_ATTR + GET_OUTPUT_FOR_ATTR, + ACQUIRE_SOUNDTRIGGER_SESSION, + RELEASE_SOUNDTRIGGER_SESSION }; class BpAudioPolicyService : public BpInterface @@ -563,6 +565,7 @@ public: } return status; } + virtual void registerClient(const sp& client) { Parcel data, reply; @@ -570,6 +573,40 @@ public: data.writeStrongBinder(client->asBinder()); remote()->transact(REGISTER_CLIENT, data, &reply); } + + virtual status_t acquireSoundTriggerSession(audio_session_t *session, + audio_io_handle_t *ioHandle, + audio_devices_t *device) + { + if (session == NULL || ioHandle == NULL || device == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + status_t status = remote()->transact(ACQUIRE_SOUNDTRIGGER_SESSION, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = (status_t)reply.readInt32(); + if (status == NO_ERROR) { + *session = (audio_session_t)reply.readInt32(); + *ioHandle = (audio_io_handle_t)reply.readInt32(); + *device = (audio_devices_t)reply.readInt32(); + } + return status; + } + + virtual status_t releaseSoundTriggerSession(audio_session_t session) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(session); + status_t status = remote()->transact(RELEASE_SOUNDTRIGGER_SESSION, data, &reply); + if (status != NO_ERROR) { + return status; + } + return (status_t)reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -984,6 +1021,7 @@ status_t BnAudioPolicyService::onTransact( reply->writeInt32(status); return NO_ERROR; } + case REGISTER_CLIENT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); sp client = interface_cast( @@ -992,6 +1030,33 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case ACQUIRE_SOUNDTRIGGER_SESSION: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + sp client = interface_cast( + data.readStrongBinder()); + audio_session_t session; + audio_io_handle_t ioHandle; + audio_devices_t device; + status_t status = acquireSoundTriggerSession(&session, &ioHandle, &device); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(session); + reply->writeInt32(ioHandle); + reply->writeInt32(device); + } + return NO_ERROR; + } break; + + case RELEASE_SOUNDTRIGGER_SESSION: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + sp client = interface_cast( + data.readStrongBinder()); + audio_session_t session = (audio_session_t)data.readInt32(); + status_t status = releaseSoundTriggerSession(session); + reply->writeInt32(status); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 93c3d41bdb15e39dac0faea9c5b60f1637cd477c Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 1 Aug 2014 14:48:35 -0700 Subject: AudioSystem: add API to query audio HW sync source Add a method to query from the audio HAL the HW sync source used for a given audio session. Modify audio policy to select a direct output with HW sync when requested. Bug: 16132368. Change-Id: I03038f9188f2d389f8a5fd76a671854013a4513e --- media/libmedia/AudioSystem.cpp | 7 +++++++ media/libmedia/IAudioFlinger.cpp | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 172b056..3486d21 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -450,6 +450,13 @@ void AudioSystem::releaseAudioSessionId(int audioSession, pid_t pid) } } +audio_hw_sync_t AudioSystem::getAudioHwSyncForSession(audio_session_t sessionId) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return AUDIO_HW_SYNC_INVALID; + return af->getAudioHwSyncForSession(sessionId); +} + // --------------------------------------------------------------------------- void AudioSystem::AudioFlingerClient::binderDied(const wp& who __unused) diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 5331fce..346a192 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -79,7 +79,8 @@ enum { CREATE_AUDIO_PATCH, RELEASE_AUDIO_PATCH, LIST_AUDIO_PATCHES, - SET_AUDIO_PORT_CONFIG + SET_AUDIO_PORT_CONFIG, + GET_AUDIO_HW_SYNC }; class BpAudioFlinger : public BpInterface @@ -883,6 +884,17 @@ public: } return status; } + virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(sessionId); + status_t status = remote()->transact(GET_AUDIO_HW_SYNC, data, &reply); + if (status != NO_ERROR) { + return AUDIO_HW_SYNC_INVALID; + } + return (audio_hw_sync_t)reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -1345,6 +1357,11 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32(status); return NO_ERROR; } break; + case GET_AUDIO_HW_SYNC: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32(getAudioHwSyncForSession((audio_session_t)data.readInt32())); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 60b1c0e79d12a1c70758bc8d060156924635f8ba Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Wed, 6 Aug 2014 16:55:46 -0700 Subject: stagefright: rework media codec list and infos This is in preparation of serving the codec list and codec infos from the mediaserver Bug: 11990470 Change-Id: Ib8e2708679c9ce461a4ba179974a740cdcdf2731 --- media/libmedia/Android.mk | 3 + media/libmedia/IMediaCodecList.cpp | 163 ++++++++++++++++++++++++ media/libmedia/MediaCodecInfo.cpp | 252 +++++++++++++++++++++++++++++++++++++ 3 files changed, 418 insertions(+) create mode 100644 media/libmedia/IMediaCodecList.cpp create mode 100644 media/libmedia/MediaCodecInfo.cpp (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index cee26d9..3be0651 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -25,6 +25,7 @@ LOCAL_SRC_FILES:= \ AudioRecord.cpp \ AudioSystem.cpp \ mediaplayer.cpp \ + IMediaCodecList.cpp \ IMediaHTTPConnection.cpp \ IMediaHTTPService.cpp \ IMediaLogService.cpp \ @@ -36,6 +37,7 @@ LOCAL_SRC_FILES:= \ IRemoteDisplay.cpp \ IRemoteDisplayClient.cpp \ IStreamSource.cpp \ + MediaCodecInfo.cpp \ Metadata.cpp \ mediarecorder.cpp \ IMediaMetadataRetriever.cpp \ @@ -74,6 +76,7 @@ LOCAL_MODULE:= libmedia LOCAL_C_INCLUDES := \ $(TOP)/frameworks/native/include/media/openmax \ + $(TOP)/frameworks/av/media/libstagefright \ external/icu/icu4c/source/common \ external/icu/icu4c/source/i18n \ $(call include-path-for, audio-effects) \ diff --git a/media/libmedia/IMediaCodecList.cpp b/media/libmedia/IMediaCodecList.cpp new file mode 100644 index 0000000..bf7c5ca --- /dev/null +++ b/media/libmedia/IMediaCodecList.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2014, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include + +#include // for status_t + +namespace android { + +enum { + CREATE = IBinder::FIRST_CALL_TRANSACTION, + COUNT_CODECS, + GET_CODEC_INFO, + FIND_CODEC_BY_TYPE, + FIND_CODEC_BY_NAME, +}; + +class BpMediaCodecList: public BpInterface +{ +public: + BpMediaCodecList(const sp& impl) + : BpInterface(impl) + { + } + + virtual size_t countCodecs() const + { + Parcel data, reply; + data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); + remote()->transact(COUNT_CODECS, data, &reply); + return static_cast(reply.readInt32()); + } + + virtual sp getCodecInfo(size_t index) const + { + Parcel data, reply; + data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); + data.writeInt32(index); + remote()->transact(GET_CODEC_INFO, data, &reply); + status_t err = reply.readInt32(); + if (err == OK) { + return MediaCodecInfo::FromParcel(reply); + } else { + return NULL; + } + } + + virtual ssize_t findCodecByType( + const char *type, bool encoder, size_t startIndex = 0) const + { + if (startIndex > INT32_MAX) { + return NAME_NOT_FOUND; + } + + Parcel data, reply; + data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); + data.writeCString(type); + data.writeInt32(encoder); + data.writeInt32(startIndex); + remote()->transact(FIND_CODEC_BY_TYPE, data, &reply); + return static_cast(reply.readInt32()); + } + + virtual ssize_t findCodecByName(const char *name) const + { + Parcel data, reply; + data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); + data.writeCString(name); + remote()->transact(FIND_CODEC_BY_NAME, data, &reply); + return static_cast(reply.readInt32()); + } +}; + +IMPLEMENT_META_INTERFACE(MediaCodecList, "android.media.IMediaCodecList"); + +// ---------------------------------------------------------------------- + +status_t BnMediaCodecList::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case COUNT_CODECS: + { + CHECK_INTERFACE(IMediaCodecList, data, reply); + size_t count = countCodecs(); + if (count > INT32_MAX) { + count = INT32_MAX; + } + reply->writeInt32(count); + return NO_ERROR; + } + break; + + case GET_CODEC_INFO: + { + CHECK_INTERFACE(IMediaCodecList, data, reply); + size_t index = static_cast(data.readInt32()); + const sp info = getCodecInfo(index); + if (info != NULL) { + reply->writeInt32(OK); + info->writeToParcel(reply); + } else { + reply->writeInt32(-ERANGE); + } + return NO_ERROR; + } + break; + + case FIND_CODEC_BY_TYPE: + { + CHECK_INTERFACE(IMediaCodecList, data, reply); + const char *type = data.readCString(); + bool isEncoder = static_cast(data.readInt32()); + size_t startIndex = static_cast(data.readInt32()); + ssize_t index = findCodecByType(type, isEncoder, startIndex); + if (index > INT32_MAX || index < 0) { + index = NAME_NOT_FOUND; + } + reply->writeInt32(index); + return NO_ERROR; + } + break; + + case FIND_CODEC_BY_NAME: + { + CHECK_INTERFACE(IMediaCodecList, data, reply); + const char *name = data.readCString(); + ssize_t index = findCodecByName(name); + if (index > INT32_MAX || index < 0) { + index = NAME_NOT_FOUND; + } + reply->writeInt32(index); + return NO_ERROR; + } + break; + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp new file mode 100644 index 0000000..7900eae --- /dev/null +++ b/media/libmedia/MediaCodecInfo.cpp @@ -0,0 +1,252 @@ +/* + * Copyright 2014, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "MediaCodecInfo" +#include + +#include + +#include + +#include +#include +#include + +#include + +namespace android { + +void MediaCodecInfo::Capabilities::getSupportedProfileLevels( + Vector *profileLevels) const { + profileLevels->clear(); + profileLevels->appendVector(mProfileLevels); +} + +void MediaCodecInfo::Capabilities::getSupportedColorFormats( + Vector *colorFormats) const { + colorFormats->clear(); + colorFormats->appendVector(mColorFormats); +} + +uint32_t MediaCodecInfo::Capabilities::getFlags() const { + return mFlags; +} + +const sp &MediaCodecInfo::Capabilities::getDetails() const { + return mDetails; +} + +MediaCodecInfo::Capabilities::Capabilities() + : mFlags(0) { + mDetails = new AMessage; +} + +// static +sp MediaCodecInfo::Capabilities::FromParcel( + const Parcel &parcel) { + sp caps = new Capabilities(); + size_t size = static_cast(parcel.readInt32()); + for (size_t i = 0; i < size; i++) { + ProfileLevel profileLevel; + profileLevel.mProfile = static_cast(parcel.readInt32()); + profileLevel.mLevel = static_cast(parcel.readInt32()); + if (caps != NULL) { + caps->mProfileLevels.push_back(profileLevel); + } + } + size = static_cast(parcel.readInt32()); + for (size_t i = 0; i < size; i++) { + uint32_t color = static_cast(parcel.readInt32()); + if (caps != NULL) { + caps->mColorFormats.push_back(color); + } + } + uint32_t flags = static_cast(parcel.readInt32()); + sp details = AMessage::FromParcel(parcel); + if (caps != NULL) { + caps->mFlags = flags; + caps->mDetails = details; + } + return caps; +} + +status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const { + CHECK_LE(mProfileLevels.size(), INT32_MAX); + parcel->writeInt32(mProfileLevels.size()); + for (size_t i = 0; i < mProfileLevels.size(); i++) { + parcel->writeInt32(mProfileLevels.itemAt(i).mProfile); + parcel->writeInt32(mProfileLevels.itemAt(i).mLevel); + } + CHECK_LE(mColorFormats.size(), INT32_MAX); + parcel->writeInt32(mColorFormats.size()); + for (size_t i = 0; i < mColorFormats.size(); i++) { + parcel->writeInt32(mColorFormats.itemAt(i)); + } + parcel->writeInt32(mFlags); + mDetails->writeToParcel(parcel); + return OK; +} + +bool MediaCodecInfo::isEncoder() const { + return mIsEncoder; +} + +bool MediaCodecInfo::hasQuirk(const char *name) const { + for (size_t ix = 0; ix < mQuirks.size(); ix++) { + if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) { + return true; + } + } + return false; +} + +void MediaCodecInfo::getSupportedMimes(Vector *mimes) const { + mimes->clear(); + for (size_t ix = 0; ix < mCaps.size(); ix++) { + mimes->push_back(mCaps.keyAt(ix)); + } +} + +const sp & +MediaCodecInfo::getCapabilitiesFor(const char *mime) const { + ssize_t ix = getCapabilityIndex(mime); + if (ix >= 0) { + return mCaps.valueAt(ix); + } + return NULL; +} + +const char *MediaCodecInfo::getCodecName() const { + return mName.c_str(); +} + +// static +sp MediaCodecInfo::FromParcel(const Parcel &parcel) { + AString name = AString::FromParcel(parcel); + bool isEncoder = static_cast(parcel.readInt32()); + sp info = new MediaCodecInfo(name, isEncoder, NULL); + size_t size = static_cast(parcel.readInt32()); + for (size_t i = 0; i < size; i++) { + AString quirk = AString::FromParcel(parcel); + if (info != NULL) { + info->mQuirks.push_back(quirk); + } + } + size = static_cast(parcel.readInt32()); + for (size_t i = 0; i < size; i++) { + AString mime = AString::FromParcel(parcel); + sp caps = Capabilities::FromParcel(parcel); + if (info != NULL) { + info->mCaps.add(mime, caps); + } + } + return info; +} + +status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const { + mName.writeToParcel(parcel); + parcel->writeInt32(mIsEncoder); + parcel->writeInt32(mQuirks.size()); + for (size_t i = 0; i < mQuirks.size(); i++) { + mQuirks.itemAt(i).writeToParcel(parcel); + } + parcel->writeInt32(mCaps.size()); + for (size_t i = 0; i < mCaps.size(); i++) { + mCaps.keyAt(i).writeToParcel(parcel); + mCaps.valueAt(i)->writeToParcel(parcel); + } + return OK; +} + +ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const { + for (size_t ix = 0; ix < mCaps.size(); ix++) { + if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) { + return ix; + } + } + return -1; +} + +MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime) + : mName(name), + mIsEncoder(encoder), + mHasSoleMime(false) { + if (mime != NULL) { + addMime(mime); + mHasSoleMime = true; + } +} + +status_t MediaCodecInfo::addMime(const char *mime) { + if (mHasSoleMime) { + ALOGE("Codec '%s' already had its type specified", mName.c_str()); + return -EINVAL; + } + ssize_t ix = getCapabilityIndex(mime); + if (ix >= 0) { + mCurrentCaps = mCaps.valueAt(ix); + } else { + mCurrentCaps = new Capabilities(); + mCaps.add(AString(mime), mCurrentCaps); + } + return OK; +} + +status_t MediaCodecInfo::initializeCapabilities(const CodecCapabilities &caps) { + mCurrentCaps->mProfileLevels.clear(); + mCurrentCaps->mColorFormats.clear(); + + for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) { + const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i); + + ProfileLevel profileLevel; + profileLevel.mProfile = src.mProfile; + profileLevel.mLevel = src.mLevel; + mCurrentCaps->mProfileLevels.push_back(profileLevel); + } + + for (size_t i = 0; i < caps.mColorFormats.size(); ++i) { + mCurrentCaps->mColorFormats.push_back(caps.mColorFormats.itemAt(i)); + } + + mCurrentCaps->mFlags = caps.mFlags; + mCurrentCaps->mDetails = new AMessage; + + return OK; +} + +void MediaCodecInfo::addQuirk(const char *name) { + if (!hasQuirk(name)) { + mQuirks.push(name); + } +} + +void MediaCodecInfo::complete() { + mCurrentCaps = NULL; +} + +void MediaCodecInfo::addDetail(const AString &key, const AString &value) { + mCurrentCaps->mDetails->setString(key.c_str(), value.c_str()); +} + +void MediaCodecInfo::addFeature(const AString &key, int32_t value) { + AString tag = "feature-"; + tag.append(key); + mCurrentCaps->mDetails->setInt32(tag.c_str(), value); +} + +} // namespace android -- cgit v1.1 From 1381d4b5c0385aec3741073e5998773b064c1fb0 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Thu, 7 Aug 2014 15:18:35 -0700 Subject: media/playerservice: add getCodecList() to MediaPlayerService Bug: 11990470 Change-Id: I8fa45946fd9b76f9b975fc59062819c57e6881ef --- media/libmedia/IMediaPlayerService.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index d116b14..2e02d17 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ enum { ADD_BATTERY_DATA, PULL_BATTERY_DATA, LISTEN_FOR_REMOTE_DISPLAY, + GET_CODEC_LIST, }; class BpMediaPlayerService: public BpInterface @@ -191,6 +193,13 @@ public: remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply); return interface_cast(reply.readStrongBinder()); } + + virtual sp getCodecList() const { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + remote()->transact(GET_CODEC_LIST, data, &reply); + return interface_cast(reply.readStrongBinder()); + } }; IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService"); @@ -318,6 +327,12 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(display->asBinder()); return NO_ERROR; } break; + case GET_CODEC_LIST: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + sp mcl = getCodecList(); + reply->writeStrongBinder(mcl->asBinder()); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 5a446aafff3020d607ad6fb14cc7ae76dd8f7947 Mon Sep 17 00:00:00 2001 From: Rachad Date: Tue, 29 Jul 2014 16:47:56 -0700 Subject: Added Tunneled video playback support to ACodec Bug:16132368 Change-Id: I88d2d66b8548fc203f4a2c4797196af15e56ff38 --- media/libmedia/IOMX.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 5df232f..c583d32 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -54,6 +54,7 @@ enum { GET_GRAPHIC_BUFFER_USAGE, SET_INTERNAL_OPTION, UPDATE_GRAPHIC_BUFFER_IN_META, + CONFIGURE_VIDEO_TUNNEL_MODE, }; class BpOMX : public BpInterface { @@ -368,6 +369,25 @@ public: return err; } + virtual status_t configureVideoTunnelMode( + node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, + OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) { + Parcel data, reply; + data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); + data.writeInt32((int32_t)node); + data.writeInt32(portIndex); + data.writeInt32((int32_t)tunneled); + data.writeInt32(audioHwSync); + remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply); + + status_t err = reply.readInt32(); + if (sidebandHandle) { + *sidebandHandle = (native_handle_t *)reply.readNativeHandle(); + } + return err; + } + + virtual status_t allocateBuffer( node_id node, OMX_U32 port_index, size_t size, buffer_id *buffer, void **buffer_data) { @@ -804,6 +824,24 @@ status_t BnOMX::onTransact( return NO_ERROR; } + case CONFIGURE_VIDEO_TUNNEL_MODE: + { + CHECK_OMX_INTERFACE(IOMX, data, reply); + + node_id node = (node_id)data.readInt32(); + OMX_U32 port_index = data.readInt32(); + OMX_BOOL tunneled = (OMX_BOOL)data.readInt32(); + OMX_U32 audio_hw_sync = data.readInt32(); + + native_handle_t *sideband_handle; + status_t err = configureVideoTunnelMode( + node, port_index, tunneled, audio_hw_sync, &sideband_handle); + reply->writeInt32(err); + reply->writeNativeHandle(sideband_handle); + + return NO_ERROR; + } + case ALLOC_BUFFER: { CHECK_OMX_INTERFACE(IOMX, data, reply); -- cgit v1.1 From cd04484f4837b8ca0041d118286ab6a98e84fc75 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Thu, 7 Aug 2014 11:04:34 -0700 Subject: Extend downsampling ratios greater than 2:1 Also improve robustness to choice of sampling rate or buffer size such that increasing either by 10x does not cause overflow. Bug: 12979141 Bug: 15933066 Change-Id: If7989bd745d1bee3bdf811b8b7c978543ccafb65 --- media/libmedia/AudioTrack.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index b5c9125..d87e6f5 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #define WAIT_PERIOD_MS 10 #define WAIT_STREAM_END_TIMEOUT_SEC 120 @@ -82,7 +83,7 @@ status_t AudioTrack::getMinFrameCount( } *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount : - afFrameCount * minBufCount * sampleRate / afSampleRate; + afFrameCount * minBufCount * uint64_t(sampleRate) / afSampleRate; // The formula above should always produce a non-zero value, but return an error // in the unlikely event that it does not, as that's part of the API contract. if (*frameCount == 0) { @@ -646,8 +647,7 @@ status_t AudioTrack::setSampleRate(uint32_t rate) if (AudioSystem::getOutputSamplingRateForAttr(&afSamplingRate, &mAttributes) != NO_ERROR) { return NO_INIT; } - // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (rate == 0 || rate > afSamplingRate*2 ) { + if (rate == 0 || rate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) { return BAD_VALUE; } @@ -1002,7 +1002,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) minBufCount = nBuffering; } - size_t minFrameCount = (afFrameCount*mSampleRate*minBufCount)/afSampleRate; + size_t minFrameCount = afFrameCount * minBufCount * uint64_t(mSampleRate) / afSampleRate; ALOGV("minFrameCount: %zu, afFrameCount=%zu, minBufCount=%d, sampleRate=%u, afSampleRate=%u" ", afLatency=%d", minFrameCount, afFrameCount, minBufCount, mSampleRate, afSampleRate, afLatency); -- cgit v1.1 From 6ff58f04f78886b07c72c0118eb71a78d08f5651 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Mon, 11 Aug 2014 16:46:15 -0700 Subject: MediaCodecList: handle errors gracefully Handle missing OMX codecs, and codecs that do not load. Fix NULL dereference when initializing codec with no type. Bug: 16907578 Bug: 16905025 Change-Id: I5d103db36ebb029d1aab03222bf6e9324beb1566 --- media/libmedia/MediaCodecInfo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp index 7900eae..8f47292 100644 --- a/media/libmedia/MediaCodecInfo.cpp +++ b/media/libmedia/MediaCodecInfo.cpp @@ -206,6 +206,14 @@ status_t MediaCodecInfo::addMime(const char *mime) { return OK; } +void MediaCodecInfo::removeMime(const char *mime) { + ssize_t ix = getCapabilityIndex(mime); + if (ix >= 0) { + mCaps.removeItemsAt(ix); + // mCurrentCaps will be removed when completed + } +} + status_t MediaCodecInfo::initializeCapabilities(const CodecCapabilities &caps) { mCurrentCaps->mProfileLevels.clear(); mCurrentCaps->mColorFormats.clear(); -- cgit v1.1 From 2461e0cf6ae3fe5c9b52ce9e3ac764f4aff5e5eb Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Tue, 12 Aug 2014 08:55:25 -0700 Subject: MediaCodecList: don't return references Bug: 16905025 Change-Id: I5b42b294f0cc785b8e4dda0e82c8f8377a46f487 --- media/libmedia/MediaCodecInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp index 7900eae..5ea0519 100644 --- a/media/libmedia/MediaCodecInfo.cpp +++ b/media/libmedia/MediaCodecInfo.cpp @@ -46,7 +46,7 @@ uint32_t MediaCodecInfo::Capabilities::getFlags() const { return mFlags; } -const sp &MediaCodecInfo::Capabilities::getDetails() const { +const sp MediaCodecInfo::Capabilities::getDetails() const { return mDetails; } @@ -121,7 +121,7 @@ void MediaCodecInfo::getSupportedMimes(Vector *mimes) const { } } -const sp & +const sp MediaCodecInfo::getCapabilitiesFor(const char *mime) const { ssize_t ix = getCapabilityIndex(mime); if (ix >= 0) { -- cgit v1.1 From 732c6d955524ead6c31e6e1bafbd41ea4cee525d Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Thu, 14 Aug 2014 19:54:08 -0700 Subject: stagefright/media: add support for codec features with text value Bug: 11990470 Change-Id: I7600d999c5f4b6821d825d25fa7e8a2bb5a80c46 --- media/libmedia/MediaCodecInfo.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp index 446c582..7b4c4e2 100644 --- a/media/libmedia/MediaCodecInfo.cpp +++ b/media/libmedia/MediaCodecInfo.cpp @@ -257,4 +257,10 @@ void MediaCodecInfo::addFeature(const AString &key, int32_t value) { mCurrentCaps->mDetails->setInt32(tag.c_str(), value); } +void MediaCodecInfo::addFeature(const AString &key, const char *value) { + AString tag = "feature-"; + tag.append(key); + mCurrentCaps->mDetails->setString(tag.c_str(), value); +} + } // namespace android -- cgit v1.1 From a90cff5f7091bfb50c57e2d87bad3fc3f103f397 Mon Sep 17 00:00:00 2001 From: Hochi Huang Date: Sat, 23 Aug 2014 09:19:27 +0800 Subject: [AU]Sync libmedia/Android.mk modification from KLP-Sprout Bug: 17322146 Change-Id: If29fbd87252710bd794f2e0bb270bc846380ef1d Signed-off-by: Hochi Huang --- media/libmedia/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 3be0651..37bc418 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -70,7 +70,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_STATIC_LIBRARIES += libinstantssq -LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper +LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper LOCAL_MODULE:= libmedia -- cgit v1.1 From 34581f44cde67960fbac3ba1f191a2c063ea5145 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Fri, 29 Aug 2014 16:00:28 -0700 Subject: Use CharacterEncodingDetector in metadataretriever instead of media scanner. This way the java MediaMetadataRetriever API will give the same result as the media scanner. Also apply some tweaks to the encoding detector to improve handling of ISO-8859-1 tags. Bug: 16302581, 17205395 Change-Id: I1682a7a6a8bf04cffaa455044ba72dd7fd152d49 --- media/libmedia/Android.mk | 5 +- media/libmedia/CharacterEncodingDetector.cpp | 54 ++++++++++++++---- media/libmedia/CharacterEncodingDetector.h | 63 --------------------- media/libmedia/MediaScannerClient.cpp | 29 ++-------- media/libmedia/StringArray.h | 83 ---------------------------- 5 files changed, 51 insertions(+), 183 deletions(-) delete mode 100644 media/libmedia/CharacterEncodingDetector.h delete mode 100644 media/libmedia/StringArray.h (limited to 'media/libmedia') diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 3be0651..ffadb23 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -76,9 +76,10 @@ LOCAL_MODULE:= libmedia LOCAL_C_INCLUDES := \ $(TOP)/frameworks/native/include/media/openmax \ + $(TOP)/frameworks/av/include/media/ \ $(TOP)/frameworks/av/media/libstagefright \ - external/icu/icu4c/source/common \ - external/icu/icu4c/source/i18n \ + $(TOP)/external/icu/icu4c/source/common \ + $(TOP)/external/icu/icu4c/source/i18n \ $(call include-path-for, audio-effects) \ $(call include-path-for, audio-utils) diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp index 7d1ddfd..41994dc 100644 --- a/media/libmedia/CharacterEncodingDetector.cpp +++ b/media/libmedia/CharacterEncodingDetector.cpp @@ -18,7 +18,7 @@ #define LOG_TAG "CharacterEncodingDector" #include -#include "CharacterEncodingDetector.h" +#include #include "CharacterEncodingDetectorTables.h" #include "utils/Vector.h" @@ -118,10 +118,12 @@ void CharacterEncodingDetector::detectAndConvert() { int32_t matches; const UCharsetMatch** ucma = ucsdet_detectAll(csd, &matches, &status); bool goodmatch = true; + int highest = 0; const UCharsetMatch* bestCombinedMatch = getPreferred(buf, strlen(buf), - ucma, matches, &goodmatch); + ucma, matches, &goodmatch, &highest); - if (!goodmatch && strlen(buf) < 20) { + ALOGV("goodmatch: %s, highest: %d", goodmatch ? "true" : "false", highest); + if (!goodmatch && (highest < 15 || strlen(buf) < 20)) { ALOGV("not a good match, trying with more data"); // This string might be too short for ICU to do anything useful with. // (real world example: "Björk" in ISO-8859-1 might be detected as GB18030, because @@ -146,9 +148,10 @@ void CharacterEncodingDetector::detectAndConvert() { ucsdet_setText(csd, buf, strlen(buf), &status); ucma = ucsdet_detectAll(csd, &matches, &status); bestCombinedMatch = getPreferred(buf, strlen(buf), - ucma, matches, &goodmatch); - if (!goodmatch) { + ucma, matches, &goodmatch, &highest); + if (!goodmatch && highest <= 15) { ALOGV("still not a good match after adding printable tags"); + bestCombinedMatch = NULL; } } else { ALOGV("no printable tags to add"); @@ -157,6 +160,8 @@ void CharacterEncodingDetector::detectAndConvert() { if (bestCombinedMatch != NULL) { combinedenc = ucsdet_getName(bestCombinedMatch, &status); + } else { + combinedenc = "ISO-8859-1"; } } @@ -199,10 +204,17 @@ void CharacterEncodingDetector::detectAndConvert() { if (strcmp(enc,"UTF-8") != 0) { // only convert if the source encoding isn't already UTF-8 ALOGV("@@@ using converter %s for %s", enc, mNames.getEntry(i)); + status = U_ZERO_ERROR; UConverter *conv = ucnv_open(enc, &status); if (U_FAILURE(status)) { - ALOGE("could not create UConverter for %s", enc); - continue; + ALOGW("could not create UConverter for %s (%d), falling back to ISO-8859-1", + enc, status); + status = U_ZERO_ERROR; + conv = ucnv_open("ISO-8859-1", &status); + if (U_FAILURE(status)) { + ALOGW("could not create UConverter for ISO-8859-1 either"); + continue; + } } // convert from native encoding to UTF-8 @@ -224,7 +236,16 @@ void CharacterEncodingDetector::detectAndConvert() { } else { // zero terminate *target = 0; - mValues.setEntry(i, buffer); + // strip trailing spaces + while (--target > buffer && *target == ' ') { + *target = 0; + } + // skip leading spaces + char *start = buffer; + while (*start == ' ') { + start++; + } + mValues.setEntry(i, start); } delete[] buffer; @@ -261,7 +282,7 @@ void CharacterEncodingDetector::detectAndConvert() { const UCharsetMatch *CharacterEncodingDetector::getPreferred( const char *input, size_t len, const UCharsetMatch** ucma, size_t nummatches, - bool *goodmatch) { + bool *goodmatch, int *highestmatch) { *goodmatch = false; Vector matches; @@ -316,11 +337,17 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( } ALOGV("%zu: %s %d", i, encname, confidence); + status = U_ZERO_ERROR; UConverter *conv = ucnv_open(encname, &status); + int demerit = 0; + if (U_FAILURE(status)) { + ALOGV("failed to open %s: %d", encname, status); + confidence = 0; + demerit += 1000; + } const char *source = input; const char *sourceLimit = input + len; status = U_ZERO_ERROR; - int demerit = 0; int frequentchars = 0; int totalchars = 0; while (true) { @@ -337,7 +364,8 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( if (c < 0x20 || (c >= 0x7f && c <= 0x009f)) { ALOGV("control character %x", c); demerit += 100; - } else if ((c >= 0xa0 && c <= 0xbe) // symbols, superscripts + } else if ((c == 0xa0) // no-break space + || (c >= 0xa2 && c <= 0xbe) // symbols, superscripts || (c == 0xd7) || (c == 0xf7) // multiplication and division signs || (c >= 0x2000 && c <= 0x209f)) { // punctuation, superscripts ALOGV("unlikely character %x", c); @@ -408,10 +436,14 @@ const UCharsetMatch *CharacterEncodingDetector::getPreferred( } else { ALOGV("runner up: '%s' w/ %d confidence", ucsdet_getName(matches[runnerupidx], &status), runnerup); + if (runnerup < 0) { + runnerup = 0; + } if ((highest - runnerup) > 15) { *goodmatch = true; } } + *highestmatch = highest; return matches[highestidx]; } diff --git a/media/libmedia/CharacterEncodingDetector.h b/media/libmedia/CharacterEncodingDetector.h deleted file mode 100644 index 7b5ed86..0000000 --- a/media/libmedia/CharacterEncodingDetector.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CHARACTER_ENCODING_DETECTOR_H -#define _CHARACTER_ENCODING_DETECTOR_H - -#include - -#include "StringArray.h" - -#include "unicode/ucnv.h" -#include "unicode/ucsdet.h" -#include "unicode/ustring.h" - -namespace android { - -class CharacterEncodingDetector { - - public: - CharacterEncodingDetector(); - ~CharacterEncodingDetector(); - - void addTag(const char *name, const char *value); - size_t size(); - - void detectAndConvert(); - status_t getTag(int index, const char **name, const char**value); - - private: - const UCharsetMatch *getPreferred( - const char *input, size_t len, - const UCharsetMatch** ucma, size_t matches, - bool *goodmatch); - - bool isFrequent(const uint16_t *values, uint32_t c); - - // cached name and value strings, for native encoding support. - // TODO: replace these with byte blob arrays that don't require the data to be - // singlenullbyte-terminated - StringArray mNames; - StringArray mValues; - - UConverter* mUtf8Conv; -}; - - - -}; // namespace android - -#endif diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp index 1661f04..9f803cb 100644 --- a/media/libmedia/MediaScannerClient.cpp +++ b/media/libmedia/MediaScannerClient.cpp @@ -25,14 +25,10 @@ namespace android { -MediaScannerClient::MediaScannerClient() - : mEncodingDetector(NULL) -{ +MediaScannerClient::MediaScannerClient() { } -MediaScannerClient::~MediaScannerClient() -{ - delete mEncodingDetector; +MediaScannerClient::~MediaScannerClient() { } void MediaScannerClient::setLocale(const char* locale) @@ -40,31 +36,16 @@ void MediaScannerClient::setLocale(const char* locale) mLocale = locale; // not currently used } -void MediaScannerClient::beginFile() -{ - delete mEncodingDetector; - mEncodingDetector = new CharacterEncodingDetector(); +void MediaScannerClient::beginFile() { } status_t MediaScannerClient::addStringTag(const char* name, const char* value) { - mEncodingDetector->addTag(name, value); + handleStringTag(name, value); return OK; } -void MediaScannerClient::endFile() -{ - mEncodingDetector->detectAndConvert(); - - int size = mEncodingDetector->size(); - if (size) { - for (int i = 0; i < size; i++) { - const char *name; - const char *value; - mEncodingDetector->getTag(i, &name, &value); - handleStringTag(name, value); - } - } +void MediaScannerClient::endFile() { } } // namespace android diff --git a/media/libmedia/StringArray.h b/media/libmedia/StringArray.h deleted file mode 100644 index ae47085..0000000 --- a/media/libmedia/StringArray.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Sortable array of strings. STL-ish, but STL-free. -// -#ifndef _LIBS_MEDIA_STRING_ARRAY_H -#define _LIBS_MEDIA_STRING_ARRAY_H - -#include -#include - -namespace android { - -// -// An expanding array of strings. Add, get, sort, delete. -// -class StringArray { -public: - StringArray(); - virtual ~StringArray(); - - // - // Add a string. A copy of the string is made. - // - bool push_back(const char* str); - - // - // Delete an entry. - // - void erase(int idx); - - // - // Sort the array. - // - void sort(int (*compare)(const void*, const void*)); - - // - // Pass this to the sort routine to do an ascending alphabetical sort. - // - static int cmpAscendingAlpha(const void* pstr1, const void* pstr2); - - // - // Get the #of items in the array. - // - inline int size(void) const { return mCurrent; } - - // - // Return entry N. - // [should use operator[] here] - // - const char* getEntry(int idx) const { - return (unsigned(idx) >= unsigned(mCurrent)) ? NULL : mArray[idx]; - } - - // - // Set entry N to specified string. - // [should use operator[] here] - // - void setEntry(int idx, const char* str); - -private: - int mMax; - int mCurrent; - char** mArray; -}; - -}; // namespace android - -#endif // _LIBS_MEDIA_STRING_ARRAY_H -- cgit v1.1 From 640adb3cf89cc9b826372009fad8c9b3d120482e Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 5 Sep 2014 11:20:11 -0700 Subject: Cache audio attributes when player not available Cache the audio attributes stored in a Parcel in the client-side MediaPlayer object if they are set through setParameter() before the server-side MediaPlayer is available. Apply them when the player is prepared. Bug 17280746 Change-Id: I72f1a7fc4e2b076fae8cbdede77a2f74e98b2a03 --- media/libmedia/mediaplayer.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 6cd377a..9611ac7 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -50,6 +50,7 @@ MediaPlayer::MediaPlayer() mListener = NULL; mCookie = NULL; mStreamType = AUDIO_STREAM_MUSIC; + mAudioAttributesParcel = NULL; mCurrentPosition = -1; mSeekPosition = -1; mCurrentState = MEDIA_PLAYER_IDLE; @@ -68,6 +69,10 @@ MediaPlayer::MediaPlayer() MediaPlayer::~MediaPlayer() { ALOGV("destructor"); + if (mAudioAttributesParcel != NULL) { + delete mAudioAttributesParcel; + mAudioAttributesParcel = NULL; + } AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); disconnect(); IPCThreadState::self()->flushCommands(); @@ -237,6 +242,9 @@ status_t MediaPlayer::prepareAsync_l() { if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { mPlayer->setAudioStreamType(mStreamType); + if (mAudioAttributesParcel != NULL) { + mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel); + } mCurrentState = MEDIA_PLAYER_PREPARING; return mPlayer->prepareAsync(); } @@ -662,8 +670,17 @@ status_t MediaPlayer::setParameter(int key, const Parcel& request) if (mPlayer != NULL) { return mPlayer->setParameter(key, request); } - ALOGV("setParameter: no active player"); - return INVALID_OPERATION; + switch (key) { + case KEY_PARAMETER_AUDIO_ATTRIBUTES: + // no player, save the marshalled audio attributes + if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; }; + mAudioAttributesParcel = new Parcel(); + mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize()); + return OK; + default: + ALOGV("setParameter: no active player"); + return INVALID_OPERATION; + } } status_t MediaPlayer::getParameter(int key, Parcel *reply) -- cgit v1.1 From b445375f50a1a619b2d7518d32387d5ea77ceb70 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Mon, 8 Sep 2014 11:47:24 -0700 Subject: Fix potential deadlock between AudioPolicyService and AudioSystem Bug: 17109761 Change-Id: I315c1c5066f62b05e1c13b04fae1272b5fbce977 --- media/libmedia/AudioSystem.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 3486d21..1742fbe 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -582,9 +582,13 @@ const sp& AudioSystem::get_audio_policy_service() } binder->linkToDeath(gAudioPolicyServiceClient); gAudioPolicyService = interface_cast(binder); - gAudioPolicyService->registerClient(gAudioPolicyServiceClient); gLock.unlock(); + // Registering the client takes the AudioPolicyService lock. + // Don't hold the AudioSystem lock at the same time. + gAudioPolicyService->registerClient(gAudioPolicyServiceClient); } else { + // There exists a benign race condition where gAudioPolicyService + // is set, but gAudioPolicyServiceClient is not yet registered. gLock.unlock(); } return gAudioPolicyService; -- cgit v1.1 From 9520aa609c505cf8a9ee105bd78dc186cfb7770b Mon Sep 17 00:00:00 2001 From: Zhijun He Date: Tue, 9 Sep 2014 16:18:31 -0700 Subject: CamcorderProfile: Add QUALITY_HIGH_SPEED_2160P Bug: 17059255 Change-Id: Ic6b272e4ceec8fc852c9eb787370f4d366dad0ac --- media/libmedia/MediaProfiles.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'media/libmedia') diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index d2e181b..e2e6042 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -87,6 +87,7 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { {"highspeed480p", CAMCORDER_QUALITY_HIGH_SPEED_480P}, {"highspeed720p", CAMCORDER_QUALITY_HIGH_SPEED_720P}, {"highspeed1080p", CAMCORDER_QUALITY_HIGH_SPEED_1080P}, + {"highspeed2160p", CAMCORDER_QUALITY_HIGH_SPEED_2160P}, }; #if LOG_NDEBUG -- cgit v1.1 From 200092b7f21d2b98f30b800e79d152636f9ba225 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 15 Aug 2014 15:13:30 -0700 Subject: Clean up AudioTrack position and timestamp handling Replace epoch concept by observing and accumulating server delta positions. The advantage of using server deltas instead of absolute values is that they (1) are not sensitive to 32-bit wraparound, (2) are not sensitive to server behavior for stop(), and (3) prepare for future 64-bit client positions without requiring 64-bit positions on server. Add comments to AudioTrack::getTimestamp() and friends that the timestamp output parameter is undefined on error. Don't allow getTimestamp to return a negative frame position after stop(). Accumulate the client released frames, which may be useful for a future API. Bug: 11815245 Change-Id: I652940fa2db2f34a78c012a3ead0d9204fa29c6e --- media/libmedia/AudioTrack.cpp | 91 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 18 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d87e6f5..ff7da83 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -398,7 +398,7 @@ status_t AudioTrack::set( } // create the IAudioTrack - status = createTrack_l(0 /*epoch*/); + status = createTrack_l(); if (status != NO_ERROR) { if (mAudioTrackThread != 0) { @@ -417,6 +417,9 @@ status_t AudioTrack::set( mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; + mServer = 0; + mPosition = 0; + mReleased = 0; AudioSystem::acquireAudioSessionId(mSessionId, mClientPid); mSequence = 1; mObservedSequence = mSequence; @@ -443,14 +446,16 @@ status_t AudioTrack::start() } else { mState = STATE_ACTIVE; } + (void) updateAndGetPosition_l(); if (previousState == STATE_STOPPED || previousState == STATE_FLUSHED) { // reset current position as seen by client to 0 - mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); + mPosition = 0; + mReleased = 0; // force refresh of remaining frames by processAudioBuffer() as last // write before stop could be partial. mRefreshRemaining = true; } - mNewPosition = mProxy->getPosition() + mUpdatePeriod; + mNewPosition = mPosition + mUpdatePeriod; int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags); sp t = mAudioTrackThread; @@ -709,7 +714,7 @@ void AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount) { // FIXME If setting a loop also sets position to start of loop, then // this is correct. Otherwise it should be removed. - mNewPosition = mProxy->getPosition() + mUpdatePeriod; + mNewPosition = updateAndGetPosition_l() + mUpdatePeriod; mLoopPeriod = loopCount != 0 ? loopEnd - loopStart : 0; mStaticProxy->setLoop(loopStart, loopEnd, loopCount); } @@ -751,7 +756,7 @@ status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) } AutoMutex lock(mLock); - mNewPosition = mProxy->getPosition() + updatePeriod; + mNewPosition = updateAndGetPosition_l() + updatePeriod; mUpdatePeriod = updatePeriod; return NO_ERROR; @@ -791,7 +796,7 @@ status_t AudioTrack::setPosition(uint32_t position) if (mState == STATE_ACTIVE) { return INVALID_OPERATION; } - mNewPosition = mProxy->getPosition() + mUpdatePeriod; + mNewPosition = updateAndGetPosition_l() + mUpdatePeriod; mLoopPeriod = 0; // FIXME Check whether loops and setting position are incompatible in old code. // If we use setLoop for both purposes we lose the capability to set the position while looping. @@ -800,7 +805,7 @@ status_t AudioTrack::setPosition(uint32_t position) return NO_ERROR; } -status_t AudioTrack::getPosition(uint32_t *position) const +status_t AudioTrack::getPosition(uint32_t *position) { if (position == NULL) { return BAD_VALUE; @@ -823,8 +828,8 @@ status_t AudioTrack::getPosition(uint32_t *position) const *position = dspFrames; } else { // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes - *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ? 0 : - mProxy->getPosition(); + *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ? + 0 : updateAndGetPosition_l(); } return NO_ERROR; } @@ -881,7 +886,7 @@ status_t AudioTrack::attachAuxEffect(int effectId) // ------------------------------------------------------------------------- // must be called with mLock held -status_t AudioTrack::createTrack_l(size_t epoch) +status_t AudioTrack::createTrack_l() { status_t status; const sp& audioFlinger = AudioSystem::get_audio_flinger(); @@ -1184,7 +1189,6 @@ status_t AudioTrack::createTrack_l(size_t epoch) mProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY); mProxy->setSendLevel(mSendLevel); mProxy->setSampleRate(mSampleRate); - mProxy->setEpoch(epoch); mProxy->setMinimum(mNotificationFramesAct); mDeathNotifier = new DeathNotifier(this); @@ -1319,6 +1323,7 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) buffer.mRaw = audioBuffer->raw; AutoMutex lock(mLock); + mReleased += stepCount; mInUnderrun = false; mProxy->releaseBuffer(&buffer); @@ -1531,7 +1536,7 @@ nsecs_t AudioTrack::processAudioBuffer() } // Get current position of server - size_t position = mProxy->getPosition(); + size_t position = updateAndGetPosition_l(); // Manage marker callback bool markerReached = false; @@ -1796,14 +1801,18 @@ status_t AudioTrack::restoreTrack_l(const char *from) return DEAD_OBJECT; } - // if the new IAudioTrack is created, createTrack_l() will modify the + // save the old static buffer position + size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0; + + // If a new IAudioTrack is successfully created, createTrack_l() will modify the // following member variables: mAudioTrack, mCblkMemory and mCblk. - // It will also delete the strong references on previous IAudioTrack and IMemory + // It will also delete the strong references on previous IAudioTrack and IMemory. + // If a new IAudioTrack cannot be created, the previous (dead) instance will be left intact. + result = createTrack_l(); // take the frames that will be lost by track recreation into account in saved position - size_t position = mProxy->getPosition() + mProxy->getFramesFilled(); - size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0; - result = createTrack_l(position /*epoch*/); + (void) updateAndGetPosition_l(); + mPosition = mReleased; if (result == NO_ERROR) { // continue playback from last known position, but @@ -1838,6 +1847,27 @@ status_t AudioTrack::restoreTrack_l(const char *from) return result; } +uint32_t AudioTrack::updateAndGetPosition_l() +{ + // This is the sole place to read server consumed frames + uint32_t newServer = mProxy->getPosition(); + int32_t delta = newServer - mServer; + mServer = newServer; + // TODO There is controversy about whether there can be "negative jitter" in server position. + // This should be investigated further, and if possible, it should be addressed. + // A more definite failure mode is infrequent polling by client. + // One could call (void)getPosition_l() in releaseBuffer(), + // so mReleased and mPosition are always lock-step as best possible. + // That should ensure delta never goes negative for infrequent polling + // unless the server has more than 2^31 frames in its buffer, + // in which case the use of uint32_t for these counters has bigger issues. + if (delta < 0) { + ALOGE("detected illegal retrograde motion by the server: mServer advanced by %d", delta); + delta = 0; + } + return mPosition += (uint32_t) delta; +} + status_t AudioTrack::setParameters(const String8& keyValuePairs) { AutoMutex lock(mLock); @@ -1854,9 +1884,34 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) if (mState != STATE_ACTIVE && mState != STATE_PAUSED) { return INVALID_OPERATION; } + // The presented frame count must always lag behind the consumed frame count. + // To avoid a race, read the presented frames first. This ensures that presented <= consumed. status_t status = mAudioTrack->getTimestamp(timestamp); if (status == NO_ERROR) { - timestamp.mPosition += mProxy->getEpoch(); + // Update the mapping between local consumed (mPosition) and server consumed (mServer) + (void) updateAndGetPosition_l(); + // Server consumed (mServer) and presented both use the same server time base, + // and server consumed is always >= presented. + // The delta between these represents the number of frames in the buffer pipeline. + // If this delta between these is greater than the client position, it means that + // actually presented is still stuck at the starting line (figuratively speaking), + // waiting for the first frame to go by. So we can't report a valid timestamp yet. + if ((uint32_t) (mServer - timestamp.mPosition) > mPosition) { + return INVALID_OPERATION; + } + // Convert timestamp position from server time base to client time base. + // TODO The following code should work OK now because timestamp.mPosition is 32-bit. + // But if we change it to 64-bit then this could fail. + // If (mPosition - mServer) can be negative then should use: + // (int32_t)(mPosition - mServer) + timestamp.mPosition += mPosition - mServer; + // Immediately after a call to getPosition_l(), mPosition and + // mServer both represent the same frame position. mPosition is + // in client's point of view, and mServer is in server's point of + // view. So the difference between them is the "fudge factor" + // between client and server views due to stop() and/or new + // IAudioTrack. And timestamp.mPosition is initially in server's + // point of view, so we need to apply the same fudge factor to it. } return status; } -- cgit v1.1 From 7f1bc8af1c46695191bf7e2aba6467f3616629c0 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Fri, 12 Sep 2014 14:43:11 -0700 Subject: Fix AudioTrack offloaded timestamp handling. getTimestamp for offloaded tracks now returns WOULD_BLOCK for situations where the timestamp is unavailable due to the previous track still flushing or the timestamp is stale. It is fixed for normal playback conditions. Bug: 14659809 Bug: 17428188 Change-Id: Ic9ec07ccabc604236979769db5c4ea2dec252660 --- media/libmedia/AudioTrack.cpp | 98 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 5 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index ff7da83..762dca5 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -37,6 +37,19 @@ namespace android { // --------------------------------------------------------------------------- +static int64_t convertTimespecToUs(const struct timespec &tv) +{ + return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000; +} + +// current monotonic time in microseconds. +static int64_t getNowUs() +{ + struct timespec tv; + (void) clock_gettime(CLOCK_MONOTONIC, &tv); + return convertTimespecToUs(tv); +} + // static status_t AudioTrack::getMinFrameCount( size_t* frameCount, @@ -420,6 +433,7 @@ status_t AudioTrack::set( mServer = 0; mPosition = 0; mReleased = 0; + mStartUs = 0; AudioSystem::acquireAudioSessionId(mSessionId, mClientPid); mSequence = 1; mObservedSequence = mSequence; @@ -451,6 +465,12 @@ status_t AudioTrack::start() // reset current position as seen by client to 0 mPosition = 0; mReleased = 0; + // For offloaded tracks, we don't know if the hardware counters are really zero here, + // since the flush is asynchronous and stop may not fully drain. + // We save the time when the track is started to later verify whether + // the counters are realistic (i.e. start from zero after this time). + mStartUs = getNowUs(); + // force refresh of remaining frames by processAudioBuffer() as last // write before stop could be partial. mRefreshRemaining = true; @@ -587,9 +607,18 @@ void AudioTrack::pause() if (isOffloaded_l()) { if (mOutput != AUDIO_IO_HANDLE_NONE) { + // An offload output can be re-used between two audio tracks having + // the same configuration. A timestamp query for a paused track + // while the other is running would return an incorrect time. + // To fix this, cache the playback position on a pause() and return + // this time when requested until the track is resumed. + + // OffloadThread sends HAL pause in its threadLoop. Time saved + // here can be slightly off. + + // TODO: check return code for getRenderPosition. + uint32_t halFrames; - // OffloadThread sends HAL pause in its threadLoop.. time saved - // here can be slightly off AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition); ALOGV("AudioTrack::pause for offload, cache current position %u", mPausedPosition); } @@ -825,6 +854,8 @@ status_t AudioTrack::getPosition(uint32_t *position) uint32_t halFrames; AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames); } + // FIXME: dspFrames may not be zero in (mState == STATE_STOPPED || mState == STATE_FLUSHED) + // due to hardware latency. We leave this behavior for now. *position = dspFrames; } else { // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes @@ -1881,13 +1912,70 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { return INVALID_OPERATION; } - if (mState != STATE_ACTIVE && mState != STATE_PAUSED) { - return INVALID_OPERATION; + + switch (mState) { + case STATE_ACTIVE: + case STATE_PAUSED: + break; // handle below + case STATE_FLUSHED: + case STATE_STOPPED: + return WOULD_BLOCK; + case STATE_STOPPING: + case STATE_PAUSED_STOPPING: + if (!isOffloaded_l()) { + return INVALID_OPERATION; + } + break; // offloaded tracks handled below + default: + LOG_ALWAYS_FATAL("Invalid mState in getTimestamp(): %d", mState); + break; } + // The presented frame count must always lag behind the consumed frame count. // To avoid a race, read the presented frames first. This ensures that presented <= consumed. status_t status = mAudioTrack->getTimestamp(timestamp); - if (status == NO_ERROR) { + if (status != NO_ERROR) { + ALOGW_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status); + return status; + } + if (isOffloadedOrDirect_l()) { + if (isOffloaded_l() && (mState == STATE_PAUSED || mState == STATE_PAUSED_STOPPING)) { + // use cached paused position in case another offloaded track is running. + timestamp.mPosition = mPausedPosition; + clock_gettime(CLOCK_MONOTONIC, ×tamp.mTime); + return NO_ERROR; + } + + // Check whether a pending flush or stop has completed, as those commands may + // be asynchronous or return near finish. + if (mStartUs != 0 && mSampleRate != 0) { + static const int kTimeJitterUs = 100000; // 100 ms + static const int k1SecUs = 1000000; + + const int64_t timeNow = getNowUs(); + + if (timeNow < mStartUs + k1SecUs) { // within first second of starting + const int64_t timestampTimeUs = convertTimespecToUs(timestamp.mTime); + if (timestampTimeUs < mStartUs) { + return WOULD_BLOCK; // stale timestamp time, occurs before start. + } + const int64_t deltaTimeUs = timestampTimeUs - mStartUs; + const int64_t deltaPositionByUs = timestamp.mPosition * 1000000LL / mSampleRate; + + if (deltaPositionByUs > deltaTimeUs + kTimeJitterUs) { + // Verify that the counter can't count faster than the sample rate + // since the start time. If greater, then that means we have failed + // to completely flush or stop the previous playing track. + ALOGW("incomplete flush or stop:" + " deltaTimeUs(%lld) deltaPositionUs(%lld) tsmPosition(%u)", + (long long)deltaTimeUs, (long long)deltaPositionByUs, + timestamp.mPosition); + return WOULD_BLOCK; + } + } + mStartUs = 0; // no need to check again, start timestamp has either expired or unneeded. + } + } else { // Update the mapping between local consumed (mPosition) and server consumed (mServer) (void) updateAndGetPosition_l(); // Server consumed (mServer) and presented both use the same server time base, -- cgit v1.1 From a0fd9ca66a68baefd9d76800fd66823fd654ef45 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Thu, 18 Sep 2014 14:07:18 -0700 Subject: AudioEffect acquires session Currently, users of audio sessions, AudioTrack and AudioRecord, are acquiring and releasing audio sessions according to their life-cycle. AudioEffect instances were not counting as users of an audio session. This caused an effect used on a session to be purged by AudioFlinger::purgeStaleEffects_l() whenever the last user of that session went away. This CL makes AudioEffect acquire and release a session when created and destroyed. Bug 15432115 Change-Id: I922532150009988d43872f9b5928044a830ae0b3 --- media/libmedia/AudioEffect.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 35f6557..0d5d7e4 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -145,15 +145,19 @@ status_t AudioEffect::set(const effect_uuid_t *type, return mStatus; } - mIEffect = iEffect; mCblkMemory = cblk; mCblk = static_cast(cblk->pointer()); int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int); mCblk->buffer = (uint8_t *)mCblk + bufOffset; iEffect->asBinder()->linkToDeath(mIEffectClient); - ALOGV("set() %p OK effect: %s id: %d status %d enabled %d", this, mDescriptor.name, mId, - mStatus, mEnabled); + mClientPid = IPCThreadState::self()->getCallingPid(); + ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId, + mStatus, mEnabled, mClientPid); + + if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) { + AudioSystem::acquireAudioSessionId(mSessionId, mClientPid); + } return mStatus; } @@ -164,6 +168,9 @@ AudioEffect::~AudioEffect() ALOGV("Destructor %p", this); if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) { + if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) { + AudioSystem::releaseAudioSessionId(mSessionId, mClientPid); + } if (mIEffect != NULL) { mIEffect->disconnect(); mIEffect->asBinder()->unlinkToDeath(mIEffectClient); -- cgit v1.1 From dfc34daba6d6cb923683d96689a0cb7c7006eee5 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 19 Sep 2014 09:05:05 -0700 Subject: Reduce log spam from getTimestamp errors Bug: 17576481 Change-Id: I07d99e7c42b7d4f0994b5a6d9c9fe8eb29fbbe40 --- media/libmedia/AudioTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 762dca5..ea7b279 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1935,7 +1935,7 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) // To avoid a race, read the presented frames first. This ensures that presented <= consumed. status_t status = mAudioTrack->getTimestamp(timestamp); if (status != NO_ERROR) { - ALOGW_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status); + ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status); return status; } if (isOffloadedOrDirect_l()) { -- cgit v1.1 From bb6c9a05840d924b502ce0f1868fca4881ada1ed Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 25 Sep 2014 14:11:47 -0700 Subject: audio: fix stream type for accessibility usage Make sure that accessibility prompts are heard when a ringtone is active by forcing stream type to AUDIO_STREAM_RING when phone state is AUDIO_MODE_RINGTONE. Bug: 17558149. Change-Id: Ia3bead8052fca5cbf282c267f7b9b06014fef628 --- media/libmedia/AudioSystem.cpp | 9 +++++++++ media/libmedia/AudioTrack.cpp | 9 ++++++++- media/libmedia/IAudioPolicyService.cpp | 20 +++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 1742fbe..dda3657 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -939,6 +939,15 @@ status_t AudioSystem::releaseSoundTriggerSession(audio_session_t session) if (aps == 0) return PERMISSION_DENIED; return aps->releaseSoundTriggerSession(session); } + +audio_mode_t AudioSystem::getPhoneState() +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return AUDIO_MODE_INVALID; + return aps->getPhoneState(); +} + + // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index ea7b279..e3beba5 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -2124,9 +2124,16 @@ void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) { // usage to stream type mapping switch (aa.usage) { + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + // TODO once AudioPolicyManager fully supports audio_attributes_t, + // remove stream change based on phone state + if (AudioSystem::getPhoneState() == AUDIO_MODE_RINGTONE) { + mStreamType = AUDIO_STREAM_RING; + break; + } + /// FALL THROUGH case AUDIO_USAGE_MEDIA: case AUDIO_USAGE_GAME: - case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: mStreamType = AUDIO_STREAM_MUSIC; return; diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index b57f747..256cb3f 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -67,7 +67,8 @@ enum { REGISTER_CLIENT, GET_OUTPUT_FOR_ATTR, ACQUIRE_SOUNDTRIGGER_SESSION, - RELEASE_SOUNDTRIGGER_SESSION + RELEASE_SOUNDTRIGGER_SESSION, + GET_PHONE_STATE }; class BpAudioPolicyService : public BpInterface @@ -607,6 +608,17 @@ public: } return (status_t)reply.readInt32(); } + + virtual audio_mode_t getPhoneState() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_PHONE_STATE, data, &reply); + if (status != NO_ERROR) { + return AUDIO_MODE_INVALID; + } + return (audio_mode_t)reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -1057,6 +1069,12 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case GET_PHONE_STATE: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + reply->writeInt32((int32_t)getPhoneState()); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 7985dcb06e0c29d5cc12d0c0e17e03d5d863cf53 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 7 Oct 2014 15:45:14 -0700 Subject: AudioTrack: fix AudioTrackThread crash upon exit In case of error during createTrack_l(), there is a possibility that a newly created AudioTrackThread is resumed by requestExit() just after entering the Thread class _threadLoop() but before entering the class threadLoop(). In this case, processAudioBuffer() is executed once with mCblk == 0 and we assert. Bug: 17894033. Change-Id: I93d0d0d4dbf14bcb88dad23e6ad49d2ecd47badd --- media/libmedia/AudioTrack.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index e3beba5..8e0704f 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -2244,6 +2244,9 @@ bool AudioTrack::AudioTrackThread::threadLoop() return true; } } + if (exitPending()) { + return false; + } nsecs_t ns = mReceiver.processAudioBuffer(); switch (ns) { case 0: -- cgit v1.1 From c2813e568aa476e03d159529c0af28c99536db8d Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Thu, 16 Oct 2014 17:54:34 -0700 Subject: Fix AudioTrack retrograde getPosition when restoring tracks mReleased represents the number of frames written to the track, but was cleared on start() causing a mismatch if the client wrote to the track before starting. Moved the clearing to entering the STATE_STOPPED or STATE_FLUSHED state. Bug: 18017947 Bug: 18022276 Change-Id: I3788c98c4c3c4d9cc004378432797b3f3138e22e --- media/libmedia/AudioTrack.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'media/libmedia') diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 8e0704f..0a89fbb 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -464,7 +464,6 @@ status_t AudioTrack::start() if (previousState == STATE_STOPPED || previousState == STATE_FLUSHED) { // reset current position as seen by client to 0 mPosition = 0; - mReleased = 0; // For offloaded tracks, we don't know if the hardware counters are really zero here, // since the flush is asynchronous and stop may not fully drain. // We save the time when the track is started to later verify whether @@ -529,6 +528,7 @@ void AudioTrack::stop() mState = STATE_STOPPING; } else { mState = STATE_STOPPED; + mReleased = 0; } mProxy->interrupt(); @@ -585,6 +585,7 @@ void AudioTrack::flush_l() mRefreshRemaining = true; mState = STATE_FLUSHED; + mReleased = 0; if (isOffloaded_l()) { mProxy->interrupt(); } @@ -1625,6 +1626,7 @@ nsecs_t AudioTrack::processAudioBuffer() waitStreamEnd = mState == STATE_STOPPING; if (waitStreamEnd) { mState = STATE_STOPPED; + mReleased = 0; } } if (waitStreamEnd && status != DEAD_OBJECT) { @@ -1873,6 +1875,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) if (result != NO_ERROR) { ALOGW("restoreTrack_l() failed status %d", result); mState = STATE_STOPPED; + mReleased = 0; } return result; -- cgit v1.1