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