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