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