AacBqToPcmCbRenderer.cpp revision bb832e853d4afb11b0a3287b2eb0cad87696d631
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//#define USE_LOG SLAndroidLogLevel_Debug
18
19#include "sles_allinclusive.h"
20#include "android/include/AacBqToPcmCbRenderer.h"
21#include <media/stagefright/foundation/ADebug.h>
22
23namespace android {
24
25// ADTS header size is 7, but frame size information ends on byte 6 (when counting from byte 1)
26#define ADTS_HEADER_SIZE_UP_TO_FRAMESIZE 6
27
28/**
29 * Returns the size of an AAC ADTS frame.
30 * Note that if the returned value + offset > size, it means that a partial frame starts at that
31 *   offset, but this function will still return the size of the full frame.
32 * @param data pointer to the compressed audio data
33 * @param offset offset in bytes relative to data of where the frame is supposed to start
34 * @param size the size in bytes of the data block starting at data
35 * @return the size in bytes of the AAC ADTS frame starting at the given offset of the given
36 *    memory address, 0 if the frame couldn't be parsed.
37 */
38static size_t getAdtsFrameSize(const uint8_t *data, off64_t offset, size_t size) {
39    size_t frameSize = 0;
40
41    if (!(offset + ADTS_HEADER_SIZE_UP_TO_FRAMESIZE < size)) {
42        SL_LOGE("AacBqToPcmCbRenderer::getAdtsFrameSize() returns 0 (can't read syncword or header)"
43                );
44        return 0;
45    }
46
47    const uint8_t *syncword = data + offset;
48    if ((syncword[0] != 0xff) || ((syncword[1] & 0xf6) != 0xf0)) {
49        SL_LOGE("AacBqToPcmCbRenderer::getAdtsFrameSize() returns 0 (wrong syncword)");
50        return 0;
51    }
52
53    const uint8_t protectionAbsent = data[offset+1] & 0x1;
54
55    const uint8_t* header = data + offset + 3;
56    frameSize = (header[0] & 0x3) << 11 | header[1] << 3 | header[2] >> 5;
57    // the frame size read already contains the size of the header, so no need to add it here
58    frameSize += protectionAbsent ? 0 : 2;
59
60    SL_LOGV("AacBqToPcmCbRenderer::getAdtsFrameSize() returns %u", frameSize);
61
62    return frameSize;
63}
64
65/**
66 * Returns whether a block of memory starts and ends on AAC ADTS frame boundaries
67 * @param data pointer to the compressed audio data
68 * @param size the size in bytes of the data block to validate
69 * @return true if there is AAC ADTS data, and it starts and ends on frame boundaries,
70 *    false otherwise
71 */
72bool AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries(void* data, size_t size)
73{
74    off64_t offset = 0;
75    size_t frameSize = 0;
76
77    if ((NULL == data) || (size == 0)) {
78        SL_LOGE("No ADTS to validate");
79        return false;
80    }
81
82    while (offset < size) {
83        if ((frameSize = getAdtsFrameSize((uint8_t *)data, offset, size)) == 0) {
84            SL_LOGE("found ADTS frame of size 0 at offset %llu", offset);
85            return false;
86        }
87        //SL_LOGV("last good offset %llu", offset);
88        offset += frameSize;
89        if (offset > size) {
90            SL_LOGE("found incomplete ADTS frame at end of data");
91            return false;
92        }
93    }
94    if (offset != size) { SL_LOGE("ADTS parsing error: reached end of incomplete frame"); }
95    assert(offset == size);
96    return true;
97}
98
99//--------------------------------------------------------------------------------------------------
100AacBqToPcmCbRenderer::AacBqToPcmCbRenderer(AudioPlayback_Parameters* params) :
101        AudioToCbRenderer(params),
102        mBqSource(0)
103{
104    SL_LOGD("AacBqToPcmCbRenderer::AacBqToPcmCbRenderer()");
105
106}
107
108
109AacBqToPcmCbRenderer::~AacBqToPcmCbRenderer() {
110    SL_LOGD("AacBqToPcmCbRenderer::~AacBqToPcmCbRenderer()");
111
112}
113
114
115//--------------------------------------------------
116void AacBqToPcmCbRenderer::registerSourceQueueCallback(
117        const void* user, void *context,  const void *caller) {
118    SL_LOGD("AacBqToPcmCbRenderer::registerQueueCallback");
119
120    Mutex::Autolock _l(mBqSourceLock);
121
122    mBqSource = new BufferQueueSource(user, context, caller);
123
124    CHECK(mBqSource != 0);
125    SL_LOGD("AacBqToPcmCbRenderer::registerSourceQueueCallback end");
126}
127
128
129//--------------------------------------------------
130// Event handlers
131void AacBqToPcmCbRenderer::onPrepare() {
132    SL_LOGD("AacBqToPcmCbRenderer::onPrepare()");
133    Mutex::Autolock _l(mBufferSourceLock);
134
135    // Initialize the PCM format info with the known parameters before the start of the decode
136    {
137        android::Mutex::Autolock autoLock(mPcmFormatLock);
138        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_BITSPERSAMPLE] = SL_PCMSAMPLEFORMAT_FIXED_16;
139        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CONTAINERSIZE] = 16;
140        //FIXME not true on all platforms
141        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_ENDIANNESS] = SL_BYTEORDER_LITTLEENDIAN;
142        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] = 0;
143        //    initialization with the default values: they will be replaced by the actual values
144        //      once the decoder has figured them out
145        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = mChannelCount;
146        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLESPERSEC] = mSampleRateHz;
147    }
148
149    sp<DataSource> dataSource;
150    {
151        Mutex::Autolock _l(mBqSourceLock);
152        dataSource = mBqSource;
153    }
154    if (dataSource == 0) {
155        SL_LOGE("AacBqToPcmCbRenderer::onPrepare(): Error no data source");
156        notifyPrepared(MEDIA_ERROR_BASE);
157        return;
158    }
159
160    sp<MediaExtractor> extractor = new AacAdtsExtractor(dataSource);
161    if (extractor == 0) {
162        SL_LOGE("AacBqToPcmCbRenderer::onPrepare: Could not instantiate AAC extractor.");
163        notifyPrepared(ERROR_UNSUPPORTED);
164        return;
165    }
166
167    // only decoding a single track of data
168    const size_t kTrackToDecode = 0;
169
170    sp<MediaSource> source = extractor->getTrack(kTrackToDecode);
171    if (source == 0) {
172        SL_LOGE("AacBqToPcmCbRenderer::onPrepare: error getting source from extractor");
173        notifyPrepared(ERROR_UNSUPPORTED);
174        return;
175    }
176    sp<MetaData> meta = extractor->getTrackMetaData(kTrackToDecode);
177
178    // the audio content is not raw PCM, so we need a decoder
179    OMXClient client;
180    CHECK_EQ(client.connect(), (status_t)OK);
181
182    source = OMXCodec::Create(
183            client.interface(), meta, false /* createEncoder */,
184            source);
185
186    if (source == NULL) {
187        SL_LOGE("AudioSfDecoder::onPrepare: Could not instantiate decoder.");
188        notifyPrepared(ERROR_UNSUPPORTED);
189        return;
190    }
191
192    meta = source->getFormat();
193
194    SL_LOGD("AacBqToPcmCbRenderer::onPrepare() after instantiating decoder");
195
196    if (source->start() != OK) {
197        SL_LOGE("AacBqToPcmCbRenderer::onPrepare() Failed to start source/decoder.");
198        notifyPrepared(MEDIA_ERROR_BASE);
199        return;
200    }
201
202    //---------------------------------
203    CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount));
204    int32_t sr;
205    CHECK(meta->findInt32(kKeySampleRate, &sr));
206    mSampleRateHz = (uint32_t) sr;
207    {
208            android::Mutex::Autolock autoLock(mPcmFormatLock);
209            mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLESPERSEC] = mSampleRateHz;
210            mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = mChannelCount;
211    }
212    SL_LOGV("AacBqToPcmCbRenderer::onPrepare() channel count=%d SR=%d",
213            mChannelCount, mSampleRateHz);
214
215    //---------------------------------
216    // The data source, and audio source (a decoder) are ready to be used
217    mDataSource = dataSource;
218    mAudioSource = source;
219    mAudioSourceStarted = true;
220
221    //-------------------------------------
222    // signal successful completion of prepare
223    mStateFlags |= kFlagPrepared;
224
225    GenericPlayer::onPrepare();
226
227    SL_LOGD("AacBqToPcmCbRenderer::onPrepare() done, mStateFlags=0x%x", mStateFlags);
228}
229
230} // namespace android
231