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 #include <fcntl.h> 18 #include <inttypes.h> 19 #include <sys/prctl.h> 20 #include <sys/stat.h> 21 #include <sys/types.h> 22 23 //#define LOG_NDEBUG 0 24 #define LOG_TAG "AACWriter" 25 #include <utils/Log.h> 26 27 #include <media/openmax/OMX_Audio.h> 28 #include <media/stagefright/AACWriter.h> 29 #include <media/stagefright/MediaBuffer.h> 30 #include <media/stagefright/foundation/ADebug.h> 31 #include <media/stagefright/MediaDefs.h> 32 #include <media/stagefright/MediaErrors.h> 33 #include <media/stagefright/MediaSource.h> 34 #include <media/stagefright/MetaData.h> 35 #include <media/mediarecorder.h> 36 37 namespace android { 38 39 AACWriter::AACWriter(int fd) 40 : mFd(dup(fd)), 41 mInitCheck(mFd < 0? NO_INIT: OK), 42 mStarted(false), 43 mPaused(false), 44 mResumed(false), 45 mThread(0), 46 mEstimatedSizeBytes(0), 47 mEstimatedDurationUs(0), 48 mChannelCount(-1), 49 mSampleRate(-1), 50 mAACProfile(OMX_AUDIO_AACObjectLC), 51 mFrameDurationUs(0) { 52 } 53 54 AACWriter::~AACWriter() { 55 if (mStarted) { 56 reset(); 57 } 58 59 if (mFd != -1) { 60 close(mFd); 61 mFd = -1; 62 } 63 } 64 65 status_t AACWriter::initCheck() const { 66 return mInitCheck; 67 } 68 69 70 status_t AACWriter::addSource(const sp<IMediaSource> &source) { 71 if (mInitCheck != OK) { 72 return mInitCheck; 73 } 74 75 if (mSource != NULL) { 76 ALOGE("AAC files only support a single track of audio."); 77 return UNKNOWN_ERROR; 78 } 79 80 sp<MetaData> meta = source->getFormat(); 81 82 const char *mime; 83 CHECK(meta->findCString(kKeyMIMEType, &mime)); 84 85 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)); 86 CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount)); 87 CHECK(meta->findInt32(kKeySampleRate, &mSampleRate)); 88 CHECK(mChannelCount >= 1 && mChannelCount <= 2); 89 90 // Optionally, we want to check whether AACProfile is also set. 91 if (meta->findInt32(kKeyAACProfile, &mAACProfile)) { 92 ALOGI("AAC profile is changed to %d", mAACProfile); 93 } 94 95 mSource = source; 96 return OK; 97 } 98 99 status_t AACWriter::start(MetaData * /* params */) { 100 if (mInitCheck != OK) { 101 return mInitCheck; 102 } 103 104 if (mSource == NULL) { 105 return UNKNOWN_ERROR; 106 } 107 108 if (mStarted && mPaused) { 109 mPaused = false; 110 mResumed = true; 111 return OK; 112 } else if (mStarted) { 113 // Already started, does nothing 114 return OK; 115 } 116 117 mFrameDurationUs = (kSamplesPerFrame * 1000000LL + (mSampleRate >> 1)) 118 / mSampleRate; 119 120 status_t err = mSource->start(); 121 122 if (err != OK) { 123 return err; 124 } 125 126 pthread_attr_t attr; 127 pthread_attr_init(&attr); 128 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 129 130 mReachedEOS = false; 131 mDone = false; 132 133 pthread_create(&mThread, &attr, ThreadWrapper, this); 134 pthread_attr_destroy(&attr); 135 136 mStarted = true; 137 138 return OK; 139 } 140 141 status_t AACWriter::pause() { 142 if (!mStarted) { 143 return OK; 144 } 145 mPaused = true; 146 return OK; 147 } 148 149 status_t AACWriter::reset() { 150 if (!mStarted) { 151 return OK; 152 } 153 154 mDone = true; 155 156 void *dummy; 157 pthread_join(mThread, &dummy); 158 159 status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 160 { 161 status_t status = mSource->stop(); 162 if (err == OK && 163 (status != OK && status != ERROR_END_OF_STREAM)) { 164 err = status; 165 } 166 } 167 168 mStarted = false; 169 return err; 170 } 171 172 bool AACWriter::exceedsFileSizeLimit() { 173 if (mMaxFileSizeLimitBytes == 0) { 174 return false; 175 } 176 return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes; 177 } 178 179 bool AACWriter::exceedsFileDurationLimit() { 180 if (mMaxFileDurationLimitUs == 0) { 181 return false; 182 } 183 return mEstimatedDurationUs >= mMaxFileDurationLimitUs; 184 } 185 186 // static 187 void *AACWriter::ThreadWrapper(void *me) { 188 return (void *)(uintptr_t)static_cast<AACWriter *>(me)->threadFunc(); 189 } 190 191 /* 192 * Returns an index into the sample rate table if the 193 * given sample rate is found; otherwise, returns -1. 194 */ 195 static bool getSampleRateTableIndex(int sampleRate, uint8_t* tableIndex) { 196 static const int kSampleRateTable[] = { 197 96000, 88200, 64000, 48000, 44100, 32000, 198 24000, 22050, 16000, 12000, 11025, 8000 199 }; 200 const int tableSize = 201 sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]); 202 203 *tableIndex = 0; 204 for (int index = 0; index < tableSize; ++index) { 205 if (sampleRate == kSampleRateTable[index]) { 206 ALOGV("Sample rate: %d and index: %d", 207 sampleRate, index); 208 *tableIndex = index; 209 return true; 210 } 211 } 212 213 ALOGE("Sampling rate %d bps is not supported", sampleRate); 214 return false; 215 } 216 217 /* 218 * ADTS (Audio data transport stream) header structure. 219 * It consists of 7 or 9 bytes (with or without CRC): 220 * 12 bits of syncword 0xFFF, all bits must be 1 221 * 1 bit of field ID. 0 for MPEG-4, and 1 for MPEG-2 222 * 2 bits of MPEG layer. If in MPEG-TS, set to 0 223 * 1 bit of protection absense. Set to 1 if no CRC. 224 * 2 bits of profile code. Set to 1 (The MPEG-4 Audio 225 * object type minus 1. We are using AAC-LC = 2) 226 * 4 bits of sampling frequency index code (15 is not allowed) 227 * 1 bit of private stream. Set to 0. 228 * 3 bits of channel configuration code. 0 resevered for inband PCM 229 * 1 bit of originality. Set to 0. 230 * 1 bit of home. Set to 0. 231 * 1 bit of copyrighted steam. Set to 0. 232 * 1 bit of copyright start. Set to 0. 233 * 13 bits of frame length. It included 7 ot 9 bytes header length. 234 * it is set to (protection absense? 7: 9) + size(AAC frame) 235 * 11 bits of buffer fullness. 0x7FF for VBR. 236 * 2 bits of frames count in one packet. Set to 0. 237 */ 238 status_t AACWriter::writeAdtsHeader(uint32_t frameLength) { 239 uint8_t data = 0xFF; 240 write(mFd, &data, 1); 241 242 const uint8_t kFieldId = 0; 243 const uint8_t kMpegLayer = 0; 244 const uint8_t kProtectionAbsense = 1; // 1: kAdtsHeaderLength = 7 245 data = 0xF0; 246 data |= (kFieldId << 3); 247 data |= (kMpegLayer << 1); 248 data |= kProtectionAbsense; 249 write(mFd, &data, 1); 250 251 const uint8_t kProfileCode = mAACProfile - 1; 252 uint8_t kSampleFreqIndex; 253 CHECK(getSampleRateTableIndex(mSampleRate, &kSampleFreqIndex)); 254 const uint8_t kPrivateStream = 0; 255 const uint8_t kChannelConfigCode = mChannelCount; 256 data = (kProfileCode << 6); 257 data |= (kSampleFreqIndex << 2); 258 data |= (kPrivateStream << 1); 259 data |= (kChannelConfigCode >> 2); 260 write(mFd, &data, 1); 261 262 // 4 bits from originality to copyright start 263 const uint8_t kCopyright = 0; 264 const uint32_t kFrameLength = frameLength; 265 data = ((kChannelConfigCode & 3) << 6); 266 data |= (kCopyright << 2); 267 data |= ((kFrameLength & 0x1800) >> 11); 268 write(mFd, &data, 1); 269 270 data = ((kFrameLength & 0x07F8) >> 3); 271 write(mFd, &data, 1); 272 273 const uint32_t kBufferFullness = 0x7FF; // VBR 274 data = ((kFrameLength & 0x07) << 5); 275 data |= ((kBufferFullness & 0x07C0) >> 6); 276 write(mFd, &data, 1); 277 278 const uint8_t kFrameCount = 0; 279 data = ((kBufferFullness & 0x03F) << 2); 280 data |= kFrameCount; 281 write(mFd, &data, 1); 282 283 return OK; 284 } 285 286 status_t AACWriter::threadFunc() { 287 mEstimatedDurationUs = 0; 288 mEstimatedSizeBytes = 0; 289 int64_t previousPausedDurationUs = 0; 290 int64_t maxTimestampUs = 0; 291 status_t err = OK; 292 bool stoppedPrematurely = true; 293 294 prctl(PR_SET_NAME, (unsigned long)"AACWriterThread", 0, 0, 0); 295 296 while (!mDone && err == OK) { 297 MediaBuffer *buffer; 298 err = mSource->read(&buffer); 299 300 if (err != OK) { 301 break; 302 } 303 304 if (mPaused) { 305 buffer->release(); 306 buffer = NULL; 307 continue; 308 } 309 310 mEstimatedSizeBytes += kAdtsHeaderLength + buffer->range_length(); 311 if (exceedsFileSizeLimit()) { 312 buffer->release(); 313 buffer = NULL; 314 notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 315 break; 316 } 317 318 int32_t isCodecSpecific = 0; 319 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecSpecific) && isCodecSpecific) { 320 ALOGV("Drop codec specific info buffer"); 321 buffer->release(); 322 buffer = NULL; 323 continue; 324 } 325 326 int64_t timestampUs; 327 CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 328 if (timestampUs > mEstimatedDurationUs) { 329 mEstimatedDurationUs = timestampUs; 330 } 331 if (mResumed) { 332 previousPausedDurationUs += (timestampUs - maxTimestampUs - mFrameDurationUs); 333 mResumed = false; 334 } 335 timestampUs -= previousPausedDurationUs; 336 ALOGV("time stamp: %" PRId64 ", previous paused duration: %" PRId64, 337 timestampUs, previousPausedDurationUs); 338 if (timestampUs > maxTimestampUs) { 339 maxTimestampUs = timestampUs; 340 } 341 342 if (exceedsFileDurationLimit()) { 343 buffer->release(); 344 buffer = NULL; 345 notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 346 break; 347 } 348 349 // Each output AAC audio frame to the file contains 350 // 1. an ADTS header, followed by 351 // 2. the compressed audio data. 352 ssize_t dataLength = buffer->range_length(); 353 uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset(); 354 if (writeAdtsHeader(kAdtsHeaderLength + dataLength) != OK || 355 dataLength != write(mFd, data, dataLength)) { 356 err = ERROR_IO; 357 } 358 359 buffer->release(); 360 buffer = NULL; 361 362 if (err != OK) { 363 break; 364 } 365 366 if (stoppedPrematurely) { 367 stoppedPrematurely = false; 368 } 369 } 370 371 if ((err == OK || err == ERROR_END_OF_STREAM) && stoppedPrematurely) { 372 err = ERROR_MALFORMED; 373 } 374 375 close(mFd); 376 mFd = -1; 377 mReachedEOS = true; 378 if (err == ERROR_END_OF_STREAM) { 379 return OK; 380 } 381 return err; 382 } 383 384 bool AACWriter::reachedEOS() { 385 return mReachedEOS; 386 } 387 388 } // namespace android 389