Home | History | Annotate | Download | only in dec
      1 /*
      2  * Copyright (C) 2009 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 "AMRNBDecoder.h"
     18 
     19 #include "gsmamr_dec.h"
     20 
     21 #include <media/stagefright/MediaBufferGroup.h>
     22 #include <media/stagefright/MediaDebug.h>
     23 #include <media/stagefright/MediaDefs.h>
     24 #include <media/stagefright/MediaErrors.h>
     25 #include <media/stagefright/MetaData.h>
     26 
     27 namespace android {
     28 
     29 static const int32_t kNumSamplesPerFrame = 160;
     30 static const int32_t kSampleRate = 8000;
     31 
     32 AMRNBDecoder::AMRNBDecoder(const sp<MediaSource> &source)
     33     : mSource(source),
     34       mStarted(false),
     35       mBufferGroup(NULL),
     36       mState(NULL),
     37       mAnchorTimeUs(0),
     38       mNumSamplesOutput(0),
     39       mInputBuffer(NULL) {
     40 }
     41 
     42 AMRNBDecoder::~AMRNBDecoder() {
     43     if (mStarted) {
     44         stop();
     45     }
     46 }
     47 
     48 status_t AMRNBDecoder::start(MetaData *params) {
     49     CHECK(!mStarted);
     50 
     51     mBufferGroup = new MediaBufferGroup;
     52     mBufferGroup->add_buffer(
     53             new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t)));
     54 
     55     CHECK_EQ(GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder"), 0);
     56 
     57     mSource->start();
     58 
     59     mAnchorTimeUs = 0;
     60     mNumSamplesOutput = 0;
     61     mStarted = true;
     62 
     63     return OK;
     64 }
     65 
     66 status_t AMRNBDecoder::stop() {
     67     CHECK(mStarted);
     68 
     69     if (mInputBuffer) {
     70         mInputBuffer->release();
     71         mInputBuffer = NULL;
     72     }
     73 
     74     delete mBufferGroup;
     75     mBufferGroup = NULL;
     76 
     77     GSMDecodeFrameExit(&mState);
     78 
     79     mSource->stop();
     80 
     81     mStarted = false;
     82 
     83     return OK;
     84 }
     85 
     86 sp<MetaData> AMRNBDecoder::getFormat() {
     87     sp<MetaData> srcFormat = mSource->getFormat();
     88 
     89     int32_t numChannels;
     90     int32_t sampleRate;
     91 
     92     CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
     93     CHECK_EQ(numChannels, 1);
     94 
     95     CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
     96     CHECK_EQ(sampleRate, kSampleRate);
     97 
     98     sp<MetaData> meta = new MetaData;
     99     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
    100     meta->setInt32(kKeyChannelCount, numChannels);
    101     meta->setInt32(kKeySampleRate, sampleRate);
    102 
    103     int64_t durationUs;
    104     if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
    105         meta->setInt64(kKeyDuration, durationUs);
    106     }
    107 
    108     meta->setCString(kKeyDecoderComponent, "AMRNBDecoder");
    109 
    110     return meta;
    111 }
    112 
    113 status_t AMRNBDecoder::read(
    114         MediaBuffer **out, const ReadOptions *options) {
    115     status_t err;
    116 
    117     *out = NULL;
    118 
    119     int64_t seekTimeUs;
    120     if (options && options->getSeekTo(&seekTimeUs)) {
    121         CHECK(seekTimeUs >= 0);
    122 
    123         mNumSamplesOutput = 0;
    124 
    125         if (mInputBuffer) {
    126             mInputBuffer->release();
    127             mInputBuffer = NULL;
    128         }
    129     } else {
    130         seekTimeUs = -1;
    131     }
    132 
    133     if (mInputBuffer == NULL) {
    134         err = mSource->read(&mInputBuffer, options);
    135 
    136         if (err != OK) {
    137             return err;
    138         }
    139 
    140         int64_t timeUs;
    141         if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
    142             mAnchorTimeUs = timeUs;
    143             mNumSamplesOutput = 0;
    144         } else {
    145             // We must have a new timestamp after seeking.
    146             CHECK(seekTimeUs < 0);
    147         }
    148     }
    149 
    150     MediaBuffer *buffer;
    151     CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
    152 
    153     const uint8_t *inputPtr =
    154         (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
    155 
    156     size_t numBytesRead =
    157         AMRDecode(mState,
    158           (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
    159           (UWord8 *)&inputPtr[1],
    160           static_cast<int16_t *>(buffer->data()),
    161           MIME_IETF);
    162 
    163     ++numBytesRead;  // Include the frame type header byte.
    164 
    165     buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t));
    166 
    167     if (numBytesRead > mInputBuffer->range_length()) {
    168         // This is bad, should never have happened, but did. Abort now.
    169 
    170         buffer->release();
    171         buffer = NULL;
    172 
    173         return ERROR_MALFORMED;
    174     }
    175 
    176     mInputBuffer->set_range(
    177             mInputBuffer->range_offset() + numBytesRead,
    178             mInputBuffer->range_length() - numBytesRead);
    179 
    180     if (mInputBuffer->range_length() == 0) {
    181         mInputBuffer->release();
    182         mInputBuffer = NULL;
    183     }
    184 
    185     buffer->meta_data()->setInt64(
    186             kKeyTime,
    187             mAnchorTimeUs
    188                 + (mNumSamplesOutput * 1000000) / kSampleRate);
    189 
    190     mNumSamplesOutput += kNumSamplesPerFrame;
    191 
    192     *out = buffer;
    193 
    194     return OK;
    195 }
    196 
    197 }  // namespace android
    198