OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / WAVExtractor.cpp
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "WAVExtractor"
19 #include <utils/Log.h>
20
21 #include "include/WAVExtractor.h"
22
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>
31
32 namespace android {
33
34 enum {
35     WAVE_FORMAT_PCM = 1,
36     WAVE_FORMAT_ALAW = 6,
37     WAVE_FORMAT_MULAW = 7,
38 };
39
40 static uint32_t U32_LE_AT(const uint8_t *ptr) {
41     return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
42 }
43
44 static uint16_t U16_LE_AT(const uint8_t *ptr) {
45     return ptr[1] << 8 | ptr[0];
46 }
47
48 struct WAVSource : public MediaSource {
49     WAVSource(
50             const sp<DataSource> &dataSource,
51             const sp<MetaData> &meta,
52             uint16_t waveFormat,
53             int32_t bitsPerSample,
54             off_t offset, size_t size);
55
56     virtual status_t start(MetaData *params = NULL);
57     virtual status_t stop();
58     virtual sp<MetaData> getFormat();
59
60     virtual status_t read(
61             MediaBuffer **buffer, const ReadOptions *options = NULL);
62
63 protected:
64     virtual ~WAVSource();
65
66 private:
67     static const size_t kMaxFrameSize;
68
69     sp<DataSource> mDataSource;
70     sp<MetaData> mMeta;
71     uint16_t mWaveFormat;
72     int32_t mSampleRate;
73     int32_t mNumChannels;
74     int32_t mBitsPerSample;
75     off_t mOffset;
76     size_t mSize;
77     bool mStarted;
78     MediaBufferGroup *mGroup;
79     off_t mCurrentPos;
80
81     WAVSource(const WAVSource &);
82     WAVSource &operator=(const WAVSource &);
83 };
84
85 WAVExtractor::WAVExtractor(const sp<DataSource> &source)
86     : mDataSource(source),
87       mValidFormat(false) {
88     mInitCheck = init();
89 }
90
91 WAVExtractor::~WAVExtractor() {
92 }
93
94 sp<MetaData> WAVExtractor::getMetaData() {
95     sp<MetaData> meta = new MetaData;
96
97     if (mInitCheck != OK) {
98         return meta;
99     }
100
101     meta->setCString(kKeyMIMEType, "audio/x-wav");
102
103     return meta;
104 }
105
106 size_t WAVExtractor::countTracks() {
107     return mInitCheck == OK ? 1 : 0;
108 }
109
110 sp<MediaSource> WAVExtractor::getTrack(size_t index) {
111     if (mInitCheck != OK || index > 0) {
112         return NULL;
113     }
114
115     return new WAVSource(
116             mDataSource, mTrackMeta,
117             mWaveFormat, mBitsPerSample, mDataOffset, mDataSize);
118 }
119
120 sp<MetaData> WAVExtractor::getTrackMetaData(
121         size_t index, uint32_t flags) {
122     if (mInitCheck != OK || index > 0) {
123         return NULL;
124     }
125
126     return mTrackMeta;
127 }
128
129 status_t WAVExtractor::init() {
130     uint8_t header[12];
131     if (mDataSource->readAt(
132                 0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
133         return NO_INIT;
134     }
135
136     if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
137         return NO_INIT;
138     }
139
140     size_t totalSize = U32_LE_AT(&header[4]);
141
142     off_t offset = 12;
143     size_t remainingSize = totalSize;
144     while (remainingSize >= 8) {
145         uint8_t chunkHeader[8];
146         if (mDataSource->readAt(offset, chunkHeader, 8) < 8) {
147             return NO_INIT;
148         }
149
150         remainingSize -= 8;
151         offset += 8;
152
153         uint32_t chunkSize = U32_LE_AT(&chunkHeader[4]);
154
155         if (chunkSize > remainingSize) {
156             return NO_INIT;
157         }
158
159         if (!memcmp(chunkHeader, "fmt ", 4)) {
160             if (chunkSize < 16) {
161                 return NO_INIT;
162             }
163
164             uint8_t formatSpec[16];
165             if (mDataSource->readAt(offset, formatSpec, 16) < 16) {
166                 return NO_INIT;
167             }
168
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;
174             }
175
176             mNumChannels = U16_LE_AT(&formatSpec[2]);
177             if (mNumChannels != 1 && mNumChannels != 2) {
178                 return ERROR_UNSUPPORTED;
179             }
180
181             mSampleRate = U32_LE_AT(&formatSpec[4]);
182
183             if (mSampleRate == 0) {
184                 return ERROR_MALFORMED;
185             }
186
187             mBitsPerSample = U16_LE_AT(&formatSpec[14]);
188
189             if (mWaveFormat == WAVE_FORMAT_PCM) {
190                 if (mBitsPerSample != 8 && mBitsPerSample != 16
191                     && mBitsPerSample != 24) {
192                     return ERROR_UNSUPPORTED;
193                 }
194             } else {
195                 CHECK(mWaveFormat == WAVE_FORMAT_MULAW
196                         || mWaveFormat == WAVE_FORMAT_ALAW);
197                 if (mBitsPerSample != 8) {
198                     return ERROR_UNSUPPORTED;
199                 }
200             }
201
202             mValidFormat = true;
203         } else if (!memcmp(chunkHeader, "data", 4)) {
204             if (mValidFormat) {
205                 mDataOffset = offset;
206                 mDataSize = chunkSize;
207
208                 mTrackMeta = new MetaData;
209
210                 switch (mWaveFormat) {
211                     case WAVE_FORMAT_PCM:
212                         mTrackMeta->setCString(
213                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
214                         break;
215                     case WAVE_FORMAT_ALAW:
216                         mTrackMeta->setCString(
217                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
218                         break;
219                     default:
220                         CHECK_EQ(mWaveFormat, WAVE_FORMAT_MULAW);
221                         mTrackMeta->setCString(
222                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
223                         break;
224                 }
225
226                 mTrackMeta->setInt32(kKeyChannelCount, mNumChannels);
227                 mTrackMeta->setInt32(kKeySampleRate, mSampleRate);
228
229                 size_t bytesPerSample = mBitsPerSample >> 3;
230
231                 int64_t durationUs =
232                     1000000LL * (mDataSize / (mNumChannels * bytesPerSample))
233                         / mSampleRate;
234
235                 mTrackMeta->setInt64(kKeyDuration, durationUs);
236
237                 return OK;
238             }
239         }
240
241         offset += chunkSize;
242     }
243
244     return NO_INIT;
245 }
246
247 const size_t WAVSource::kMaxFrameSize = 32768;
248
249 WAVSource::WAVSource(
250         const sp<DataSource> &dataSource,
251         const sp<MetaData> &meta,
252         uint16_t waveFormat,
253         int32_t bitsPerSample,
254         off_t offset, size_t size)
255     : mDataSource(dataSource),
256       mMeta(meta),
257       mWaveFormat(waveFormat),
258       mSampleRate(0),
259       mNumChannels(0),
260       mBitsPerSample(bitsPerSample),
261       mOffset(offset),
262       mSize(size),
263       mStarted(false),
264       mGroup(NULL) {
265     CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
266     CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
267 }
268
269 WAVSource::~WAVSource() {
270     if (mStarted) {
271         stop();
272     }
273 }
274
275 status_t WAVSource::start(MetaData *params) {
276     LOGV("WAVSource::start");
277
278     CHECK(!mStarted);
279
280     mGroup = new MediaBufferGroup;
281     mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
282
283     if (mBitsPerSample == 8) {
284         // As a temporary buffer for 8->16 bit conversion.
285         mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
286     }
287
288     mCurrentPos = mOffset;
289
290     mStarted = true;
291
292     return OK;
293 }
294
295 status_t WAVSource::stop() {
296     LOGV("WAVSource::stop");
297
298     CHECK(mStarted);
299
300     delete mGroup;
301     mGroup = NULL;
302
303     mStarted = false;
304
305     return OK;
306 }
307
308 sp<MetaData> WAVSource::getFormat() {
309     LOGV("WAVSource::getFormat");
310
311     return mMeta;
312 }
313
314 status_t WAVSource::read(
315         MediaBuffer **out, const ReadOptions *options) {
316     *out = NULL;
317
318     int64_t seekTimeUs;
319     ReadOptions::SeekMode mode;
320     if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
321         int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * 2;
322         if (pos > mSize) {
323             pos = mSize;
324         }
325         mCurrentPos = pos + mOffset;
326     }
327
328     MediaBuffer *buffer;
329     status_t err = mGroup->acquire_buffer(&buffer);
330     if (err != OK) {
331         return err;
332     }
333
334     size_t maxBytesToRead =
335         mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize;
336
337     size_t maxBytesAvailable =
338         (mCurrentPos - mOffset >= (off_t)mSize)
339             ? 0 : mSize - (mCurrentPos - mOffset);
340
341     if (maxBytesToRead > maxBytesAvailable) {
342         maxBytesToRead = maxBytesAvailable;
343     }
344
345     ssize_t n = mDataSource->readAt(
346             mCurrentPos, buffer->data(),
347             maxBytesToRead);
348
349     if (n <= 0) {
350         buffer->release();
351         buffer = NULL;
352
353         return ERROR_END_OF_STREAM;
354     }
355
356     mCurrentPos += n;
357
358     buffer->set_range(0, n);
359
360     if (mWaveFormat == WAVE_FORMAT_PCM) {
361         if (mBitsPerSample == 8) {
362             // Convert 8-bit unsigned samples to 16-bit signed.
363
364             MediaBuffer *tmp;
365             CHECK_EQ(mGroup->acquire_buffer(&tmp), OK);
366
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);
370
371             int16_t *dst = (int16_t *)tmp->data();
372             const uint8_t *src = (const uint8_t *)buffer->data();
373             while (n-- > 0) {
374                 *dst++ = ((int16_t)(*src) - 128) * 256;
375                 ++src;
376             }
377
378             buffer->release();
379             buffer = tmp;
380         } else if (mBitsPerSample == 24) {
381             // Convert 24-bit signed samples to 16-bit signed.
382
383             const uint8_t *src =
384                 (const uint8_t *)buffer->data() + buffer->range_offset();
385             int16_t *dst = (int16_t *)src;
386
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
391
392                 x = x >> 8;
393                 *dst++ = (int16_t)x;
394                 src += 3;
395             }
396
397             buffer->set_range(buffer->range_offset(), 2 * numSamples);
398         }
399     }
400
401     size_t bytesPerSample = mBitsPerSample >> 3;
402
403     buffer->meta_data()->setInt64(
404             kKeyTime,
405             1000000LL * (mCurrentPos - mOffset)
406                 / (mNumChannels * bytesPerSample) / mSampleRate);
407
408     buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
409
410     *out = buffer;
411
412     return OK;
413 }
414
415 ////////////////////////////////////////////////////////////////////////////////
416
417 bool SniffWAV(
418         const sp<DataSource> &source, String8 *mimeType, float *confidence,
419         sp<AMessage> *) {
420     char header[12];
421     if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
422         return false;
423     }
424
425     if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
426         return false;
427     }
428
429     *mimeType = MEDIA_MIMETYPE_CONTAINER_WAV;
430     *confidence = 0.3f;
431
432     return true;
433 }
434
435 }  // namespace android
436