1/* 2 * Copyright (C) 2010 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 "G711Decoder" 19#include <utils/Log.h> 20 21#include "G711Decoder.h" 22 23#include <media/stagefright/MediaBufferGroup.h> 24#include <media/stagefright/MediaDebug.h> 25#include <media/stagefright/MediaDefs.h> 26#include <media/stagefright/MediaErrors.h> 27#include <media/stagefright/MetaData.h> 28 29static const size_t kMaxNumSamplesPerFrame = 16384; 30 31namespace android { 32 33G711Decoder::G711Decoder(const sp<MediaSource> &source) 34 : mSource(source), 35 mStarted(false), 36 mBufferGroup(NULL) { 37} 38 39G711Decoder::~G711Decoder() { 40 if (mStarted) { 41 stop(); 42 } 43} 44 45status_t G711Decoder::start(MetaData *params) { 46 CHECK(!mStarted); 47 48 const char *mime; 49 CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 50 51 mIsMLaw = false; 52 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 53 mIsMLaw = true; 54 } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)) { 55 return ERROR_UNSUPPORTED; 56 } 57 58 mBufferGroup = new MediaBufferGroup; 59 mBufferGroup->add_buffer( 60 new MediaBuffer(kMaxNumSamplesPerFrame * sizeof(int16_t))); 61 62 mSource->start(); 63 64 mStarted = true; 65 66 return OK; 67} 68 69status_t G711Decoder::stop() { 70 CHECK(mStarted); 71 72 delete mBufferGroup; 73 mBufferGroup = NULL; 74 75 mSource->stop(); 76 77 mStarted = false; 78 79 return OK; 80} 81 82sp<MetaData> G711Decoder::getFormat() { 83 sp<MetaData> srcFormat = mSource->getFormat(); 84 85 int32_t numChannels; 86 int32_t sampleRate; 87 88 CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); 89 CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); 90 91 sp<MetaData> meta = new MetaData; 92 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 93 meta->setInt32(kKeyChannelCount, numChannels); 94 meta->setInt32(kKeySampleRate, sampleRate); 95 96 int64_t durationUs; 97 if (srcFormat->findInt64(kKeyDuration, &durationUs)) { 98 meta->setInt64(kKeyDuration, durationUs); 99 } 100 101 meta->setCString(kKeyDecoderComponent, "G711Decoder"); 102 103 return meta; 104} 105 106status_t G711Decoder::read( 107 MediaBuffer **out, const ReadOptions *options) { 108 status_t err; 109 110 *out = NULL; 111 112 int64_t seekTimeUs; 113 ReadOptions::SeekMode mode; 114 if (options && options->getSeekTo(&seekTimeUs, &mode)) { 115 CHECK(seekTimeUs >= 0); 116 } else { 117 seekTimeUs = -1; 118 } 119 120 MediaBuffer *inBuffer; 121 err = mSource->read(&inBuffer, options); 122 123 if (err != OK) { 124 return err; 125 } 126 127 if (inBuffer->range_length() > kMaxNumSamplesPerFrame) { 128 LOGE("input buffer too large (%d).", inBuffer->range_length()); 129 130 inBuffer->release(); 131 inBuffer = NULL; 132 133 return ERROR_UNSUPPORTED; 134 } 135 136 int64_t timeUs; 137 CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 138 139 const uint8_t *inputPtr = 140 (const uint8_t *)inBuffer->data() + inBuffer->range_offset(); 141 142 MediaBuffer *outBuffer; 143 CHECK_EQ(mBufferGroup->acquire_buffer(&outBuffer), OK); 144 145 if (mIsMLaw) { 146 DecodeMLaw( 147 static_cast<int16_t *>(outBuffer->data()), 148 inputPtr, inBuffer->range_length()); 149 } else { 150 DecodeALaw( 151 static_cast<int16_t *>(outBuffer->data()), 152 inputPtr, inBuffer->range_length()); 153 } 154 155 // Each 8-bit byte is converted into a 16-bit sample. 156 outBuffer->set_range(0, inBuffer->range_length() * 2); 157 158 outBuffer->meta_data()->setInt64(kKeyTime, timeUs); 159 160 inBuffer->release(); 161 inBuffer = NULL; 162 163 *out = outBuffer; 164 165 return OK; 166} 167 168// static 169void G711Decoder::DecodeALaw( 170 int16_t *out, const uint8_t *in, size_t inSize) { 171 while (inSize-- > 0) { 172 int32_t x = *in++; 173 174 int32_t ix = x ^ 0x55; 175 ix &= 0x7f; 176 177 int32_t iexp = ix >> 4; 178 int32_t mant = ix & 0x0f; 179 180 if (iexp > 0) { 181 mant += 16; 182 } 183 184 mant = (mant << 4) + 8; 185 186 if (iexp > 1) { 187 mant = mant << (iexp - 1); 188 } 189 190 *out++ = (x > 127) ? mant : -mant; 191 } 192} 193 194// static 195void G711Decoder::DecodeMLaw( 196 int16_t *out, const uint8_t *in, size_t inSize) { 197 while (inSize-- > 0) { 198 int32_t x = *in++; 199 200 int32_t mantissa = ~x; 201 int32_t exponent = (mantissa >> 4) & 7; 202 int32_t segment = exponent + 1; 203 mantissa &= 0x0f; 204 205 int32_t step = 4 << segment; 206 207 int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33; 208 209 *out++ = (x < 0x80) ? -abs : abs; 210 } 211} 212 213} // namespace android 214