1760943b5e7a09b602aba04ec451e97662f48b0a4James Dong/* 2760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * Copyright (C) 2011 The Android Open Source Project 3760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 4760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * Licensed under the Apache License, Version 2.0 (the "License"); 5760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * you may not use this file except in compliance with the License. 6760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * You may obtain a copy of the License at 7760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 8760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * http://www.apache.org/licenses/LICENSE-2.0 9760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 10760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * Unless required by applicable law or agreed to in writing, software 11760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * distributed under the License is distributed on an "AS IS" BASIS, 12760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * See the License for the specific language governing permissions and 14760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * limitations under the License. 15760943b5e7a09b602aba04ec451e97662f48b0a4James Dong */ 16760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 17a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h> 18a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h> 19a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/prctl.h> 20a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h> 21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h> 22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 23760943b5e7a09b602aba04ec451e97662f48b0a4James Dong//#define LOG_NDEBUG 0 24760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#define LOG_TAG "AACWriter" 25760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <utils/Log.h> 26760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 27aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/openmax/OMX_Audio.h> 28760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/AACWriter.h> 29760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/MediaBuffer.h> 30760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/foundation/ADebug.h> 31760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/MediaDefs.h> 32760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/MediaErrors.h> 33760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/MediaSource.h> 34760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/MetaData.h> 35760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/mediarecorder.h> 36760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 37760943b5e7a09b602aba04ec451e97662f48b0a4James Dongnamespace android { 38760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 39760943b5e7a09b602aba04ec451e97662f48b0a4James DongAACWriter::AACWriter(const char *filename) 40760943b5e7a09b602aba04ec451e97662f48b0a4James Dong : mFd(-1), 41760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mInitCheck(NO_INIT), 42760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mStarted(false), 43760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mPaused(false), 44760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mResumed(false), 45760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mChannelCount(-1), 46aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke mSampleRate(-1), 47aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke mAACProfile(OMX_AUDIO_AACObjectLC) { 48760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("AACWriter Constructor"); 50760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 51af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); 52760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mFd >= 0) { 53760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mInitCheck = OK; 54760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 55760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 56760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 57760943b5e7a09b602aba04ec451e97662f48b0a4James DongAACWriter::AACWriter(int fd) 58760943b5e7a09b602aba04ec451e97662f48b0a4James Dong : mFd(dup(fd)), 59760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mInitCheck(mFd < 0? NO_INIT: OK), 60760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mStarted(false), 61760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mPaused(false), 62760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mResumed(false), 63760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mChannelCount(-1), 649fa3db9a8c164daaf0d7334595dbd0ca24fe97bfMarco Nelissen mSampleRate(-1), 659fa3db9a8c164daaf0d7334595dbd0ca24fe97bfMarco Nelissen mAACProfile(OMX_AUDIO_AACObjectLC) { 66760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 67760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 68760943b5e7a09b602aba04ec451e97662f48b0a4James DongAACWriter::~AACWriter() { 69760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mStarted) { 708bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 71760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 72760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 73760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mFd != -1) { 74760943b5e7a09b602aba04ec451e97662f48b0a4James Dong close(mFd); 75760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mFd = -1; 76760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 77760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 78760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 79760943b5e7a09b602aba04ec451e97662f48b0a4James Dongstatus_t AACWriter::initCheck() const { 80760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return mInitCheck; 81760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 82760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 83760943b5e7a09b602aba04ec451e97662f48b0a4James Dongstatic int writeInt8(int fd, uint8_t x) { 84760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return ::write(fd, &x, 1); 85760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 86760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 87760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 88760943b5e7a09b602aba04ec451e97662f48b0a4James Dongstatus_t AACWriter::addSource(const sp<MediaSource> &source) { 89760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mInitCheck != OK) { 90760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return mInitCheck; 91760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 92760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 93760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mSource != NULL) { 9429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("AAC files only support a single track of audio."); 95760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return UNKNOWN_ERROR; 96760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 97760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 98760943b5e7a09b602aba04ec451e97662f48b0a4James Dong sp<MetaData> meta = source->getFormat(); 99760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 100760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const char *mime; 101760943b5e7a09b602aba04ec451e97662f48b0a4James Dong CHECK(meta->findCString(kKeyMIMEType, &mime)); 102760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 103760943b5e7a09b602aba04ec451e97662f48b0a4James Dong CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)); 104760943b5e7a09b602aba04ec451e97662f48b0a4James Dong CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount)); 105760943b5e7a09b602aba04ec451e97662f48b0a4James Dong CHECK(meta->findInt32(kKeySampleRate, &mSampleRate)); 106760943b5e7a09b602aba04ec451e97662f48b0a4James Dong CHECK(mChannelCount >= 1 && mChannelCount <= 2); 107760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 1082d94235a343151bed9aa74e86697fa01241ea5cfJames Dong // Optionally, we want to check whether AACProfile is also set. 1092d94235a343151bed9aa74e86697fa01241ea5cfJames Dong if (meta->findInt32(kKeyAACProfile, &mAACProfile)) { 1102d94235a343151bed9aa74e86697fa01241ea5cfJames Dong ALOGI("AAC profile is changed to %d", mAACProfile); 1112d94235a343151bed9aa74e86697fa01241ea5cfJames Dong } 1122d94235a343151bed9aa74e86697fa01241ea5cfJames Dong 113760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mSource = source; 114760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 115760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 116760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 11784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t AACWriter::start(MetaData * /* params */) { 118760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mInitCheck != OK) { 119760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return mInitCheck; 120760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 121760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 122760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mSource == NULL) { 123760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return UNKNOWN_ERROR; 124760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 125760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 126760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mStarted && mPaused) { 127760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mPaused = false; 128760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mResumed = true; 129760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 130760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } else if (mStarted) { 131760943b5e7a09b602aba04ec451e97662f48b0a4James Dong // Already started, does nothing 132760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 133760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 134760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 135760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mFrameDurationUs = (kSamplesPerFrame * 1000000LL + (mSampleRate >> 1)) 136760943b5e7a09b602aba04ec451e97662f48b0a4James Dong / mSampleRate; 137760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 138760943b5e7a09b602aba04ec451e97662f48b0a4James Dong status_t err = mSource->start(); 139760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 140760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (err != OK) { 141760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return err; 142760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 143760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 144760943b5e7a09b602aba04ec451e97662f48b0a4James Dong pthread_attr_t attr; 145760943b5e7a09b602aba04ec451e97662f48b0a4James Dong pthread_attr_init(&attr); 146760943b5e7a09b602aba04ec451e97662f48b0a4James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 147760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 148760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mReachedEOS = false; 149760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mDone = false; 150760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 151760943b5e7a09b602aba04ec451e97662f48b0a4James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 152760943b5e7a09b602aba04ec451e97662f48b0a4James Dong pthread_attr_destroy(&attr); 153760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 154760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mStarted = true; 155760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 156760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 157760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 158760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 159760943b5e7a09b602aba04ec451e97662f48b0a4James Dongstatus_t AACWriter::pause() { 160760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (!mStarted) { 161760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 162760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 163760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mPaused = true; 164760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 165760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 166760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 1678bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t AACWriter::reset() { 168760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (!mStarted) { 169760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 170760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 171760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 172760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mDone = true; 173760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 174760943b5e7a09b602aba04ec451e97662f48b0a4James Dong void *dummy; 175760943b5e7a09b602aba04ec451e97662f48b0a4James Dong pthread_join(mThread, &dummy); 176760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 177377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 178760943b5e7a09b602aba04ec451e97662f48b0a4James Dong { 179760943b5e7a09b602aba04ec451e97662f48b0a4James Dong status_t status = mSource->stop(); 180760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (err == OK && 181760943b5e7a09b602aba04ec451e97662f48b0a4James Dong (status != OK && status != ERROR_END_OF_STREAM)) { 182760943b5e7a09b602aba04ec451e97662f48b0a4James Dong err = status; 183760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 184760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 185760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 186760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mStarted = false; 187760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return err; 188760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 189760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 190760943b5e7a09b602aba04ec451e97662f48b0a4James Dongbool AACWriter::exceedsFileSizeLimit() { 191760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mMaxFileSizeLimitBytes == 0) { 192760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return false; 193760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 194760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes; 195760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 196760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 197760943b5e7a09b602aba04ec451e97662f48b0a4James Dongbool AACWriter::exceedsFileDurationLimit() { 198760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mMaxFileDurationLimitUs == 0) { 199760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return false; 200760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 201760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return mEstimatedDurationUs >= mMaxFileDurationLimitUs; 202760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 203760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 204760943b5e7a09b602aba04ec451e97662f48b0a4James Dong// static 205760943b5e7a09b602aba04ec451e97662f48b0a4James Dongvoid *AACWriter::ThreadWrapper(void *me) { 206377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)static_cast<AACWriter *>(me)->threadFunc(); 207760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 208760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 209760943b5e7a09b602aba04ec451e97662f48b0a4James Dong/* 210760943b5e7a09b602aba04ec451e97662f48b0a4James Dong* Returns an index into the sample rate table if the 211760943b5e7a09b602aba04ec451e97662f48b0a4James Dong* given sample rate is found; otherwise, returns -1. 212760943b5e7a09b602aba04ec451e97662f48b0a4James Dong*/ 213760943b5e7a09b602aba04ec451e97662f48b0a4James Dongstatic bool getSampleRateTableIndex(int sampleRate, uint8_t* tableIndex) { 214760943b5e7a09b602aba04ec451e97662f48b0a4James Dong static const int kSampleRateTable[] = { 215760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 96000, 88200, 64000, 48000, 44100, 32000, 216760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 24000, 22050, 16000, 12000, 11025, 8000 217760943b5e7a09b602aba04ec451e97662f48b0a4James Dong }; 218760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const int tableSize = 219760943b5e7a09b602aba04ec451e97662f48b0a4James Dong sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]); 220760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 221760943b5e7a09b602aba04ec451e97662f48b0a4James Dong *tableIndex = 0; 222760943b5e7a09b602aba04ec451e97662f48b0a4James Dong for (int index = 0; index < tableSize; ++index) { 223760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (sampleRate == kSampleRateTable[index]) { 2243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Sample rate: %d and index: %d", 225760943b5e7a09b602aba04ec451e97662f48b0a4James Dong sampleRate, index); 226760943b5e7a09b602aba04ec451e97662f48b0a4James Dong *tableIndex = index; 227760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return true; 228760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 229760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 230760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 23129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sampling rate %d bps is not supported", sampleRate); 232760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return false; 233760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 234760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 235760943b5e7a09b602aba04ec451e97662f48b0a4James Dong/* 236760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * ADTS (Audio data transport stream) header structure. 237760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * It consists of 7 or 9 bytes (with or without CRC): 238760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 12 bits of syncword 0xFFF, all bits must be 1 239760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 1 bit of field ID. 0 for MPEG-4, and 1 for MPEG-2 240760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 2 bits of MPEG layer. If in MPEG-TS, set to 0 241760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 1 bit of protection absense. Set to 1 if no CRC. 242760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 2 bits of profile code. Set to 1 (The MPEG-4 Audio 243760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * object type minus 1. We are using AAC-LC = 2) 244760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 4 bits of sampling frequency index code (15 is not allowed) 245760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 1 bit of private stream. Set to 0. 246760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 3 bits of channel configuration code. 0 resevered for inband PCM 247760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 1 bit of originality. Set to 0. 248760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 1 bit of home. Set to 0. 249760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 1 bit of copyrighted steam. Set to 0. 250760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 1 bit of copyright start. Set to 0. 251760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 13 bits of frame length. It included 7 ot 9 bytes header length. 252760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * it is set to (protection absense? 7: 9) + size(AAC frame) 253760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 11 bits of buffer fullness. 0x7FF for VBR. 254760943b5e7a09b602aba04ec451e97662f48b0a4James Dong * 2 bits of frames count in one packet. Set to 0. 255760943b5e7a09b602aba04ec451e97662f48b0a4James Dong */ 256760943b5e7a09b602aba04ec451e97662f48b0a4James Dongstatus_t AACWriter::writeAdtsHeader(uint32_t frameLength) { 257760943b5e7a09b602aba04ec451e97662f48b0a4James Dong uint8_t data = 0xFF; 258760943b5e7a09b602aba04ec451e97662f48b0a4James Dong write(mFd, &data, 1); 259760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 260760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint8_t kFieldId = 0; 261760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint8_t kMpegLayer = 0; 262760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint8_t kProtectionAbsense = 1; // 1: kAdtsHeaderLength = 7 263760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data = 0xF0; 264760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= (kFieldId << 3); 265760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= (kMpegLayer << 1); 266760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= kProtectionAbsense; 267760943b5e7a09b602aba04ec451e97662f48b0a4James Dong write(mFd, &data, 1); 268760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 269aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke const uint8_t kProfileCode = mAACProfile - 1; 270760943b5e7a09b602aba04ec451e97662f48b0a4James Dong uint8_t kSampleFreqIndex; 271760943b5e7a09b602aba04ec451e97662f48b0a4James Dong CHECK(getSampleRateTableIndex(mSampleRate, &kSampleFreqIndex)); 272760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint8_t kPrivateStream = 0; 273760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint8_t kChannelConfigCode = mChannelCount; 274760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data = (kProfileCode << 6); 275760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= (kSampleFreqIndex << 2); 276760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= (kPrivateStream << 1); 277760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= (kChannelConfigCode >> 2); 278760943b5e7a09b602aba04ec451e97662f48b0a4James Dong write(mFd, &data, 1); 279760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 280760943b5e7a09b602aba04ec451e97662f48b0a4James Dong // 4 bits from originality to copyright start 281760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint8_t kCopyright = 0; 282760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint32_t kFrameLength = frameLength; 283760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data = ((kChannelConfigCode & 3) << 6); 284760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= (kCopyright << 2); 285760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= ((kFrameLength & 0x1800) >> 11); 286760943b5e7a09b602aba04ec451e97662f48b0a4James Dong write(mFd, &data, 1); 287760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 288760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data = ((kFrameLength & 0x07F8) >> 3); 289760943b5e7a09b602aba04ec451e97662f48b0a4James Dong write(mFd, &data, 1); 290760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 291760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint32_t kBufferFullness = 0x7FF; // VBR 292760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data = ((kFrameLength & 0x07) << 5); 293760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= ((kBufferFullness & 0x07C0) >> 6); 294760943b5e7a09b602aba04ec451e97662f48b0a4James Dong write(mFd, &data, 1); 295760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 296760943b5e7a09b602aba04ec451e97662f48b0a4James Dong const uint8_t kFrameCount = 0; 297760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data = ((kBufferFullness & 0x03F) << 2); 298760943b5e7a09b602aba04ec451e97662f48b0a4James Dong data |= kFrameCount; 299760943b5e7a09b602aba04ec451e97662f48b0a4James Dong write(mFd, &data, 1); 300760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 301760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 302760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 303760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 304760943b5e7a09b602aba04ec451e97662f48b0a4James Dongstatus_t AACWriter::threadFunc() { 305760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mEstimatedDurationUs = 0; 306760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mEstimatedSizeBytes = 0; 307760943b5e7a09b602aba04ec451e97662f48b0a4James Dong int64_t previousPausedDurationUs = 0; 308760943b5e7a09b602aba04ec451e97662f48b0a4James Dong int64_t maxTimestampUs = 0; 309760943b5e7a09b602aba04ec451e97662f48b0a4James Dong status_t err = OK; 310fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong bool stoppedPrematurely = true; 311760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 312760943b5e7a09b602aba04ec451e97662f48b0a4James Dong prctl(PR_SET_NAME, (unsigned long)"AACWriterThread", 0, 0, 0); 313760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 314760943b5e7a09b602aba04ec451e97662f48b0a4James Dong while (!mDone && err == OK) { 315760943b5e7a09b602aba04ec451e97662f48b0a4James Dong MediaBuffer *buffer; 316760943b5e7a09b602aba04ec451e97662f48b0a4James Dong err = mSource->read(&buffer); 317760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 318760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (err != OK) { 319760943b5e7a09b602aba04ec451e97662f48b0a4James Dong break; 320760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 321760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 322760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mPaused) { 323760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer->release(); 324760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer = NULL; 325760943b5e7a09b602aba04ec451e97662f48b0a4James Dong continue; 326760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 327760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 328760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mEstimatedSizeBytes += kAdtsHeaderLength + buffer->range_length(); 329760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (exceedsFileSizeLimit()) { 330760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer->release(); 331760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer = NULL; 332760943b5e7a09b602aba04ec451e97662f48b0a4James Dong notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 333760943b5e7a09b602aba04ec451e97662f48b0a4James Dong break; 334760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 335760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 336760943b5e7a09b602aba04ec451e97662f48b0a4James Dong int32_t isCodecSpecific = 0; 337760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecSpecific) && isCodecSpecific) { 3383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Drop codec specific info buffer"); 339760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer->release(); 340760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer = NULL; 341760943b5e7a09b602aba04ec451e97662f48b0a4James Dong continue; 342760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 343760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 344760943b5e7a09b602aba04ec451e97662f48b0a4James Dong int64_t timestampUs; 345760943b5e7a09b602aba04ec451e97662f48b0a4James Dong CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 346760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (timestampUs > mEstimatedDurationUs) { 347760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mEstimatedDurationUs = timestampUs; 348760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 349760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (mResumed) { 350760943b5e7a09b602aba04ec451e97662f48b0a4James Dong previousPausedDurationUs += (timestampUs - maxTimestampUs - mFrameDurationUs); 351760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mResumed = false; 352760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 353760943b5e7a09b602aba04ec451e97662f48b0a4James Dong timestampUs -= previousPausedDurationUs; 354a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("time stamp: %" PRId64 ", previous paused duration: %" PRId64, 355760943b5e7a09b602aba04ec451e97662f48b0a4James Dong timestampUs, previousPausedDurationUs); 356760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (timestampUs > maxTimestampUs) { 357760943b5e7a09b602aba04ec451e97662f48b0a4James Dong maxTimestampUs = timestampUs; 358760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 359760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 360760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (exceedsFileDurationLimit()) { 361760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer->release(); 362760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer = NULL; 363760943b5e7a09b602aba04ec451e97662f48b0a4James Dong notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 364760943b5e7a09b602aba04ec451e97662f48b0a4James Dong break; 365760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 366760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 367760943b5e7a09b602aba04ec451e97662f48b0a4James Dong // Each output AAC audio frame to the file contains 368760943b5e7a09b602aba04ec451e97662f48b0a4James Dong // 1. an ADTS header, followed by 369760943b5e7a09b602aba04ec451e97662f48b0a4James Dong // 2. the compressed audio data. 370760943b5e7a09b602aba04ec451e97662f48b0a4James Dong ssize_t dataLength = buffer->range_length(); 371760943b5e7a09b602aba04ec451e97662f48b0a4James Dong uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset(); 372760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (writeAdtsHeader(kAdtsHeaderLength + dataLength) != OK || 373760943b5e7a09b602aba04ec451e97662f48b0a4James Dong dataLength != write(mFd, data, dataLength)) { 374760943b5e7a09b602aba04ec451e97662f48b0a4James Dong err = ERROR_IO; 375760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 376760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 377760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer->release(); 378760943b5e7a09b602aba04ec451e97662f48b0a4James Dong buffer = NULL; 379fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong 380fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong if (err != OK) { 381fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong break; 382fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong } 383fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong 384fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong if (stoppedPrematurely) { 385fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong stoppedPrematurely = false; 386fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong } 387fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong } 388fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong 389fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong if ((err == OK || err == ERROR_END_OF_STREAM) && stoppedPrematurely) { 390fa514f007bd144eb99cdd68f2fe5302a4508db28James Dong err = ERROR_MALFORMED; 391760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 392760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 393760943b5e7a09b602aba04ec451e97662f48b0a4James Dong close(mFd); 394760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mFd = -1; 395760943b5e7a09b602aba04ec451e97662f48b0a4James Dong mReachedEOS = true; 396760943b5e7a09b602aba04ec451e97662f48b0a4James Dong if (err == ERROR_END_OF_STREAM) { 397760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return OK; 398760943b5e7a09b602aba04ec451e97662f48b0a4James Dong } 399760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return err; 400760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 401760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 402760943b5e7a09b602aba04ec451e97662f48b0a4James Dongbool AACWriter::reachedEOS() { 403760943b5e7a09b602aba04ec451e97662f48b0a4James Dong return mReachedEOS; 404760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} 405760943b5e7a09b602aba04ec451e97662f48b0a4James Dong 406760943b5e7a09b602aba04ec451e97662f48b0a4James Dong} // namespace android 407