1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker *
4*bebae9c0SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker *
8*bebae9c0SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker *
10*bebae9c0SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker */
16*bebae9c0SAndroid Build Coastguard Worker
17*bebae9c0SAndroid Build Coastguard Worker //#define USE_LOG SLAndroidLogLevel_Debug
18*bebae9c0SAndroid Build Coastguard Worker
19*bebae9c0SAndroid Build Coastguard Worker #include "sles_allinclusive.h"
20*bebae9c0SAndroid Build Coastguard Worker #include "android/include/AacBqToPcmCbRenderer.h"
21*bebae9c0SAndroid Build Coastguard Worker #include "android/channels.h"
22*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/SimpleDecodingSource.h>
23*bebae9c0SAndroid Build Coastguard Worker
24*bebae9c0SAndroid Build Coastguard Worker namespace android {
25*bebae9c0SAndroid Build Coastguard Worker
26*bebae9c0SAndroid Build Coastguard Worker // ADTS header size is 7, but frame size information ends on byte 6 (when counting from byte 1)
27*bebae9c0SAndroid Build Coastguard Worker #define ADTS_HEADER_SIZE_UP_TO_FRAMESIZE 6
28*bebae9c0SAndroid Build Coastguard Worker
29*bebae9c0SAndroid Build Coastguard Worker /**
30*bebae9c0SAndroid Build Coastguard Worker * Returns the size of an AAC ADTS frame.
31*bebae9c0SAndroid Build Coastguard Worker * Note that if the returned value + offset > size, it means that a partial frame starts at that
32*bebae9c0SAndroid Build Coastguard Worker * offset, but this function will still return the size of the full frame.
33*bebae9c0SAndroid Build Coastguard Worker * @param data pointer to the compressed audio data
34*bebae9c0SAndroid Build Coastguard Worker * @param offset offset in bytes relative to data of where the frame is supposed to start
35*bebae9c0SAndroid Build Coastguard Worker * @param size the size in bytes of the data block starting at data
36*bebae9c0SAndroid Build Coastguard Worker * @return the size in bytes of the AAC ADTS frame starting at the given offset of the given
37*bebae9c0SAndroid Build Coastguard Worker * memory address, 0 if the frame couldn't be parsed.
38*bebae9c0SAndroid Build Coastguard Worker */
getAdtsFrameSize(const uint8_t * data,off64_t offset,size_t size)39*bebae9c0SAndroid Build Coastguard Worker static size_t getAdtsFrameSize(const uint8_t *data, off64_t offset, size_t size) {
40*bebae9c0SAndroid Build Coastguard Worker size_t frameSize = 0;
41*bebae9c0SAndroid Build Coastguard Worker
42*bebae9c0SAndroid Build Coastguard Worker if (!(offset + ADTS_HEADER_SIZE_UP_TO_FRAMESIZE < (off64_t) size)) {
43*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AacBqToPcmCbRenderer::getAdtsFrameSize() returns 0 (can't read syncword or header)"
44*bebae9c0SAndroid Build Coastguard Worker );
45*bebae9c0SAndroid Build Coastguard Worker return 0;
46*bebae9c0SAndroid Build Coastguard Worker }
47*bebae9c0SAndroid Build Coastguard Worker
48*bebae9c0SAndroid Build Coastguard Worker const uint8_t *syncword = data + offset;
49*bebae9c0SAndroid Build Coastguard Worker if ((syncword[0] != 0xff) || ((syncword[1] & 0xf6) != 0xf0)) {
50*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AacBqToPcmCbRenderer::getAdtsFrameSize() returns 0 (wrong syncword)");
51*bebae9c0SAndroid Build Coastguard Worker return 0;
52*bebae9c0SAndroid Build Coastguard Worker }
53*bebae9c0SAndroid Build Coastguard Worker
54*bebae9c0SAndroid Build Coastguard Worker const uint8_t protectionAbsent = data[offset+1] & 0x1;
55*bebae9c0SAndroid Build Coastguard Worker
56*bebae9c0SAndroid Build Coastguard Worker const uint8_t* header = data + offset + 3;
57*bebae9c0SAndroid Build Coastguard Worker frameSize = (header[0] & 0x3) << 11 | header[1] << 3 | header[2] >> 5;
58*bebae9c0SAndroid Build Coastguard Worker // the frame size read already contains the size of the header, so no need to add it here
59*bebae9c0SAndroid Build Coastguard Worker
60*bebae9c0SAndroid Build Coastguard Worker // protectionAbsent is 0 if there is CRC
61*bebae9c0SAndroid Build Coastguard Worker static const size_t kAdtsHeaderLengthNoCrc = 7;
62*bebae9c0SAndroid Build Coastguard Worker static const size_t kAdtsHeaderLengthWithCrc = 9;
63*bebae9c0SAndroid Build Coastguard Worker size_t headSize = protectionAbsent ? kAdtsHeaderLengthNoCrc : kAdtsHeaderLengthWithCrc;
64*bebae9c0SAndroid Build Coastguard Worker if (headSize > frameSize) {
65*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AacBqToPcmCbRenderer::getAdtsFrameSize() returns 0 (frameSize %zu < headSize %zu)",
66*bebae9c0SAndroid Build Coastguard Worker frameSize, headSize);
67*bebae9c0SAndroid Build Coastguard Worker return 0;
68*bebae9c0SAndroid Build Coastguard Worker }
69*bebae9c0SAndroid Build Coastguard Worker
70*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AacBqToPcmCbRenderer::getAdtsFrameSize() returns %u", frameSize);
71*bebae9c0SAndroid Build Coastguard Worker
72*bebae9c0SAndroid Build Coastguard Worker return frameSize;
73*bebae9c0SAndroid Build Coastguard Worker }
74*bebae9c0SAndroid Build Coastguard Worker
75*bebae9c0SAndroid Build Coastguard Worker /**
76*bebae9c0SAndroid Build Coastguard Worker * Returns whether a block of memory starts and ends on AAC ADTS frame boundaries
77*bebae9c0SAndroid Build Coastguard Worker * @param data pointer to the compressed audio data
78*bebae9c0SAndroid Build Coastguard Worker * @param size the size in bytes of the data block to validate
79*bebae9c0SAndroid Build Coastguard Worker * @return SL_RESULT_SUCCESS if there is AAC ADTS data, and it starts and ends on frame boundaries,
80*bebae9c0SAndroid Build Coastguard Worker * or an appropriate error code otherwise:
81*bebae9c0SAndroid Build Coastguard Worker * SL_RESULT_PARAMETER_INVALID if not possible to attempt validation of even one frame
82*bebae9c0SAndroid Build Coastguard Worker * SL_RESULT_CONTENT_CORRUPTED if the frame contents are otherwise invalid
83*bebae9c0SAndroid Build Coastguard Worker */
validateBufferStartEndOnFrameBoundaries(void * data,size_t size)84*bebae9c0SAndroid Build Coastguard Worker SLresult AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries(void* data, size_t size)
85*bebae9c0SAndroid Build Coastguard Worker {
86*bebae9c0SAndroid Build Coastguard Worker off64_t offset = 0;
87*bebae9c0SAndroid Build Coastguard Worker size_t frameSize = 0;
88*bebae9c0SAndroid Build Coastguard Worker
89*bebae9c0SAndroid Build Coastguard Worker if ((NULL == data) || (size == 0)) {
90*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("No ADTS to validate");
91*bebae9c0SAndroid Build Coastguard Worker return SL_RESULT_PARAMETER_INVALID;
92*bebae9c0SAndroid Build Coastguard Worker }
93*bebae9c0SAndroid Build Coastguard Worker
94*bebae9c0SAndroid Build Coastguard Worker while (offset < (off64_t) size) {
95*bebae9c0SAndroid Build Coastguard Worker if ((frameSize = getAdtsFrameSize((uint8_t *)data, offset, size)) == 0) {
96*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("found ADTS frame of size 0 at offset %lld", (long long) offset);
97*bebae9c0SAndroid Build Coastguard Worker return SL_RESULT_CONTENT_CORRUPTED;
98*bebae9c0SAndroid Build Coastguard Worker }
99*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("last good offset %llu", offset);
100*bebae9c0SAndroid Build Coastguard Worker offset += frameSize;
101*bebae9c0SAndroid Build Coastguard Worker if (offset > (off64_t) size) {
102*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("found incomplete ADTS frame at end of data");
103*bebae9c0SAndroid Build Coastguard Worker return SL_RESULT_CONTENT_CORRUPTED;
104*bebae9c0SAndroid Build Coastguard Worker }
105*bebae9c0SAndroid Build Coastguard Worker }
106*bebae9c0SAndroid Build Coastguard Worker if (offset != (off64_t) size) {
107*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("ADTS parsing error: reached end of incomplete frame");
108*bebae9c0SAndroid Build Coastguard Worker }
109*bebae9c0SAndroid Build Coastguard Worker assert(offset == (off64_t) size);
110*bebae9c0SAndroid Build Coastguard Worker return SL_RESULT_SUCCESS;
111*bebae9c0SAndroid Build Coastguard Worker }
112*bebae9c0SAndroid Build Coastguard Worker
113*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
AacBqToPcmCbRenderer(const AudioPlayback_Parameters * params,IAndroidBufferQueue * androidBufferQueue)114*bebae9c0SAndroid Build Coastguard Worker AacBqToPcmCbRenderer::AacBqToPcmCbRenderer(const AudioPlayback_Parameters* params,
115*bebae9c0SAndroid Build Coastguard Worker IAndroidBufferQueue *androidBufferQueue) :
116*bebae9c0SAndroid Build Coastguard Worker AudioToCbRenderer(params),
117*bebae9c0SAndroid Build Coastguard Worker mBqSource(new BufferQueueSource(androidBufferQueue))
118*bebae9c0SAndroid Build Coastguard Worker {
119*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AacBqToPcmCbRenderer::AacBqToPcmCbRenderer()");
120*bebae9c0SAndroid Build Coastguard Worker }
121*bebae9c0SAndroid Build Coastguard Worker
122*bebae9c0SAndroid Build Coastguard Worker
~AacBqToPcmCbRenderer()123*bebae9c0SAndroid Build Coastguard Worker AacBqToPcmCbRenderer::~AacBqToPcmCbRenderer() {
124*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AacBqToPcmCbRenderer::~AacBqToPcmCbRenderer()");
125*bebae9c0SAndroid Build Coastguard Worker
126*bebae9c0SAndroid Build Coastguard Worker }
127*bebae9c0SAndroid Build Coastguard Worker
128*bebae9c0SAndroid Build Coastguard Worker
129*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
130*bebae9c0SAndroid Build Coastguard Worker // Event handlers
onPrepare()131*bebae9c0SAndroid Build Coastguard Worker void AacBqToPcmCbRenderer::onPrepare() {
132*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AacBqToPcmCbRenderer::onPrepare()");
133*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mBufferSourceLock);
134*bebae9c0SAndroid Build Coastguard Worker
135*bebae9c0SAndroid Build Coastguard Worker // Initialize the PCM format info with the known parameters before the start of the decode
136*bebae9c0SAndroid Build Coastguard Worker {
137*bebae9c0SAndroid Build Coastguard Worker android::Mutex::Autolock autoLock(mPcmFormatLock);
138*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_BITSPERSAMPLE] = SL_PCMSAMPLEFORMAT_FIXED_16;
139*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CONTAINERSIZE] = 16;
140*bebae9c0SAndroid Build Coastguard Worker //FIXME not true on all platforms
141*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_ENDIANNESS] = SL_BYTEORDER_LITTLEENDIAN;
142*bebae9c0SAndroid Build Coastguard Worker // initialization with the default values: they will be replaced by the actual values
143*bebae9c0SAndroid Build Coastguard Worker // once the decoder has figured them out
144*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = UNKNOWN_NUMCHANNELS;
145*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE] = UNKNOWN_SAMPLERATE;
146*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] = SL_ANDROID_UNKNOWN_CHANNELMASK;
147*bebae9c0SAndroid Build Coastguard Worker }
148*bebae9c0SAndroid Build Coastguard Worker
149*bebae9c0SAndroid Build Coastguard Worker sp<AacAdtsExtractor> extractor = new AacAdtsExtractor(mBqSource);
150*bebae9c0SAndroid Build Coastguard Worker
151*bebae9c0SAndroid Build Coastguard Worker // only decoding a single track of data
152*bebae9c0SAndroid Build Coastguard Worker const size_t kTrackToDecode = 0;
153*bebae9c0SAndroid Build Coastguard Worker
154*bebae9c0SAndroid Build Coastguard Worker sp<MediaSource> source = extractor->getTrack(kTrackToDecode);
155*bebae9c0SAndroid Build Coastguard Worker if (source == 0) {
156*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AacBqToPcmCbRenderer::onPrepare: error getting source from extractor");
157*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(ERROR_UNSUPPORTED);
158*bebae9c0SAndroid Build Coastguard Worker return;
159*bebae9c0SAndroid Build Coastguard Worker }
160*bebae9c0SAndroid Build Coastguard Worker
161*bebae9c0SAndroid Build Coastguard Worker // the audio content is not raw PCM, so we need a decoder
162*bebae9c0SAndroid Build Coastguard Worker source = SimpleDecodingSource::Create(source);
163*bebae9c0SAndroid Build Coastguard Worker
164*bebae9c0SAndroid Build Coastguard Worker if (source == NULL) {
165*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AacBqToPcmCbRenderer::onPrepare: Could not instantiate decoder.");
166*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(ERROR_UNSUPPORTED);
167*bebae9c0SAndroid Build Coastguard Worker return;
168*bebae9c0SAndroid Build Coastguard Worker }
169*bebae9c0SAndroid Build Coastguard Worker
170*bebae9c0SAndroid Build Coastguard Worker sp<MetaData> meta = source->getFormat();
171*bebae9c0SAndroid Build Coastguard Worker
172*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AacBqToPcmCbRenderer::onPrepare() after instantiating decoder");
173*bebae9c0SAndroid Build Coastguard Worker
174*bebae9c0SAndroid Build Coastguard Worker if (source->start() != OK) {
175*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AacBqToPcmCbRenderer::onPrepare() Failed to start source/decoder.");
176*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(MEDIA_ERROR_BASE);
177*bebae9c0SAndroid Build Coastguard Worker return;
178*bebae9c0SAndroid Build Coastguard Worker }
179*bebae9c0SAndroid Build Coastguard Worker
180*bebae9c0SAndroid Build Coastguard Worker //---------------------------------
181*bebae9c0SAndroid Build Coastguard Worker int32_t channelCount;
182*bebae9c0SAndroid Build Coastguard Worker CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
183*bebae9c0SAndroid Build Coastguard Worker int32_t sr;
184*bebae9c0SAndroid Build Coastguard Worker CHECK(meta->findInt32(kKeySampleRate, &sr));
185*bebae9c0SAndroid Build Coastguard Worker // FIXME similar to AudioSfDecoder::onPrepare()
186*bebae9c0SAndroid Build Coastguard Worker
187*bebae9c0SAndroid Build Coastguard Worker // already "good to go" (compare to AudioSfDecoder::onPrepare)
188*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusHigh;
189*bebae9c0SAndroid Build Coastguard Worker mCacheFill = 1000;
190*bebae9c0SAndroid Build Coastguard Worker notifyStatus();
191*bebae9c0SAndroid Build Coastguard Worker notifyCacheFill();
192*bebae9c0SAndroid Build Coastguard Worker
193*bebae9c0SAndroid Build Coastguard Worker {
194*bebae9c0SAndroid Build Coastguard Worker android::Mutex::Autolock autoLock(mPcmFormatLock);
195*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE] = sr;
196*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = channelCount;
197*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] =
198*bebae9c0SAndroid Build Coastguard Worker sles_channel_out_mask_from_count(channelCount);
199*bebae9c0SAndroid Build Coastguard Worker }
200*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AacBqToPcmCbRenderer::onPrepare() channel count=%d SR=%d",
201*bebae9c0SAndroid Build Coastguard Worker channelCount, sr);
202*bebae9c0SAndroid Build Coastguard Worker
203*bebae9c0SAndroid Build Coastguard Worker //---------------------------------
204*bebae9c0SAndroid Build Coastguard Worker // The data source, and audio source (a decoder) are ready to be used
205*bebae9c0SAndroid Build Coastguard Worker mDataSource = mBqSource;
206*bebae9c0SAndroid Build Coastguard Worker mAudioSource = source;
207*bebae9c0SAndroid Build Coastguard Worker mAudioSourceStarted = true;
208*bebae9c0SAndroid Build Coastguard Worker
209*bebae9c0SAndroid Build Coastguard Worker //-------------------------------------
210*bebae9c0SAndroid Build Coastguard Worker // signal successful completion of prepare
211*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagPrepared;
212*bebae9c0SAndroid Build Coastguard Worker
213*bebae9c0SAndroid Build Coastguard Worker // skipping past AudioToCbRenderer and AudioSfDecoder
214*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onPrepare();
215*bebae9c0SAndroid Build Coastguard Worker
216*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AacBqToPcmCbRenderer::onPrepare() done, mStateFlags=0x%x", mStateFlags);
217*bebae9c0SAndroid Build Coastguard Worker }
218*bebae9c0SAndroid Build Coastguard Worker
219*bebae9c0SAndroid Build Coastguard Worker } // namespace android
220