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 LOG_NDEBUG 0 18#define LOG_TAG "AACExtractor" 19#include <utils/Log.h> 20 21#include "include/AACExtractor.h" 22#include "include/avc_utils.h" 23 24#include <media/stagefright/foundation/ABuffer.h> 25#include <media/stagefright/foundation/AMessage.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/DataSource.h> 28#include <media/stagefright/MediaBufferGroup.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MediaErrors.h> 31#include <media/stagefright/MediaSource.h> 32#include <media/stagefright/MetaData.h> 33#include <utils/String8.h> 34 35namespace android { 36 37class AACSource : public MediaSource { 38public: 39 AACSource(const sp<DataSource> &source, 40 const sp<MetaData> &meta, 41 const Vector<uint64_t> &offset_vector, 42 int64_t frame_duration_us); 43 44 virtual status_t start(MetaData *params = NULL); 45 virtual status_t stop(); 46 47 virtual sp<MetaData> getFormat(); 48 49 virtual status_t read( 50 MediaBuffer **buffer, const ReadOptions *options = NULL); 51 52protected: 53 virtual ~AACSource(); 54 55private: 56 static const size_t kMaxFrameSize; 57 sp<DataSource> mDataSource; 58 sp<MetaData> mMeta; 59 60 off64_t mOffset; 61 int64_t mCurrentTimeUs; 62 bool mStarted; 63 MediaBufferGroup *mGroup; 64 65 Vector<uint64_t> mOffsetVector; 66 int64_t mFrameDurationUs; 67 68 AACSource(const AACSource &); 69 AACSource &operator=(const AACSource &); 70}; 71 72//////////////////////////////////////////////////////////////////////////////// 73 74// Returns the sample rate based on the sampling frequency index 75uint32_t get_sample_rate(const uint8_t sf_index) 76{ 77 static const uint32_t sample_rates[] = 78 { 79 96000, 88200, 64000, 48000, 44100, 32000, 80 24000, 22050, 16000, 12000, 11025, 8000 81 }; 82 83 if (sf_index < sizeof(sample_rates) / sizeof(sample_rates[0])) { 84 return sample_rates[sf_index]; 85 } 86 87 return 0; 88} 89 90// Returns the frame length in bytes as described in an ADTS header starting at the given offset, 91// or 0 if the size can't be read due to an error in the header or a read failure. 92// The returned value is the AAC frame size with the ADTS header length (regardless of 93// the presence of the CRC). 94// If headerSize is non-NULL, it will be used to return the size of the header of this ADTS frame. 95static size_t getAdtsFrameLength(const sp<DataSource> &source, off64_t offset, size_t* headerSize) { 96 97 const size_t kAdtsHeaderLengthNoCrc = 7; 98 const size_t kAdtsHeaderLengthWithCrc = 9; 99 100 size_t frameSize = 0; 101 102 uint8_t syncword[2]; 103 if (source->readAt(offset, &syncword, 2) != 2) { 104 return 0; 105 } 106 if ((syncword[0] != 0xff) || ((syncword[1] & 0xf6) != 0xf0)) { 107 return 0; 108 } 109 110 uint8_t protectionAbsent; 111 if (source->readAt(offset + 1, &protectionAbsent, 1) < 1) { 112 return 0; 113 } 114 protectionAbsent &= 0x1; 115 116 uint8_t header[3]; 117 if (source->readAt(offset + 3, &header, 3) < 3) { 118 return 0; 119 } 120 121 frameSize = (header[0] & 0x3) << 11 | header[1] << 3 | header[2] >> 5; 122 123 // protectionAbsent is 0 if there is CRC 124 size_t headSize = protectionAbsent ? kAdtsHeaderLengthNoCrc : kAdtsHeaderLengthWithCrc; 125 if (headSize > frameSize) { 126 return 0; 127 } 128 if (headerSize != NULL) { 129 *headerSize = headSize; 130 } 131 132 return frameSize; 133} 134 135AACExtractor::AACExtractor( 136 const sp<DataSource> &source, const sp<AMessage> &_meta) 137 : mDataSource(source), 138 mInitCheck(NO_INIT), 139 mFrameDurationUs(0) { 140 sp<AMessage> meta = _meta; 141 142 if (meta == NULL) { 143 String8 mimeType; 144 float confidence; 145 sp<AMessage> _meta; 146 147 if (!SniffAAC(mDataSource, &mimeType, &confidence, &meta)) { 148 return; 149 } 150 } 151 152 int64_t offset; 153 CHECK(meta->findInt64("offset", &offset)); 154 155 uint8_t profile, sf_index, channel, header[2]; 156 if (mDataSource->readAt(offset + 2, &header, 2) < 2) { 157 return; 158 } 159 160 profile = (header[0] >> 6) & 0x3; 161 sf_index = (header[0] >> 2) & 0xf; 162 uint32_t sr = get_sample_rate(sf_index); 163 if (sr == 0) { 164 return; 165 } 166 channel = (header[0] & 0x1) << 2 | (header[1] >> 6); 167 168 mMeta = MakeAACCodecSpecificData(profile, sf_index, channel); 169 170 off64_t streamSize, numFrames = 0; 171 size_t frameSize = 0; 172 int64_t duration = 0; 173 174 if (mDataSource->getSize(&streamSize) == OK) { 175 while (offset < streamSize) { 176 if ((frameSize = getAdtsFrameLength(source, offset, NULL)) == 0) { 177 ALOGW("prematured AAC stream (%lld vs %lld)", 178 (long long)offset, (long long)streamSize); 179 break; 180 } 181 182 mOffsetVector.push(offset); 183 184 offset += frameSize; 185 numFrames ++; 186 } 187 188 // Round up and get the duration 189 mFrameDurationUs = (1024 * 1000000ll + (sr - 1)) / sr; 190 duration = numFrames * mFrameDurationUs; 191 mMeta->setInt64(kKeyDuration, duration); 192 } 193 194 mInitCheck = OK; 195} 196 197AACExtractor::~AACExtractor() { 198} 199 200sp<MetaData> AACExtractor::getMetaData() { 201 sp<MetaData> meta = new MetaData; 202 203 if (mInitCheck != OK) { 204 return meta; 205 } 206 207 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS); 208 209 return meta; 210} 211 212size_t AACExtractor::countTracks() { 213 return mInitCheck == OK ? 1 : 0; 214} 215 216sp<IMediaSource> AACExtractor::getTrack(size_t index) { 217 if (mInitCheck != OK || index != 0) { 218 return NULL; 219 } 220 221 return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs); 222} 223 224sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) { 225 if (mInitCheck != OK || index != 0) { 226 return NULL; 227 } 228 229 return mMeta; 230} 231 232//////////////////////////////////////////////////////////////////////////////// 233 234// 8192 = 2^13, 13bit AAC frame size (in bytes) 235const size_t AACSource::kMaxFrameSize = 8192; 236 237AACSource::AACSource( 238 const sp<DataSource> &source, const sp<MetaData> &meta, 239 const Vector<uint64_t> &offset_vector, 240 int64_t frame_duration_us) 241 : mDataSource(source), 242 mMeta(meta), 243 mOffset(0), 244 mCurrentTimeUs(0), 245 mStarted(false), 246 mGroup(NULL), 247 mOffsetVector(offset_vector), 248 mFrameDurationUs(frame_duration_us) { 249} 250 251AACSource::~AACSource() { 252 if (mStarted) { 253 stop(); 254 } 255} 256 257status_t AACSource::start(MetaData * /* params */) { 258 CHECK(!mStarted); 259 260 if (mOffsetVector.empty()) { 261 mOffset = 0; 262 } else { 263 mOffset = mOffsetVector.itemAt(0); 264 } 265 266 mCurrentTimeUs = 0; 267 mGroup = new MediaBufferGroup; 268 mGroup->add_buffer(new MediaBuffer(kMaxFrameSize)); 269 mStarted = true; 270 271 return OK; 272} 273 274status_t AACSource::stop() { 275 CHECK(mStarted); 276 277 delete mGroup; 278 mGroup = NULL; 279 280 mStarted = false; 281 return OK; 282} 283 284sp<MetaData> AACSource::getFormat() { 285 return mMeta; 286} 287 288status_t AACSource::read( 289 MediaBuffer **out, const ReadOptions *options) { 290 *out = NULL; 291 292 int64_t seekTimeUs; 293 ReadOptions::SeekMode mode; 294 if (options && options->getSeekTo(&seekTimeUs, &mode)) { 295 if (mFrameDurationUs > 0) { 296 int64_t seekFrame = seekTimeUs / mFrameDurationUs; 297 mCurrentTimeUs = seekFrame * mFrameDurationUs; 298 299 mOffset = mOffsetVector.itemAt(seekFrame); 300 } 301 } 302 303 size_t frameSize, frameSizeWithoutHeader, headerSize; 304 if ((frameSize = getAdtsFrameLength(mDataSource, mOffset, &headerSize)) == 0) { 305 return ERROR_END_OF_STREAM; 306 } 307 308 MediaBuffer *buffer; 309 status_t err = mGroup->acquire_buffer(&buffer); 310 if (err != OK) { 311 return err; 312 } 313 314 frameSizeWithoutHeader = frameSize - headerSize; 315 if (mDataSource->readAt(mOffset + headerSize, buffer->data(), 316 frameSizeWithoutHeader) != (ssize_t)frameSizeWithoutHeader) { 317 buffer->release(); 318 buffer = NULL; 319 320 return ERROR_IO; 321 } 322 323 buffer->set_range(0, frameSizeWithoutHeader); 324 buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); 325 buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 326 327 mOffset += frameSize; 328 mCurrentTimeUs += mFrameDurationUs; 329 330 *out = buffer; 331 return OK; 332} 333 334//////////////////////////////////////////////////////////////////////////////// 335 336bool SniffAAC( 337 const sp<DataSource> &source, String8 *mimeType, float *confidence, 338 sp<AMessage> *meta) { 339 off64_t pos = 0; 340 341 for (;;) { 342 uint8_t id3header[10]; 343 if (source->readAt(pos, id3header, sizeof(id3header)) 344 < (ssize_t)sizeof(id3header)) { 345 return false; 346 } 347 348 if (memcmp("ID3", id3header, 3)) { 349 break; 350 } 351 352 // Skip the ID3v2 header. 353 354 size_t len = 355 ((id3header[6] & 0x7f) << 21) 356 | ((id3header[7] & 0x7f) << 14) 357 | ((id3header[8] & 0x7f) << 7) 358 | (id3header[9] & 0x7f); 359 360 len += 10; 361 362 pos += len; 363 364 ALOGV("skipped ID3 tag, new starting offset is %lld (0x%016llx)", 365 (long long)pos, (long long)pos); 366 } 367 368 uint8_t header[2]; 369 370 if (source->readAt(pos, &header, 2) != 2) { 371 return false; 372 } 373 374 // ADTS syncword 375 if ((header[0] == 0xff) && ((header[1] & 0xf6) == 0xf0)) { 376 *mimeType = MEDIA_MIMETYPE_AUDIO_AAC_ADTS; 377 *confidence = 0.2; 378 379 *meta = new AMessage; 380 (*meta)->setInt64("offset", pos); 381 382 return true; 383 } 384 385 return false; 386} 387 388} // namespace android 389