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