summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Ekenberg <stefan.ekenberg@stericsson.com>2012-08-20 12:00:26 +0200
committerGerrit Code Review <gerrit@review.cyanogenmod.com>2013-01-30 00:16:57 -0800
commit69d8d46c5985ed76947f875ee3b7d32febfcf201 (patch)
tree8ccac17232e22005b25277ba9f9bb85a494e04cc
parent95dc7fae7a3d8ddbd020e588a33d9215e9105c50 (diff)
downloadframeworks_av-69d8d46c5985ed76947f875ee3b7d32febfcf201.zip
frameworks_av-69d8d46c5985ed76947f875ee3b7d32febfcf201.tar.gz
frameworks_av-69d8d46c5985ed76947f875ee3b7d32febfcf201.tar.bz2
FM Radio: Add support for FM Radio in Android
Creating interface and framework for using FM Radio RX and TX from different vendors. Change-Id: I1a71aed01bfffdddfabf1cdfbfa3707cb1ed016b Signed-off-by: Benn Porscke <benn.porscke@stericsson.com>
-rw-r--r--include/media/stagefright/FMRadioSource.h64
-rwxr-xr-xmedia/libstagefright/Android.mk6
-rw-r--r--media/libstagefright/AwesomePlayer.cpp10
-rw-r--r--media/libstagefright/FMRadioSource.cpp201
-rw-r--r--media/libstagefright/MediaExtractor.cpp5
-rw-r--r--media/libstagefright/PCMExtractor.cpp302
-rw-r--r--media/libstagefright/include/PCMExtractor.h61
7 files changed, 649 insertions, 0 deletions
diff --git a/include/media/stagefright/FMRadioSource.h b/include/media/stagefright/FMRadioSource.h
new file mode 100644
index 0000000..32db156
--- /dev/null
+++ b/include/media/stagefright/FMRadioSource.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Stefan Ekenberg (stefan.ekenberg@stericsson.com) for ST-Ericsson
+ */
+
+#ifndef FMRADIO_SOURCE_H_
+
+#define FMRADIO_SOURCE_H_
+
+#include <media/AudioRecord.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <system/audio.h>
+
+namespace android {
+
+class FMRadioSource : public DataSource {
+public:
+ FMRadioSource();
+
+ virtual status_t initCheck() const;
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+ virtual status_t getSize(off64_t *size);
+
+protected:
+ virtual ~FMRadioSource();
+
+private:
+ struct Buffer {
+ size_t frameCount;
+ size_t size;
+ int8_t* data;
+ };
+
+ status_t openRecord(int frameCount, audio_io_handle_t input);
+ status_t obtainBuffer(Buffer* audioBuffer);
+
+ status_t mInitCheck;
+ bool mStarted;
+ int mSessionId;
+ sp<IAudioRecord> mAudioRecord;
+ sp<IMemory> mCblkMemory;
+ audio_track_cblk_t* mCblk;
+
+ DISALLOW_EVIL_CONSTRUCTORS(FMRadioSource);
+};
+
+} // namespace android
+
+#endif // FMRADIO_SOURCE_H_
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 7939be4..eb89cfe 100755
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -77,6 +77,12 @@ else
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
endif
+ifeq ($(BOARD_USES_STE_FMRADIO),true)
+LOCAL_SRC_FILES += \
+ FMRadioSource.cpp \
+ PCMExtractor.cpp
+endif
+
ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
LOCAL_SRC_FILES += \
ExtendedWriter.cpp \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 83c480d..97ee08a 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -50,6 +50,7 @@
#endif
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
+#include <media/stagefright/FMRadioSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaExtractor.h>
@@ -2411,6 +2412,15 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return UNKNOWN_ERROR;
}
}
+#ifdef STE_FM
+ } else if (!strncasecmp("fmradio://rx", mUri.string(), 12)) {
+ sniffedMIME = MEDIA_MIMETYPE_AUDIO_RAW;
+ dataSource = new FMRadioSource();
+ status_t err = dataSource->initCheck();
+ if (err != OK) {
+ return err;
+ }
+#endif
} else {
dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
}
diff --git a/media/libstagefright/FMRadioSource.cpp b/media/libstagefright/FMRadioSource.cpp
new file mode 100644
index 0000000..4229f23
--- /dev/null
+++ b/media/libstagefright/FMRadioSource.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Stefan Ekenberg (stefan.ekenberg@stericsson.com) for ST-Ericsson
+ */
+
+#define LOG_TAG "FMRadioSource"
+#include <utils/Log.h>
+
+#include <media/stagefright/FMRadioSource.h>
+#include <media/AudioSystem.h>
+#include <private/media/AudioTrackShared.h>
+#include <cutils/compiler.h>
+
+namespace android {
+
+static const int kSampleRate = 48000;
+static const audio_format_t kAudioFormat = AUDIO_FORMAT_PCM_16_BIT;
+static const audio_channel_mask_t kChannelMask = AUDIO_CHANNEL_IN_STEREO;
+static const int kBufferTimeoutMs = 3000;
+
+FMRadioSource::FMRadioSource()
+ : mInitCheck(NO_INIT),
+ mStarted(false),
+ mSessionId(AudioSystem::newAudioSessionId()) {
+
+ // get FM Radio RX input
+ audio_io_handle_t input = AudioSystem::getInput(AUDIO_SOURCE_FM_RADIO_RX,
+ kSampleRate,
+ kAudioFormat,
+ kChannelMask,
+ mSessionId);
+ if (input == 0) {
+ ALOGE("Could not get audio input for FM Radio source");
+ mInitCheck = UNKNOWN_ERROR;
+ return;
+ }
+
+ // get frame count
+ int frameCount = 0;
+ status_t status = AudioRecord::getMinFrameCount(&frameCount, kSampleRate,
+ kAudioFormat, popcount(kChannelMask));
+ if (status != NO_ERROR) {
+ mInitCheck = status;
+ return;
+ }
+
+ // create the IAudioRecord
+ status = openRecord(frameCount, input);
+ if (status != NO_ERROR) {
+ mInitCheck = status;
+ return;
+ }
+
+ AudioSystem::acquireAudioSessionId(mSessionId);
+
+ mInitCheck = OK;
+ return;
+}
+
+FMRadioSource::~FMRadioSource() {
+ AudioSystem::releaseAudioSessionId(mSessionId);
+}
+
+status_t FMRadioSource::initCheck() const {
+ return mInitCheck;
+}
+
+ssize_t FMRadioSource::readAt(off64_t offset, void *data, size_t size) {
+ Buffer audioBuffer;
+
+ if (!mStarted) {
+ status_t err = mAudioRecord->start(AudioSystem::SYNC_EVENT_NONE, 0);
+ if (err == OK) {
+ mStarted = true;
+ } else {
+ ALOGE("Failed to start audio source");
+ return 0;
+ }
+ }
+
+ // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
+ // while we are accessing the cblk
+ sp<IAudioRecord> audioRecord = mAudioRecord;
+ sp<IMemory> iMem = mCblkMemory;
+ audio_track_cblk_t* cblk = mCblk;
+
+ audioBuffer.frameCount = size / cblk->frameSize;
+
+ status_t err = obtainBuffer(&audioBuffer);
+ if (err != NO_ERROR) {
+ ALOGE("Error obtaining an audio buffer, giving up (err:%d).", err);
+ return 0;
+ }
+
+ memcpy(data, audioBuffer.data, audioBuffer.size);
+ mCblk->stepUser(audioBuffer.frameCount);
+
+ return audioBuffer.size;
+}
+
+status_t FMRadioSource::getSize(off64_t *size) {
+ *size = 0;
+ return OK;
+}
+
+// -------------------------------------------------------------------------
+
+status_t FMRadioSource::openRecord(int frameCount, audio_io_handle_t input)
+{
+ status_t status;
+ const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+ if (audioFlinger == 0) {
+ return NO_INIT;
+ }
+
+ sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
+ kSampleRate,
+ kAudioFormat,
+ kChannelMask,
+ frameCount,
+ IAudioFlinger::TRACK_DEFAULT,
+ gettid(),
+ &mSessionId,
+ &status);
+
+ if (record == 0) {
+ ALOGE("AudioFlinger could not create record track, status: %d", status);
+ return status;
+ }
+
+ sp<IMemory> cblk = record->getCblk();
+ if (cblk == 0) {
+ ALOGE("Could not get control block");
+ return NO_INIT;
+ }
+ mAudioRecord = record;
+ mCblkMemory = cblk;
+ mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+ mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+ android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
+ return NO_ERROR;
+}
+
+status_t FMRadioSource::obtainBuffer(Buffer* audioBuffer)
+{
+ status_t result = NO_ERROR;
+ uint32_t framesReq = audioBuffer->frameCount;
+
+ audioBuffer->frameCount = 0;
+ audioBuffer->size = 0;
+
+ mCblk->lock.lock();
+ uint32_t framesReady = mCblk->framesReady();
+ if (framesReady == 0) {
+ do {
+ result = mCblk->cv.waitRelative(mCblk->lock, milliseconds(kBufferTimeoutMs));
+ if (CC_UNLIKELY(result != NO_ERROR)) {
+ ALOGE("obtainBuffer timed out (is the CPU pegged?) "
+ "user=%08x, server=%08x", mCblk->user, mCblk->server);
+ mCblk->lock.unlock();
+ return TIMED_OUT;
+ }
+
+ framesReady = mCblk->framesReady();
+ } while (framesReady == 0);
+ }
+ mCblk->lock.unlock();
+
+ if (framesReq > framesReady) {
+ framesReq = framesReady;
+ }
+
+ uint32_t u = mCblk->user;
+ uint32_t bufferEnd = mCblk->userBase + mCblk->frameCount;
+
+ if (framesReq > bufferEnd - u) {
+ framesReq = bufferEnd - u;
+ }
+
+ audioBuffer->frameCount = framesReq;
+ audioBuffer->size = framesReq * mCblk->frameSize;
+ audioBuffer->data = (int8_t*)mCblk->buffer(u);
+
+ return NO_ERROR;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 833084a..218448b 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -25,6 +25,7 @@
#include "include/FragmentedMP4Extractor.h"
#include "include/WAVExtractor.h"
#include "include/OggExtractor.h"
+#include "include/PCMExtractor.h"
#include "include/MPEG2PSExtractor.h"
#include "include/MPEG2TSExtractor.h"
#include "include/DRMExtractor.h"
@@ -136,6 +137,10 @@ sp<MediaExtractor> MediaExtractor::Create(
ret = new AACExtractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) {
ret = new MPEG2PSExtractor(source);
+#ifdef STE_FM
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
+ ret = new PCMExtractor(source);
+#endif
}
if (ret != NULL) {
diff --git a/media/libstagefright/PCMExtractor.cpp b/media/libstagefright/PCMExtractor.cpp
new file mode 100644
index 0000000..bb26bcd
--- /dev/null
+++ b/media/libstagefright/PCMExtractor.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Andreas Gustafsson (andreas.a.gustafsson@stericsson.com)
+ * for ST-Ericsson
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "PCMExtractor"
+#include <utils/Log.h>
+
+#include "include/PCMExtractor.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+/**
+* The default buffer size.
+*/
+static const uint16_t kDefaultNumChannels = 2;
+
+/**
+* The default Sample rate.
+*/
+static const uint32_t kDefaultSampleRate = 48000;
+
+/**
+* Bits per sample.
+*/
+static const uint16_t kDefaultBitsPerSample = 16;
+
+/**
+* The default buffer size.
+*/
+static const uint32_t kDefaultBufferSize = 4800;
+
+/**
+* Buffer duration in ms, to be used for input
+*/
+static const uint16_t kInputBufferDuration = 64;
+
+/**
+* Buffer granulairity in samples to be used for input.
+*/
+static const uint16_t kBufferGranularityInSamples = 16;
+
+struct PCMSource : public MediaSource {
+ PCMSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &meta,
+ int32_t bitsPerSample,
+ off_t offset, size_t size);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+protected:
+ virtual ~PCMSource();
+
+private:
+ static const size_t kMaxFrameSize;
+
+ sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+ int32_t mSampleRate;
+ int32_t mNumChannels;
+ int32_t mBitsPerSample;
+ off_t mOffset;
+ size_t mSize;
+ bool mStarted;
+ MediaBufferGroup *mGroup;
+ off_t mCurrentPos;
+ uint32_t mBufferSize;
+
+ DISALLOW_EVIL_CONSTRUCTORS(PCMSource);
+};
+
+PCMExtractor::PCMExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mValidFormat(false) {
+ mInitCheck = init();
+}
+
+PCMExtractor::~PCMExtractor() {
+}
+
+sp<MetaData> PCMExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck != OK) {
+ return meta;
+ }
+
+ meta->setCString(kKeyMIMEType, "audio/raw");
+
+ return meta;
+}
+
+size_t PCMExtractor::countTracks() {
+ return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> PCMExtractor::getTrack(size_t index) {
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+
+ return new PCMSource(
+ mDataSource, mTrackMeta,
+ kDefaultBitsPerSample, mDataOffset, mDataSize);
+}
+
+sp<MetaData> PCMExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+
+ return mTrackMeta;
+}
+
+status_t PCMExtractor::init() {
+ mDataOffset = 0;
+ mDataSize = 0;
+ mValidFormat = true;
+ mTrackMeta = new MetaData;mTrackMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ mTrackMeta->setInt32(kKeyChannelCount, kDefaultNumChannels);
+ mTrackMeta->setInt32(kKeySampleRate, kDefaultSampleRate);
+ return OK;
+}
+
+const size_t PCMSource::kMaxFrameSize = 4800;
+
+PCMSource::PCMSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &meta,
+ int32_t bitsPerSample,
+ off_t offset, size_t size)
+ : mDataSource(dataSource),
+ mMeta(meta),
+ mSampleRate(0),
+ mNumChannels(0),
+ mBitsPerSample(bitsPerSample),
+ mOffset(offset),
+ mSize(size),
+ mStarted(false),
+ mGroup(NULL),
+ mBufferSize(0) {
+ CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
+ CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
+}
+
+PCMSource::~PCMSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t PCMSource::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ size_t size = kDefaultBufferSize;
+
+ if (mSampleRate != 0 && mNumChannels != 0) {
+ mBufferSize = mSampleRate * kInputBufferDuration / 1000 * mNumChannels * 2;
+ size_t granularity = kBufferGranularityInSamples * 2 * mNumChannels;
+ mBufferSize = (mBufferSize / granularity) * granularity;
+ }
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+ if (mBitsPerSample == 8) {
+ // As a temporary buffer for 8->16 bit conversion.
+ mGroup->add_buffer(new MediaBuffer(mBufferSize));
+ }
+
+ mCurrentPos = mOffset;
+
+ mStarted = true;
+ return OK;
+}
+
+status_t PCMSource::stop() {
+
+ CHECK(mStarted);
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+ return OK;
+}
+
+sp<MetaData> PCMSource::getFormat() {
+ return mMeta;
+}
+
+status_t PCMSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seek = ReadOptions::SEEK_CLOSEST_SYNC;
+ if (options != NULL && options->getSeekTo(&seekTimeUs,&seek)) {
+ int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * 2;
+ if (pos > mSize) {
+ pos = mSize;
+ }
+ mCurrentPos = pos + mOffset;
+ }
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ ssize_t n = mDataSource->readAt(
+ mCurrentPos, buffer->data(), mBufferSize);
+ if (n <= 0) {
+ buffer->release();
+ buffer = NULL;
+ return ERROR_END_OF_STREAM;
+ }
+
+ mCurrentPos += n;
+
+ buffer->set_range(0, n);
+
+ if (mBitsPerSample == 8) {
+ // Convert 8-bit unsigned samples to 16-bit signed.
+
+ MediaBuffer *tmp;
+ CHECK_EQ(mGroup->acquire_buffer(&tmp), (status_t)OK);
+
+ // The new buffer holds the sample number of samples, but each
+ // one is 2 bytes wide.
+ tmp->set_range(0, 2 * n);
+
+ int16_t *dst = (int16_t *)tmp->data();
+ const uint8_t *src = (const uint8_t *)buffer->data();
+ while (n-- > 0) {
+ *dst++ = ((int16_t)(*src) - 128) * 256;
+ ++src;
+ }
+
+ 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;
+ }
+
+ buffer->set_range(buffer->range_offset(), 2 * numSamples);
+ }
+
+ size_t bytesPerSample = mBitsPerSample >> 3;
+
+ buffer->meta_data()->setInt64(
+ kKeyTime,
+ 1000000LL * (mCurrentPos - mOffset)
+ / (mNumChannels * bytesPerSample) / mSampleRate);
+
+
+ *out = buffer;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/include/PCMExtractor.h b/media/libstagefright/include/PCMExtractor.h
new file mode 100644
index 0000000..4717d10
--- /dev/null
+++ b/media/libstagefright/include/PCMExtractor.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Andreas Gustafsson (andreas.a.gustafsson@stericsson.com)
+ * for ST-Ericsson
+ */
+
+#ifndef PCM_EXTRACTOR_H_
+
+#define PCM_EXTRACTOR_H_
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+class PCMExtractor : public MediaExtractor {
+public:
+ // Extractor assumes ownership of "source".
+ PCMExtractor(const sp<DataSource> &source);
+
+ virtual size_t countTracks();
+ virtual sp<MediaSource> getTrack(size_t index);
+ virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+
+ virtual sp<MetaData> getMetaData();
+
+protected:
+ virtual ~PCMExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+ status_t mInitCheck;
+ bool mValidFormat;
+ off_t mDataOffset;
+ size_t mDataSize;
+ sp<MetaData> mTrackMeta;
+
+ status_t init();
+
+ DISALLOW_EVIL_CONSTRUCTORS(PCMExtractor);
+};
+
+} // namespace android
+
+#endif // PCM_EXTRACTOR_H_