2 * Copyright (C) 2009 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "WAVExtractor"
19 #include <utils/Log.h>
21 #include "include/WAVExtractor.h"
23 #include <media/stagefright/DataSource.h>
24 #include <media/stagefright/MediaBufferGroup.h>
25 #include <media/stagefright/MediaDebug.h>
26 #include <media/stagefright/MediaDefs.h>
27 #include <media/stagefright/MediaErrors.h>
28 #include <media/stagefright/MediaSource.h>
29 #include <media/stagefright/MetaData.h>
30 #include <utils/String8.h>
37 WAVE_FORMAT_MULAW = 7,
40 static uint32_t U32_LE_AT(const uint8_t *ptr) {
41 return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
44 static uint16_t U16_LE_AT(const uint8_t *ptr) {
45 return ptr[1] << 8 | ptr[0];
48 struct WAVSource : public MediaSource {
50 const sp<DataSource> &dataSource,
51 const sp<MetaData> &meta,
53 int32_t bitsPerSample,
54 off_t offset, size_t size);
56 virtual status_t start(MetaData *params = NULL);
57 virtual status_t stop();
58 virtual sp<MetaData> getFormat();
60 virtual status_t read(
61 MediaBuffer **buffer, const ReadOptions *options = NULL);
67 static const size_t kMaxFrameSize;
69 sp<DataSource> mDataSource;
74 int32_t mBitsPerSample;
78 MediaBufferGroup *mGroup;
81 WAVSource(const WAVSource &);
82 WAVSource &operator=(const WAVSource &);
85 WAVExtractor::WAVExtractor(const sp<DataSource> &source)
86 : mDataSource(source),
91 WAVExtractor::~WAVExtractor() {
94 sp<MetaData> WAVExtractor::getMetaData() {
95 sp<MetaData> meta = new MetaData;
97 if (mInitCheck != OK) {
101 meta->setCString(kKeyMIMEType, "audio/x-wav");
106 size_t WAVExtractor::countTracks() {
107 return mInitCheck == OK ? 1 : 0;
110 sp<MediaSource> WAVExtractor::getTrack(size_t index) {
111 if (mInitCheck != OK || index > 0) {
115 return new WAVSource(
116 mDataSource, mTrackMeta,
117 mWaveFormat, mBitsPerSample, mDataOffset, mDataSize);
120 sp<MetaData> WAVExtractor::getTrackMetaData(
121 size_t index, uint32_t flags) {
122 if (mInitCheck != OK || index > 0) {
129 status_t WAVExtractor::init() {
131 if (mDataSource->readAt(
132 0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
136 if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
140 size_t totalSize = U32_LE_AT(&header[4]);
143 size_t remainingSize = totalSize;
144 while (remainingSize >= 8) {
145 uint8_t chunkHeader[8];
146 if (mDataSource->readAt(offset, chunkHeader, 8) < 8) {
153 uint32_t chunkSize = U32_LE_AT(&chunkHeader[4]);
155 if (chunkSize > remainingSize) {
159 if (!memcmp(chunkHeader, "fmt ", 4)) {
160 if (chunkSize < 16) {
164 uint8_t formatSpec[16];
165 if (mDataSource->readAt(offset, formatSpec, 16) < 16) {
169 mWaveFormat = U16_LE_AT(formatSpec);
170 if (mWaveFormat != WAVE_FORMAT_PCM
171 && mWaveFormat != WAVE_FORMAT_ALAW
172 && mWaveFormat != WAVE_FORMAT_MULAW) {
173 return ERROR_UNSUPPORTED;
176 mNumChannels = U16_LE_AT(&formatSpec[2]);
177 if (mNumChannels != 1 && mNumChannels != 2) {
178 return ERROR_UNSUPPORTED;
181 mSampleRate = U32_LE_AT(&formatSpec[4]);
183 if (mSampleRate == 0) {
184 return ERROR_MALFORMED;
187 mBitsPerSample = U16_LE_AT(&formatSpec[14]);
189 if (mWaveFormat == WAVE_FORMAT_PCM) {
190 if (mBitsPerSample != 8 && mBitsPerSample != 16
191 && mBitsPerSample != 24) {
192 return ERROR_UNSUPPORTED;
195 CHECK(mWaveFormat == WAVE_FORMAT_MULAW
196 || mWaveFormat == WAVE_FORMAT_ALAW);
197 if (mBitsPerSample != 8) {
198 return ERROR_UNSUPPORTED;
203 } else if (!memcmp(chunkHeader, "data", 4)) {
205 mDataOffset = offset;
206 mDataSize = chunkSize;
208 mTrackMeta = new MetaData;
210 switch (mWaveFormat) {
211 case WAVE_FORMAT_PCM:
212 mTrackMeta->setCString(
213 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
215 case WAVE_FORMAT_ALAW:
216 mTrackMeta->setCString(
217 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
220 CHECK_EQ(mWaveFormat, WAVE_FORMAT_MULAW);
221 mTrackMeta->setCString(
222 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
226 mTrackMeta->setInt32(kKeyChannelCount, mNumChannels);
227 mTrackMeta->setInt32(kKeySampleRate, mSampleRate);
229 size_t bytesPerSample = mBitsPerSample >> 3;
232 1000000LL * (mDataSize / (mNumChannels * bytesPerSample))
235 mTrackMeta->setInt64(kKeyDuration, durationUs);
247 const size_t WAVSource::kMaxFrameSize = 32768;
249 WAVSource::WAVSource(
250 const sp<DataSource> &dataSource,
251 const sp<MetaData> &meta,
253 int32_t bitsPerSample,
254 off_t offset, size_t size)
255 : mDataSource(dataSource),
257 mWaveFormat(waveFormat),
260 mBitsPerSample(bitsPerSample),
265 CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
266 CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
269 WAVSource::~WAVSource() {
275 status_t WAVSource::start(MetaData *params) {
276 LOGV("WAVSource::start");
280 mGroup = new MediaBufferGroup;
281 mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
283 if (mBitsPerSample == 8) {
284 // As a temporary buffer for 8->16 bit conversion.
285 mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
288 mCurrentPos = mOffset;
295 status_t WAVSource::stop() {
296 LOGV("WAVSource::stop");
308 sp<MetaData> WAVSource::getFormat() {
309 LOGV("WAVSource::getFormat");
314 status_t WAVSource::read(
315 MediaBuffer **out, const ReadOptions *options) {
319 ReadOptions::SeekMode mode;
320 if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
321 int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * 2;
325 mCurrentPos = pos + mOffset;
329 status_t err = mGroup->acquire_buffer(&buffer);
334 size_t maxBytesToRead =
335 mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize;
337 size_t maxBytesAvailable =
338 (mCurrentPos - mOffset >= (off_t)mSize)
339 ? 0 : mSize - (mCurrentPos - mOffset);
341 if (maxBytesToRead > maxBytesAvailable) {
342 maxBytesToRead = maxBytesAvailable;
345 ssize_t n = mDataSource->readAt(
346 mCurrentPos, buffer->data(),
353 return ERROR_END_OF_STREAM;
358 buffer->set_range(0, n);
360 if (mWaveFormat == WAVE_FORMAT_PCM) {
361 if (mBitsPerSample == 8) {
362 // Convert 8-bit unsigned samples to 16-bit signed.
365 CHECK_EQ(mGroup->acquire_buffer(&tmp), OK);
367 // The new buffer holds the sample number of samples, but each
368 // one is 2 bytes wide.
369 tmp->set_range(0, 2 * n);
371 int16_t *dst = (int16_t *)tmp->data();
372 const uint8_t *src = (const uint8_t *)buffer->data();
374 *dst++ = ((int16_t)(*src) - 128) * 256;
380 } else if (mBitsPerSample == 24) {
381 // Convert 24-bit signed samples to 16-bit signed.
384 (const uint8_t *)buffer->data() + buffer->range_offset();
385 int16_t *dst = (int16_t *)src;
387 size_t numSamples = buffer->range_length() / 3;
388 for (size_t i = 0; i < numSamples; ++i) {
389 int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16);
390 x = (x << 8) >> 8; // sign extension
397 buffer->set_range(buffer->range_offset(), 2 * numSamples);
401 size_t bytesPerSample = mBitsPerSample >> 3;
403 buffer->meta_data()->setInt64(
405 1000000LL * (mCurrentPos - mOffset)
406 / (mNumChannels * bytesPerSample) / mSampleRate);
408 buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
415 ////////////////////////////////////////////////////////////////////////////////
418 const sp<DataSource> &source, String8 *mimeType, float *confidence,
421 if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
425 if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
429 *mimeType = MEDIA_MIMETYPE_CONTAINER_WAV;
435 } // namespace android