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