xref: /aosp_15_r20/frameworks/wilhelm/src/android/AacBqToPcmCbRenderer.cpp (revision bebae9c0e76121f8312ccb50385c080b3a0b023c)
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