summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/FLACExtractor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/FLACExtractor.cpp')
-rw-r--r--media/libstagefright/FLACExtractor.cpp199
1 files changed, 67 insertions, 132 deletions
diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp
index 89a91f7..55ce566 100644
--- a/media/libstagefright/FLACExtractor.cpp
+++ b/media/libstagefright/FLACExtractor.cpp
@@ -32,6 +32,8 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MediaBuffer.h>
+#include <system/audio.h>
+
namespace android {
class FLACParser;
@@ -72,6 +74,8 @@ private:
class FLACParser : public RefBase {
+friend class FLACSource;
+
public:
FLACParser(
const sp<DataSource> &dataSource,
@@ -84,9 +88,18 @@ public:
}
// stream properties
+ unsigned getMinBlockSize() const {
+ return mStreamInfo.min_blocksize;
+ }
unsigned getMaxBlockSize() const {
return mStreamInfo.max_blocksize;
}
+ unsigned getMinFrameSize() const {
+ return mStreamInfo.min_framesize;
+ }
+ unsigned getMaxFrameSize() const {
+ return mStreamInfo.max_framesize;
+ }
unsigned getSampleRate() const {
return mStreamInfo.sample_rate;
}
@@ -103,6 +116,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 +128,7 @@ public:
protected:
virtual ~FLACParser();
+
private:
sp<DataSource> mDataSource;
sp<MetaData> mFileMetadata;
@@ -122,7 +138,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;
@@ -139,7 +154,7 @@ private:
bool mWriteRequested;
bool mWriteCompleted;
FLAC__FrameHeader mWriteHeader;
- const FLAC__int32 * const *mWriteBuffer;
+ const FLAC__int32 * mWriteBuffer[FLAC__MAX_CHANNELS];
// most recent error reported by libFLAC parser
FLAC__StreamDecoderErrorStatus mErrorStatus;
@@ -323,7 +338,9 @@ FLAC__StreamDecoderWriteStatus FLACParser::writeCallback(
mWriteRequested = false;
// FLAC parser doesn't free or realloc buffer until next frame or finish
mWriteHeader = frame->header;
- mWriteBuffer = buffer;
+ for(unsigned channel = 0; channel < frame->header.channels; channel++) {
+ mWriteBuffer[channel] = buffer[channel];
+ }
mWriteCompleted = true;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
} else {
@@ -377,109 +394,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)
-{
- 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)
+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;
+ 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,14 +441,12 @@ FLACParser::FLACParser(
mInitCheck(false),
mMaxBufferSize(0),
mGroup(NULL),
- mCopy(copyTrespass),
mDecoder(NULL),
mCurrentPos(0LL),
mEOF(false),
mStreamInfoValid(false),
mWriteRequested(false),
mWriteCompleted(false),
- mWriteBuffer(NULL),
mErrorStatus((FLAC__StreamDecoderErrorStatus) -1)
{
ALOGV("FLACParser::FLACParser");
@@ -571,6 +518,8 @@ status_t FLACParser::init()
}
// check sample rate
switch (getSampleRate()) {
+ case 100:
+ case 1000:
case 8000:
case 11025:
case 12000:
@@ -578,38 +527,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 +547,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 +563,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 +618,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, (const FLAC__int32 * const *)(&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 +658,10 @@ FLACSource::~FLACSource()
status_t FLACSource::start(MetaData * /* params */)
{
+ CHECK(!mStarted);
+
ALOGV("FLACSource::start");
- CHECK(!mStarted);
mParser->allocateBuffers();
mStarted = true;
@@ -845,12 +778,14 @@ bool SniffFLAC(
{
// first 4 is the signature word
// second 4 is the sizeof STREAMINFO
+ // 1st bit of 2nd 4 bytes represent whether last block of metadata or not
// 042 is the mandatory STREAMINFO
// no need to read rest of the header, as a premature EOF will be caught later
uint8_t header[4+4];
if (source->readAt(0, header, sizeof(header)) != sizeof(header)
- || memcmp("fLaC\0\0\0\042", header, 4+4))
- {
+ || memcmp("fLaC", header, 4)
+ || !(header[4] == 0x80 || header[4] == 0x00)
+ || memcmp("\0\0\042", header + 5, 3)) {
return false;
}