diff options
author | Chih-Chung Chang <chihchung@google.com> | 2011-08-28 21:57:59 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-08-28 21:57:59 -0700 |
commit | a007d502e7572b225124eea31defbd27b59d4161 (patch) | |
tree | 42028f700b5faa622f56e0bdf7def9dbd164b16a | |
parent | 5f9cd08076587935f798b2b2eba4aa202362f532 (diff) | |
parent | 3d974e7763495d8fda6f264810619cb3bd265293 (diff) | |
download | frameworks_av-a007d502e7572b225124eea31defbd27b59d4161.zip frameworks_av-a007d502e7572b225124eea31defbd27b59d4161.tar.gz frameworks_av-a007d502e7572b225124eea31defbd27b59d4161.tar.bz2 |
Merge "Fix 5123908: Native crash rewinding movie"
-rwxr-xr-x | libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp | 8 | ||||
-rwxr-xr-x | libvideoeditor/lvpp/VideoEditorSRC.cpp | 384 | ||||
-rwxr-xr-x | libvideoeditor/lvpp/VideoEditorSRC.h | 18 |
3 files changed, 149 insertions, 261 deletions
diff --git a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp index fea24c7..89a0450 100755 --- a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp +++ b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp @@ -499,18 +499,10 @@ size_t VideoEditorAudioPlayer::fillBuffer(void *data, size_t size) { bgFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc( len, 1, (M4OSA_Char*)"bgFrame"); - if (NULL == bgFrame.m_dataAddress) { - LOGE("mBackgroundAudioSetting Malloc failed"); - } - bgFrame.m_bufferSize = len; mixFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc(len, 1, (M4OSA_Char*)"mixFrame"); - if (NULL == mixFrame.m_dataAddress) { - LOGE("mBackgroundAudioSetting Malloc failed"); - } - mixFrame.m_bufferSize = len; LOGV("mix with bgm with size %lld", mBGAudioPCMFileLength); diff --git a/libvideoeditor/lvpp/VideoEditorSRC.cpp b/libvideoeditor/lvpp/VideoEditorSRC.cpp index 71411ab..1ea32ef 100755 --- a/libvideoeditor/lvpp/VideoEditorSRC.cpp +++ b/libvideoeditor/lvpp/VideoEditorSRC.cpp @@ -14,10 +14,8 @@ * limitations under the License. */ -#define LOG_NDEBUG 1 -#define LOG_TAG "VEAudioSource" -#include <utils/Log.h> - +//#define LOG_NDEBUG 0 +#define LOG_TAG "VideoEditorSRC" #include "VideoEditorSRC.h" #include <media/stagefright/MetaData.h> @@ -25,99 +23,53 @@ #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaDefs.h> #include "AudioMixer.h" - +#include <utils/Log.h> namespace android { -VideoEditorSRC::VideoEditorSRC( - const sp<MediaSource> &source) { - - LOGV("VideoEditorSRC::Create"); +VideoEditorSRC::VideoEditorSRC(const sp<MediaSource> &source) { + LOGV("VideoEditorSRC::VideoEditorSRC %p(%p)", this, source.get()); mSource = source; mResampler = NULL; - mBitDepth = 16; mChannelCnt = 0; mSampleRate = 0; mOutputSampleRate = DEFAULT_SAMPLING_FREQ; mStarted = false; - mIsResamplingRequired = false; - mIsChannelConvertionRequired = false; mInitialTimeStampUs = -1; mAccuOutBufferSize = 0; mSeekTimeUs = -1; + mBuffer = NULL; mLeftover = 0; - mLastReadSize = 0; - mReSampledBuffer = NULL; - mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC; - - mOutputFormat = new MetaData; + mFormatChanged = false; + mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC; // Input Source validation sp<MetaData> format = mSource->getFormat(); const char *mime; - bool success = format->findCString(kKeyMIMEType, &mime); - CHECK(success); + CHECK(format->findCString(kKeyMIMEType, &mime)); CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); - //set the meta data of the output after convertion. - if(mOutputFormat != NULL) { - mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - mOutputFormat->setInt32(kKeySampleRate, DEFAULT_SAMPLING_FREQ); - - //by default we convert all data to stereo - mOutputFormat->setInt32(kKeyChannelCount, 2); - } else { - LOGE("Meta data was not allocated."); - } - - // Allocate a 1 sec buffer (test only, to be refined) - mInterframeBufferPosition = 0; - mInterframeBuffer = new uint8_t[DEFAULT_SAMPLING_FREQ * 2 * 2]; //stereo=2 * bytespersample=2 - - -} - -VideoEditorSRC::~VideoEditorSRC(){ - if (mStarted == true) - stop(); - - if(mOutputFormat != NULL) { - mOutputFormat.clear(); - mOutputFormat = NULL; - } - - if (mInterframeBuffer != NULL){ - delete mInterframeBuffer; - mInterframeBuffer = NULL; - } + // Set the metadata of the output after resampling. + mOutputFormat = new MetaData; + mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); + mOutputFormat->setInt32(kKeySampleRate, DEFAULT_SAMPLING_FREQ); + mOutputFormat->setInt32(kKeyChannelCount, 2); } -void VideoEditorSRC::setResampling(int32_t sampleRate) { - Mutex::Autolock autoLock(mLock); - LOGV("VideoEditorSRC::setResampling called with samplreRate = %d", sampleRate); - if(sampleRate != DEFAULT_SAMPLING_FREQ) { //default case - LOGV("VideoEditor Audio resampler, freq set is other than default"); - CHECK(mOutputFormat->setInt32(kKeySampleRate, DEFAULT_SAMPLING_FREQ)); - } - mOutputSampleRate = sampleRate; - return; +VideoEditorSRC::~VideoEditorSRC() { + LOGV("VideoEditorSRC::~VideoEditorSRC %p(%p)", this, mSource.get()); + stop(); } -status_t VideoEditorSRC::start (MetaData *params) { - Mutex::Autolock autoLock(mLock); - +status_t VideoEditorSRC::start(MetaData *params) { CHECK(!mStarted); - LOGV(" VideoEditorSRC:start() called"); + LOGV("VideoEditorSRC:start %p(%p)", this, mSource.get()); // Set resampler if required - status_t err = checkAndSetResampler(); - if (err != OK) { - LOGE("checkAndSetResampler() returned error %d", err); - return err; - } + checkAndSetResampler(); mSeekTimeUs = -1; - mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC; + mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC; mStarted = true; mSource->start(); @@ -125,9 +77,12 @@ status_t VideoEditorSRC::start (MetaData *params) { } status_t VideoEditorSRC::stop() { - - Mutex::Autolock autoLock(mLock); - LOGV("VideoEditorSRC::stop()"); + LOGV("VideoEditorSRC::stop %p(%p)", this, mSource.get()); + if (!mStarted) return OK; + if (mBuffer) { + mBuffer->release(); + mBuffer = NULL; + } mSource->stop(); if(mResampler != NULL) { delete mResampler; @@ -135,101 +90,87 @@ status_t VideoEditorSRC::stop() { } mStarted = false; mInitialTimeStampUs = -1; - mAccuOutBufferSize = 0; + mAccuOutBufferSize = 0; mLeftover = 0; - mLastReadSize = 0; - if (mReSampledBuffer != NULL) { - free(mReSampledBuffer); - mReSampledBuffer = NULL; - } return OK; } sp<MetaData> VideoEditorSRC::getFormat() { - LOGV("AudioSRC getFormat"); - //Mutex::Autolock autoLock(mLock); + LOGV("VideoEditorSRC::getFormat"); return mOutputFormat; } -status_t VideoEditorSRC::read ( +status_t VideoEditorSRC::read( MediaBuffer **buffer_out, const ReadOptions *options) { - Mutex::Autolock autoLock(mLock); + LOGV("VideoEditorSRC::read %p(%p)", this, mSource.get()); *buffer_out = NULL; - int32_t leftover = 0; - - LOGV("VideoEditorSRC::read"); if (!mStarted) { return ERROR_END_OF_STREAM; } - if(mIsResamplingRequired == true) { - - LOGV("mIsResamplingRequired = true"); - + if (mResampler) { // Store the seek parameters int64_t seekTimeUs; ReadOptions::SeekMode mode = ReadOptions::SEEK_PREVIOUS_SYNC; if (options && options->getSeekTo(&seekTimeUs, &mode)) { LOGV("read Seek %lld", seekTimeUs); - mInitialTimeStampUs = -1; mSeekTimeUs = seekTimeUs; mSeekMode = mode; } // We ask for 1024 frames in output - size_t outFrameCnt = 1024; - int32_t outBufferSize = (outFrameCnt) * 2 * sizeof(int16_t); //out is always 2 channels & 16 bits - int64_t outDurationUs = (outBufferSize * 1000000) /(mOutputSampleRate * 2 * sizeof(int16_t)); //2 channels out * 2 bytes per sample - LOGV("outBufferSize %d", outBufferSize); - LOGV("outFrameCnt %d", outFrameCnt); - - int32_t *pTmpBuffer = (int32_t*)malloc(outFrameCnt * 2 * sizeof(int32_t)); //out is always 2 channels and resampler out is 32 bits - memset(pTmpBuffer, 0x00, outFrameCnt * 2 * sizeof(int32_t)); + const size_t outFrameCnt = 1024; + // resampler output is always 2 channels and 32 bits + int32_t *pTmpBuffer = (int32_t *)calloc(1, outFrameCnt * 2 * sizeof(int32_t)); // Resample to target quality mResampler->resample(pTmpBuffer, outFrameCnt, this); - // Free previous allocation - if (mReSampledBuffer != NULL) { - free(mReSampledBuffer); - mReSampledBuffer = NULL; + // Change resampler and retry if format change happened + if (mFormatChanged) { + mFormatChanged = false; + checkAndSetResampler(); + free(pTmpBuffer); + return read(buffer_out, NULL); } - mReSampledBuffer = (int16_t*)malloc(outBufferSize); - memset(mReSampledBuffer, 0x00, outBufferSize); - // Convert back to 16 bits - AudioMixer::ditherAndClamp((int32_t*)mReSampledBuffer, pTmpBuffer, outFrameCnt); - LOGV("Resampled buffer size %d", outFrameCnt* 2 * sizeof(int16_t)); + // Create a new MediaBuffer + int32_t outBufferSize = outFrameCnt * 2 * sizeof(int16_t); + MediaBuffer* outBuffer = new MediaBuffer(outBufferSize); - // Create new MediaBuffer - mCopyBuffer = new MediaBuffer((void*)mReSampledBuffer, outBufferSize); + // Convert back to 2 channels and 16 bits + AudioMixer::ditherAndClamp( + (int32_t *)((uint8_t*)outBuffer->data() + outBuffer->range_offset()), + pTmpBuffer, outFrameCnt); + free(pTmpBuffer); // Compute and set the new timestamp - sp<MetaData> to = mCopyBuffer->meta_data(); - int64_t totalOutDurationUs = (mAccuOutBufferSize * 1000000) /(mOutputSampleRate * 2 * 2); //2 channels out * 2 bytes per sample + sp<MetaData> to = outBuffer->meta_data(); + int64_t totalOutDurationUs = (mAccuOutBufferSize * 1000000) / (mOutputSampleRate * 2 * 2); int64_t timeUs = mInitialTimeStampUs + totalOutDurationUs; to->setInt64(kKeyTime, timeUs); - LOGV("buffer duration %lld timestamp %lld init %lld", outDurationUs, timeUs, mInitialTimeStampUs); // update the accumulate size mAccuOutBufferSize += outBufferSize; - - mCopyBuffer->set_range(0, outBufferSize); - *buffer_out = mCopyBuffer; - - free(pTmpBuffer); - - } else if(mIsChannelConvertionRequired == true) { - //TODO convert to stereo here. + *buffer_out = outBuffer; } else { - //LOGI("Resampling not required"); + // Resampling not required. Read and pass-through. MediaBuffer *aBuffer; status_t err = mSource->read(&aBuffer, options); - LOGV("mSource->read returned %d", err); + if (err != OK) { + LOGV("read returns err = %d", err); + } + + if (err == INFO_FORMAT_CHANGED) { + checkAndSetResampler(); + return read(buffer_out, NULL); + } + + // EOS or some other error if(err != OK) { + stop(); *buffer_out = NULL; - mStarted = false; return err; } *buffer_out = aBuffer; @@ -239,166 +180,131 @@ status_t VideoEditorSRC::read ( } status_t VideoEditorSRC::getNextBuffer(AudioBufferProvider::Buffer *pBuffer) { - LOGV("Requesting %d", pBuffer->frameCount); - uint32_t availableFrames; - bool lastBuffer = false; - MediaBuffer *aBuffer; - - //update the internal buffer - // Store the leftover at the beginning of the local buffer - if (mLeftover > 0) { - LOGV("Moving mLeftover =%d from %d", mLeftover, mLastReadSize); - if (mLastReadSize > 0) { - memcpy(mInterframeBuffer, (uint8_t*) (mInterframeBuffer + mLastReadSize), mLeftover); - } - mInterframeBufferPosition = mLeftover; - } - else { - mInterframeBufferPosition = 0; - } + LOGV("Requesting %d, chan = %d", pBuffer->frameCount, mChannelCnt); + uint32_t done = 0; + uint32_t want = pBuffer->frameCount * mChannelCnt * 2; + pBuffer->raw = malloc(want); + + while (mStarted && want > 0) { + // If we don't have any data left, read a new buffer. + if (!mBuffer) { + // if we seek, reset the initial time stamp and accumulated time + ReadOptions options; + if (mSeekTimeUs >= 0) { + LOGV("%p cacheMore_l Seek requested = %lld", this, mSeekTimeUs); + ReadOptions::SeekMode mode = mSeekMode; + options.setSeekTo(mSeekTimeUs, mode); + mSeekTimeUs = -1; + mInitialTimeStampUs = -1; + mAccuOutBufferSize = 0; + } - availableFrames = mInterframeBufferPosition / (mChannelCnt*2); + status_t err = mSource->read(&mBuffer, &options); - while ((availableFrames < pBuffer->frameCount)&&(mStarted)) { - // if we seek, reset the initial time stamp and accumulated time - ReadOptions options; - if (mSeekTimeUs >= 0) { - LOGV("%p cacheMore_l Seek requested = %lld", this, mSeekTimeUs); - ReadOptions::SeekMode mode = mSeekMode; - options.setSeekTo(mSeekTimeUs, mode); - mSeekTimeUs = -1; - } - /* The first call to read() will require to buffer twice as much data */ - /* This will be needed by the resampler */ - status_t err = mSource->read(&aBuffer, &options); - LOGV("mSource->read returned %d", err); - if (err == INFO_FORMAT_CHANGED) { - LOGV("getNextBuffer: source read returned INFO_FORMAT_CHANGED"); - // Change resampler if required - status_t err1 = checkAndSetResampler(); - if (err1 != OK) { - LOGE("checkAndSetResampler() returned error %d", err1); - return err1; + if (err != OK) { + free(pBuffer->raw); + pBuffer->raw = NULL; + pBuffer->frameCount = 0; } - // Update availableFrames with new channel count - availableFrames = mInterframeBufferPosition / (mChannelCnt*2); - continue; - } else if (err != OK) { - if (mInterframeBufferPosition == 0) { - mStarted = false; - } - //Empty the internal buffer if there is no more data left in the source - else { - lastBuffer = true; - //clear the end of the buffer, just in case - memset(mInterframeBuffer+mInterframeBufferPosition, 0x00, DEFAULT_SAMPLING_FREQ * 2 * 2 - mInterframeBufferPosition); - mStarted = false; + + if (err == INFO_FORMAT_CHANGED) { + LOGV("getNextBuffer: source read returned INFO_FORMAT_CHANGED"); + // At this point we cannot switch to a new AudioResampler because + // we are in a callback called by the AudioResampler itself. So + // just remember the fact that the format has changed, and let + // read() handles this. + mFormatChanged = true; + return err; } - } - else { - //copy the buffer - memcpy(((uint8_t*) mInterframeBuffer) + mInterframeBufferPosition, - ((uint8_t*) aBuffer->data()) + aBuffer->range_offset(), - aBuffer->range_length()); - LOGV("Read from buffer %d", aBuffer->range_length()); - mInterframeBufferPosition += aBuffer->range_length(); - LOGV("Stored %d", mInterframeBufferPosition); + // EOS or some other error + if (err != OK) { + LOGV("EOS or some err: %d", err); + stop(); + return err; + } - // Get the time stamp of the first buffer + CHECK(mBuffer); + mLeftover = mBuffer->range_length(); if (mInitialTimeStampUs == -1) { int64_t curTS; - sp<MetaData> from = aBuffer->meta_data(); + sp<MetaData> from = mBuffer->meta_data(); from->findInt64(kKeyTime, &curTS); LOGV("setting mInitialTimeStampUs to %lld", mInitialTimeStampUs); mInitialTimeStampUs = curTS; } + } - // release the buffer - aBuffer->release(); + // Now copy data to the destination + uint32_t todo = mLeftover; + if (todo > want) { + todo = want; } - availableFrames = mInterframeBufferPosition / (mChannelCnt*2); - LOGV("availableFrames %d", availableFrames); - } - if (lastBuffer) { - pBuffer->frameCount = availableFrames; + uint8_t* end = (uint8_t*)mBuffer->data() + mBuffer->range_offset() + + mBuffer->range_length(); + memcpy((uint8_t*)pBuffer->raw + done, end - mLeftover, todo); + done += todo; + want -= todo; + mLeftover -= todo; + + // Release MediaBuffer as soon as possible. + if (mLeftover == 0) { + mBuffer->release(); + mBuffer = NULL; + } } - //update the input buffer - pBuffer->raw = (void*)(mInterframeBuffer); - - // Update how many bytes are left - // (actualReadSize is updated in getNextBuffer() called from resample()) - int32_t actualReadSize = pBuffer->frameCount * mChannelCnt * 2; - mLeftover = mInterframeBufferPosition - actualReadSize; - LOGV("mLeftover %d", mLeftover); - - mLastReadSize = actualReadSize; - - LOGV("inFrameCount %d", pBuffer->frameCount); - + pBuffer->frameCount = done / (mChannelCnt * 2); + LOGV("getNextBuffer done %d", pBuffer->frameCount); return OK; } void VideoEditorSRC::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) { - if(pBuffer->raw != NULL) { - pBuffer->raw = NULL; - } + free(pBuffer->raw); + pBuffer->raw = NULL; pBuffer->frameCount = 0; } -status_t VideoEditorSRC::checkAndSetResampler() { - +void VideoEditorSRC::checkAndSetResampler() { LOGV("checkAndSetResampler"); sp<MetaData> format = mSource->getFormat(); const char *mime; - bool success = format->findCString(kKeyMIMEType, &mime); - CHECK(success); + CHECK(format->findCString(kKeyMIMEType, &mime)); CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); - success = format->findInt32(kKeySampleRate, &mSampleRate); - CHECK(success); + CHECK(format->findInt32(kKeySampleRate, &mSampleRate)); + CHECK(format->findInt32(kKeyChannelCount, &mChannelCnt)); - int32_t numChannels; - success = format->findInt32(kKeyChannelCount, &mChannelCnt); - CHECK(success); - - // If Resampler exists, delete it first + // If a resampler exists, delete it first if (mResampler != NULL) { delete mResampler; mResampler = NULL; } - if (mSampleRate != mOutputSampleRate) { - LOGV("Resampling required (%d != %d)", mSampleRate, mOutputSampleRate); - mIsResamplingRequired = true; - LOGV("Create resampler %d %d %d", mBitDepth, mChannelCnt, mOutputSampleRate); + // Clear previous buffer + if (mBuffer) { + mBuffer->release(); + mBuffer = NULL; + } - mResampler = AudioResampler::create( - mBitDepth, mChannelCnt, mOutputSampleRate, AudioResampler::DEFAULT); + if (mSampleRate != mOutputSampleRate || mChannelCnt != 2) { + LOGV("Resampling required (in rate %d, out rate %d, in channel %d)", + mSampleRate, mOutputSampleRate, mChannelCnt); - if (mResampler == NULL) { - return NO_MEMORY; - } - LOGV("Set input rate %d", mSampleRate); + mResampler = AudioResampler::create( + 16 /* bit depth */, + mChannelCnt, + mOutputSampleRate, + AudioResampler::DEFAULT); + CHECK(mResampler); mResampler->setSampleRate(mSampleRate); mResampler->setVolume(UNITY_GAIN, UNITY_GAIN); - } else { LOGV("Resampling not required (%d = %d)", mSampleRate, mOutputSampleRate); - mIsResamplingRequired = false; - if (mChannelCnt != 2) { - // we always make sure to provide stereo - LOGV("Only Channel convertion required"); - mIsChannelConvertionRequired = true; - } } - - return OK; - } } //namespce android diff --git a/libvideoeditor/lvpp/VideoEditorSRC.h b/libvideoeditor/lvpp/VideoEditorSRC.h index 20313e3..a5e8e22 100755 --- a/libvideoeditor/lvpp/VideoEditorSRC.h +++ b/libvideoeditor/lvpp/VideoEditorSRC.h @@ -43,8 +43,6 @@ class VideoEditorSRC : public MediaSource , public AudioBufferProvider { virtual status_t getNextBuffer(Buffer* buffer); virtual void releaseBuffer(Buffer* buffer); - void setResampling(int32_t sampleRate=kFreq32000Hz); - enum { //Sampling freq kFreq8000Hz = 8000, kFreq11025Hz = 11025, @@ -58,7 +56,7 @@ class VideoEditorSRC : public MediaSource , public AudioBufferProvider { }; static const uint16_t UNITY_GAIN = 0x1000; - static const int32_t DEFAULT_SAMPLING_FREQ = (int32_t)kFreq32000Hz; // kFreq44100; + static const int32_t DEFAULT_SAMPLING_FREQ = (int32_t)kFreq32000Hz; protected : virtual ~VideoEditorSRC(); @@ -67,33 +65,25 @@ class VideoEditorSRC : public MediaSource , public AudioBufferProvider { VideoEditorSRC(); VideoEditorSRC &operator=(const VideoEditorSRC &); - status_t checkAndSetResampler(); + void checkAndSetResampler(); AudioResampler *mResampler; sp<MediaSource> mSource; - MediaBuffer *mCopyBuffer; - int mBitDepth; int mChannelCnt; int mSampleRate; int32_t mOutputSampleRate; bool mStarted; - bool mIsResamplingRequired; - bool mIsChannelConvertionRequired; // for mono to stereo sp<MetaData> mOutputFormat; - Mutex mLock; - uint8_t* mInterframeBuffer; - int32_t mInterframeBufferPosition; + MediaBuffer* mBuffer; int32_t mLeftover; - int32_t mLastReadSize ; + bool mFormatChanged; int64_t mInitialTimeStampUs; int64_t mAccuOutBufferSize; int64_t mSeekTimeUs; ReadOptions::SeekMode mSeekMode; - int16_t *mReSampledBuffer; - }; } //namespce android |