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