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