Loading include/media/stagefright/MetaData.h +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ enum { kKeyHeight = 'heig', kKeyChannelCount = '#chn', kKeySampleRate = 'srte', kKeyBitRate = 'brte', kKeyBitRate = 'brte', // int32_t (bps) kKeyESDS = 'esds', // raw data kKeyAVCC = 'avcc', // raw data kKeyWantsNALFragments = 'NALf', Loading media/libstagefright/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true) LOCAL_STATIC_LIBRARIES := \ libstagefright_aacdec \ libstagefright_amrnbdec \ libstagefright_amrnbenc \ libstagefright_amrwbdec \ libstagefright_avcdec \ libstagefright_mp3dec Loading media/libstagefright/MP3Extractor.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ MP3Extractor::MP3Extractor(const sp<DataSource> &source) mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); mMeta->setInt32(kKeySampleRate, sample_rate); mMeta->setInt32(kKeyBitRate, bitrate); mMeta->setInt32(kKeyBitRate, bitrate * 1000); mMeta->setInt32(kKeyChannelCount, num_channels); off_t fileSize; Loading Loading @@ -462,14 +462,14 @@ status_t MP3Source::read( if (options != NULL && options->getSeekTo(&seekTimeUs)) { int32_t bitrate; if (!mMeta->findInt32(kKeyBitRate, &bitrate)) { // bitrate is in kbits/sec. // bitrate is in bits/sec. LOGI("no bitrate"); return ERROR_UNSUPPORTED; } mCurrentTimeUs = seekTimeUs; mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 1000000 * 125; mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000; } MediaBuffer *buffer; Loading media/libstagefright/OMXCodec.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #if BUILD_WITH_FULL_STAGEFRIGHT #include "include/AACDecoder.h" #include "include/AMRNBDecoder.h" #include "include/AMRNBEncoder.h" #include "include/AMRWBDecoder.h" #include "include/AVCDecoder.h" #include "include/MP3Decoder.h" Loading Loading @@ -306,6 +307,10 @@ sp<MediaSource> OMXCodec::Create( && (flags & kPreferSoftwareCodecs)) { return new AVCDecoder(source); } } else { if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { return new AMRNBEncoder(source); } } #endif Loading media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp 0 → 100644 +234 −0 Original line number Diff line number Diff line /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "AMRNBEncoder.h" #include "gsmamr_enc.h" #include <media/stagefright/MediaBufferGroup.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> namespace android { static const int32_t kNumSamplesPerFrame = 160; static const int32_t kSampleRate = 8000; AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source) : mSource(source), mStarted(false), mBufferGroup(NULL), mEncState(NULL), mSidState(NULL), mAnchorTimeUs(0), mNumFramesOutput(0), mInputBuffer(NULL), mMode(MR475), mNumInputSamples(0) { } AMRNBEncoder::~AMRNBEncoder() { if (mStarted) { stop(); } } static Mode PickModeFromBitrate(int32_t bps) { if (bps <= 4750) { return MR475; } else if (bps <= 5150) { return MR515; } else if (bps <= 5900) { return MR59; } else if (bps <= 6700) { return MR67; } else if (bps <= 7400) { return MR74; } else if (bps <= 7950) { return MR795; } else if (bps <= 10200) { return MR102; } else { return MR122; } } status_t AMRNBEncoder::start(MetaData *params) { CHECK(!mStarted); mBufferGroup = new MediaBufferGroup; mBufferGroup->add_buffer(new MediaBuffer(32)); CHECK_EQ(AMREncodeInit( &mEncState, &mSidState, false /* dtx_enable */), 0); mSource->start(); mAnchorTimeUs = 0; mNumFramesOutput = 0; mStarted = true; mNumInputSamples = 0; int32_t bitrate; if (params && params->findInt32(kKeyBitRate, &bitrate)) { mMode = PickModeFromBitrate(bitrate); } else { mMode = MR475; } return OK; } status_t AMRNBEncoder::stop() { CHECK(mStarted); if (mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } delete mBufferGroup; mBufferGroup = NULL; mSource->stop(); AMREncodeExit(&mEncState, &mSidState); mEncState = mSidState = NULL; mStarted = false; return OK; } sp<MetaData> AMRNBEncoder::getFormat() { sp<MetaData> srcFormat = mSource->getFormat(); int32_t numChannels; int32_t sampleRate; CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); CHECK_EQ(numChannels, 1); CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); CHECK_EQ(sampleRate, kSampleRate); sp<MetaData> meta = new MetaData; meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); meta->setInt32(kKeyChannelCount, numChannels); meta->setInt32(kKeySampleRate, sampleRate); int64_t durationUs; if (srcFormat->findInt64(kKeyDuration, &durationUs)) { meta->setInt64(kKeyDuration, durationUs); } return meta; } status_t AMRNBEncoder::read( MediaBuffer **out, const ReadOptions *options) { status_t err; *out = NULL; int64_t seekTimeUs; CHECK(options == NULL || !options->getSeekTo(&seekTimeUs)); while (mNumInputSamples < kNumSamplesPerFrame) { if (mInputBuffer == NULL) { err = mSource->read(&mInputBuffer, options); if (err != OK) { if (mNumInputSamples == 0) { return ERROR_END_OF_STREAM; } memset(&mInputFrame[mNumInputSamples], 0, sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples)); mNumInputSamples = kNumSamplesPerFrame; break; } size_t align = mInputBuffer->range_length() % sizeof(int16_t); CHECK_EQ(align, 0); int64_t timeUs; if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { mAnchorTimeUs = timeUs; mNumFramesOutput = 0; } } size_t copy = (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); if (copy > mInputBuffer->range_length()) { copy = mInputBuffer->range_length(); } memcpy(&mInputFrame[mNumInputSamples], (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(), copy); mNumInputSamples += copy / sizeof(int16_t); mInputBuffer->set_range( mInputBuffer->range_offset() + copy, mInputBuffer->range_length() - copy); if (mInputBuffer->range_length() == 0) { mInputBuffer->release(); mInputBuffer = NULL; } } MediaBuffer *buffer; CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); uint8_t *outPtr = (uint8_t *)buffer->data(); Frame_Type_3GPP frameType; int res = AMREncode( mEncState, mSidState, (Mode)mMode, mInputFrame, outPtr, &frameType, AMR_TX_WMF); CHECK(res >= 0); CHECK((size_t)res < buffer->size()); // Convert header byte from WMF to IETF format. outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c; buffer->set_range(0, res); // Each frame of 160 samples is 20ms long. buffer->meta_data()->setInt64( kKeyTime, mAnchorTimeUs + mNumFramesOutput * 20000); ++mNumFramesOutput; *out = buffer; mNumInputSamples = 0; return OK; } } // namespace android Loading
include/media/stagefright/MetaData.h +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ enum { kKeyHeight = 'heig', kKeyChannelCount = '#chn', kKeySampleRate = 'srte', kKeyBitRate = 'brte', kKeyBitRate = 'brte', // int32_t (bps) kKeyESDS = 'esds', // raw data kKeyAVCC = 'avcc', // raw data kKeyWantsNALFragments = 'NALf', Loading
media/libstagefright/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true) LOCAL_STATIC_LIBRARIES := \ libstagefright_aacdec \ libstagefright_amrnbdec \ libstagefright_amrnbenc \ libstagefright_amrwbdec \ libstagefright_avcdec \ libstagefright_mp3dec Loading
media/libstagefright/MP3Extractor.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ MP3Extractor::MP3Extractor(const sp<DataSource> &source) mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); mMeta->setInt32(kKeySampleRate, sample_rate); mMeta->setInt32(kKeyBitRate, bitrate); mMeta->setInt32(kKeyBitRate, bitrate * 1000); mMeta->setInt32(kKeyChannelCount, num_channels); off_t fileSize; Loading Loading @@ -462,14 +462,14 @@ status_t MP3Source::read( if (options != NULL && options->getSeekTo(&seekTimeUs)) { int32_t bitrate; if (!mMeta->findInt32(kKeyBitRate, &bitrate)) { // bitrate is in kbits/sec. // bitrate is in bits/sec. LOGI("no bitrate"); return ERROR_UNSUPPORTED; } mCurrentTimeUs = seekTimeUs; mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 1000000 * 125; mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000; } MediaBuffer *buffer; Loading
media/libstagefright/OMXCodec.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #if BUILD_WITH_FULL_STAGEFRIGHT #include "include/AACDecoder.h" #include "include/AMRNBDecoder.h" #include "include/AMRNBEncoder.h" #include "include/AMRWBDecoder.h" #include "include/AVCDecoder.h" #include "include/MP3Decoder.h" Loading Loading @@ -306,6 +307,10 @@ sp<MediaSource> OMXCodec::Create( && (flags & kPreferSoftwareCodecs)) { return new AVCDecoder(source); } } else { if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { return new AMRNBEncoder(source); } } #endif Loading
media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp 0 → 100644 +234 −0 Original line number Diff line number Diff line /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "AMRNBEncoder.h" #include "gsmamr_enc.h" #include <media/stagefright/MediaBufferGroup.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> namespace android { static const int32_t kNumSamplesPerFrame = 160; static const int32_t kSampleRate = 8000; AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source) : mSource(source), mStarted(false), mBufferGroup(NULL), mEncState(NULL), mSidState(NULL), mAnchorTimeUs(0), mNumFramesOutput(0), mInputBuffer(NULL), mMode(MR475), mNumInputSamples(0) { } AMRNBEncoder::~AMRNBEncoder() { if (mStarted) { stop(); } } static Mode PickModeFromBitrate(int32_t bps) { if (bps <= 4750) { return MR475; } else if (bps <= 5150) { return MR515; } else if (bps <= 5900) { return MR59; } else if (bps <= 6700) { return MR67; } else if (bps <= 7400) { return MR74; } else if (bps <= 7950) { return MR795; } else if (bps <= 10200) { return MR102; } else { return MR122; } } status_t AMRNBEncoder::start(MetaData *params) { CHECK(!mStarted); mBufferGroup = new MediaBufferGroup; mBufferGroup->add_buffer(new MediaBuffer(32)); CHECK_EQ(AMREncodeInit( &mEncState, &mSidState, false /* dtx_enable */), 0); mSource->start(); mAnchorTimeUs = 0; mNumFramesOutput = 0; mStarted = true; mNumInputSamples = 0; int32_t bitrate; if (params && params->findInt32(kKeyBitRate, &bitrate)) { mMode = PickModeFromBitrate(bitrate); } else { mMode = MR475; } return OK; } status_t AMRNBEncoder::stop() { CHECK(mStarted); if (mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } delete mBufferGroup; mBufferGroup = NULL; mSource->stop(); AMREncodeExit(&mEncState, &mSidState); mEncState = mSidState = NULL; mStarted = false; return OK; } sp<MetaData> AMRNBEncoder::getFormat() { sp<MetaData> srcFormat = mSource->getFormat(); int32_t numChannels; int32_t sampleRate; CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); CHECK_EQ(numChannels, 1); CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); CHECK_EQ(sampleRate, kSampleRate); sp<MetaData> meta = new MetaData; meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); meta->setInt32(kKeyChannelCount, numChannels); meta->setInt32(kKeySampleRate, sampleRate); int64_t durationUs; if (srcFormat->findInt64(kKeyDuration, &durationUs)) { meta->setInt64(kKeyDuration, durationUs); } return meta; } status_t AMRNBEncoder::read( MediaBuffer **out, const ReadOptions *options) { status_t err; *out = NULL; int64_t seekTimeUs; CHECK(options == NULL || !options->getSeekTo(&seekTimeUs)); while (mNumInputSamples < kNumSamplesPerFrame) { if (mInputBuffer == NULL) { err = mSource->read(&mInputBuffer, options); if (err != OK) { if (mNumInputSamples == 0) { return ERROR_END_OF_STREAM; } memset(&mInputFrame[mNumInputSamples], 0, sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples)); mNumInputSamples = kNumSamplesPerFrame; break; } size_t align = mInputBuffer->range_length() % sizeof(int16_t); CHECK_EQ(align, 0); int64_t timeUs; if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { mAnchorTimeUs = timeUs; mNumFramesOutput = 0; } } size_t copy = (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); if (copy > mInputBuffer->range_length()) { copy = mInputBuffer->range_length(); } memcpy(&mInputFrame[mNumInputSamples], (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(), copy); mNumInputSamples += copy / sizeof(int16_t); mInputBuffer->set_range( mInputBuffer->range_offset() + copy, mInputBuffer->range_length() - copy); if (mInputBuffer->range_length() == 0) { mInputBuffer->release(); mInputBuffer = NULL; } } MediaBuffer *buffer; CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); uint8_t *outPtr = (uint8_t *)buffer->data(); Frame_Type_3GPP frameType; int res = AMREncode( mEncState, mSidState, (Mode)mMode, mInputFrame, outPtr, &frameType, AMR_TX_WMF); CHECK(res >= 0); CHECK((size_t)res < buffer->size()); // Convert header byte from WMF to IETF format. outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c; buffer->set_range(0, res); // Each frame of 160 samples is 20ms long. buffer->meta_data()->setInt64( kKeyTime, mAnchorTimeUs + mNumFramesOutput * 20000); ++mNumFramesOutput; *out = buffer; mNumInputSamples = 0; return OK; } } // namespace android