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