MP3Extractor.cpp revision 293e03d8684663cc42f99735e6e4b4c1ae62cacd
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 23aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber#include "include/ID3.h" 241bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber#include "include/VBRISeeker.h" 251bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber#include "include/XINGSeeker.h" 26aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 27efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber#include <media/stagefright/foundation/AMessage.h> 28e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h> 29e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h> 30e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 31b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber#include <media/stagefright/MediaDebug.h> 32e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h> 33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaErrors.h> 34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h> 35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h> 36e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h> 37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h> 38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android { 40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 41b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber// Everything must match except for 42858b673a3518b2b15302cfdbf9433f111536c72cJames Dong// protection, bitrate, padding, private bits, mode, mode extension, 431d200e3b959f7562b21a6e9d94910ddd051cfe10Andreas Huber// copyright bit, original bit and emphasis. 441d200e3b959f7562b21a6e9d94910ddd051cfe10Andreas Huber// Yes ... there are things that must indeed match... 45858b673a3518b2b15302cfdbf9433f111536c72cJames Dongstatic const uint32_t kMask = 0xfffe0c00; 46b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber 471bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber// static 481bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huberbool MP3Extractor::get_mp3_frame_size( 49e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t header, size_t *frame_size, 501bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber int *out_sampling_rate, int *out_channels, 51293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons int *out_bitrate, int *out_num_samples) { 52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *frame_size = 0; 53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 54e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_sampling_rate) { 55e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_sampling_rate = 0; 56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 58e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_channels) { 59e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_channels = 0; 60e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 61e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 62e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_bitrate) { 63e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_bitrate = 0; 64e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 65e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 66293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons if (out_num_samples) { 67293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons *out_num_samples = 1152; 68293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons } 69293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons 70e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((header & 0xffe00000) != 0xffe00000) { 71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 72e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 73e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 74e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber unsigned version = (header >> 19) & 3; 75e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 76e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 0x01) { 77e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 78e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 79b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber 80e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber unsigned layer = (header >> 17) & 3; 81e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 82e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (layer == 0x00) { 83e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 84e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 85e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 86e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber unsigned protection = (header >> 16) & 1; 87e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber unsigned bitrate_index = (header >> 12) & 0x0f; 89e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 90e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (bitrate_index == 0 || bitrate_index == 0x0f) { 91e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Disallow "free" bitrate. 92e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 93e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 94e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 95e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber unsigned sampling_rate_index = (header >> 10) & 3; 96e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 97e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (sampling_rate_index == 3) { 98e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 99e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 100e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 101e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const int kSamplingRateV1[] = { 44100, 48000, 32000 }; 102e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int sampling_rate = kSamplingRateV1[sampling_rate_index]; 103e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 2 /* V2 */) { 104e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber sampling_rate /= 2; 105e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else if (version == 0 /* V2.5 */) { 106e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber sampling_rate /= 4; 107e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 108e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 109e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber unsigned padding = (header >> 9) & 1; 110e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 111e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (layer == 3) { 112e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // layer I 113e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 114e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const int kBitrateV1[] = { 115e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 32, 64, 96, 128, 160, 192, 224, 256, 116e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 288, 320, 352, 384, 416, 448 117e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber }; 118e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 119e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const int kBitrateV2[] = { 120e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 32, 48, 56, 64, 80, 96, 112, 128, 121e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 144, 160, 176, 192, 224, 256 122e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber }; 123e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 124e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int bitrate = 125e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber (version == 3 /* V1 */) 126e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ? kBitrateV1[bitrate_index - 1] 127e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : kBitrateV2[bitrate_index - 1]; 128e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 129e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_bitrate) { 130e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_bitrate = bitrate; 131e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 132e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 133e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *frame_size = (12000 * bitrate / sampling_rate + padding) * 4; 134293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons 135293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons if (out_num_samples) { 136293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons *out_num_samples = 384; 137293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons } 138e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 139e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // layer II or III 140e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 141e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const int kBitrateV1L2[] = { 142e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 32, 48, 56, 64, 80, 96, 112, 128, 143e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 160, 192, 224, 256, 320, 384 144e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber }; 145e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 146e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const int kBitrateV1L3[] = { 147e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 32, 40, 48, 56, 64, 80, 96, 112, 148e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 128, 160, 192, 224, 256, 320 149e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber }; 150e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 151e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const int kBitrateV2[] = { 152e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8, 16, 24, 32, 40, 48, 56, 64, 153e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 80, 96, 112, 128, 144, 160 154e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber }; 155e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 156e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int bitrate; 157e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 3 /* V1 */) { 158e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bitrate = (layer == 2 /* L2 */) 159e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ? kBitrateV1L2[bitrate_index - 1] 160e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : kBitrateV1L3[bitrate_index - 1]; 161293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons 162293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons if (out_num_samples) { 163293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons *out_num_samples = 1152; 164293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons } 165e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 166e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // V2 (or 2.5) 167e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 168e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bitrate = kBitrateV2[bitrate_index - 1]; 169293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons if (out_num_samples) { 170293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons *out_num_samples = 576; 171293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons } 172e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 173e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 174e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_bitrate) { 175e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_bitrate = bitrate; 176e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 177e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17863f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber if (version == 3 /* V1 */) { 17963f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber *frame_size = 144000 * bitrate / sampling_rate + padding; 18063f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber } else { 18163f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber // V2 or V2.5 18263f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber *frame_size = 72000 * bitrate / sampling_rate + padding; 18363f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber } 184e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 185e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 186e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_sampling_rate) { 187e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_sampling_rate = sampling_rate; 188e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 189e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 190e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_channels) { 191e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int channel_mode = (header >> 6) & 3; 192e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 193e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_channels = (channel_mode == 3) ? 1 : 2; 194e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 195e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return true; 197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic bool Resync( 200be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &source, uint32_t match_header, 201b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) { 2021bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (post_id3_pos != NULL) { 2031bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber *post_id3_pos = 0; 2041bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber } 2051bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 20663f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber if (*inout_pos == 0) { 20763f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber // Skip an optional ID3 header if syncing at the very beginning 20863f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber // of the datasource. 20963f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber 2100d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber for (;;) { 2110d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber uint8_t id3header[10]; 2120d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber if (source->readAt(*inout_pos, id3header, sizeof(id3header)) 2130d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber < (ssize_t)sizeof(id3header)) { 2140d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber // If we can't even read these 10 bytes, we might as well bail 2150d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber // out, even if there _were_ 10 bytes of valid mp3 audio data... 2160d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber return false; 2170d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber } 2180d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber 2190d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber if (memcmp("ID3", id3header, 3)) { 2200d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber break; 2210d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber } 22263f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber 22363f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber // Skip the ID3v2 header. 22463f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber 22563f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber size_t len = 22663f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber ((id3header[6] & 0x7f) << 21) 22763f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber | ((id3header[7] & 0x7f) << 14) 22863f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber | ((id3header[8] & 0x7f) << 7) 22963f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber | (id3header[9] & 0x7f); 23063f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber 23163f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber len += 10; 23263f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber 23363f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber *inout_pos += len; 2340d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber 235563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong LOGV("skipped ID3 tag, new starting offset is %lld (0x%016llx)", 2360d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber *inout_pos, *inout_pos); 23763f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber } 2381bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 2391bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (post_id3_pos != NULL) { 2401bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber *post_id3_pos = *inout_pos; 2411bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber } 24263f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber } 24363f20ec1a8d31c85261056c6c171140b93bcde0aAndreas Huber 244b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t pos = *inout_pos; 245e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool valid = false; 24631d8a03e44b272afacad07a7670aaad764172797James Dong 24731d8a03e44b272afacad07a7670aaad764172797James Dong const size_t kMaxReadBytes = 1024; 24831d8a03e44b272afacad07a7670aaad764172797James Dong const size_t kMaxBytesChecked = 128 * 1024; 24931d8a03e44b272afacad07a7670aaad764172797James Dong uint8_t buf[kMaxReadBytes]; 25031d8a03e44b272afacad07a7670aaad764172797James Dong ssize_t bytesToRead = kMaxReadBytes; 25131d8a03e44b272afacad07a7670aaad764172797James Dong ssize_t totalBytesRead = 0; 25231d8a03e44b272afacad07a7670aaad764172797James Dong ssize_t remainingBytes = 0; 25331d8a03e44b272afacad07a7670aaad764172797James Dong bool reachEOS = false; 25431d8a03e44b272afacad07a7670aaad764172797James Dong uint8_t *tmp = buf; 25531d8a03e44b272afacad07a7670aaad764172797James Dong 256e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber do { 25731d8a03e44b272afacad07a7670aaad764172797James Dong if (pos >= *inout_pos + kMaxBytesChecked) { 2580d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber // Don't scan forever. 259563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong LOGV("giving up at offset %lld", pos); 2600d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber break; 2610d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber } 262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 26331d8a03e44b272afacad07a7670aaad764172797James Dong if (remainingBytes < 4) { 26431d8a03e44b272afacad07a7670aaad764172797James Dong if (reachEOS) { 26531d8a03e44b272afacad07a7670aaad764172797James Dong break; 26631d8a03e44b272afacad07a7670aaad764172797James Dong } else { 26731d8a03e44b272afacad07a7670aaad764172797James Dong memcpy(buf, tmp, remainingBytes); 26831d8a03e44b272afacad07a7670aaad764172797James Dong bytesToRead = kMaxReadBytes - remainingBytes; 269563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong 270563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong /* 271563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong * The next read position should start from the end of 272563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong * the last buffer, and thus should include the remaining 273563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong * bytes in the buffer. 274563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong */ 275563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong totalBytesRead = source->readAt(pos + remainingBytes, 276563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong buf + remainingBytes, 277563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong bytesToRead); 27831d8a03e44b272afacad07a7670aaad764172797James Dong if (totalBytesRead <= 0) { 27931d8a03e44b272afacad07a7670aaad764172797James Dong break; 28031d8a03e44b272afacad07a7670aaad764172797James Dong } 28131d8a03e44b272afacad07a7670aaad764172797James Dong reachEOS = (totalBytesRead != bytesToRead); 28231d8a03e44b272afacad07a7670aaad764172797James Dong totalBytesRead += remainingBytes; 28331d8a03e44b272afacad07a7670aaad764172797James Dong remainingBytes = totalBytesRead; 28431d8a03e44b272afacad07a7670aaad764172797James Dong tmp = buf; 28531d8a03e44b272afacad07a7670aaad764172797James Dong continue; 28631d8a03e44b272afacad07a7670aaad764172797James Dong } 287e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 288e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2890d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber uint32_t header = U32_AT(tmp); 290e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 291e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (match_header != 0 && (header & kMask) != (match_header & kMask)) { 2920d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber ++pos; 29331d8a03e44b272afacad07a7670aaad764172797James Dong ++tmp; 29431d8a03e44b272afacad07a7670aaad764172797James Dong --remainingBytes; 295e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber continue; 296e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 297e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 298e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t frame_size; 299e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int sample_rate, num_channels, bitrate; 3001bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (!MP3Extractor::get_mp3_frame_size( 3011bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber header, &frame_size, 3021bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber &sample_rate, &num_channels, &bitrate)) { 3030d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber ++pos; 30431d8a03e44b272afacad07a7670aaad764172797James Dong ++tmp; 30531d8a03e44b272afacad07a7670aaad764172797James Dong --remainingBytes; 3062e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber continue; 3072e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber } 308e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 309563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong LOGV("found possible 1st frame at %lld (header = 0x%08x)", pos, header); 310e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3112e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber // We found what looks like a valid frame, 3122e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber // now find its successors. 313e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 314b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t test_pos = pos + frame_size; 315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3162e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber valid = true; 3172e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber for (int j = 0; j < 3; ++j) { 3182e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber uint8_t tmp[4]; 3199a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (source->readAt(test_pos, tmp, 4) < 4) { 3202e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber valid = false; 3212e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber break; 3222e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber } 323b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber 3242e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber uint32_t test_header = U32_AT(tmp); 325e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3262e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber LOGV("subsequent header is %08x", test_header); 327e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3282e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber if ((test_header & kMask) != (header & kMask)) { 3292e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber valid = false; 3302e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber break; 3312e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber } 332e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3332e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber size_t test_frame_size; 3341bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (!MP3Extractor::get_mp3_frame_size( 3351bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber test_header, &test_frame_size)) { 3362e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber valid = false; 3372e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber break; 338e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 3392e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber 340563ab6ec5ec16db78567f8b3c9dff22c5dfaab08James Dong LOGV("found subsequent frame #%d at %lld", j + 2, test_pos); 3412e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber 3422e337a4e4b5d36228619d426255f7aa500b5b4acAndreas Huber test_pos += test_frame_size; 343e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 344e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 345e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (valid) { 3460d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber *inout_pos = pos; 347e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 348e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (out_header != NULL) { 349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out_header = header; 350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 351e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber LOGV("no dice, no valid sequence of frames found."); 353e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 354e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3550d34d8b4d5ad8695daef2e0db9e8316fab8942d4Andreas Huber ++pos; 35631d8a03e44b272afacad07a7670aaad764172797James Dong ++tmp; 35731d8a03e44b272afacad07a7670aaad764172797James Dong --remainingBytes; 358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } while (!valid); 359e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return valid; 361e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 362e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 363e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MP3Source : public MediaSource { 364e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic: 365e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MP3Source( 366be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<MetaData> &meta, const sp<DataSource> &source, 367b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t first_frame_pos, uint32_t fixed_header, 3681bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber const sp<MP3Seeker> &seeker); 369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t start(MetaData *params = NULL); 371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t stop(); 372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 373e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual sp<MetaData> getFormat(); 374e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 375e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t read( 376e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 377e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 378be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected: 379be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber virtual ~MP3Source(); 380be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber 381e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate: 382e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber sp<MetaData> mMeta; 383be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber sp<DataSource> mDataSource; 384b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t mFirstFramePos; 385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t mFixedHeader; 386b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t mCurrentPos; 387e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t mCurrentTimeUs; 388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool mStarted; 3891bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber sp<MP3Seeker> mSeeker; 390e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBufferGroup *mGroup; 391e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 392293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons int64_t mBasisTimeUs; 393293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons int64_t mSamplesRead; 394293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons 395e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MP3Source(const MP3Source &); 396e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MP3Source &operator=(const MP3Source &); 397e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}; 398e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 399efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas HuberMP3Extractor::MP3Extractor( 400efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber const sp<DataSource> &source, const sp<AMessage> &meta) 4013e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber : mInitCheck(NO_INIT), 4023e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mDataSource(source), 403e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstFramePos(-1), 4041bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mFixedHeader(0) { 405b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t pos = 0; 406b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t post_id3_pos; 407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t header; 408efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber bool success; 409efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber 410efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber int64_t meta_offset; 411efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber uint32_t meta_header; 4121bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber int64_t meta_post_id3_offset; 413efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber if (meta != NULL 414efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber && meta->findInt64("offset", &meta_offset) 4151bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber && meta->findInt32("header", (int32_t *)&meta_header) 4161bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) { 417efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber // The sniffer has already done all the hard work for us, simply 418efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber // accept its judgement. 419b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong pos = (off64_t)meta_offset; 420efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber header = meta_header; 421b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong post_id3_pos = (off64_t)meta_post_id3_offset; 422efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber 423efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber success = true; 424efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber } else { 4251bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber success = Resync(mDataSource, 0, &pos, &post_id3_pos, &header); 426efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber } 427e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 4283e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber if (!success) { 4293e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber // mInitCheck will remain NO_INIT 4303e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber return; 4313e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber } 432e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 4333e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mFirstFramePos = pos; 4343e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mFixedHeader = header; 435e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 4363e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber size_t frame_size; 4373e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber int sample_rate; 4383e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber int num_channels; 4393e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber int bitrate; 4403e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber get_mp3_frame_size( 4413e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber header, &frame_size, &sample_rate, &num_channels, &bitrate); 4423e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber 4433e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mMeta = new MetaData; 4443e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber 4453e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 4463e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mMeta->setInt32(kKeySampleRate, sample_rate); 4473e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mMeta->setInt32(kKeyBitRate, bitrate * 1000); 4483e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mMeta->setInt32(kKeyChannelCount, num_channels); 4493e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber 4501bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mSeeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos); 4511bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 4521bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (mSeeker == NULL) { 4531bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos); 4541bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber } 4551bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 4561bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber int64_t durationUs; 4571bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 4581bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (mSeeker == NULL || !mSeeker->getDuration(&durationUs)) { 459b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t fileSize; 4603e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber if (mDataSource->getSize(&fileSize) == OK) { 4611bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber durationUs = 8000LL * (fileSize - mFirstFramePos) / bitrate; 4621bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber } else { 4631bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber durationUs = -1; 464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 466e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 4671bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (durationUs >= 0) { 4681bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mMeta->setInt64(kKeyDuration, durationUs); 4691bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber } 4701bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 4713e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber mInitCheck = OK; 472e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 473e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 474be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MP3Extractor::countTracks() { 4753e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber return mInitCheck != OK ? 0 : 1; 476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 478be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MP3Extractor::getTrack(size_t index) { 4793e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber if (mInitCheck != OK || index != 0) { 480be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 481e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 482e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 483be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return new MP3Source( 4841ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang mMeta, mDataSource, mFirstFramePos, mFixedHeader, 4851bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mSeeker); 486e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 488e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) { 4893e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber if (mInitCheck != OK || index != 0) { 490e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 491e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 492e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return mMeta; 494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 496e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber//////////////////////////////////////////////////////////////////////////////// 497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 498e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMP3Source::MP3Source( 499be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<MetaData> &meta, const sp<DataSource> &source, 500b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t first_frame_pos, uint32_t fixed_header, 5011bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber const sp<MP3Seeker> &seeker) 502e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mMeta(meta), 503e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mDataSource(source), 504e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstFramePos(first_frame_pos), 505e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFixedHeader(fixed_header), 506e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentPos(0), 507e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentTimeUs(0), 508e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted(false), 5091bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mSeeker(seeker), 510293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mGroup(NULL), 511293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mBasisTimeUs(0), 512293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mSamplesRead(0) { 513e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 514e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 515e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMP3Source::~MP3Source() { 516e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mStarted) { 517e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber stop(); 518e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 519e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 520e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 521e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MP3Source::start(MetaData *) { 522b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber CHECK(!mStarted); 523e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 524e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = new MediaBufferGroup; 525e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 526e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const size_t kMaxFrameSize = 32768; 527e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup->add_buffer(new MediaBuffer(kMaxFrameSize)); 528e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 529e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentPos = mFirstFramePos; 530e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentTimeUs = 0; 531e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 532293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mBasisTimeUs = mCurrentTimeUs; 533293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mSamplesRead = 0; 534293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons 535e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = true; 536e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 538e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MP3Source::stop() { 541b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber CHECK(mStarted); 542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 543e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete mGroup; 544e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = NULL; 545e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 546e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = false; 547e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 548e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 549e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 550e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 551e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MP3Source::getFormat() { 552e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return mMeta; 553e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 554e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 555e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MP3Source::read( 556e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **out, const ReadOptions *options) { 557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = NULL; 558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t seekTimeUs; 5606624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 5616624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) { 5621bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber int64_t actualSeekTimeUs = seekTimeUs; 5631bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (mSeeker == NULL 5641bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber || !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) { 5651bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber int32_t bitrate; 5661bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (!mMeta->findInt32(kKeyBitRate, &bitrate)) { 5671bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber // bitrate is in bits/sec. 5681bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber LOGI("no bitrate"); 5691bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 5701bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber return ERROR_UNSUPPORTED; 5711ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang } 5721bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber 5731bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mCurrentTimeUs = seekTimeUs; 5741ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000; 5751bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber } else { 5761bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber mCurrentTimeUs = actualSeekTimeUs; 5771ba307d3c5800705e3fda10fb6c809f811c0f275Gloria Wang } 578293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons 579293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mBasisTimeUs = mCurrentTimeUs; 580293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mSamplesRead = 0; 581e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 582e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 583e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer *buffer; 584e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = mGroup->acquire_buffer(&buffer); 585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t frame_size; 590b64af9a221c1df4853ab7c7766d5f956c61b8765Andreas Huber int bitrate; 591293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons int num_samples; 592293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons int sample_rate; 593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (;;) { 5949a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4); 595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n < 4) { 596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber buffer->release(); 597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber buffer = NULL; 598e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_END_OF_STREAM; 600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t header = U32_AT((const uint8_t *)buffer->data()); 603b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber 604b16e5543713cc557bdc7ceef7c0a5a8b61f3232dAndreas Huber if ((header & kMask) == (mFixedHeader & kMask) 6051bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber && MP3Extractor::get_mp3_frame_size( 606293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons header, &frame_size, &sample_rate, NULL, &bitrate, &num_samples)) { 607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Lost sync. 6111d200e3b959f7562b21a6e9d94910ddd051cfe10Andreas Huber LOGV("lost sync! header = 0x%08x, old header = 0x%08x\n", header, mFixedHeader); 612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 613b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t pos = mCurrentPos; 6141bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (!Resync(mDataSource, mFixedHeader, &pos, NULL, NULL)) { 615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber LOGE("Unable to resync. Signalling end of stream."); 616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber buffer->release(); 618e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber buffer = NULL; 619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_END_OF_STREAM; 621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentPos = pos; 624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Try again with the new position. 626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 628b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber CHECK(frame_size <= buffer->size()); 629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 6309a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), frame_size); 631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n < (ssize_t)frame_size) { 632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber buffer->release(); 633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber buffer = NULL; 634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_END_OF_STREAM; 636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber buffer->set_range(0, frame_size); 639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 640fa8de752507feaca695123911915070c1ce463b2Andreas Huber buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); 641ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentPos += frame_size; 644293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons 645293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mSamplesRead += num_samples; 646293e03d8684663cc42f99735e6e4b4c1ae62cacdJason Simmons mCurrentTimeUs = mBasisTimeUs + ((mSamplesRead * 1000000) / sample_rate); 647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = buffer; 649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 653aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Hubersp<MetaData> MP3Extractor::getMetaData() { 654aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber sp<MetaData> meta = new MetaData; 655aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 6563e0f2be7d6501b923d586512e86a1c205b162fd6Andreas Huber if (mInitCheck != OK) { 6571cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber return meta; 6581cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber } 6591cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 660aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber meta->setCString(kKeyMIMEType, "audio/mpeg"); 661aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 662aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber ID3 id3(mDataSource); 663aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 664aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber if (!id3.isValid()) { 665aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber return meta; 666aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber } 667aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 668aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber struct Map { 669aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber int key; 670aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber const char *tag1; 671aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber const char *tag2; 672aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber }; 673aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber static const Map kMap[] = { 674aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber { kKeyAlbum, "TALB", "TAL" }, 675aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber { kKeyArtist, "TPE1", "TP1" }, 676c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen { kKeyAlbumArtist, "TPE2", "TP2" }, 677aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber { kKeyComposer, "TCOM", "TCM" }, 678aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber { kKeyGenre, "TCON", "TCO" }, 6793a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber { kKeyTitle, "TIT2", "TT2" }, 680aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber { kKeyYear, "TYE", "TYER" }, 6813a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber { kKeyAuthor, "TXT", "TEXT" }, 6823a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber { kKeyCDTrackNumber, "TRK", "TRCK" }, 683655306f8a80b3e9fc52daf458ef319a8ed8c564cMarco Nelissen { kKeyDiscNumber, "TPA", "TPOS" }, 684ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen { kKeyCompilation, "TCP", "TCMP" }, 685aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber }; 686aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); 687aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 688aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber for (size_t i = 0; i < kNumMapEntries; ++i) { 689aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1); 690aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber if (it->done()) { 691aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber delete it; 692aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber it = new ID3::Iterator(id3, kMap[i].tag2); 693aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber } 694aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 695aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber if (it->done()) { 696aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber delete it; 697aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber continue; 698aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber } 699aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 700aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber String8 s; 701aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber it->getString(&s); 702aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber delete it; 703aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 704aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber meta->setCString(kMap[i].key, s); 705aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber } 706aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 707aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber size_t dataSize; 708aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber String8 mime; 709aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber const void *data = id3.getAlbumArt(&dataSize, &mime); 710aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 711aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber if (data) { 712aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize); 713aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber meta->setCString(kKeyAlbumArtMIME, mime.string()); 714aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber } 715aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 716aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber return meta; 717aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber} 718aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber 719be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberbool SniffMP3( 720efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber const sp<DataSource> &source, String8 *mimeType, 721efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber float *confidence, sp<AMessage> *meta) { 722b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t pos = 0; 723b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t post_id3_pos; 724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t header; 7251bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber if (!Resync(source, 0, &pos, &post_id3_pos, &header)) { 726e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 727e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 729efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber *meta = new AMessage; 730efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber (*meta)->setInt64("offset", pos); 731efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber (*meta)->setInt32("header", header); 7321bd9949815b93b5a741c0f2533bf50d32542dbe5Andreas Huber (*meta)->setInt64("post-id3-offset", post_id3_pos); 733efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber 734e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_MPEG; 735efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber *confidence = 0.2f; 736e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 737e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return true; 738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} // namespace android 741