1e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber/*
2e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
4e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * you may not use this file except in compliance with the License.
6e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * You may obtain a copy of the License at
7e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
8e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
10e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Unless required by applicable law or agreed to in writing, software
11e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * See the License for the specific language governing permissions and
14e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * limitations under the License.
15e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber */
16e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
17e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber//#define LOG_NDEBUG 0
18e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#define LOG_TAG "MP3Extractor"
19e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/Log.h>
20e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2157515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber#include "include/MP3Extractor.h"
2257515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber
23eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber#include "include/avc_utils.h"
24aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber#include "include/ID3.h"
251bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber#include "include/VBRISeeker.h"
261bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber#include "include/XINGSeeker.h"
27aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
28bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber#include <media/stagefright/foundation/ADebug.h>
29efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber#include <media/stagefright/foundation/AMessage.h>
30e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h>
31e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h>
32e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
33e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h>
34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaErrors.h>
35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h>
36e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h>
37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h>
38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h>
39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android {
41e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
42b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber// Everything must match except for
43858b673a3518b2b15302cfdbf9433f111536c72cJames Dong// protection, bitrate, padding, private bits, mode, mode extension,
441d200e3b959f7562b21a6e9d94910ddd051cfe10Andreas Huber// copyright bit, original bit and emphasis.
451d200e3b959f7562b21a6e9d94910ddd051cfe10Andreas Huber// Yes ... there are things that must indeed match...
46858b673a3518b2b15302cfdbf9433f111536c72cJames Dongstatic const uint32_t kMask = 0xfffe0c00;
47b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber
48e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic bool Resync(
49be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<DataSource> &source, uint32_t match_header,
50b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) {
511bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    if (post_id3_pos != NULL) {
521bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        *post_id3_pos = 0;
531bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    }
541bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
5563f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber    if (*inout_pos == 0) {
5663f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber        // Skip an optional ID3 header if syncing at the very beginning
5763f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber        // of the datasource.
5863f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber
590d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber        for (;;) {
600d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            uint8_t id3header[10];
610d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            if (source->readAt(*inout_pos, id3header, sizeof(id3header))
620d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber                    < (ssize_t)sizeof(id3header)) {
630d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber                // If we can't even read these 10 bytes, we might as well bail
640d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber                // out, even if there _were_ 10 bytes of valid mp3 audio data...
650d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber                return false;
660d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            }
670d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber
680d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            if (memcmp("ID3", id3header, 3)) {
690d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber                break;
700d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            }
7163f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber
7263f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber            // Skip the ID3v2 header.
7363f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber
7463f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber            size_t len =
7563f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber                ((id3header[6] & 0x7f) << 21)
7663f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber                | ((id3header[7] & 0x7f) << 14)
7763f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber                | ((id3header[8] & 0x7f) << 7)
7863f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber                | (id3header[9] & 0x7f);
7963f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber
8063f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber            len += 10;
8163f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber
8263f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber            *inout_pos += len;
830d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber
84563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong            LOGV("skipped ID3 tag, new starting offset is %lld (0x%016llx)",
850d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber                 *inout_pos, *inout_pos);
8663f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber        }
871bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
881bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        if (post_id3_pos != NULL) {
891bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            *post_id3_pos = *inout_pos;
901bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        }
9163f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber    }
9263f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber
93b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t pos = *inout_pos;
94e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool valid = false;
9531d8a03e44b272afacad07a7670aaad764172797James Dong
9631d8a03e44b272afacad07a7670aaad764172797James Dong    const size_t kMaxReadBytes = 1024;
9731d8a03e44b272afacad07a7670aaad764172797James Dong    const size_t kMaxBytesChecked = 128 * 1024;
9831d8a03e44b272afacad07a7670aaad764172797James Dong    uint8_t buf[kMaxReadBytes];
9931d8a03e44b272afacad07a7670aaad764172797James Dong    ssize_t bytesToRead = kMaxReadBytes;
10031d8a03e44b272afacad07a7670aaad764172797James Dong    ssize_t totalBytesRead = 0;
10131d8a03e44b272afacad07a7670aaad764172797James Dong    ssize_t remainingBytes = 0;
10231d8a03e44b272afacad07a7670aaad764172797James Dong    bool reachEOS = false;
10331d8a03e44b272afacad07a7670aaad764172797James Dong    uint8_t *tmp = buf;
10431d8a03e44b272afacad07a7670aaad764172797James Dong
105e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    do {
10631d8a03e44b272afacad07a7670aaad764172797James Dong        if (pos >= *inout_pos + kMaxBytesChecked) {
1070d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            // Don't scan forever.
108563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong            LOGV("giving up at offset %lld", pos);
1090d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            break;
1100d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber        }
111e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
11231d8a03e44b272afacad07a7670aaad764172797James Dong        if (remainingBytes < 4) {
11331d8a03e44b272afacad07a7670aaad764172797James Dong            if (reachEOS) {
11431d8a03e44b272afacad07a7670aaad764172797James Dong                break;
11531d8a03e44b272afacad07a7670aaad764172797James Dong            } else {
11631d8a03e44b272afacad07a7670aaad764172797James Dong                memcpy(buf, tmp, remainingBytes);
11731d8a03e44b272afacad07a7670aaad764172797James Dong                bytesToRead = kMaxReadBytes - remainingBytes;
118563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong
119563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                /*
120563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                 * The next read position should start from the end of
121563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                 * the last buffer, and thus should include the remaining
122563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                 * bytes in the buffer.
123563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                 */
124563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                totalBytesRead = source->readAt(pos + remainingBytes,
125563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                                                buf + remainingBytes,
126563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong                                                bytesToRead);
12731d8a03e44b272afacad07a7670aaad764172797James Dong                if (totalBytesRead <= 0) {
12831d8a03e44b272afacad07a7670aaad764172797James Dong                    break;
12931d8a03e44b272afacad07a7670aaad764172797James Dong                }
13031d8a03e44b272afacad07a7670aaad764172797James Dong                reachEOS = (totalBytesRead != bytesToRead);
13131d8a03e44b272afacad07a7670aaad764172797James Dong                totalBytesRead += remainingBytes;
13231d8a03e44b272afacad07a7670aaad764172797James Dong                remainingBytes = totalBytesRead;
13331d8a03e44b272afacad07a7670aaad764172797James Dong                tmp = buf;
13431d8a03e44b272afacad07a7670aaad764172797James Dong                continue;
13531d8a03e44b272afacad07a7670aaad764172797James Dong            }
136e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
137e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1380d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber        uint32_t header = U32_AT(tmp);
139e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
14030856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong        if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
14130856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            ++pos;
14230856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            ++tmp;
14330856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            --remainingBytes;
14430856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            continue;
14530856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong        }
14630856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong
147e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        size_t frame_size;
14830856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong        int sample_rate, num_channels, bitrate;
14930856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong        if (!GetMPEGAudioFrameSize(
15030856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong                    header, &frame_size,
15130856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong                    &sample_rate, &num_channels, &bitrate)) {
15230856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            ++pos;
15330856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            ++tmp;
15430856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            --remainingBytes;
15530856a76dcbc3983cfbe43466bdcf67cd76677f4James Dong            continue;
1562e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber        }
157e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
158563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong        LOGV("found possible 1st frame at %lld (header = 0x%08x)", pos, header);
159e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1602e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber        // We found what looks like a valid frame,
1612e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber        // now find its successors.
162e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
163b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        off64_t test_pos = pos + frame_size;
164e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1652e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber        valid = true;
1662e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber        for (int j = 0; j < 3; ++j) {
1672e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            uint8_t tmp[4];
1689a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber            if (source->readAt(test_pos, tmp, 4) < 4) {
1692e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber                valid = false;
1702e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber                break;
1712e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            }
172b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber
1732e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            uint32_t test_header = U32_AT(tmp);
174e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1752e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            LOGV("subsequent header is %08x", test_header);
176e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1772e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            if ((test_header & kMask) != (header & kMask)) {
1782e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber                valid = false;
1792e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber                break;
1802e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            }
181e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1822e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            size_t test_frame_size;
183eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber            if (!GetMPEGAudioFrameSize(
1841bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber                        test_header, &test_frame_size)) {
1852e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber                valid = false;
1862e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber                break;
187e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
1882e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber
189563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong            LOGV("found subsequent frame #%d at %lld", j + 2, test_pos);
1902e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber
1912e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber            test_pos += test_frame_size;
192e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
193e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
194e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (valid) {
1950d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber            *inout_pos = pos;
196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            if (out_header != NULL) {
198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber                *out_header = header;
199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            }
200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        } else {
201e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            LOGV("no dice, no valid sequence of frames found.");
202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2040d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber        ++pos;
20531d8a03e44b272afacad07a7670aaad764172797James Dong        ++tmp;
20631d8a03e44b272afacad07a7670aaad764172797James Dong        --remainingBytes;
207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    } while (!valid);
208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return valid;
210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MP3Source : public MediaSource {
213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic:
214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MP3Source(
215be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber            const sp<MetaData> &meta, const sp<DataSource> &source,
216b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong            off64_t first_frame_pos, uint32_t fixed_header,
2171bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            const sp<MP3Seeker> &seeker);
218e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t start(MetaData *params = NULL);
220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t stop();
221e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual sp<MetaData> getFormat();
223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    virtual status_t read(
225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
227be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected:
228be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    virtual ~MP3Source();
229be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber
230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate:
231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    sp<MetaData> mMeta;
232be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    sp<DataSource> mDataSource;
233b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t mFirstFramePos;
234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t mFixedHeader;
235b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t mCurrentPos;
236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t mCurrentTimeUs;
237e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    bool mStarted;
2381bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    sp<MP3Seeker> mSeeker;
239e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBufferGroup *mGroup;
240e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
241293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    int64_t mBasisTimeUs;
242293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    int64_t mSamplesRead;
243293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons
244e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MP3Source(const MP3Source &);
245e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MP3Source &operator=(const MP3Source &);
246e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber};
247e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
248efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas HuberMP3Extractor::MP3Extractor(
249efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        const sp<DataSource> &source, const sp<AMessage> &meta)
2503e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    : mInitCheck(NO_INIT),
2513e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber      mDataSource(source),
252e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mFirstFramePos(-1),
2531bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber      mFixedHeader(0) {
254b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t pos = 0;
255b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t post_id3_pos;
256e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t header;
257efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    bool success;
258efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber
259efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    int64_t meta_offset;
260efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    uint32_t meta_header;
2611bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    int64_t meta_post_id3_offset;
262efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    if (meta != NULL
263efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber            && meta->findInt64("offset", &meta_offset)
2641bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            && meta->findInt32("header", (int32_t *)&meta_header)
2651bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) {
266efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        // The sniffer has already done all the hard work for us, simply
267efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        // accept its judgement.
268b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        pos = (off64_t)meta_offset;
269efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        header = meta_header;
270b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        post_id3_pos = (off64_t)meta_post_id3_offset;
271efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber
272efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        success = true;
273efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    } else {
2741bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        success = Resync(mDataSource, 0, &pos, &post_id3_pos, &header);
275efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    }
276e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2773e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    if (!success) {
2783e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber        // mInitCheck will remain NO_INIT
2793e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber        return;
2803e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    }
281e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2823e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    mFirstFramePos = pos;
2833e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    mFixedHeader = header;
284e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
2853e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    size_t frame_size;
2863e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    int sample_rate;
2873e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    int num_channels;
2883e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    int bitrate;
289eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber    GetMPEGAudioFrameSize(
2903e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber            header, &frame_size, &sample_rate, &num_channels, &bitrate);
2913e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber
292bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber    unsigned layer = 4 - ((header >> 17) & 3);
293bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber
2943e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    mMeta = new MetaData;
2953e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber
296bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber    switch (layer) {
297bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber        case 1:
298bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber            mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
299bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber            break;
300bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber        case 2:
301bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber            mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
302bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber            break;
303bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber        case 3:
304bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber            mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
305bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber            break;
306bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber        default:
307bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber            TRESPASS();
308bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber    }
309bc554956128d69d8d2e60365fb6cffe6facf659bAndreas Huber
3103e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    mMeta->setInt32(kKeySampleRate, sample_rate);
3113e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    mMeta->setInt32(kKeyBitRate, bitrate * 1000);
3123e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    mMeta->setInt32(kKeyChannelCount, num_channels);
3133e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber
3141bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    mSeeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
3151bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
3161bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    if (mSeeker == NULL) {
3171bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos);
3181bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    }
3191bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
3201bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    int64_t durationUs;
3211bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
3221bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    if (mSeeker == NULL || !mSeeker->getDuration(&durationUs)) {
323b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        off64_t fileSize;
3243e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber        if (mDataSource->getSize(&fileSize) == OK) {
3251bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            durationUs = 8000LL * (fileSize - mFirstFramePos) / bitrate;
3261bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        } else {
3271bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            durationUs = -1;
328e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
329e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
330e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
3311bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    if (durationUs >= 0) {
3321bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        mMeta->setInt64(kKeyDuration, durationUs);
3331bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    }
3341bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
3353e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    mInitCheck = OK;
336e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
337e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
338be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MP3Extractor::countTracks() {
3393e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    return mInitCheck != OK ? 0 : 1;
340e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
341e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
342be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MP3Extractor::getTrack(size_t index) {
3433e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    if (mInitCheck != OK || index != 0) {
344be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        return NULL;
345e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
346e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
347be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    return new MP3Source(
3481ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang            mMeta, mDataSource, mFirstFramePos, mFixedHeader,
3491bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            mSeeker);
350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
351e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
352e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) {
3533e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    if (mInitCheck != OK || index != 0) {
354e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return NULL;
355e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return mMeta;
358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
359e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber////////////////////////////////////////////////////////////////////////////////
361e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
362e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMP3Source::MP3Source(
363be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber        const sp<MetaData> &meta, const sp<DataSource> &source,
364b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        off64_t first_frame_pos, uint32_t fixed_header,
3651bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        const sp<MP3Seeker> &seeker)
366e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    : mMeta(meta),
367e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mDataSource(source),
368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mFirstFramePos(first_frame_pos),
369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mFixedHeader(fixed_header),
370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mCurrentPos(0),
371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mCurrentTimeUs(0),
372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber      mStarted(false),
3731bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber      mSeeker(seeker),
374293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons      mGroup(NULL),
375293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons      mBasisTimeUs(0),
376293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons      mSamplesRead(0) {
377e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
378e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
379e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMP3Source::~MP3Source() {
380e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mStarted) {
381e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        stop();
382e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
383e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
384e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MP3Source::start(MetaData *) {
386b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber    CHECK(!mStarted);
387e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = new MediaBufferGroup;
389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
390e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    const size_t kMaxFrameSize = 32768;
391e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
392e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
393e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentPos = mFirstFramePos;
394e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentTimeUs = 0;
395e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
396293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    mBasisTimeUs = mCurrentTimeUs;
397293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    mSamplesRead = 0;
398293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons
399e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = true;
400e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
401e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
402e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
403e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
404e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MP3Source::stop() {
405b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber    CHECK(mStarted);
406e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    delete mGroup;
408e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mGroup = NULL;
409e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
410e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = false;
411e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
412e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
413e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
414e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
415e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MP3Source::getFormat() {
416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return mMeta;
417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
418e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
419e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MP3Source::read(
420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *out = NULL;
422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
423e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t seekTimeUs;
4246624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    ReadOptions::SeekMode mode;
4257ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang    bool seekCBR = false;
4267ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang
4276624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
4281bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        int64_t actualSeekTimeUs = seekTimeUs;
4291bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        if (mSeeker == NULL
4301bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber                || !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) {
4311bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            int32_t bitrate;
4321bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            if (!mMeta->findInt32(kKeyBitRate, &bitrate)) {
4331bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber                // bitrate is in bits/sec.
4341bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber                LOGI("no bitrate");
4351bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
4361bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber                return ERROR_UNSUPPORTED;
4371ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang            }
4381bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber
4391bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            mCurrentTimeUs = seekTimeUs;
4401ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang            mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000;
4417ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang            seekCBR = true;
4421bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        } else {
4431bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber            mCurrentTimeUs = actualSeekTimeUs;
4441ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang        }
445293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons
446293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons        mBasisTimeUs = mCurrentTimeUs;
447293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons        mSamplesRead = 0;
448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MediaBuffer *buffer;
451e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    status_t err = mGroup->acquire_buffer(&buffer);
452e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (err != OK) {
453e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return err;
454e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
455e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
456e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    size_t frame_size;
457b64af9a221c1df4853ab7c7766d5f956c61b8765Andreas Huber    int bitrate;
458293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    int num_samples;
459293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    int sample_rate;
460e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    for (;;) {
4619a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber        ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
462e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        if (n < 4) {
463e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            buffer->release();
464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            buffer = NULL;
465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
466e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return ERROR_END_OF_STREAM;
467e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
468e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
469e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        uint32_t header = U32_AT((const uint8_t *)buffer->data());
470b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber
471b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber        if ((header & kMask) == (mFixedHeader & kMask)
472eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber            && GetMPEGAudioFrameSize(
473eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber                header, &frame_size, &sample_rate, NULL,
474eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber                &bitrate, &num_samples)) {
4757ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang
4767ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang            // re-calculate mCurrentTimeUs because we might have called Resync()
4777ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang            if (seekCBR) {
4787ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang                mCurrentTimeUs = (mCurrentPos - mFirstFramePos) * 8000 / bitrate;
4797ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang                mBasisTimeUs = mCurrentTimeUs;
4807ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang            }
4817ffa1ea8cb810d3f4b8c9eb57e1941484d0c5bb9Gloria Wang
482e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            break;
483e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        // Lost sync.
4861d200e3b959f7562b21a6e9d94910ddd051cfe10Andreas Huber        LOGV("lost sync! header = 0x%08x, old header = 0x%08x\n", header, mFixedHeader);
487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
488b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong        off64_t pos = mCurrentPos;
4891bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber        if (!Resync(mDataSource, mFixedHeader, &pos, NULL, NULL)) {
490e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            LOGE("Unable to resync. Signalling end of stream.");
491e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
492e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            buffer->release();
493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            buffer = NULL;
494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber            return ERROR_END_OF_STREAM;
496e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
498e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        mCurrentPos = pos;
499e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
500e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        // Try again with the new position.
501e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
502e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
503b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber    CHECK(frame_size <= buffer->size());
504e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
5059a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), frame_size);
506e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (n < (ssize_t)frame_size) {
507e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        buffer->release();
508e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        buffer = NULL;
509e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
510e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return ERROR_END_OF_STREAM;
511e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
512e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
513e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    buffer->set_range(0, frame_size);
514e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
515fa8de752507feaca695123911915070c1ce463b2Andreas Huber    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
516ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
517e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
518e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mCurrentPos += frame_size;
519293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons
520293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    mSamplesRead += num_samples;
521293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons    mCurrentTimeUs = mBasisTimeUs + ((mSamplesRead * 1000000) / sample_rate);
522e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
523e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *out = buffer;
524e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
525e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
526e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
527e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
528aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Hubersp<MetaData> MP3Extractor::getMetaData() {
529aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sp<MetaData> meta = new MetaData;
530aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
5313e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber    if (mInitCheck != OK) {
5321cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber        return meta;
5331cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    }
5341cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
535aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    meta->setCString(kKeyMIMEType, "audio/mpeg");
536aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
537aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    ID3 id3(mDataSource);
538aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
539aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!id3.isValid()) {
540aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return meta;
541aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
542aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
543aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    struct Map {
544aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int key;
545aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        const char *tag1;
546aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        const char *tag2;
547aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
548aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const Map kMap[] = {
549aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyAlbum, "TALB", "TAL" },
550aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyArtist, "TPE1", "TP1" },
551c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        { kKeyAlbumArtist, "TPE2", "TP2" },
552aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyComposer, "TCOM", "TCM" },
553aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyGenre, "TCON", "TCO" },
5543a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyTitle, "TIT2", "TT2" },
555aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyYear, "TYE", "TYER" },
5563a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyAuthor, "TXT", "TEXT" },
5573a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyCDTrackNumber, "TRK", "TRCK" },
558655306f8a80b3e9fc52daf458ef319a8ed8c564cMarco Nelissen        { kKeyDiscNumber, "TPA", "TPOS" },
559ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen        { kKeyCompilation, "TCP", "TCMP" },
560aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
561aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
562aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
563aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    for (size_t i = 0; i < kNumMapEntries; ++i) {
564aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
565aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (it->done()) {
566aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            delete it;
567aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            it = new ID3::Iterator(id3, kMap[i].tag2);
568aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
569aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
570aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (it->done()) {
571aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            delete it;
572aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            continue;
573aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
574aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
575aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        String8 s;
576aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        it->getString(&s);
577aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        delete it;
578aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
579aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        meta->setCString(kMap[i].key, s);
580aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
581aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
582aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    size_t dataSize;
583aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    String8 mime;
584aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    const void *data = id3.getAlbumArt(&dataSize, &mime);
585aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
586aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (data) {
587aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
588aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        meta->setCString(kKeyAlbumArtMIME, mime.string());
589aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
590aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
591aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return meta;
592aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber}
593aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
594be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberbool SniffMP3(
595efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        const sp<DataSource> &source, String8 *mimeType,
596efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        float *confidence, sp<AMessage> *meta) {
597b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t pos = 0;
598b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong    off64_t post_id3_pos;
599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    uint32_t header;
6001bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    if (!Resync(source, 0, &pos, &post_id3_pos, &header)) {
601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return false;
602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
604efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    *meta = new AMessage;
605efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    (*meta)->setInt64("offset", pos);
606efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    (*meta)->setInt32("header", header);
6071bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber    (*meta)->setInt64("post-id3-offset", post_id3_pos);
608efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber
609e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber    *mimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
610efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    *confidence = 0.2f;
611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return true;
613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
616