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