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