AacAdtsExtractor.cpp revision 02b9a8f9d11512ff604ada5b4d76fbb5d06cc488
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "sllog.h"
18#include <utils/Log.h>
19
20#include "android/include/AacAdtsExtractor.h"
21#include "include/avc_utils.h"
22
23
24namespace android {
25
26#define ADTS_HEADER_LENGTH 7
27// ADTS header size is 7, but frame size information ends on byte 6 (when counting from byte 1)
28#define ADTS_HEADER_SIZE_UP_TO_FRAMESIZE 6
29
30////////////////////////////////////////////////////////////////////////////////
31
32// Returns the sample rate based on the sampling frequency index
33static uint32_t get_sample_rate(const uint8_t sf_index)
34{
35    static const uint32_t sample_rates[] =
36    {
37        96000, 88200, 64000, 48000, 44100, 32000,
38        24000, 22050, 16000, 12000, 11025, 8000
39    };
40
41    if (sf_index < sizeof(sample_rates) / sizeof(sample_rates[0])) {
42        return sample_rates[sf_index];
43    }
44
45    return 0;
46}
47
48static size_t getFrameSize(const sp<DataSource> &source, off64_t offset) {
49    size_t frameSize = 0;
50
51    uint8_t syncHeader[ADTS_HEADER_SIZE_UP_TO_FRAMESIZE];
52    const uint8_t *syncword = syncHeader;
53    const uint8_t *header = syncHeader + 3;
54
55    ssize_t readSize = source->readAt(offset, &syncHeader, ADTS_HEADER_SIZE_UP_TO_FRAMESIZE);
56    if (readSize == 0) {
57        // EOS is normal, not an error
58        SL_LOGV("AacAdtsExtractor::getFrameSize EOS");
59        return 0;
60    }
61    if (readSize != ADTS_HEADER_SIZE_UP_TO_FRAMESIZE) {
62        SL_LOGE("AacAdtsExtractor:: getFrameSize() returns %d (syncword and header read error)",
63                (int) readSize);
64        return 0;
65    }
66
67    if ((syncword[0] != 0xff) || ((syncword[1] & 0xf6) != 0xf0)) {
68        SL_LOGE("AacAdtsExtractor:: getFrameSize() returns 0 (syncword pb)");
69        return 0;
70    }
71
72    const uint8_t protectionAbsent = syncword[1] & 0x1;
73
74    frameSize = (header[0] & 0x3) << 11 | header[1] << 3 | header[2] >> 5;
75    // the frame size read already contains the size of the ADTS header, so no need to add it here
76    frameSize += protectionAbsent ? 0 : 2;
77
78    //SL_LOGV("AacAdtsExtractor:: getFrameSize() returns %u", frameSize);
79
80    return frameSize;
81}
82
83
84AacAdtsExtractor::AacAdtsExtractor(const sp<DataSource> &source)
85    : mDataSource(source),
86      mInitCheck(NO_INIT),
87      mFrameDurationUs(0) {
88
89    // difference with framework's AAC Extractor: we have already validated the data
90    // upon enqueueing, so no need to sniff the data:
91    //    String8 mimeType;
92    //    float confidence;
93    //    if (!SniffAAC(mDataSource, &mimeType, &confidence, NULL)) {
94    //        return;
95    //    }
96
97    uint8_t profile, sf_index, channel, header[2];
98    if (mDataSource->readAt(2, &header, 2) < 2) {
99        return;
100    }
101
102    profile = (header[0] >> 6) & 0x3;
103    sf_index = (header[0] >> 2) & 0xf;
104    uint32_t sr = get_sample_rate(sf_index);
105
106    if (sr == 0) {
107        return;
108    }
109    channel = (header[0] & 0x1) << 2 | (header[1] >> 6);
110
111    SL_LOGV("AacAdtsExtractor has found sr=%d channel=%d", sr, channel);
112
113    mMeta = MakeAACCodecSpecificData(profile, sf_index, channel);
114
115    off64_t offset = 0;
116    off64_t streamSize, numFrames = 0;
117    size_t frameSize = 0;
118    int64_t duration = 0;
119
120    if (mDataSource->getSize(&streamSize) == OK) {
121        while (offset < streamSize) {
122            if ((frameSize = getFrameSize(mDataSource, offset)) == 0) {
123                //SL_LOGV("AacAdtsExtractor() querying framesize at offset=%lld", offset);
124                return;
125            }
126
127            offset += frameSize;
128            numFrames ++;
129        }
130
131        // Round up and get the duration
132        mFrameDurationUs = (1024 * 1000000ll + (sr - 1)) / sr;
133        duration = numFrames * mFrameDurationUs;
134        mMeta->setInt64(kKeyDuration, duration);
135    }
136
137    mInitCheck = OK;
138
139}
140
141
142AacAdtsExtractor::~AacAdtsExtractor() {
143}
144
145
146sp<MetaData> AacAdtsExtractor::getMetaData() {
147    sp<MetaData> meta = new MetaData;
148
149    if (mInitCheck != OK) {
150        return meta;
151    }
152
153    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
154
155    return meta;
156}
157
158
159size_t AacAdtsExtractor::countTracks() {
160    return mInitCheck == OK ? 1 : 0;
161}
162
163
164sp<MediaSource> AacAdtsExtractor::getTrack(size_t index) {
165    if (mInitCheck != OK || index != 0) {
166        return NULL;
167    }
168
169    return new AacAdtsSource(mDataSource, mMeta, mFrameDurationUs);
170}
171
172
173sp<MetaData> AacAdtsExtractor::getTrackMetaData(size_t index, uint32_t flags) {
174    if (mInitCheck != OK || index != 0) {
175        return NULL;
176    }
177
178    return mMeta;
179}
180
181
182////////////////////////////////////////////////////////////////////////////////
183
184// 8192 = 2^13, 13bit AAC frame size (in bytes)
185const size_t AacAdtsSource::kMaxFrameSize = 8192;
186
187AacAdtsSource::AacAdtsSource(
188        const sp<DataSource> &source, const sp<MetaData> &meta,
189        int64_t frame_duration_us)
190    : mDataSource(source),
191      mMeta(meta),
192      mOffset(0),
193      mCurrentTimeUs(0),
194      mStarted(false),
195      mGroup(NULL),
196      mFrameDurationUs(frame_duration_us) {
197}
198
199
200AacAdtsSource::~AacAdtsSource() {
201    if (mStarted) {
202        stop();
203    }
204}
205
206
207status_t AacAdtsSource::start(MetaData *params) {
208    CHECK(!mStarted);
209
210    mOffset = 0;
211    mCurrentTimeUs = 0;
212    mGroup = new MediaBufferGroup;
213    mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
214    mStarted = true;
215
216    return OK;
217}
218
219
220status_t AacAdtsSource::stop() {
221    CHECK(mStarted);
222
223    delete mGroup;
224    mGroup = NULL;
225
226    mStarted = false;
227    return OK;
228}
229
230
231sp<MetaData> AacAdtsSource::getFormat() {
232    return mMeta;
233}
234
235
236status_t AacAdtsSource::read(
237        MediaBuffer **out, const ReadOptions *options) {
238    *out = NULL;
239
240    int64_t seekTimeUs;
241    ReadOptions::SeekMode mode;
242    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
243        // difference with framework's AAC Extractor: no seeking
244        SL_LOGE("Can't seek in AAC ADTS buffer queue");
245    }
246
247    size_t frameSize, frameSizeWithoutHeader;
248    SL_LOGV("AacAdtsSource::read() offset=%lld", mOffset);
249    if ((frameSize = getFrameSize(mDataSource, mOffset)) == 0) {
250        SL_LOGV("AacAdtsSource::read() returns EOS");
251        return ERROR_END_OF_STREAM;
252        // FIXME if we return EOS here, verify we can restart decoding when we get new data
253        //  with start()
254        //LOGE("AacAdtsSource::read() should return EOS, but returning OK");
255        //return OK;
256    }
257
258    MediaBuffer *buffer;
259    status_t err = mGroup->acquire_buffer(&buffer);
260    if (err != OK) {
261        return err;
262    }
263
264    frameSizeWithoutHeader = frameSize - ADTS_HEADER_LENGTH;
265    ssize_t readSize = mDataSource->readAt(mOffset + ADTS_HEADER_LENGTH, buffer->data(),
266            frameSizeWithoutHeader);
267    //SL_LOGV("AacAdtsSource::read() readAt returned %u bytes", readSize);
268    if (readSize != (ssize_t)frameSizeWithoutHeader) {
269        SL_LOGW("AacAdtsSource::read() readSize != frameSizeWithoutHeader");
270        buffer->release();
271        buffer = NULL;
272        return ERROR_IO;
273    }
274
275    buffer->set_range(0, frameSizeWithoutHeader);
276    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
277    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
278
279    mOffset += frameSize;
280    mCurrentTimeUs += mFrameDurationUs;
281
282    *out = buffer;
283    return OK;
284}
285
286}  // namespace android
287