AacBqToPcmCbRenderer.cpp revision 377c6471dbefd6251c11d9c5633193cd57598991
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
59    // protectionAbsent is 0 if there is CRC
60    static const size_t kAdtsHeaderLengthNoCrc = 7;
61    static const size_t kAdtsHeaderLengthWithCrc = 9;
62    size_t headSize = protectionAbsent ? kAdtsHeaderLengthNoCrc : kAdtsHeaderLengthWithCrc;
63    if (headSize > frameSize) {
64        SL_LOGE("AacBqToPcmCbRenderer::getAdtsFrameSize() returns 0 (frameSize %u < headSize %u)",
65                frameSize, headSize);
66        return 0;
67    }
68
69    SL_LOGV("AacBqToPcmCbRenderer::getAdtsFrameSize() returns %u", frameSize);
70
71    return frameSize;
72}
73
74/**
75 * Returns whether a block of memory starts and ends on AAC ADTS frame boundaries
76 * @param data pointer to the compressed audio data
77 * @param size the size in bytes of the data block to validate
78 * @return SL_RESULT_SUCCESS if there is AAC ADTS data, and it starts and ends on frame boundaries,
79 *    or an appropriate error code otherwise:
80 *      SL_RESULT_PARAMETER_INVALID if not possible to attempt validation of even one frame
81 *      SL_RESULT_CONTENT_CORRUPTED if the frame contents are otherwise invalid
82 */
83SLresult AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries(void* data, size_t size)
84{
85    off64_t offset = 0;
86    size_t frameSize = 0;
87
88    if ((NULL == data) || (size == 0)) {
89        SL_LOGE("No ADTS to validate");
90        return SL_RESULT_PARAMETER_INVALID;
91    }
92
93    while (offset < size) {
94        if ((frameSize = getAdtsFrameSize((uint8_t *)data, offset, size)) == 0) {
95            SL_LOGE("found ADTS frame of size 0 at offset %llu", offset);
96            return SL_RESULT_CONTENT_CORRUPTED;
97        }
98        //SL_LOGV("last good offset %llu", offset);
99        offset += frameSize;
100        if (offset > size) {
101            SL_LOGE("found incomplete ADTS frame at end of data");
102            return SL_RESULT_CONTENT_CORRUPTED;
103        }
104    }
105    if (offset != size) { SL_LOGE("ADTS parsing error: reached end of incomplete frame"); }
106    assert(offset == size);
107    return SL_RESULT_SUCCESS;
108}
109
110//--------------------------------------------------------------------------------------------------
111AacBqToPcmCbRenderer::AacBqToPcmCbRenderer(AudioPlayback_Parameters* params) :
112        AudioToCbRenderer(params),
113        mBqSource(0)
114{
115    SL_LOGD("AacBqToPcmCbRenderer::AacBqToPcmCbRenderer()");
116
117}
118
119
120AacBqToPcmCbRenderer::~AacBqToPcmCbRenderer() {
121    SL_LOGD("AacBqToPcmCbRenderer::~AacBqToPcmCbRenderer()");
122
123}
124
125
126//--------------------------------------------------
127void AacBqToPcmCbRenderer::registerSourceQueueCallback(
128        const void* user, void *context,  const void *caller) {
129    SL_LOGD("AacBqToPcmCbRenderer::registerQueueCallback");
130
131    Mutex::Autolock _l(mBqSourceLock);
132
133    mBqSource = new BufferQueueSource(user, context, caller);
134
135    CHECK(mBqSource != 0);
136    SL_LOGD("AacBqToPcmCbRenderer::registerSourceQueueCallback end");
137}
138
139
140//--------------------------------------------------
141// Event handlers
142void AacBqToPcmCbRenderer::onPrepare() {
143    SL_LOGD("AacBqToPcmCbRenderer::onPrepare()");
144    Mutex::Autolock _l(mBufferSourceLock);
145
146    // Initialize the PCM format info with the known parameters before the start of the decode
147    {
148        android::Mutex::Autolock autoLock(mPcmFormatLock);
149        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_BITSPERSAMPLE] = SL_PCMSAMPLEFORMAT_FIXED_16;
150        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CONTAINERSIZE] = 16;
151        //FIXME not true on all platforms
152        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_ENDIANNESS] = SL_BYTEORDER_LITTLEENDIAN;
153        //    initialization with the default values: they will be replaced by the actual values
154        //      once the decoder has figured them out
155        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = mChannelCount;
156        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE] = mSampleRateHz;
157        mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] = mChannelMask;
158    }
159
160    sp<DataSource> dataSource;
161    {
162        Mutex::Autolock _l(mBqSourceLock);
163        dataSource = mBqSource;
164    }
165    if (dataSource == 0) {
166        SL_LOGE("AacBqToPcmCbRenderer::onPrepare(): Error no data source");
167        notifyPrepared(MEDIA_ERROR_BASE);
168        return;
169    }
170
171    sp<MediaExtractor> extractor = new AacAdtsExtractor(dataSource);
172    if (extractor == 0) {
173        SL_LOGE("AacBqToPcmCbRenderer::onPrepare: Could not instantiate AAC extractor.");
174        notifyPrepared(ERROR_UNSUPPORTED);
175        return;
176    }
177
178    // only decoding a single track of data
179    const size_t kTrackToDecode = 0;
180
181    sp<MediaSource> source = extractor->getTrack(kTrackToDecode);
182    if (source == 0) {
183        SL_LOGE("AacBqToPcmCbRenderer::onPrepare: error getting source from extractor");
184        notifyPrepared(ERROR_UNSUPPORTED);
185        return;
186    }
187    sp<MetaData> meta = extractor->getTrackMetaData(kTrackToDecode);
188
189    // the audio content is not raw PCM, so we need a decoder
190    OMXClient client;
191    CHECK_EQ(client.connect(), (status_t)OK);
192
193    source = OMXCodec::Create(
194            client.interface(), meta, false /* createEncoder */,
195            source);
196
197    if (source == NULL) {
198        SL_LOGE("AacBqToPcmCbRenderer::onPrepare: Could not instantiate decoder.");
199        notifyPrepared(ERROR_UNSUPPORTED);
200        return;
201    }
202
203    meta = source->getFormat();
204
205    SL_LOGD("AacBqToPcmCbRenderer::onPrepare() after instantiating decoder");
206
207    if (source->start() != OK) {
208        SL_LOGE("AacBqToPcmCbRenderer::onPrepare() Failed to start source/decoder.");
209        notifyPrepared(MEDIA_ERROR_BASE);
210        return;
211    }
212
213    //---------------------------------
214    CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount));
215    int32_t sr;
216    CHECK(meta->findInt32(kKeySampleRate, &sr));
217    mSampleRateHz = (uint32_t) sr;
218    // FIXME similar to AudioSfDecoder::onPrepare()
219    mChannelMask = channelCountToMask(mChannelCount);
220
221    {
222            android::Mutex::Autolock autoLock(mPcmFormatLock);
223            mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE] = mSampleRateHz;
224            mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = mChannelCount;
225            mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] = mChannelMask;
226    }
227    SL_LOGV("AacBqToPcmCbRenderer::onPrepare() channel count=%d SR=%d",
228            mChannelCount, mSampleRateHz);
229
230    //---------------------------------
231    // The data source, and audio source (a decoder) are ready to be used
232    mDataSource = dataSource;
233    mAudioSource = source;
234    mAudioSourceStarted = true;
235
236    //-------------------------------------
237    // signal successful completion of prepare
238    mStateFlags |= kFlagPrepared;
239
240    GenericPlayer::onPrepare();
241
242    SL_LOGD("AacBqToPcmCbRenderer::onPrepare() done, mStateFlags=0x%x", mStateFlags);
243}
244
245} // namespace android
246