MP3Extractor.cpp revision 2eb6a47b58c5b36f887a372e89f3d70f5d40812c
15bc087c573c70c84c6a39946457590b42d392a33Andreas Huber/* 25bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * Copyright (C) 2009 The Android Open Source Project 35bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * 45bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 55bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * you may not use this file except in compliance with the License. 65bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * You may obtain a copy of the License at 75bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * 85bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 95bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * 105bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * Unless required by applicable law or agreed to in writing, software 115bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 125bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * See the License for the specific language governing permissions and 145bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * limitations under the License. 155bc087c573c70c84c6a39946457590b42d392a33Andreas Huber */ 165bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 175bc087c573c70c84c6a39946457590b42d392a33Andreas Huber//#define LOG_NDEBUG 0 185bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#define LOG_TAG "MP3Extractor" 195bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <utils/Log.h> 205bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 215bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include "include/MP3Extractor.h" 225bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 235bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include "include/ID3.h" 245bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include "include/VBRISeeker.h" 255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include "include/XINGSeeker.h" 265bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 275bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/AMessage.h> 285bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/DataSource.h> 295bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaBuffer.h> 305bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 315bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaDebug.h> 325bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaDefs.h> 335bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaErrors.h> 345bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaSource.h> 35b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber#include <media/stagefright/MetaData.h> 36b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber#include <media/stagefright/Utils.h> 37b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber#include <utils/String8.h> 38b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber 39b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Hubernamespace android { 40180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 41180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang// Everything must match except for 425bc087c573c70c84c6a39946457590b42d392a33Andreas Huber// protection, bitrate, padding, private bits, mode, mode extension, 435bc087c573c70c84c6a39946457590b42d392a33Andreas Huber// copyright bit, original bit and emphasis. 445bc087c573c70c84c6a39946457590b42d392a33Andreas Huber// Yes ... there are things that must indeed match... 45180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangstatic const uint32_t kMask = 0xfffe0c00; 46180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 47180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang// static 48180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangbool MP3Extractor::get_mp3_frame_size( 495bc087c573c70c84c6a39946457590b42d392a33Andreas Huber uint32_t header, size_t *frame_size, 505bc087c573c70c84c6a39946457590b42d392a33Andreas Huber int *out_sampling_rate, int *out_channels, 519575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber int *out_bitrate) { 52180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *frame_size = 0; 53180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 54180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (out_sampling_rate) { 55180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *out_sampling_rate = 0; 56180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 57180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 58180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (out_channels) { 59180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *out_channels = 0; 60ced1c2f8f6c422063092f5cc5c675ccdebb2dc10Chong Zhang } 619575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber 629575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber if (out_bitrate) { 639575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber *out_bitrate = 0; 649575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber } 655bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 661d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar if ((header & 0xffe00000) != 0xffe00000) { 6787f2a558dd12043631e12c361abef301bf603140Andreas Huber return false; 6887f2a558dd12043631e12c361abef301bf603140Andreas Huber } 6987f2a558dd12043631e12c361abef301bf603140Andreas Huber 7087f2a558dd12043631e12c361abef301bf603140Andreas Huber unsigned version = (header >> 19) & 3; 7187f2a558dd12043631e12c361abef301bf603140Andreas Huber 7287f2a558dd12043631e12c361abef301bf603140Andreas Huber if (version == 0x01) { 7387f2a558dd12043631e12c361abef301bf603140Andreas Huber return false; 7487f2a558dd12043631e12c361abef301bf603140Andreas Huber } 7587f2a558dd12043631e12c361abef301bf603140Andreas Huber 765bc087c573c70c84c6a39946457590b42d392a33Andreas Huber unsigned layer = (header >> 17) & 3; 775bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 78180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (layer == 0x00) { 79180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return false; 805bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 815bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 82eac68baf095aeef54865c28b6888924dc6295cbdAndreas Huber unsigned protection = (header >> 16) & 1; 83180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 84180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang unsigned bitrate_index = (header >> 12) & 0x0f; 855bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 86180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (bitrate_index == 0 || bitrate_index == 0x0f) { 87078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber // Disallow "free" bitrate. 885bc087c573c70c84c6a39946457590b42d392a33Andreas Huber return false; 8932f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber } 9032f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber 915bc087c573c70c84c6a39946457590b42d392a33Andreas Huber unsigned sampling_rate_index = (header >> 10) & 3; 925bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 93df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block if (sampling_rate_index == 3) { 945bc087c573c70c84c6a39946457590b42d392a33Andreas Huber return false; 95180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 965bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 975bc087c573c70c84c6a39946457590b42d392a33Andreas Huber static const int kSamplingRateV1[] = { 44100, 48000, 32000 }; 98fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia int sampling_rate = kSamplingRateV1[sampling_rate_index]; 9942e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber if (version == 2 /* V2 */) { 100bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber sampling_rate /= 2; 10142e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber } else if (version == 0 /* V2.5 */) { 10242e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber sampling_rate /= 4; 103bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber } 104bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber 10529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block unsigned padding = (header >> 9) & 1; 106180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 107180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (layer == 3) { 108bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber // layer I 109bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber 110bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber static const int kBitrateV1[] = { 11142e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber 32, 64, 96, 128, 160, 192, 224, 256, 11242e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber 288, 320, 352, 384, 416, 448 113bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber }; 114bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber 1155bc087c573c70c84c6a39946457590b42d392a33Andreas Huber static const int kBitrateV2[] = { 1165bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 32, 48, 56, 64, 80, 96, 112, 128, 1175bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 144, 160, 176, 192, 224, 256 1185bc087c573c70c84c6a39946457590b42d392a33Andreas Huber }; 1195bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 120b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber int bitrate = 121b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber (version == 3 /* V1 */) 122b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber ? kBitrateV1[bitrate_index - 1] 123b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber : kBitrateV2[bitrate_index - 1]; 124b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 125b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber if (out_bitrate) { 126b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber *out_bitrate = bitrate; 127b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } 128b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 129b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber *frame_size = (12000 * bitrate / sampling_rate + padding) * 4; 130b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } else { 131b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber // layer II or III 132b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 133b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber static const int kBitrateV1L2[] = { 1345bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 32, 48, 56, 64, 80, 96, 112, 128, 135b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 160, 192, 224, 256, 320, 384 136fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia }; 13732f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber 13832f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber static const int kBitrateV1L3[] = { 1395bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 32, 40, 48, 56, 64, 80, 96, 112, 14006528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber 128, 160, 192, 224, 256, 320 14106528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber }; 14206528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber 14329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block static const int kBitrateV2[] = { 14406528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber 8, 16, 24, 32, 40, 48, 56, 64, 14506528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber 80, 96, 112, 128, 144, 160 146180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang }; 14706528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber 14806528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber int bitrate; 1495bc087c573c70c84c6a39946457590b42d392a33Andreas Huber if (version == 3 /* V1 */) { 1505bc087c573c70c84c6a39946457590b42d392a33Andreas Huber bitrate = (layer == 2 /* L2 */) 1515bc087c573c70c84c6a39946457590b42d392a33Andreas Huber ? kBitrateV1L2[bitrate_index - 1] 152180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang : kBitrateV1L3[bitrate_index - 1]; 153180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } else { 154180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang // V2 (or 2.5) 155180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 156180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang bitrate = kBitrateV2[bitrate_index - 1]; 157180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 158180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 159180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (out_bitrate) { 160180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *out_bitrate = bitrate; 161180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 162180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 163180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (version == 3 /* V1 */) { 164180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *frame_size = 144000 * bitrate / sampling_rate + padding; 1655bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } else { 1661d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar // V2 or V2.5 167eac68baf095aeef54865c28b6888924dc6295cbdAndreas Huber *frame_size = 72000 * bitrate / sampling_rate + padding; 1685bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 1695bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 170180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 171180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (out_sampling_rate) { 172180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *out_sampling_rate = sampling_rate; 173180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 174180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 175180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (out_channels) { 176180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang int channel_mode = (header >> 6) & 3; 177180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 178180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *out_channels = (channel_mode == 3) ? 1 : 2; 179180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 180180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 181180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return true; 182180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang} 183180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 184180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangstatic bool Resync( 185180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang const sp<DataSource> &source, uint32_t match_header, 186180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) { 187180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (post_id3_pos != NULL) { 188180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *post_id3_pos = 0; 189180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 190180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 191180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (*inout_pos == 0) { 192180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang // Skip an optional ID3 header if syncing at the very beginning 193180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang // of the datasource. 194180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 195180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang for (;;) { 196180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang uint8_t id3header[10]; 197180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (source->readAt(*inout_pos, id3header, sizeof(id3header)) 198180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang < (ssize_t)sizeof(id3header)) { 199180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang // If we can't even read these 10 bytes, we might as well bail 200180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang // out, even if there _were_ 10 bytes of valid mp3 audio data... 201180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return false; 202180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 203180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 204180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (memcmp("ID3", id3header, 3)) { 205180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang break; 206180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 207180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 208ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia // Skip the ID3v2 header. 209ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia 210ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia size_t len = 211ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia ((id3header[6] & 0x7f) << 21) 212180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang | ((id3header[7] & 0x7f) << 14) 213180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang | ((id3header[8] & 0x7f) << 7) 2145bc087c573c70c84c6a39946457590b42d392a33Andreas Huber | (id3header[9] & 0x7f); 215180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 216180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang len += 10; 217180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 218180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang *inout_pos += len; 219180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 2205bc087c573c70c84c6a39946457590b42d392a33Andreas Huber LOGV("skipped ID3 tag, new starting offset is %lld (0x%016llx)", 2215bc087c573c70c84c6a39946457590b42d392a33Andreas Huber *inout_pos, *inout_pos); 2225bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 2235bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 2245bc087c573c70c84c6a39946457590b42d392a33Andreas Huber if (post_id3_pos != NULL) { 2255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber *post_id3_pos = *inout_pos; 2265bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 2275bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 2285bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 2295bc087c573c70c84c6a39946457590b42d392a33Andreas Huber off64_t pos = *inout_pos; 230180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang bool valid = false; 2315bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 2325bc087c573c70c84c6a39946457590b42d392a33Andreas Huber const size_t kMaxReadBytes = 1024; 2335bc087c573c70c84c6a39946457590b42d392a33Andreas Huber const size_t kMaxBytesChecked = 128 * 1024; 2345bc087c573c70c84c6a39946457590b42d392a33Andreas Huber uint8_t buf[kMaxReadBytes]; 2355bc087c573c70c84c6a39946457590b42d392a33Andreas Huber ssize_t bytesToRead = kMaxReadBytes; 236180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang ssize_t totalBytesRead = 0; 237180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang ssize_t remainingBytes = 0; 238180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang bool reachEOS = false; 239180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang uint8_t *tmp = buf; 2405bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 2415bc087c573c70c84c6a39946457590b42d392a33Andreas Huber do { 2425bc087c573c70c84c6a39946457590b42d392a33Andreas Huber if (pos >= *inout_pos + kMaxBytesChecked) { 2435bc087c573c70c84c6a39946457590b42d392a33Andreas Huber // Don't scan forever. 2445bc087c573c70c84c6a39946457590b42d392a33Andreas Huber LOGV("giving up at offset %lld", pos); 24587f2a558dd12043631e12c361abef301bf603140Andreas Huber break; 24687f2a558dd12043631e12c361abef301bf603140Andreas Huber } 24787f2a558dd12043631e12c361abef301bf603140Andreas Huber 24887f2a558dd12043631e12c361abef301bf603140Andreas Huber if (remainingBytes < 4) { 24987f2a558dd12043631e12c361abef301bf603140Andreas Huber if (reachEOS) { 25087f2a558dd12043631e12c361abef301bf603140Andreas Huber break; 25187f2a558dd12043631e12c361abef301bf603140Andreas Huber } else { 25287f2a558dd12043631e12c361abef301bf603140Andreas Huber memcpy(buf, tmp, remainingBytes); 25387f2a558dd12043631e12c361abef301bf603140Andreas Huber bytesToRead = kMaxReadBytes - remainingBytes; 25487f2a558dd12043631e12c361abef301bf603140Andreas Huber 25587f2a558dd12043631e12c361abef301bf603140Andreas Huber /* 2565bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * The next read position should start from the end of 2575bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * the last buffer, and thus should include the remaining 258d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber * bytes in the buffer. 259d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber */ 260d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber totalBytesRead = source->readAt(pos + remainingBytes, 261d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber buf + remainingBytes, 262180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang bytesToRead); 263180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (totalBytesRead <= 0) { 264180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang break; 265180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 266180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang reachEOS = (totalBytesRead != bytesToRead); 267180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang totalBytesRead += remainingBytes; 268180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang remainingBytes = totalBytesRead; 269180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang tmp = buf; 270180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang continue; 271180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 272180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 273180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 274180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang uint32_t header = U32_AT(tmp); 275180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 276180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (match_header != 0 && (header & kMask) != (match_header & kMask)) { 277180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang ++pos; 278180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang ++tmp; 279180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang --remainingBytes; 280180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang continue; 281180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 282180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 2835bc087c573c70c84c6a39946457590b42d392a33Andreas Huber size_t frame_size; 2845bc087c573c70c84c6a39946457590b42d392a33Andreas Huber int sample_rate, num_channels, bitrate; 285 if (!MP3Extractor::get_mp3_frame_size( 286 header, &frame_size, 287 &sample_rate, &num_channels, &bitrate)) { 288 ++pos; 289 ++tmp; 290 --remainingBytes; 291 continue; 292 } 293 294 LOGV("found possible 1st frame at %lld (header = 0x%08x)", pos, header); 295 296 // We found what looks like a valid frame, 297 // now find its successors. 298 299 off64_t test_pos = pos + frame_size; 300 301 valid = true; 302 for (int j = 0; j < 3; ++j) { 303 uint8_t tmp[4]; 304 if (source->readAt(test_pos, tmp, 4) < 4) { 305 valid = false; 306 break; 307 } 308 309 uint32_t test_header = U32_AT(tmp); 310 311 LOGV("subsequent header is %08x", test_header); 312 313 if ((test_header & kMask) != (header & kMask)) { 314 valid = false; 315 break; 316 } 317 318 size_t test_frame_size; 319 if (!MP3Extractor::get_mp3_frame_size( 320 test_header, &test_frame_size)) { 321 valid = false; 322 break; 323 } 324 325 LOGV("found subsequent frame #%d at %lld", j + 2, test_pos); 326 327 test_pos += test_frame_size; 328 } 329 330 if (valid) { 331 *inout_pos = pos; 332 333 if (out_header != NULL) { 334 *out_header = header; 335 } 336 } else { 337 LOGV("no dice, no valid sequence of frames found."); 338 } 339 340 ++pos; 341 ++tmp; 342 --remainingBytes; 343 } while (!valid); 344 345 return valid; 346} 347 348class MP3Source : public MediaSource { 349public: 350 MP3Source( 351 const sp<MetaData> &meta, const sp<DataSource> &source, 352 off64_t first_frame_pos, uint32_t fixed_header, 353 const sp<MP3Seeker> &seeker); 354 355 virtual status_t start(MetaData *params = NULL); 356 virtual status_t stop(); 357 358 virtual sp<MetaData> getFormat(); 359 360 virtual status_t read( 361 MediaBuffer **buffer, const ReadOptions *options = NULL); 362 363protected: 364 virtual ~MP3Source(); 365 366private: 367 sp<MetaData> mMeta; 368 sp<DataSource> mDataSource; 369 off64_t mFirstFramePos; 370 uint32_t mFixedHeader; 371 off64_t mCurrentPos; 372 int64_t mCurrentTimeUs; 373 bool mStarted; 374 sp<MP3Seeker> mSeeker; 375 MediaBufferGroup *mGroup; 376 377 MP3Source(const MP3Source &); 378 MP3Source &operator=(const MP3Source &); 379}; 380 381MP3Extractor::MP3Extractor( 382 const sp<DataSource> &source, const sp<AMessage> &meta) 383 : mInitCheck(NO_INIT), 384 mDataSource(source), 385 mFirstFramePos(-1), 386 mFixedHeader(0) { 387 off64_t pos = 0; 388 off64_t post_id3_pos; 389 uint32_t header; 390 bool success; 391 392 int64_t meta_offset; 393 uint32_t meta_header; 394 int64_t meta_post_id3_offset; 395 if (meta != NULL 396 && meta->findInt64("offset", &meta_offset) 397 && meta->findInt32("header", (int32_t *)&meta_header) 398 && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) { 399 // The sniffer has already done all the hard work for us, simply 400 // accept its judgement. 401 pos = (off64_t)meta_offset; 402 header = meta_header; 403 post_id3_pos = (off64_t)meta_post_id3_offset; 404 405 success = true; 406 } else { 407 success = Resync(mDataSource, 0, &pos, &post_id3_pos, &header); 408 } 409 410 if (!success) { 411 // mInitCheck will remain NO_INIT 412 return; 413 } 414 415 mFirstFramePos = pos; 416 mFixedHeader = header; 417 418 size_t frame_size; 419 int sample_rate; 420 int num_channels; 421 int bitrate; 422 get_mp3_frame_size( 423 header, &frame_size, &sample_rate, &num_channels, &bitrate); 424 425 mMeta = new MetaData; 426 427 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 428 mMeta->setInt32(kKeySampleRate, sample_rate); 429 mMeta->setInt32(kKeyBitRate, bitrate * 1000); 430 mMeta->setInt32(kKeyChannelCount, num_channels); 431 432 mSeeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos); 433 434 if (mSeeker == NULL) { 435 mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos); 436 } 437 438 int64_t durationUs; 439 440 if (mSeeker == NULL || !mSeeker->getDuration(&durationUs)) { 441 off64_t fileSize; 442 if (mDataSource->getSize(&fileSize) == OK) { 443 durationUs = 8000LL * (fileSize - mFirstFramePos) / bitrate; 444 } else { 445 durationUs = -1; 446 } 447 } 448 449 if (durationUs >= 0) { 450 mMeta->setInt64(kKeyDuration, durationUs); 451 } 452 453 mInitCheck = OK; 454} 455 456size_t MP3Extractor::countTracks() { 457 return mInitCheck != OK ? 0 : 1; 458} 459 460sp<MediaSource> MP3Extractor::getTrack(size_t index) { 461 if (mInitCheck != OK || index != 0) { 462 return NULL; 463 } 464 465 return new MP3Source( 466 mMeta, mDataSource, mFirstFramePos, mFixedHeader, 467 mSeeker); 468} 469 470sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) { 471 if (mInitCheck != OK || index != 0) { 472 return NULL; 473 } 474 475 return mMeta; 476} 477 478//////////////////////////////////////////////////////////////////////////////// 479 480MP3Source::MP3Source( 481 const sp<MetaData> &meta, const sp<DataSource> &source, 482 off64_t first_frame_pos, uint32_t fixed_header, 483 const sp<MP3Seeker> &seeker) 484 : mMeta(meta), 485 mDataSource(source), 486 mFirstFramePos(first_frame_pos), 487 mFixedHeader(fixed_header), 488 mCurrentPos(0), 489 mCurrentTimeUs(0), 490 mStarted(false), 491 mSeeker(seeker), 492 mGroup(NULL) { 493} 494 495MP3Source::~MP3Source() { 496 if (mStarted) { 497 stop(); 498 } 499} 500 501status_t MP3Source::start(MetaData *) { 502 CHECK(!mStarted); 503 504 mGroup = new MediaBufferGroup; 505 506 const size_t kMaxFrameSize = 32768; 507 mGroup->add_buffer(new MediaBuffer(kMaxFrameSize)); 508 509 mCurrentPos = mFirstFramePos; 510 mCurrentTimeUs = 0; 511 512 mStarted = true; 513 514 return OK; 515} 516 517status_t MP3Source::stop() { 518 CHECK(mStarted); 519 520 delete mGroup; 521 mGroup = NULL; 522 523 mStarted = false; 524 525 return OK; 526} 527 528sp<MetaData> MP3Source::getFormat() { 529 return mMeta; 530} 531 532status_t MP3Source::read( 533 MediaBuffer **out, const ReadOptions *options) { 534 *out = NULL; 535 536 int64_t seekTimeUs; 537 ReadOptions::SeekMode mode; 538 if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) { 539 int64_t actualSeekTimeUs = seekTimeUs; 540 if (mSeeker == NULL 541 || !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) { 542 int32_t bitrate; 543 if (!mMeta->findInt32(kKeyBitRate, &bitrate)) { 544 // bitrate is in bits/sec. 545 LOGI("no bitrate"); 546 547 return ERROR_UNSUPPORTED; 548 } 549 550 mCurrentTimeUs = seekTimeUs; 551 mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000; 552 } else { 553 mCurrentTimeUs = actualSeekTimeUs; 554 } 555 } 556 557 MediaBuffer *buffer; 558 status_t err = mGroup->acquire_buffer(&buffer); 559 if (err != OK) { 560 return err; 561 } 562 563 size_t frame_size; 564 int bitrate; 565 for (;;) { 566 ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4); 567 if (n < 4) { 568 buffer->release(); 569 buffer = NULL; 570 571 return ERROR_END_OF_STREAM; 572 } 573 574 uint32_t header = U32_AT((const uint8_t *)buffer->data()); 575 576 if ((header & kMask) == (mFixedHeader & kMask) 577 && MP3Extractor::get_mp3_frame_size( 578 header, &frame_size, NULL, NULL, &bitrate)) { 579 break; 580 } 581 582 // Lost sync. 583 LOGV("lost sync! header = 0x%08x, old header = 0x%08x\n", header, mFixedHeader); 584 585 off64_t pos = mCurrentPos; 586 if (!Resync(mDataSource, mFixedHeader, &pos, NULL, NULL)) { 587 LOGE("Unable to resync. Signalling end of stream."); 588 589 buffer->release(); 590 buffer = NULL; 591 592 return ERROR_END_OF_STREAM; 593 } 594 595 mCurrentPos = pos; 596 597 // Try again with the new position. 598 } 599 600 CHECK(frame_size <= buffer->size()); 601 602 ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), frame_size); 603 if (n < (ssize_t)frame_size) { 604 buffer->release(); 605 buffer = NULL; 606 607 return ERROR_END_OF_STREAM; 608 } 609 610 buffer->set_range(0, frame_size); 611 612 buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); 613 buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 614 615 mCurrentPos += frame_size; 616 mCurrentTimeUs += frame_size * 8000ll / bitrate; 617 618 *out = buffer; 619 620 return OK; 621} 622 623sp<MetaData> MP3Extractor::getMetaData() { 624 sp<MetaData> meta = new MetaData; 625 626 if (mInitCheck != OK) { 627 return meta; 628 } 629 630 meta->setCString(kKeyMIMEType, "audio/mpeg"); 631 632 ID3 id3(mDataSource); 633 634 if (!id3.isValid()) { 635 return meta; 636 } 637 638 struct Map { 639 int key; 640 const char *tag1; 641 const char *tag2; 642 }; 643 static const Map kMap[] = { 644 { kKeyAlbum, "TALB", "TAL" }, 645 { kKeyArtist, "TPE1", "TP1" }, 646 { kKeyAlbumArtist, "TPE2", "TP2" }, 647 { kKeyComposer, "TCOM", "TCM" }, 648 { kKeyGenre, "TCON", "TCO" }, 649 { kKeyTitle, "TIT2", "TT2" }, 650 { kKeyYear, "TYE", "TYER" }, 651 { kKeyAuthor, "TXT", "TEXT" }, 652 { kKeyCDTrackNumber, "TRK", "TRCK" }, 653 { kKeyDiscNumber, "TPA", "TPOS" }, 654 { kKeyCompilation, "TCP", "TCMP" }, 655 }; 656 static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); 657 658 for (size_t i = 0; i < kNumMapEntries; ++i) { 659 ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1); 660 if (it->done()) { 661 delete it; 662 it = new ID3::Iterator(id3, kMap[i].tag2); 663 } 664 665 if (it->done()) { 666 delete it; 667 continue; 668 } 669 670 String8 s; 671 it->getString(&s); 672 delete it; 673 674 meta->setCString(kMap[i].key, s); 675 } 676 677 size_t dataSize; 678 String8 mime; 679 const void *data = id3.getAlbumArt(&dataSize, &mime); 680 681 if (data) { 682 meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize); 683 meta->setCString(kKeyAlbumArtMIME, mime.string()); 684 } 685 686 return meta; 687} 688 689bool SniffMP3( 690 const sp<DataSource> &source, String8 *mimeType, 691 float *confidence, sp<AMessage> *meta) { 692 off64_t pos = 0; 693 off64_t post_id3_pos; 694 uint32_t header; 695 if (!Resync(source, 0, &pos, &post_id3_pos, &header)) { 696 return false; 697 } 698 699 *meta = new AMessage; 700 (*meta)->setInt64("offset", pos); 701 (*meta)->setInt32("header", header); 702 (*meta)->setInt64("post-id3-offset", post_id3_pos); 703 704 *mimeType = MEDIA_MIMETYPE_AUDIO_MPEG; 705 *confidence = 0.2f; 706 707 return true; 708} 709 710} // namespace android 711