107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber/*
207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * Copyright (C) 2010 The Android Open Source Project
307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *
407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * you may not use this file except in compliance with the License.
607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * You may obtain a copy of the License at
707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *
807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *
1007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * Unless required by applicable law or agreed to in writing, software
1107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * See the License for the specific language governing permissions and
1407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * limitations under the License.
1507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber */
1607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
1707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/AMRWriter.h>
1807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
1907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaBuffer.h>
2007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaDebug.h>
2107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaDefs.h>
2207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaErrors.h>
2307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaSource.h>
2407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MetaData.h>
2507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
2607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Hubernamespace android {
2707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
2807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas HuberAMRWriter::AMRWriter(const char *filename)
2907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    : mFile(fopen(filename, "wb")),
3007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber      mInitCheck(mFile != NULL ? OK : NO_INIT),
3107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber      mStarted(false) {
3207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
3307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
3407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas HuberAMRWriter::AMRWriter(int fd)
3507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    : mFile(fdopen(fd, "wb")),
3607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber      mInitCheck(mFile != NULL ? OK : NO_INIT),
3707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber      mStarted(false) {
3807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
3907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
4007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas HuberAMRWriter::~AMRWriter() {
4107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mStarted) {
4207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        stop();
4307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
4407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
4507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mFile != NULL) {
4607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        fclose(mFile);
4707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mFile = NULL;
4807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
4907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
5007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
5107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AMRWriter::initCheck() const {
5207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return mInitCheck;
5307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
5407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
5507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AMRWriter::addSource(const sp<MediaSource> &source) {
5607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    Mutex::Autolock autoLock(mLock);
5707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
5807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mInitCheck != OK) {
5907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return mInitCheck;
6007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
6107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
6207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mSource != NULL) {
6307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        // AMR files only support a single track of audio.
6407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return UNKNOWN_ERROR;
6507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
6607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
6707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    sp<MetaData> meta = source->getFormat();
6807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
6907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    const char *mime;
7007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    CHECK(meta->findCString(kKeyMIMEType, &mime));
7107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
7207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    bool isWide = false;
7307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
7407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        isWide = true;
7507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
7607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return ERROR_UNSUPPORTED;
7707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
7807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
7907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    int32_t channelCount;
8007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    int32_t sampleRate;
8107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
8207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    CHECK_EQ(channelCount, 1);
8307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
8407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    CHECK_EQ(sampleRate, (isWide ? 16000 : 8000));
8507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
8607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mSource = source;
8707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
8807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    const char *kHeader = isWide ? "#!AMR-WB\n" : "#!AMR\n";
8907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    size_t n = strlen(kHeader);
9007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (fwrite(kHeader, 1, n, mFile) != n) {
9107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return ERROR_IO;
9207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
9307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
9407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return OK;
9507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
9607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
9707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AMRWriter::start() {
9807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    Mutex::Autolock autoLock(mLock);
9907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mInitCheck != OK) {
10107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return mInitCheck;
10207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
10307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mStarted || mSource == NULL) {
10507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return UNKNOWN_ERROR;
10607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
10707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    status_t err = mSource->start();
10907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
11007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (err != OK) {
11107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return err;
11207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
11307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
11407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    pthread_attr_t attr;
11507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    pthread_attr_init(&attr);
11607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
11707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
118996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    mReachedEOS = false;
11907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mDone = false;
12007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
12107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
12207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    pthread_attr_destroy(&attr);
12307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
12407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mStarted = true;
12507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
12607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return OK;
12707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
12807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
12907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Hubervoid AMRWriter::stop() {
13007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    {
13107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        Mutex::Autolock autoLock(mLock);
13207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
13307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        if (!mStarted) {
13407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber            return;
13507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        }
13607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
13707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mDone = true;
13807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
13907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
14007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    void *dummy;
14107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    pthread_join(mThread, &dummy);
14207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
14307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mSource->stop();
14407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
14507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mStarted = false;
14607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
14707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
14807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber// static
14907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Hubervoid *AMRWriter::ThreadWrapper(void *me) {
15007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    static_cast<AMRWriter *>(me)->threadFunc();
15107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
15207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return NULL;
15307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
15407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
15507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Hubervoid AMRWriter::threadFunc() {
15607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    for (;;) {
15707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        Mutex::Autolock autoLock(mLock);
15807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
15907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        if (mDone) {
16007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber            break;
16107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        }
16207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
16307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        MediaBuffer *buffer;
16407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        status_t err = mSource->read(&buffer);
16507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
16607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        if (err != OK) {
16707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber            break;
16807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        }
16907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
17007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        ssize_t n = fwrite(
17107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset(),
17207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber                1,
17307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber                buffer->range_length(),
17407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber                mFile);
17507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
17607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        if (n < (ssize_t)buffer->range_length()) {
177259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber            buffer->release();
178259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber            buffer = NULL;
179259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber
18007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber            break;
18107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        }
182259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber
183259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber        buffer->release();
184259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber        buffer = NULL;
18507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
186996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
187996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    Mutex::Autolock autoLock(mLock);
188996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    mReachedEOS = true;
189996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber}
190996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
191996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huberbool AMRWriter::reachedEOS() {
192996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    Mutex::Autolock autoLock(mLock);
193996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    return mReachedEOS;
19407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
19507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
19607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}  // namespace android
197