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, &timestampUs));
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