Loading include/media/stagefright/AudioSource.h +9 −2 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ struct AudioSource : public MediaSource, public MediaBufferObserver { MediaBuffer **buffer, const ReadOptions *options = NULL); status_t dataCallback(const AudioRecord::Buffer& buffer); virtual void onEvent(int event, void* info); virtual void signalBufferReturned(MediaBuffer *buffer); protected: Loading @@ -60,7 +61,9 @@ protected: private: enum { kMaxBufferSize = 2048, //This max buffer size is derived from aggregation of audio //buffers for max duration 80 msec with 48K sampling rate. kMaxBufferSize = 30720, // After the initial mute, we raise the volume linearly // over kAutoRampDurationUs. Loading @@ -75,6 +78,11 @@ private: Condition mFrameAvailableCondition; Condition mFrameEncodingCompletionCondition; AudioRecord::Buffer mTempBuf; uint32_t mPrevPosition; uint32_t mAllocBytes; int32_t mAudioSessionId; AudioRecord::transfer_type mTransferMode; sp<AudioRecord> mRecord; status_t mInitCheck; bool mStarted; Loading @@ -91,7 +99,6 @@ private: int64_t mAutoRampStartUs; List<MediaBuffer * > mBuffersReceived; void trackMaxAmplitude(int16_t *data, int nSamples); // This is used to raise the volume from mute to the Loading media/libstagefright/AudioSource.cpp +138 −20 Original line number Diff line number Diff line Loading @@ -31,23 +31,12 @@ #include <cutils/properties.h> #include <system/audio.h> #define AUDIO_RECORD_DEFAULT_BUFFER_DURATION 20 namespace android { static void AudioRecordCallbackFunction(int event, void *user, void *info) { AudioSource *source = (AudioSource *) user; switch (event) { case AudioRecord::EVENT_MORE_DATA: { source->dataCallback(*((AudioRecord::Buffer *) info)); break; } case AudioRecord::EVENT_OVERRUN: { ALOGW("AudioRecord reported overrun!"); break; } default: // does nothing break; } source->onEvent(event, info); } AudioSource::AudioSource( Loading Loading @@ -80,6 +69,60 @@ AudioSource::AudioSource( bufCount++; } mTempBuf.size = 0; mTempBuf.frameCount = 0; mTempBuf.i16 = (short*)NULL; mPrevPosition = 0; mAudioSessionId = -1; mAllocBytes = 0; mTransferMode = AudioRecord::TRANSFER_CALLBACK; //decide whether to use callback or event pos callback //use position marker only for PCM 16 bit and mono or stereo capture //and if input source is camera if((mFormat == AUDIO_FORMAT_PCM_16_BIT) && ((channelCount == 1) || (channelCount == 2)) && (inputSource == AUDIO_SOURCE_CAMCORDER)) { //Need audioSession Id in the extended audio record constructor //where the transfer mode can be specified mAudioSessionId = AudioSystem::newAudioUniqueId(); AudioSystem::acquireAudioSessionId(mAudioSessionId, -1); mRecord = new AudioRecord( inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_in_mask_from_count(channelCount), (size_t) (bufCount * frameCount), AudioRecordCallbackFunction, this, frameCount /*notificationFrames*/, mAudioSessionId, AudioRecord::TRANSFER_SYNC, AUDIO_INPUT_FLAG_NONE); int buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION; char propValue[PROPERTY_VALUE_MAX]; if (property_get("audio.record.buffer.duration", propValue, NULL)) { if (atoi(propValue) < AUDIO_RECORD_DEFAULT_BUFFER_DURATION) buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION; else buffDuration = atoi(propValue); } else buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION; //set to update position after frames worth of buffduration time for 16 bits mAllocBytes = ((sizeof(uint8_t) * frameCount * 2 * channelCount)); ALOGI("AudioSource in TRANSFER_SYNC with duration %d ms", buffDuration); mTempBuf.i16 = (short*) malloc(mAllocBytes); if (mTempBuf.i16 == NULL) { mAllocBytes = 0; mInitCheck = NO_MEMORY; } mTransferMode = AudioRecord::TRANSFER_SYNC; mRecord->setPositionUpdatePeriod((sampleRate * buffDuration)/1000); } else { //Sound recorder and VOIP use cases does NOT use aggregation mRecord = new AudioRecord( inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_in_mask_from_count(channelCount), Loading @@ -87,7 +130,12 @@ AudioSource::AudioSource( AudioRecordCallbackFunction, this, frameCount /*notificationFrames*/); ALOGI("AudioSource in TRANSFER_CALLBACK"); mTransferMode = AudioRecord::TRANSFER_CALLBACK; } mInitCheck = mRecord->initCheck(); mAutoRampStartUs = kAutoRampStartUs; uint32_t playbackLatencyMs = 0; if (AudioSystem::getOutputLatency(&playbackLatencyMs, Loading @@ -100,6 +148,7 @@ AudioSource::AudioSource( } else { mInitCheck = status; } ALOGV("mInitCheck %d", mInitCheck); } AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta ) Loading Loading @@ -137,6 +186,14 @@ AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta ) AudioRecordCallbackFunction, this); mInitCheck = mRecord->initCheck(); mTempBuf.size = 0; mTempBuf.frameCount = 0; mTempBuf.i16 = (short*)NULL; mPrevPosition = 0; mAudioSessionId = -1; mAllocBytes = 0; mTransferMode = AudioRecord::TRANSFER_CALLBACK; } AudioSource::~AudioSource() { Loading Loading @@ -223,6 +280,16 @@ status_t AudioSource::reset() { waitOutstandingEncodingFrames_l(); releaseQueuedFrames_l(); if (mTransferMode == AudioRecord::TRANSFER_SYNC) { if(mAudioSessionId != -1) AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); mAudioSessionId = -1; if(mTempBuf.i16) { free(mTempBuf.i16); mTempBuf.i16 = (short*)NULL; } } return OK; } Loading Loading @@ -408,6 +475,57 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { return OK; } void AudioSource::onEvent(int event, void* info) { switch (event) { case AudioRecord::EVENT_MORE_DATA: { dataCallback(*((AudioRecord::Buffer *) info)); break; } case AudioRecord::EVENT_NEW_POS: { uint32_t position = 0; mRecord->getPosition(&position); size_t framestoRead = position - mPrevPosition; size_t bytestoRead = (framestoRead * 2 * mRecord->channelCount()); if(bytestoRead <=0 || bytestoRead > mAllocBytes) { //try to read only max ALOGI("greater than allocated size in callback, adjusting size"); bytestoRead = mAllocBytes; framestoRead = (mAllocBytes / (2 * mRecord->channelCount())); } if(mTempBuf.i16 && framestoRead > 0) { //read only if you have valid data size_t bytesRead = mRecord->read(mTempBuf.i16, framestoRead); size_t framesRead = 0; ALOGV("event_new_pos, new pos %d, frames to read %d\n", \ position, framestoRead); ALOGV("bytes read = %d \n", bytesRead); if(bytesRead > 0){ framesRead = (bytesRead / (2 * mRecord->channelCount())); mPrevPosition += framesRead; mTempBuf.size = bytesRead; mTempBuf.frameCount = framesRead; dataCallback(mTempBuf); } else { ALOGE("EVENT_NEW_POS did not return any data"); } } else { ALOGE("Init error"); } break; } case AudioRecord::EVENT_OVERRUN: { ALOGW("AudioRecord reported overrun!"); break; } default: // does nothing break; } return; } void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) { if (mRecPaused) { if (!mBuffersReceived.empty()) { Loading Loading
include/media/stagefright/AudioSource.h +9 −2 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ struct AudioSource : public MediaSource, public MediaBufferObserver { MediaBuffer **buffer, const ReadOptions *options = NULL); status_t dataCallback(const AudioRecord::Buffer& buffer); virtual void onEvent(int event, void* info); virtual void signalBufferReturned(MediaBuffer *buffer); protected: Loading @@ -60,7 +61,9 @@ protected: private: enum { kMaxBufferSize = 2048, //This max buffer size is derived from aggregation of audio //buffers for max duration 80 msec with 48K sampling rate. kMaxBufferSize = 30720, // After the initial mute, we raise the volume linearly // over kAutoRampDurationUs. Loading @@ -75,6 +78,11 @@ private: Condition mFrameAvailableCondition; Condition mFrameEncodingCompletionCondition; AudioRecord::Buffer mTempBuf; uint32_t mPrevPosition; uint32_t mAllocBytes; int32_t mAudioSessionId; AudioRecord::transfer_type mTransferMode; sp<AudioRecord> mRecord; status_t mInitCheck; bool mStarted; Loading @@ -91,7 +99,6 @@ private: int64_t mAutoRampStartUs; List<MediaBuffer * > mBuffersReceived; void trackMaxAmplitude(int16_t *data, int nSamples); // This is used to raise the volume from mute to the Loading
media/libstagefright/AudioSource.cpp +138 −20 Original line number Diff line number Diff line Loading @@ -31,23 +31,12 @@ #include <cutils/properties.h> #include <system/audio.h> #define AUDIO_RECORD_DEFAULT_BUFFER_DURATION 20 namespace android { static void AudioRecordCallbackFunction(int event, void *user, void *info) { AudioSource *source = (AudioSource *) user; switch (event) { case AudioRecord::EVENT_MORE_DATA: { source->dataCallback(*((AudioRecord::Buffer *) info)); break; } case AudioRecord::EVENT_OVERRUN: { ALOGW("AudioRecord reported overrun!"); break; } default: // does nothing break; } source->onEvent(event, info); } AudioSource::AudioSource( Loading Loading @@ -80,6 +69,60 @@ AudioSource::AudioSource( bufCount++; } mTempBuf.size = 0; mTempBuf.frameCount = 0; mTempBuf.i16 = (short*)NULL; mPrevPosition = 0; mAudioSessionId = -1; mAllocBytes = 0; mTransferMode = AudioRecord::TRANSFER_CALLBACK; //decide whether to use callback or event pos callback //use position marker only for PCM 16 bit and mono or stereo capture //and if input source is camera if((mFormat == AUDIO_FORMAT_PCM_16_BIT) && ((channelCount == 1) || (channelCount == 2)) && (inputSource == AUDIO_SOURCE_CAMCORDER)) { //Need audioSession Id in the extended audio record constructor //where the transfer mode can be specified mAudioSessionId = AudioSystem::newAudioUniqueId(); AudioSystem::acquireAudioSessionId(mAudioSessionId, -1); mRecord = new AudioRecord( inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_in_mask_from_count(channelCount), (size_t) (bufCount * frameCount), AudioRecordCallbackFunction, this, frameCount /*notificationFrames*/, mAudioSessionId, AudioRecord::TRANSFER_SYNC, AUDIO_INPUT_FLAG_NONE); int buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION; char propValue[PROPERTY_VALUE_MAX]; if (property_get("audio.record.buffer.duration", propValue, NULL)) { if (atoi(propValue) < AUDIO_RECORD_DEFAULT_BUFFER_DURATION) buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION; else buffDuration = atoi(propValue); } else buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION; //set to update position after frames worth of buffduration time for 16 bits mAllocBytes = ((sizeof(uint8_t) * frameCount * 2 * channelCount)); ALOGI("AudioSource in TRANSFER_SYNC with duration %d ms", buffDuration); mTempBuf.i16 = (short*) malloc(mAllocBytes); if (mTempBuf.i16 == NULL) { mAllocBytes = 0; mInitCheck = NO_MEMORY; } mTransferMode = AudioRecord::TRANSFER_SYNC; mRecord->setPositionUpdatePeriod((sampleRate * buffDuration)/1000); } else { //Sound recorder and VOIP use cases does NOT use aggregation mRecord = new AudioRecord( inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_in_mask_from_count(channelCount), Loading @@ -87,7 +130,12 @@ AudioSource::AudioSource( AudioRecordCallbackFunction, this, frameCount /*notificationFrames*/); ALOGI("AudioSource in TRANSFER_CALLBACK"); mTransferMode = AudioRecord::TRANSFER_CALLBACK; } mInitCheck = mRecord->initCheck(); mAutoRampStartUs = kAutoRampStartUs; uint32_t playbackLatencyMs = 0; if (AudioSystem::getOutputLatency(&playbackLatencyMs, Loading @@ -100,6 +148,7 @@ AudioSource::AudioSource( } else { mInitCheck = status; } ALOGV("mInitCheck %d", mInitCheck); } AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta ) Loading Loading @@ -137,6 +186,14 @@ AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta ) AudioRecordCallbackFunction, this); mInitCheck = mRecord->initCheck(); mTempBuf.size = 0; mTempBuf.frameCount = 0; mTempBuf.i16 = (short*)NULL; mPrevPosition = 0; mAudioSessionId = -1; mAllocBytes = 0; mTransferMode = AudioRecord::TRANSFER_CALLBACK; } AudioSource::~AudioSource() { Loading Loading @@ -223,6 +280,16 @@ status_t AudioSource::reset() { waitOutstandingEncodingFrames_l(); releaseQueuedFrames_l(); if (mTransferMode == AudioRecord::TRANSFER_SYNC) { if(mAudioSessionId != -1) AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); mAudioSessionId = -1; if(mTempBuf.i16) { free(mTempBuf.i16); mTempBuf.i16 = (short*)NULL; } } return OK; } Loading Loading @@ -408,6 +475,57 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { return OK; } void AudioSource::onEvent(int event, void* info) { switch (event) { case AudioRecord::EVENT_MORE_DATA: { dataCallback(*((AudioRecord::Buffer *) info)); break; } case AudioRecord::EVENT_NEW_POS: { uint32_t position = 0; mRecord->getPosition(&position); size_t framestoRead = position - mPrevPosition; size_t bytestoRead = (framestoRead * 2 * mRecord->channelCount()); if(bytestoRead <=0 || bytestoRead > mAllocBytes) { //try to read only max ALOGI("greater than allocated size in callback, adjusting size"); bytestoRead = mAllocBytes; framestoRead = (mAllocBytes / (2 * mRecord->channelCount())); } if(mTempBuf.i16 && framestoRead > 0) { //read only if you have valid data size_t bytesRead = mRecord->read(mTempBuf.i16, framestoRead); size_t framesRead = 0; ALOGV("event_new_pos, new pos %d, frames to read %d\n", \ position, framestoRead); ALOGV("bytes read = %d \n", bytesRead); if(bytesRead > 0){ framesRead = (bytesRead / (2 * mRecord->channelCount())); mPrevPosition += framesRead; mTempBuf.size = bytesRead; mTempBuf.frameCount = framesRead; dataCallback(mTempBuf); } else { ALOGE("EVENT_NEW_POS did not return any data"); } } else { ALOGE("Init error"); } break; } case AudioRecord::EVENT_OVERRUN: { ALOGW("AudioRecord reported overrun!"); break; } default: // does nothing break; } return; } void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) { if (mRecPaused) { if (!mBuffersReceived.empty()) { Loading