MP3Extractor.cpp revision e23da615c0b1721fe7d9d2e06e82e43b9bd89df3
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 "MP3Extractor"
19#include <utils/Log.h>
20
21#include "include/MP3Extractor.h"
22
23#include "include/ID3.h"
24#include "include/VBRISeeker.h"
25#include "include/XINGSeeker.h"
26
27#include <media/stagefright/foundation/AMessage.h>
28#include <media/stagefright/DataSource.h>
29#include <media/stagefright/MediaBuffer.h>
30#include <media/stagefright/MediaBufferGroup.h>
31#include <media/stagefright/MediaDebug.h>
32#include <media/stagefright/MediaDefs.h>
33#include <media/stagefright/MediaErrors.h>
34#include <media/stagefright/MediaSource.h>
35#include <media/stagefright/MetaData.h>
36#include <media/stagefright/Utils.h>
37#include <utils/String8.h>
38
39namespace android {
40
41// Everything must match except for
42// protection, bitrate, padding, private bits, mode extension,
43// copyright bit, original bit and emphasis.
44// Yes ... there are things that must indeed match...
45static const uint32_t kMask = 0xfffe0cc0;
46
47// static
48bool MP3Extractor::get_mp3_frame_size(
49        uint32_t header, size_t *frame_size,
50        int *out_sampling_rate, int *out_channels,
51        int *out_bitrate) {
52    *frame_size = 0;
53
54    if (out_sampling_rate) {
55        *out_sampling_rate = 0;
56    }
57
58    if (out_channels) {
59        *out_channels = 0;
60    }
61
62    if (out_bitrate) {
63        *out_bitrate = 0;
64    }
65
66    if ((header & 0xffe00000) != 0xffe00000) {
67        return false;
68    }
69
70    unsigned version = (header >> 19) & 3;
71
72    if (version == 0x01) {
73        return false;
74    }
75
76    unsigned layer = (header >> 17) & 3;
77
78    if (layer == 0x00) {
79        return false;
80    }
81
82    unsigned protection = (header >> 16) & 1;
83
84    unsigned bitrate_index = (header >> 12) & 0x0f;
85
86    if (bitrate_index == 0 || bitrate_index == 0x0f) {
87        // Disallow "free" bitrate.
88        return false;
89    }
90
91    unsigned sampling_rate_index = (header >> 10) & 3;
92
93    if (sampling_rate_index == 3) {
94        return false;
95    }
96
97    static const int kSamplingRateV1[] = { 44100, 48000, 32000 };
98    int sampling_rate = kSamplingRateV1[sampling_rate_index];
99    if (version == 2 /* V2 */) {
100        sampling_rate /= 2;
101    } else if (version == 0 /* V2.5 */) {
102        sampling_rate /= 4;
103    }
104
105    unsigned padding = (header >> 9) & 1;
106
107    if (layer == 3) {
108        // layer I
109
110        static const int kBitrateV1[] = {
111            32, 64, 96, 128, 160, 192, 224, 256,
112            288, 320, 352, 384, 416, 448
113        };
114
115        static const int kBitrateV2[] = {
116            32, 48, 56, 64, 80, 96, 112, 128,
117            144, 160, 176, 192, 224, 256
118        };
119
120        int bitrate =
121            (version == 3 /* V1 */)
122                ? kBitrateV1[bitrate_index - 1]
123                : kBitrateV2[bitrate_index - 1];
124
125        if (out_bitrate) {
126            *out_bitrate = bitrate;
127        }
128
129        *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
130    } else {
131        // layer II or III
132
133        static const int kBitrateV1L2[] = {
134            32, 48, 56, 64, 80, 96, 112, 128,
135            160, 192, 224, 256, 320, 384
136        };
137
138        static const int kBitrateV1L3[] = {
139            32, 40, 48, 56, 64, 80, 96, 112,
140            128, 160, 192, 224, 256, 320
141        };
142
143        static const int kBitrateV2[] = {
144            8, 16, 24, 32, 40, 48, 56, 64,
145            80, 96, 112, 128, 144, 160
146        };
147
148        int bitrate;
149        if (version == 3 /* V1 */) {
150            bitrate = (layer == 2 /* L2 */)
151                ? kBitrateV1L2[bitrate_index - 1]
152                : kBitrateV1L3[bitrate_index - 1];
153        } else {
154            // V2 (or 2.5)
155
156            bitrate = kBitrateV2[bitrate_index - 1];
157        }
158
159        if (out_bitrate) {
160            *out_bitrate = bitrate;
161        }
162
163        if (version == 3 /* V1 */) {
164            *frame_size = 144000 * bitrate / sampling_rate + padding;
165        } else {
166            // V2 or V2.5
167            *frame_size = 72000 * bitrate / sampling_rate + padding;
168        }
169    }
170
171    if (out_sampling_rate) {
172        *out_sampling_rate = sampling_rate;
173    }
174
175    if (out_channels) {
176        int channel_mode = (header >> 6) & 3;
177
178        *out_channels = (channel_mode == 3) ? 1 : 2;
179    }
180
181    return true;
182}
183
184static bool Resync(
185        const sp<DataSource> &source, uint32_t match_header,
186        off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) {
187    if (post_id3_pos != NULL) {
188        *post_id3_pos = 0;
189    }
190
191    if (*inout_pos == 0) {
192        // Skip an optional ID3 header if syncing at the very beginning
193        // of the datasource.
194
195        for (;;) {
196            uint8_t id3header[10];
197            if (source->readAt(*inout_pos, id3header, sizeof(id3header))
198                    < (ssize_t)sizeof(id3header)) {
199                // If we can't even read these 10 bytes, we might as well bail
200                // out, even if there _were_ 10 bytes of valid mp3 audio data...
201                return false;
202            }
203
204            if (memcmp("ID3", id3header, 3)) {
205                break;
206            }
207
208            // Skip the ID3v2 header.
209
210            size_t len =
211                ((id3header[6] & 0x7f) << 21)
212                | ((id3header[7] & 0x7f) << 14)
213                | ((id3header[8] & 0x7f) << 7)
214                | (id3header[9] & 0x7f);
215
216            len += 10;
217
218            *inout_pos += len;
219
220            LOGV("skipped ID3 tag, new starting offset is %lld (0x%016llx)",
221                 *inout_pos, *inout_pos);
222        }
223
224        if (post_id3_pos != NULL) {
225            *post_id3_pos = *inout_pos;
226        }
227    }
228
229    off64_t pos = *inout_pos;
230    bool valid = false;
231
232    const size_t kMaxReadBytes = 1024;
233    const size_t kMaxBytesChecked = 128 * 1024;
234    uint8_t buf[kMaxReadBytes];
235    ssize_t bytesToRead = kMaxReadBytes;
236    ssize_t totalBytesRead = 0;
237    ssize_t remainingBytes = 0;
238    bool reachEOS = false;
239    uint8_t *tmp = buf;
240
241    do {
242        if (pos >= *inout_pos + kMaxBytesChecked) {
243            // Don't scan forever.
244            LOGV("giving up at offset %lld", pos);
245            break;
246        }
247
248        if (remainingBytes < 4) {
249            if (reachEOS) {
250                break;
251            } else {
252                memcpy(buf, tmp, remainingBytes);
253                bytesToRead = kMaxReadBytes - remainingBytes;
254
255                /*
256                 * The next read position should start from the end of
257                 * the last buffer, and thus should include the remaining
258                 * bytes in the buffer.
259                 */
260                totalBytesRead = source->readAt(pos + remainingBytes,
261                                                buf + remainingBytes,
262                                                bytesToRead);
263                if (totalBytesRead <= 0) {
264                    break;
265                }
266                reachEOS = (totalBytesRead != bytesToRead);
267                totalBytesRead += remainingBytes;
268                remainingBytes = totalBytesRead;
269                tmp = buf;
270                continue;
271            }
272        }
273
274        uint32_t header = U32_AT(tmp);
275
276        if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
277            ++pos;
278            ++tmp;
279            --remainingBytes;
280            continue;
281        }
282
283        size_t frame_size;
284        int sample_rate, num_channels, bitrate;
285        if (!MP3Extractor::get_mp3_frame_size(
286                    header, &frame_size,
287                    &sample_rate, &num_channels, &bitrate)) {
288            ++pos;
289            ++tmp;
290            --remainingBytes;
291            continue;
292        }
293
294        LOGV("found possible 1st frame at %lld (header = 0x%08x)", pos, header);
295
296        // We found what looks like a valid frame,
297        // now find its successors.
298
299        off64_t test_pos = pos + frame_size;
300
301        valid = true;
302        for (int j = 0; j < 3; ++j) {
303            uint8_t tmp[4];
304            if (source->readAt(test_pos, tmp, 4) < 4) {
305                valid = false;
306                break;
307            }
308
309            uint32_t test_header = U32_AT(tmp);
310
311            LOGV("subsequent header is %08x", test_header);
312
313            if ((test_header & kMask) != (header & kMask)) {
314                valid = false;
315                break;
316            }
317
318            size_t test_frame_size;
319            if (!MP3Extractor::get_mp3_frame_size(
320                        test_header, &test_frame_size)) {
321                valid = false;
322                break;
323            }
324
325            LOGV("found subsequent frame #%d at %lld", j + 2, test_pos);
326
327            test_pos += test_frame_size;
328        }
329
330        if (valid) {
331            *inout_pos = pos;
332
333            if (out_header != NULL) {
334                *out_header = header;
335            }
336        } else {
337            LOGV("no dice, no valid sequence of frames found.");
338        }
339
340        ++pos;
341        ++tmp;
342        --remainingBytes;
343    } while (!valid);
344
345    return valid;
346}
347
348class MP3Source : public MediaSource {
349public:
350    MP3Source(
351            const sp<MetaData> &meta, const sp<DataSource> &source,
352            off64_t first_frame_pos, uint32_t fixed_header,
353            const sp<MP3Seeker> &seeker);
354
355    virtual status_t start(MetaData *params = NULL);
356    virtual status_t stop();
357
358    virtual sp<MetaData> getFormat();
359
360    virtual status_t read(
361            MediaBuffer **buffer, const ReadOptions *options = NULL);
362
363protected:
364    virtual ~MP3Source();
365
366private:
367    sp<MetaData> mMeta;
368    sp<DataSource> mDataSource;
369    off64_t mFirstFramePos;
370    uint32_t mFixedHeader;
371    off64_t mCurrentPos;
372    int64_t mCurrentTimeUs;
373    bool mStarted;
374    sp<MP3Seeker> mSeeker;
375    MediaBufferGroup *mGroup;
376
377    MP3Source(const MP3Source &);
378    MP3Source &operator=(const MP3Source &);
379};
380
381MP3Extractor::MP3Extractor(
382        const sp<DataSource> &source, const sp<AMessage> &meta)
383    : mInitCheck(NO_INIT),
384      mDataSource(source),
385      mFirstFramePos(-1),
386      mFixedHeader(0) {
387    off64_t pos = 0;
388    off64_t post_id3_pos;
389    uint32_t header;
390    bool success;
391
392    int64_t meta_offset;
393    uint32_t meta_header;
394    int64_t meta_post_id3_offset;
395    if (meta != NULL
396            && meta->findInt64("offset", &meta_offset)
397            && meta->findInt32("header", (int32_t *)&meta_header)
398            && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) {
399        // The sniffer has already done all the hard work for us, simply
400        // accept its judgement.
401        pos = (off64_t)meta_offset;
402        header = meta_header;
403        post_id3_pos = (off64_t)meta_post_id3_offset;
404
405        success = true;
406    } else {
407        success = Resync(mDataSource, 0, &pos, &post_id3_pos, &header);
408    }
409
410    if (!success) {
411        // mInitCheck will remain NO_INIT
412        return;
413    }
414
415    mFirstFramePos = pos;
416    mFixedHeader = header;
417
418    size_t frame_size;
419    int sample_rate;
420    int num_channels;
421    int bitrate;
422    get_mp3_frame_size(
423            header, &frame_size, &sample_rate, &num_channels, &bitrate);
424
425    mMeta = new MetaData;
426
427    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
428    mMeta->setInt32(kKeySampleRate, sample_rate);
429    mMeta->setInt32(kKeyBitRate, bitrate * 1000);
430    mMeta->setInt32(kKeyChannelCount, num_channels);
431
432    mSeeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
433
434    if (mSeeker == NULL) {
435        mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos);
436    }
437
438    int64_t durationUs;
439
440    if (mSeeker == NULL || !mSeeker->getDuration(&durationUs)) {
441        off64_t fileSize;
442        if (mDataSource->getSize(&fileSize) == OK) {
443            durationUs = 8000LL * (fileSize - mFirstFramePos) / bitrate;
444        } else {
445            durationUs = -1;
446        }
447    }
448
449    if (durationUs >= 0) {
450        mMeta->setInt64(kKeyDuration, durationUs);
451    }
452
453    mInitCheck = OK;
454}
455
456size_t MP3Extractor::countTracks() {
457    return mInitCheck != OK ? 0 : 1;
458}
459
460sp<MediaSource> MP3Extractor::getTrack(size_t index) {
461    if (mInitCheck != OK || index != 0) {
462        return NULL;
463    }
464
465    return new MP3Source(
466            mMeta, mDataSource, mFirstFramePos, mFixedHeader,
467            mSeeker);
468}
469
470sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) {
471    if (mInitCheck != OK || index != 0) {
472        return NULL;
473    }
474
475    return mMeta;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479
480MP3Source::MP3Source(
481        const sp<MetaData> &meta, const sp<DataSource> &source,
482        off64_t first_frame_pos, uint32_t fixed_header,
483        const sp<MP3Seeker> &seeker)
484    : mMeta(meta),
485      mDataSource(source),
486      mFirstFramePos(first_frame_pos),
487      mFixedHeader(fixed_header),
488      mCurrentPos(0),
489      mCurrentTimeUs(0),
490      mStarted(false),
491      mSeeker(seeker),
492      mGroup(NULL) {
493}
494
495MP3Source::~MP3Source() {
496    if (mStarted) {
497        stop();
498    }
499}
500
501status_t MP3Source::start(MetaData *) {
502    CHECK(!mStarted);
503
504    mGroup = new MediaBufferGroup;
505
506    const size_t kMaxFrameSize = 32768;
507    mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
508
509    mCurrentPos = mFirstFramePos;
510    mCurrentTimeUs = 0;
511
512    mStarted = true;
513
514    return OK;
515}
516
517status_t MP3Source::stop() {
518    CHECK(mStarted);
519
520    delete mGroup;
521    mGroup = NULL;
522
523    mStarted = false;
524
525    return OK;
526}
527
528sp<MetaData> MP3Source::getFormat() {
529    return mMeta;
530}
531
532status_t MP3Source::read(
533        MediaBuffer **out, const ReadOptions *options) {
534    *out = NULL;
535
536    int64_t seekTimeUs;
537    ReadOptions::SeekMode mode;
538    if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
539        int64_t actualSeekTimeUs = seekTimeUs;
540        if (mSeeker == NULL
541                || !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) {
542            int32_t bitrate;
543            if (!mMeta->findInt32(kKeyBitRate, &bitrate)) {
544                // bitrate is in bits/sec.
545                LOGI("no bitrate");
546
547                return ERROR_UNSUPPORTED;
548            }
549
550            mCurrentTimeUs = seekTimeUs;
551            mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000;
552        } else {
553            mCurrentTimeUs = actualSeekTimeUs;
554        }
555    }
556
557    MediaBuffer *buffer;
558    status_t err = mGroup->acquire_buffer(&buffer);
559    if (err != OK) {
560        return err;
561    }
562
563    size_t frame_size;
564    int bitrate;
565    for (;;) {
566        ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
567        if (n < 4) {
568            buffer->release();
569            buffer = NULL;
570
571            return ERROR_END_OF_STREAM;
572        }
573
574        uint32_t header = U32_AT((const uint8_t *)buffer->data());
575
576        if ((header & kMask) == (mFixedHeader & kMask)
577            && MP3Extractor::get_mp3_frame_size(
578                header, &frame_size, NULL, NULL, &bitrate)) {
579            break;
580        }
581
582        // Lost sync.
583        LOGV("lost sync! header = 0x%08x, old header = 0x%08x\n", header, mFixedHeader);
584
585        off64_t pos = mCurrentPos;
586        if (!Resync(mDataSource, mFixedHeader, &pos, NULL, NULL)) {
587            LOGE("Unable to resync. Signalling end of stream.");
588
589            buffer->release();
590            buffer = NULL;
591
592            return ERROR_END_OF_STREAM;
593        }
594
595        mCurrentPos = pos;
596
597        // Try again with the new position.
598    }
599
600    CHECK(frame_size <= buffer->size());
601
602    ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), frame_size);
603    if (n < (ssize_t)frame_size) {
604        buffer->release();
605        buffer = NULL;
606
607        return ERROR_END_OF_STREAM;
608    }
609
610    buffer->set_range(0, frame_size);
611
612    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
613    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
614
615    mCurrentPos += frame_size;
616    mCurrentTimeUs += frame_size * 8000ll / bitrate;
617
618    *out = buffer;
619
620    return OK;
621}
622
623sp<MetaData> MP3Extractor::getMetaData() {
624    sp<MetaData> meta = new MetaData;
625
626    if (mInitCheck != OK) {
627        return meta;
628    }
629
630    meta->setCString(kKeyMIMEType, "audio/mpeg");
631
632    ID3 id3(mDataSource);
633
634    if (!id3.isValid()) {
635        return meta;
636    }
637
638    struct Map {
639        int key;
640        const char *tag1;
641        const char *tag2;
642    };
643    static const Map kMap[] = {
644        { kKeyAlbum, "TALB", "TAL" },
645        { kKeyArtist, "TPE1", "TP1" },
646        { kKeyAlbumArtist, "TPE2", "TP2" },
647        { kKeyComposer, "TCOM", "TCM" },
648        { kKeyGenre, "TCON", "TCO" },
649        { kKeyTitle, "TIT2", "TT2" },
650        { kKeyYear, "TYE", "TYER" },
651        { kKeyAuthor, "TXT", "TEXT" },
652        { kKeyCDTrackNumber, "TRK", "TRCK" },
653        { kKeyDiscNumber, "TPA", "TPOS" },
654        { kKeyCompilation, "TCP", "TCMP" },
655    };
656    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
657
658    for (size_t i = 0; i < kNumMapEntries; ++i) {
659        ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
660        if (it->done()) {
661            delete it;
662            it = new ID3::Iterator(id3, kMap[i].tag2);
663        }
664
665        if (it->done()) {
666            delete it;
667            continue;
668        }
669
670        String8 s;
671        it->getString(&s);
672        delete it;
673
674        meta->setCString(kMap[i].key, s);
675    }
676
677    size_t dataSize;
678    String8 mime;
679    const void *data = id3.getAlbumArt(&dataSize, &mime);
680
681    if (data) {
682        meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
683        meta->setCString(kKeyAlbumArtMIME, mime.string());
684    }
685
686    return meta;
687}
688
689bool SniffMP3(
690        const sp<DataSource> &source, String8 *mimeType,
691        float *confidence, sp<AMessage> *meta) {
692    off64_t pos = 0;
693    off64_t post_id3_pos;
694    uint32_t header;
695    if (!Resync(source, 0, &pos, &post_id3_pos, &header)) {
696        return false;
697    }
698
699    *meta = new AMessage;
700    (*meta)->setInt64("offset", pos);
701    (*meta)->setInt32("header", header);
702    (*meta)->setInt64("post-id3-offset", post_id3_pos);
703
704    *mimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
705    *confidence = 0.2f;
706
707    return true;
708}
709
710}  // namespace android
711