diff options
author | Steve Kondik <steve@cyngn.com> | 2014-11-28 23:26:30 -0800 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-10-28 16:44:24 -0700 |
commit | cdb6566861c4741f5bd114aa25c0e754ba7e8ae0 (patch) | |
tree | a15cc0f8cc7963ef41f0a4d8411aeecd28bebf51 | |
parent | e8e76dbe389171f25ba95f0ef95169bae953a028 (diff) | |
download | frameworks_av-cdb6566861c4741f5bd114aa25c0e754ba7e8ae0.zip frameworks_av-cdb6566861c4741f5bd114aa25c0e754ba7e8ae0.tar.gz frameworks_av-cdb6566861c4741f5bd114aa25c0e754ba7e8ae0.tar.bz2 |
stagefright: Improve FLAC and WAV support for 24-bit
* Forward-port changes from CM11
* Remove truncation support as AudioFlinger handles
rebuffering in case it can't go to the hardware.
Change-Id: Iad30d04ee051050e444c3d665fa8bb7a1cfef348
-rw-r--r-- | media/libstagefright/FLACExtractor.cpp | 182 | ||||
-rw-r--r-- | media/libstagefright/WAVExtractor.cpp | 56 |
2 files changed, 88 insertions, 150 deletions
diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp index c79180b..87345e1 100644 --- a/media/libstagefright/FLACExtractor.cpp +++ b/media/libstagefright/FLACExtractor.cpp @@ -32,6 +32,13 @@ #include <media/stagefright/MediaSource.h> #include <media/stagefright/MediaBuffer.h> +#ifdef ENABLE_AV_ENHANCEMENTS +#include "QCMediaDefs.h" +#include "QCMetaData.h" +#endif + +#include <system/audio.h> + namespace android { class FLACParser; @@ -72,6 +79,8 @@ private: class FLACParser : public RefBase { +friend class FLACSource; + public: FLACParser( const sp<DataSource> &dataSource, @@ -103,6 +112,8 @@ public: // media buffers void allocateBuffers(); void releaseBuffers(); + void copyBuffer(short *dst, const int *const *src, unsigned nSamples); + MediaBuffer *readBuffer() { return readBuffer(false, 0LL); } @@ -113,6 +124,7 @@ public: protected: virtual ~FLACParser(); + private: sp<DataSource> mDataSource; sp<MetaData> mFileMetadata; @@ -122,7 +134,6 @@ private: // media buffers size_t mMaxBufferSize; MediaBufferGroup *mGroup; - void (*mCopy)(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels); // handle to underlying libFLAC parser FLAC__StreamDecoder *mDecoder; @@ -377,109 +388,41 @@ void FLACParser::errorCallback(FLAC__StreamDecoderErrorStatus status) mErrorStatus = status; } -// Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved. -// These are candidates for optimization if needed. - -static void copyMono8( - short *dst, - const int *const *src, - unsigned nSamples, - unsigned /* nChannels */) { - for (unsigned i = 0; i < nSamples; ++i) { - *dst++ = src[0][i] << 8; - } -} - -static void copyStereo8( - short *dst, - const int *const *src, - unsigned nSamples, - unsigned /* nChannels */) { - for (unsigned i = 0; i < nSamples; ++i) { - *dst++ = src[0][i] << 8; - *dst++ = src[1][i] << 8; - } -} - -static void copyMultiCh8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) +void FLACParser::copyBuffer(short *dst, const int *const *src, unsigned nSamples) { - for (unsigned i = 0; i < nSamples; ++i) { - for (unsigned c = 0; c < nChannels; ++c) { - *dst++ = src[c][i] << 8; - } - } -} - -static void copyMono16( - short *dst, - const int *const *src, - unsigned nSamples, - unsigned /* nChannels */) { - for (unsigned i = 0; i < nSamples; ++i) { - *dst++ = src[0][i]; - } -} - -static void copyStereo16( - short *dst, - const int *const *src, - unsigned nSamples, - unsigned /* nChannels */) { - for (unsigned i = 0; i < nSamples; ++i) { - *dst++ = src[0][i]; - *dst++ = src[1][i]; - } -} - -static void copyMultiCh16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ - for (unsigned i = 0; i < nSamples; ++i) { - for (unsigned c = 0; c < nChannels; ++c) { - *dst++ = src[c][i]; - } - } -} - -// 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger - -static void copyMono24( - short *dst, - const int *const *src, - unsigned nSamples, - unsigned /* nChannels */) { - for (unsigned i = 0; i < nSamples; ++i) { - *dst++ = src[0][i] >> 8; - } -} - -static void copyStereo24( - short *dst, - const int *const *src, - unsigned nSamples, - unsigned /* nChannels */) { - for (unsigned i = 0; i < nSamples; ++i) { - *dst++ = src[0][i] >> 8; - *dst++ = src[1][i] >> 8; - } -} - -static void copyMultiCh24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ - for (unsigned i = 0; i < nSamples; ++i) { - for (unsigned c = 0; c < nChannels; ++c) { - *dst++ = src[c][i] >> 8; + unsigned int nChannels = getChannels(); + unsigned int nBits = getBitsPerSample(); + switch (nBits) { + case 8: + for (unsigned i = 0; i < nSamples; ++i) { + for (unsigned c = 0; c < nChannels; ++c) { + *dst++ = src[c][i] << 8; + } + } + break; + case 16: + for (unsigned i = 0; i < nSamples; ++i) { + for (unsigned c = 0; c < nChannels; ++c) { + *dst++ = src[c][i]; + } + } + break; + case 24: + case 32: + { + int32_t *out = (int32_t *)dst; + for (unsigned i = 0; i < nSamples; ++i) { + for (unsigned c = 0; c < nChannels; ++c) { + *out++ = src[c][i] << 8; + } + } + break; } + default: + TRESPASS(); } } -static void copyTrespass( - short * /* dst */, - const int *const * /* src */, - unsigned /* nSamples */, - unsigned /* nChannels */) { - TRESPASS(); -} - // FLACParser FLACParser::FLACParser( @@ -492,7 +435,6 @@ FLACParser::FLACParser( mInitCheck(false), mMaxBufferSize(0), mGroup(NULL), - mCopy(copyTrespass), mDecoder(NULL), mCurrentPos(0LL), mEOF(false), @@ -571,6 +513,8 @@ status_t FLACParser::init() } // check sample rate switch (getSampleRate()) { + case 100: + case 1000: case 8000: case 11025: case 12000: @@ -578,38 +522,18 @@ status_t FLACParser::init() case 22050: case 24000: case 32000: + case 42000: case 44100: + case 46000: case 48000: case 88200: case 96000: + case 192000: break; default: ALOGE("unsupported sample rate %u", getSampleRate()); return NO_INIT; } - // configure the appropriate copy function, defaulting to trespass - static const struct { - unsigned mChannels; - unsigned mBitsPerSample; - void (*mCopy)(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels); - } table[] = { - { 1, 8, copyMono8 }, - { 2, 8, copyStereo8 }, - { 8, 8, copyMultiCh8 }, - { 1, 16, copyMono16 }, - { 2, 16, copyStereo16 }, - { 8, 16, copyMultiCh16 }, - { 1, 24, copyMono24 }, - { 2, 24, copyStereo24 }, - { 8, 24, copyMultiCh24 }, - }; - for (unsigned i = 0; i < sizeof(table)/sizeof(table[0]); ++i) { - if (table[i].mChannels >= getChannels() && - table[i].mBitsPerSample == getBitsPerSample()) { - mCopy = table[i].mCopy; - break; - } - } // populate track metadata if (mTrackMetadata != 0) { mTrackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); @@ -618,6 +542,7 @@ status_t FLACParser::init() // sample rate is non-zero, so division by zero not possible mTrackMetadata->setInt64(kKeyDuration, (getTotalSamples() * 1000000LL) / getSampleRate()); + mTrackMetadata->setInt32(kKeyBitsPerSample, getBitsPerSample()); } } else { ALOGE("missing STREAMINFO"); @@ -633,7 +558,9 @@ void FLACParser::allocateBuffers() { CHECK(mGroup == NULL); mGroup = new MediaBufferGroup; - mMaxBufferSize = getMaxBlockSize() * getChannels() * sizeof(short); + // allocate enough to hold 24-bits (packed in 32 bits) + unsigned int bytesPerSample = getBitsPerSample() > 16 ? 4 : 2; + mMaxBufferSize = getMaxBlockSize() * getChannels() * bytesPerSample; mGroup->add_buffer(new MediaBuffer(mMaxBufferSize)); } @@ -686,12 +613,12 @@ MediaBuffer *FLACParser::readBuffer(bool doSeek, FLAC__uint64 sample) if (err != OK) { return NULL; } - size_t bufferSize = blocksize * getChannels() * sizeof(short); + size_t bufferSize = blocksize * getChannels() * (getBitsPerSample() > 16 ? 4 : 2); CHECK(bufferSize <= mMaxBufferSize); short *data = (short *) buffer->data(); buffer->set_range(0, bufferSize); // copy PCM from FLAC write buffer to our media buffer, with interleaving - (*mCopy)(data, mWriteBuffer, blocksize, getChannels()); + copyBuffer(data, mWriteBuffer, blocksize); // fill in buffer metadata CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); FLAC__uint64 sampleNumber = mWriteHeader.number.sample_number; @@ -726,9 +653,10 @@ FLACSource::~FLACSource() status_t FLACSource::start(MetaData * /* params */) { + CHECK(!mStarted); + ALOGV("FLACSource::start"); - CHECK(!mStarted); mParser->allocateBuffers(); mStarted = true; diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index 335ac84..bb2a33c 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 @@ -284,6 +285,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( @@ -359,15 +361,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 +430,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 %d, ", + __func__, mBitsPerSample, kMaxFrameSize); size_t maxBytesAvailable = (mCurrentPos - mOffset >= (off64_t)mSize) @@ -488,23 +497,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 = %d", 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 = %d", buffer->range_length()); } } |