Loading include/media/AudioRecord.h +2 −1 Original line number Diff line number Diff line Loading @@ -145,7 +145,7 @@ public: * Parameters: * * inputSource: Select the audio input to record from (e.g. AUDIO_SOURCE_DEFAULT). * sampleRate: Data sink sampling rate in Hz. * sampleRate: Data sink sampling rate in Hz. Zero means to use the source sample rate. * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed * 16 bits per sample). * channelMask: Channel mask, such that audio_is_input_channel(channelMask) is true. Loading Loading @@ -258,6 +258,7 @@ public: bool stopped() const; /* Return the sink sample rate for this record track in Hz. * If specified as zero in constructor or set(), this will be the source sample rate. * Unlike AudioTrack, the sample rate is const after initialization, so doesn't need a lock. */ uint32_t getSampleRate() const { return mSampleRate; } Loading include/media/AudioTrack.h +9 −3 Original line number Diff line number Diff line Loading @@ -167,7 +167,10 @@ public: * * streamType: Select the type of audio stream this track is attached to * (e.g. AUDIO_STREAM_MUSIC). * sampleRate: Data source sampling rate in Hz. * sampleRate: Data source sampling rate in Hz. Zero means to use the sink sample rate. * A non-zero value must be specified if AUDIO_OUTPUT_FLAG_DIRECT is set. * 0 will not work with current policy implementation for direct output * selection where an exact match is needed for sampling rate. * format: Audio format. For mixed tracks, any PCM format supported by server is OK. * For direct and offloaded tracks, the possible format(s) depends on the * output sink. Loading Loading @@ -395,11 +398,14 @@ public: status_t setAuxEffectSendLevel(float level); void getAuxEffectSendLevel(float* level) const; /* Set source sample rate for this track in Hz, mostly used for games' sound effects /* Set source sample rate for this track in Hz, mostly used for games' sound effects. * Zero is not permitted. */ status_t setSampleRate(uint32_t sampleRate); /* Return current source sample rate in Hz */ /* Return current source sample rate in Hz. * If specified as zero in constructor or set(), this will be the sink sample rate. */ uint32_t getSampleRate() const; /* Return the original source sample rate in Hz. This corresponds to the sample rate Loading media/libmedia/AudioRecord.cpp +62 −45 Original line number Diff line number Diff line Loading @@ -191,10 +191,6 @@ status_t AudioRecord::set( mAttributes.source, mAttributes.flags, mAttributes.tags); } if (sampleRate == 0) { ALOGE("Invalid sample rate %u", sampleRate); return BAD_VALUE; } mSampleRate = sampleRate; // these below should probably come from the audioFlinger too... Loading Loading @@ -517,27 +513,71 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 return NO_INIT; } // 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"); if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); } audio_io_handle_t input; status_t status; status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId, // FIXME compare to AudioTrack IPCThreadState::self()->getCallingUid(), mSampleRate, mFormat, mChannelMask, mFlags, mSelectedDeviceId); if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE) { ALOGE("Could not get audio input for session %d, record source %d, sample rate %u, " "format %#x, channel mask %#x, flags %#x", mSessionId, mAttributes.source, 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. #if 0 size_t afFrameCount; status = AudioSystem::getFrameCount(input, &afFrameCount); if (status != NO_ERROR) { ALOGE("getFrameCount(input=%d) status %d", input, status); goto release; } #endif uint32_t afSampleRate; status = AudioSystem::getSamplingRate(input, &afSampleRate); if (status != NO_ERROR) { ALOGE("getSamplingRate(input=%d) status %d", input, status); goto release; } if (mSampleRate == 0) { mSampleRate = afSampleRate; } // Client can only express a preference for FAST. Server will perform additional tests. if ((mFlags & AUDIO_INPUT_FLAG_FAST) && !(( if (mFlags & AUDIO_INPUT_FLAG_FAST) { bool useCaseAllowed = // either of these use cases: // use case 1: callback transfer mode (mTransfer == TRANSFER_CALLBACK) || // use case 2: obtain/release mode (mTransfer == TRANSFER_OBTAIN)) && // matching sample rate (mSampleRate == afSampleRate))) { ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, track %u Hz, primary %u Hz", (mTransfer == TRANSFER_OBTAIN); // sample rates must also match bool fastAllowed = useCaseAllowed && (mSampleRate == afSampleRate); if (!fastAllowed) { ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, " "track %u Hz, input %u Hz", mTransfer, mSampleRate, afSampleRate); // once denied, do not request again if IAudioRecord is re-created mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); } } // The notification frame count is the period between callbacks, as suggested by the client // but moderated by the server. For record, the calculations are done entirely on server side. size_t notificationFrames = mNotificationFramesReq; size_t frameCount = mReqFrameCount; IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; Loading @@ -549,35 +589,10 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 } } if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); } audio_io_handle_t input; status_t status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId, IPCThreadState::self()->getCallingUid(), mSampleRate, mFormat, mChannelMask, mFlags, mSelectedDeviceId); if (status != NO_ERROR) { ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " "channel mask %#x, session %d, flags %#x", mAttributes.source, mSampleRate, mFormat, mChannelMask, mSessionId, 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. 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 = mNotificationFramesReq; sp<IMemory> iMem; // for cblk sp<IMemory> bufferMem; sp<IAudioRecord> record = audioFlinger->openRecord(input, Loading Loading @@ -660,11 +675,13 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 } } // 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); // Make sure that application is notified with sufficient margin before overrun. // The computation is done on server side. if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) { ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu", mNotificationFramesReq, notificationFrames, frameCount); } mNotificationFramesAct = notificationFrames; mNotificationFramesAct = (uint32_t) notificationFrames; // We retain a copy of the I/O handle, but don't own the reference mInput = input; Loading media/libmedia/AudioTrack.cpp +21 −15 Original line number Diff line number Diff line Loading @@ -1192,6 +1192,7 @@ status_t AudioTrack::createTrack_l() mSampleRate = mAfSampleRate; mOriginalSampleRate = mAfSampleRate; } // Client can only express a preference for FAST. Server will perform additional tests. if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { bool useCaseAllowed = Loading @@ -1215,13 +1216,6 @@ status_t AudioTrack::createTrack_l() } } // 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 // n = 2 normal track, (including those with sample rate conversion) // n >= 3 very high latency or very small notification interval (unused). const uint32_t nBuffering = 2; mNotificationFramesAct = mNotificationFramesReq; size_t frameCount = mReqFrameCount; Loading Loading @@ -1320,6 +1314,7 @@ status_t AudioTrack::createTrack_l() // AudioFlinger now owns the reference to the I/O handle, // so we are no longer responsible for releasing it. // FIXME compare to AudioRecord sp<IMemory> iMem = track->getCblk(); if (iMem == 0) { ALOGE("Could not get control block"); Loading Loading @@ -1383,14 +1378,25 @@ status_t AudioTrack::createTrack_l() //return NO_INIT; } } // Make sure that application is notified with sufficient margin before underrun // Make sure that application is notified with sufficient margin before underrun. // 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 // n = 2 normal track, (including those with sample rate conversion) // n >= 3 very high latency or very small notification interval (unused). // FIXME Move the computation from client side to server side, // and allow nBuffering to be larger than 1 for OpenSL ES, like it can be for Java. if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) { // 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 // for fast tracks just like normal streaming tracks. if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount / nBuffering) { mNotificationFramesAct = frameCount / nBuffering; size_t maxNotificationFrames = frameCount; if (!(trackFlags & IAudioFlinger::TRACK_FAST)) { const uint32_t nBuffering = 2; maxNotificationFrames /= nBuffering; } if (mNotificationFramesAct == 0 || mNotificationFramesAct > maxNotificationFrames) { ALOGW("Client adjusted notificationFrames from %u to %zu for frameCount %zu", mNotificationFramesAct, maxNotificationFrames, frameCount); mNotificationFramesAct = (uint32_t) maxNotificationFrames; } } Loading services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -564,6 +564,7 @@ private: PlaybackThread *srcThread, PlaybackThread *dstThread, bool reRegister); // return thread associated with primary hardware device, or NULL PlaybackThread *primaryPlaybackThread_l() const; audio_devices_t primaryOutputDevice_l() const; Loading Loading
include/media/AudioRecord.h +2 −1 Original line number Diff line number Diff line Loading @@ -145,7 +145,7 @@ public: * Parameters: * * inputSource: Select the audio input to record from (e.g. AUDIO_SOURCE_DEFAULT). * sampleRate: Data sink sampling rate in Hz. * sampleRate: Data sink sampling rate in Hz. Zero means to use the source sample rate. * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed * 16 bits per sample). * channelMask: Channel mask, such that audio_is_input_channel(channelMask) is true. Loading Loading @@ -258,6 +258,7 @@ public: bool stopped() const; /* Return the sink sample rate for this record track in Hz. * If specified as zero in constructor or set(), this will be the source sample rate. * Unlike AudioTrack, the sample rate is const after initialization, so doesn't need a lock. */ uint32_t getSampleRate() const { return mSampleRate; } Loading
include/media/AudioTrack.h +9 −3 Original line number Diff line number Diff line Loading @@ -167,7 +167,10 @@ public: * * streamType: Select the type of audio stream this track is attached to * (e.g. AUDIO_STREAM_MUSIC). * sampleRate: Data source sampling rate in Hz. * sampleRate: Data source sampling rate in Hz. Zero means to use the sink sample rate. * A non-zero value must be specified if AUDIO_OUTPUT_FLAG_DIRECT is set. * 0 will not work with current policy implementation for direct output * selection where an exact match is needed for sampling rate. * format: Audio format. For mixed tracks, any PCM format supported by server is OK. * For direct and offloaded tracks, the possible format(s) depends on the * output sink. Loading Loading @@ -395,11 +398,14 @@ public: status_t setAuxEffectSendLevel(float level); void getAuxEffectSendLevel(float* level) const; /* Set source sample rate for this track in Hz, mostly used for games' sound effects /* Set source sample rate for this track in Hz, mostly used for games' sound effects. * Zero is not permitted. */ status_t setSampleRate(uint32_t sampleRate); /* Return current source sample rate in Hz */ /* Return current source sample rate in Hz. * If specified as zero in constructor or set(), this will be the sink sample rate. */ uint32_t getSampleRate() const; /* Return the original source sample rate in Hz. This corresponds to the sample rate Loading
media/libmedia/AudioRecord.cpp +62 −45 Original line number Diff line number Diff line Loading @@ -191,10 +191,6 @@ status_t AudioRecord::set( mAttributes.source, mAttributes.flags, mAttributes.tags); } if (sampleRate == 0) { ALOGE("Invalid sample rate %u", sampleRate); return BAD_VALUE; } mSampleRate = sampleRate; // these below should probably come from the audioFlinger too... Loading Loading @@ -517,27 +513,71 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 return NO_INIT; } // 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"); if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); } audio_io_handle_t input; status_t status; status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId, // FIXME compare to AudioTrack IPCThreadState::self()->getCallingUid(), mSampleRate, mFormat, mChannelMask, mFlags, mSelectedDeviceId); if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE) { ALOGE("Could not get audio input for session %d, record source %d, sample rate %u, " "format %#x, channel mask %#x, flags %#x", mSessionId, mAttributes.source, 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. #if 0 size_t afFrameCount; status = AudioSystem::getFrameCount(input, &afFrameCount); if (status != NO_ERROR) { ALOGE("getFrameCount(input=%d) status %d", input, status); goto release; } #endif uint32_t afSampleRate; status = AudioSystem::getSamplingRate(input, &afSampleRate); if (status != NO_ERROR) { ALOGE("getSamplingRate(input=%d) status %d", input, status); goto release; } if (mSampleRate == 0) { mSampleRate = afSampleRate; } // Client can only express a preference for FAST. Server will perform additional tests. if ((mFlags & AUDIO_INPUT_FLAG_FAST) && !(( if (mFlags & AUDIO_INPUT_FLAG_FAST) { bool useCaseAllowed = // either of these use cases: // use case 1: callback transfer mode (mTransfer == TRANSFER_CALLBACK) || // use case 2: obtain/release mode (mTransfer == TRANSFER_OBTAIN)) && // matching sample rate (mSampleRate == afSampleRate))) { ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, track %u Hz, primary %u Hz", (mTransfer == TRANSFER_OBTAIN); // sample rates must also match bool fastAllowed = useCaseAllowed && (mSampleRate == afSampleRate); if (!fastAllowed) { ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, " "track %u Hz, input %u Hz", mTransfer, mSampleRate, afSampleRate); // once denied, do not request again if IAudioRecord is re-created mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); } } // The notification frame count is the period between callbacks, as suggested by the client // but moderated by the server. For record, the calculations are done entirely on server side. size_t notificationFrames = mNotificationFramesReq; size_t frameCount = mReqFrameCount; IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; Loading @@ -549,35 +589,10 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 } } if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); } audio_io_handle_t input; status_t status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId, IPCThreadState::self()->getCallingUid(), mSampleRate, mFormat, mChannelMask, mFlags, mSelectedDeviceId); if (status != NO_ERROR) { ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " "channel mask %#x, session %d, flags %#x", mAttributes.source, mSampleRate, mFormat, mChannelMask, mSessionId, 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. 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 = mNotificationFramesReq; sp<IMemory> iMem; // for cblk sp<IMemory> bufferMem; sp<IAudioRecord> record = audioFlinger->openRecord(input, Loading Loading @@ -660,11 +675,13 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 } } // 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); // Make sure that application is notified with sufficient margin before overrun. // The computation is done on server side. if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) { ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu", mNotificationFramesReq, notificationFrames, frameCount); } mNotificationFramesAct = notificationFrames; mNotificationFramesAct = (uint32_t) notificationFrames; // We retain a copy of the I/O handle, but don't own the reference mInput = input; Loading
media/libmedia/AudioTrack.cpp +21 −15 Original line number Diff line number Diff line Loading @@ -1192,6 +1192,7 @@ status_t AudioTrack::createTrack_l() mSampleRate = mAfSampleRate; mOriginalSampleRate = mAfSampleRate; } // Client can only express a preference for FAST. Server will perform additional tests. if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { bool useCaseAllowed = Loading @@ -1215,13 +1216,6 @@ status_t AudioTrack::createTrack_l() } } // 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 // n = 2 normal track, (including those with sample rate conversion) // n >= 3 very high latency or very small notification interval (unused). const uint32_t nBuffering = 2; mNotificationFramesAct = mNotificationFramesReq; size_t frameCount = mReqFrameCount; Loading Loading @@ -1320,6 +1314,7 @@ status_t AudioTrack::createTrack_l() // AudioFlinger now owns the reference to the I/O handle, // so we are no longer responsible for releasing it. // FIXME compare to AudioRecord sp<IMemory> iMem = track->getCblk(); if (iMem == 0) { ALOGE("Could not get control block"); Loading Loading @@ -1383,14 +1378,25 @@ status_t AudioTrack::createTrack_l() //return NO_INIT; } } // Make sure that application is notified with sufficient margin before underrun // Make sure that application is notified with sufficient margin before underrun. // 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 // n = 2 normal track, (including those with sample rate conversion) // n >= 3 very high latency or very small notification interval (unused). // FIXME Move the computation from client side to server side, // and allow nBuffering to be larger than 1 for OpenSL ES, like it can be for Java. if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) { // 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 // for fast tracks just like normal streaming tracks. if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount / nBuffering) { mNotificationFramesAct = frameCount / nBuffering; size_t maxNotificationFrames = frameCount; if (!(trackFlags & IAudioFlinger::TRACK_FAST)) { const uint32_t nBuffering = 2; maxNotificationFrames /= nBuffering; } if (mNotificationFramesAct == 0 || mNotificationFramesAct > maxNotificationFrames) { ALOGW("Client adjusted notificationFrames from %u to %zu for frameCount %zu", mNotificationFramesAct, maxNotificationFrames, frameCount); mNotificationFramesAct = (uint32_t) maxNotificationFrames; } } Loading
services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -564,6 +564,7 @@ private: PlaybackThread *srcThread, PlaybackThread *dstThread, bool reRegister); // return thread associated with primary hardware device, or NULL PlaybackThread *primaryPlaybackThread_l() const; audio_devices_t primaryOutputDevice_l() const; Loading