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