AacAdtsExtractor.cpp revision 145156a92c1d379e494cb69920d49b87f9c0e300
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
77    // protectionAbsent is 0 if there is CRC
78    static const size_t kAdtsHeaderLengthNoCrc = 7;
79    static const size_t kAdtsHeaderLengthWithCrc = 9;
80    size_t headSize = protectionAbsent ? kAdtsHeaderLengthNoCrc : kAdtsHeaderLengthWithCrc;
81    if (headSize > frameSize) {
82        SL_LOGE("AacAdtsExtractor:: getFrameSize() returns 0 (frameSize %u < headSize %u)",
83                frameSize, headSize);
84        return 0;
85    }
86
87    //SL_LOGV("AacAdtsExtractor:: getFrameSize() returns %u", frameSize);
88
89    return frameSize;
90}
91
92
93AacAdtsExtractor::AacAdtsExtractor(const sp<DataSource> &source)
94    : mDataSource(source),
95      mInitCheck(NO_INIT),
96      mFrameDurationUs(0) {
97
98    // difference with framework's AAC Extractor: we have already validated the data
99    // upon enqueueing, so no need to sniff the data:
100    //    String8 mimeType;
101    //    float confidence;
102    //    if (!SniffAAC(mDataSource, &mimeType, &confidence, NULL)) {
103    //        return;
104    //    }
105
106    uint8_t profile, sf_index, channel, header[2];
107    if (mDataSource->readAt(2, &header, 2) < 2) {
108        return;
109    }
110
111    profile = (header[0] >> 6) & 0x3;
112    sf_index = (header[0] >> 2) & 0xf;
113    uint32_t sr = get_sample_rate(sf_index);
114
115    if (sr == 0) {
116        return;
117    }
118    channel = (header[0] & 0x1) << 2 | (header[1] >> 6);
119
120    SL_LOGV("AacAdtsExtractor has found sr=%d channel=%d", sr, channel);
121
122    mMeta = MakeAACCodecSpecificData(profile, sf_index, channel);
123
124    off64_t offset = 0;
125    off64_t streamSize, numFrames = 0;
126    size_t frameSize = 0;
127    int64_t duration = 0;
128
129    if (mDataSource->getSize(&streamSize) == OK) {
130        while (offset < streamSize) {
131            if ((frameSize = getFrameSize(mDataSource, offset)) == 0) {
132                //SL_LOGV("AacAdtsExtractor() querying framesize at offset=%lld", offset);
133                return;
134            }
135
136            offset += frameSize;
137            numFrames ++;
138        }
139
140        // Round up and get the duration
141        mFrameDurationUs = (1024 * 1000000ll + (sr - 1)) / sr;
142        duration = numFrames * mFrameDurationUs;
143        mMeta->setInt64(kKeyDuration, duration);
144    }
145
146    mInitCheck = OK;
147
148}
149
150
151AacAdtsExtractor::~AacAdtsExtractor() {
152}
153
154
155sp<MetaData> AacAdtsExtractor::getMetaData() {
156    sp<MetaData> meta = new MetaData;
157
158    if (mInitCheck != OK) {
159        return meta;
160    }
161
162    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
163
164    return meta;
165}
166
167
168size_t AacAdtsExtractor::countTracks() {
169    return mInitCheck == OK ? 1 : 0;
170}
171
172
173sp<MediaSource> AacAdtsExtractor::getTrack(size_t index) {
174    if (mInitCheck != OK || index != 0) {
175        return NULL;
176    }
177
178    return new AacAdtsSource(mDataSource, mMeta, mFrameDurationUs);
179}
180
181
182sp<MetaData> AacAdtsExtractor::getTrackMetaData(size_t index, uint32_t flags) {
183    if (mInitCheck != OK || index != 0) {
184        return NULL;
185    }
186
187    return mMeta;
188}
189
190
191////////////////////////////////////////////////////////////////////////////////
192
193// 8192 = 2^13, 13bit AAC frame size (in bytes)
194const size_t AacAdtsSource::kMaxFrameSize = 8192;
195
196AacAdtsSource::AacAdtsSource(
197        const sp<DataSource> &source, const sp<MetaData> &meta,
198        int64_t frame_duration_us)
199    : mDataSource(source),
200      mMeta(meta),
201      mOffset(0),
202      mCurrentTimeUs(0),
203      mStarted(false),
204      mGroup(NULL),
205      mFrameDurationUs(frame_duration_us) {
206}
207
208
209AacAdtsSource::~AacAdtsSource() {
210    if (mStarted) {
211        stop();
212    }
213}
214
215
216status_t AacAdtsSource::start(MetaData *params) {
217    CHECK(!mStarted);
218
219    mOffset = 0;
220    mCurrentTimeUs = 0;
221    mGroup = new MediaBufferGroup;
222    mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
223    mStarted = true;
224
225    return OK;
226}
227
228
229status_t AacAdtsSource::stop() {
230    CHECK(mStarted);
231
232    delete mGroup;
233    mGroup = NULL;
234
235    mStarted = false;
236    return OK;
237}
238
239
240sp<MetaData> AacAdtsSource::getFormat() {
241    return mMeta;
242}
243
244
245status_t AacAdtsSource::read(
246        MediaBuffer **out, const ReadOptions *options) {
247    *out = NULL;
248
249    int64_t seekTimeUs;
250    ReadOptions::SeekMode mode;
251    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
252        // difference with framework's AAC Extractor: no seeking
253        SL_LOGE("Can't seek in AAC ADTS buffer queue");
254    }
255
256    size_t frameSize, frameSizeWithoutHeader;
257    SL_LOGV("AacAdtsSource::read() offset=%lld", mOffset);
258    if ((frameSize = getFrameSize(mDataSource, mOffset)) == 0) {
259        SL_LOGV("AacAdtsSource::read() returns EOS");
260        return ERROR_END_OF_STREAM;
261        // FIXME if we return EOS here, verify we can restart decoding when we get new data
262        //  with start()
263        //LOGE("AacAdtsSource::read() should return EOS, but returning OK");
264        //return OK;
265    }
266
267    MediaBuffer *buffer;
268    status_t err = mGroup->acquire_buffer(&buffer);
269    if (err != OK) {
270        return err;
271    }
272
273    frameSizeWithoutHeader = frameSize - ADTS_HEADER_LENGTH;
274    ssize_t readSize = mDataSource->readAt(mOffset + ADTS_HEADER_LENGTH, buffer->data(),
275            frameSizeWithoutHeader);
276    //SL_LOGV("AacAdtsSource::read() readAt returned %u bytes", readSize);
277    if (readSize != (ssize_t)frameSizeWithoutHeader) {
278        SL_LOGW("AacAdtsSource::read() readSize != frameSizeWithoutHeader");
279        buffer->release();
280        buffer = NULL;
281        return ERROR_IO;
282    }
283
284    buffer->set_range(0, frameSizeWithoutHeader);
285    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
286    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
287
288    mOffset += frameSize;
289    mCurrentTimeUs += mFrameDurationUs;
290
291    *out = buffer;
292    return OK;
293}
294
295}  // namespace android
296