diff options
Diffstat (limited to 'media/libstagefright/WAVExtractor.cpp')
-rw-r--r-- | media/libstagefright/WAVExtractor.cpp | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index 335ac84..62bb416 100644 --- a/media/libstagefright/WAVExtractor.cpp +++ b/media/libstagefright/WAVExtractor.cpp @@ -29,6 +29,7 @@ #include <media/stagefright/MetaData.h> #include <utils/String8.h> #include <cutils/bitops.h> +#include <system/audio.h> #define CHANNEL_MASK_USE_CHANNEL_ORDER 0 @@ -193,15 +194,17 @@ status_t WAVExtractor::init() { } mNumChannels = U16_LE_AT(&formatSpec[2]); + + if (mNumChannels < 1 || mNumChannels > 8) { + ALOGE("Unsupported number of channels (%d)", mNumChannels); + return ERROR_UNSUPPORTED; + } + if (mWaveFormat != WAVE_FORMAT_EXTENSIBLE) { if (mNumChannels != 1 && mNumChannels != 2) { ALOGW("More than 2 channels (%d) in non-WAVE_EXT, unknown channel mask", mNumChannels); } - } else { - if (mNumChannels < 1 && mNumChannels > 8) { - return ERROR_UNSUPPORTED; - } } mSampleRate = U32_LE_AT(&formatSpec[4]); @@ -284,6 +287,7 @@ status_t WAVExtractor::init() { case WAVE_FORMAT_PCM: mTrackMeta->setCString( kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); + mTrackMeta->setInt32(kKeyBitsPerSample, mBitsPerSample); break; case WAVE_FORMAT_ALAW: mTrackMeta->setCString( @@ -311,9 +315,17 @@ status_t WAVExtractor::init() { 1000000LL * (mDataSize / 65 * 320) / 8000; } else { size_t bytesPerSample = mBitsPerSample >> 3; + + if (!bytesPerSample || !mNumChannels) + return ERROR_MALFORMED; + + size_t num_samples = mDataSize / (mNumChannels * bytesPerSample); + + if (!mSampleRate) + return ERROR_MALFORMED; + durationUs = - 1000000LL * (mDataSize / (mNumChannels * bytesPerSample)) - / mSampleRate; + 1000000LL * num_samples / mSampleRate; } mTrackMeta->setInt64(kKeyDuration, durationUs); @@ -359,15 +371,16 @@ WAVSource::~WAVSource() { } status_t WAVSource::start(MetaData * /* params */) { - ALOGV("WAVSource::start"); - CHECK(!mStarted); + if (mStarted) { + return OK; + } mGroup = new MediaBufferGroup; mGroup->add_buffer(new MediaBuffer(kMaxFrameSize)); - if (mBitsPerSample == 8) { - // As a temporary buffer for 8->16 bit conversion. + if (mBitsPerSample == 8 || mBitsPerSample == 24) { + // As a temporary buffer for 8->16/24->32 bit conversion. mGroup->add_buffer(new MediaBuffer(kMaxFrameSize)); } @@ -427,9 +440,15 @@ status_t WAVSource::read( } // make sure that maxBytesToRead is multiple of 3, in 24-bit case - size_t maxBytesToRead = - mBitsPerSample == 8 ? kMaxFrameSize / 2 : - (mBitsPerSample == 24 ? 3*(kMaxFrameSize/3): kMaxFrameSize); + size_t maxBytesToRead; + if(8 == mBitsPerSample) + maxBytesToRead = kMaxFrameSize / 2; + else if (24 == mBitsPerSample) { + maxBytesToRead = 3*(kMaxFrameSize/4); + } else + maxBytesToRead = kMaxFrameSize; + ALOGV("%s mBitsPerSample %d, kMaxFrameSize %zu, ", + __func__, mBitsPerSample, kMaxFrameSize); size_t maxBytesAvailable = (mCurrentPos - mOffset >= (off64_t)mSize) @@ -488,23 +507,24 @@ status_t WAVSource::read( buffer->release(); buffer = tmp; } else if (mBitsPerSample == 24) { - // Convert 24-bit signed samples to 16-bit signed. - - const uint8_t *src = - (const uint8_t *)buffer->data() + buffer->range_offset(); - int16_t *dst = (int16_t *)src; - - size_t numSamples = buffer->range_length() / 3; - for (size_t i = 0; i < numSamples; ++i) { - int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16); - x = (x << 8) >> 8; // sign extension - - x = x >> 8; - *dst++ = (int16_t)x; - src += 3; + // Padding done here to convert to 32-bit samples + MediaBuffer *tmp; + CHECK_EQ(mGroup->acquire_buffer(&tmp), (status_t)OK); + ssize_t numBytes = buffer->range_length() / 3; + tmp->set_range(0, 4 * numBytes); + int8_t *dst = (int8_t *)tmp->data(); + const uint8_t *src = (const uint8_t *)buffer->data(); + ALOGV("numBytes = %zd", numBytes); + while(numBytes-- > 0) { + *dst++ = 0x0; + *dst++ = src[0]; + *dst++ = src[1]; + *dst++ = src[2]; + src += 3; } - - buffer->set_range(buffer->range_offset(), 2 * numSamples); + buffer->release(); + buffer = tmp; + ALOGV("length = %zu", buffer->range_length()); } } |