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