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