summaryrefslogtreecommitdiffstats
path: root/media/libstagefright
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright')
-rw-r--r--media/libstagefright/ACodec.cpp220
-rwxr-xr-xmedia/libstagefright/Android.mk3
-rw-r--r--media/libstagefright/AudioPlayer.cpp13
-rw-r--r--media/libstagefright/AudioSource.cpp195
-rw-r--r--media/libstagefright/AwesomePlayer.cpp58
-rwxr-xr-xmedia/libstagefright/CameraSource.cpp10
-rw-r--r--media/libstagefright/LPAPlayerALSA.cpp5
-rwxr-xr-xmedia/libstagefright/MPEG4Writer.cpp14
-rw-r--r--media/libstagefright/MediaCodecList.cpp12
-rw-r--r--media/libstagefright/MediaExtractor.cpp53
-rw-r--r--media/libstagefright/OMXCodec.cpp108
-rw-r--r--media/libstagefright/QCOMXCodec.cpp13
-rw-r--r--media/libstagefright/QCUtilityClass.cpp356
-rw-r--r--media/libstagefright/SampleTable.cpp5
-rw-r--r--media/libstagefright/Utils.cpp51
-rw-r--r--media/libstagefright/WAVExtractor.cpp8
-rw-r--r--media/libstagefright/avc_utils.cpp14
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.cpp9
-rw-r--r--media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp2
-rw-r--r--media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp2
-rw-r--r--media/libstagefright/codecs/mp3dec/SoftMP3.cpp13
-rw-r--r--media/libstagefright/include/AwesomePlayer.h1
-rw-r--r--media/libstagefright/include/QCUtilityClass.h111
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp13
24 files changed, 1172 insertions, 117 deletions
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ddf95dc..a9e344d 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -32,6 +32,16 @@
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/MetaData.h>
+
+#ifdef QCOM_ENHANCED_AUDIO
+#include <QCMediaDefs.h>
+#include <QCMetaData.h>
+#include <QOMX_AudioExtensions.h>
+#include <OMX_QCOMExtns.h>
+#include "include/QCUtilityClass.h"
+#endif
+
#include <media/hardware/HardwareAPI.h>
#include <OMX_Component.h>
@@ -925,6 +935,100 @@ status_t ACodec::configureCodec(
mIsEncoder = encoder;
+#ifdef QCOM_ENHANCED_AUDIO
+ if (!strcasecmp(mime, "audio/x-ms-wma")) {
+ if (mIsEncoder) {
+ ALOGE("WMA encoding not supported");
+ return ERROR_UNSUPPORTED;
+ } else {
+ int32_t version;
+ OMX_AUDIO_PARAM_WMATYPE paramWMA;
+ QOMX_AUDIO_PARAM_WMA10PROTYPE paramWMA10;
+ CHECK(msg->findInt32("WMA-Version", &version));
+ int32_t numChannels;
+ int32_t bitRate;
+ int32_t sampleRate;
+ int32_t encodeOptions;
+ int32_t blockAlign;
+ int32_t bitspersample;
+ int32_t formattag;
+ int32_t advencopt1;
+ int32_t advencopt2;
+ int32_t VirtualPktSize;
+ if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+ CHECK(msg->findInt32("bsps", &bitspersample));
+ CHECK(msg->findInt32("fmtt", &formattag));
+ CHECK(msg->findInt32("ade1",&advencopt1));
+ CHECK(msg->findInt32("ade2",&advencopt2));
+ CHECK(msg->findInt32("vpks",&VirtualPktSize));
+ }
+ if(version==kTypeWMA) {
+ InitOMXParams(&paramWMA);
+ paramWMA.nPortIndex = kPortIndexInput;
+ } else if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+ InitOMXParams(&paramWMA10);
+ paramWMA10.nPortIndex = kPortIndexInput;
+ }
+ CHECK(msg->findInt32("channel-count", &numChannels));
+ CHECK(msg->findInt32("sample-rate", &sampleRate));
+ CHECK(msg->findInt32("brte", &bitRate));
+ CHECK(msg->findInt32("eopt", &encodeOptions));
+ CHECK(msg->findInt32("blka", &blockAlign));
+ ALOGV("Channels: %d, SampleRate: %d, BitRate; %d"
+ "EncodeOptions: %d, blockAlign: %d", numChannels,
+ sampleRate, bitRate, encodeOptions, blockAlign);
+ if(sampleRate>48000 || numChannels>2){
+ ALOGE("Unsupported samplerate/channels");
+ return ERROR_UNSUPPORTED;
+ }
+ if(version==kTypeWMAPro || version==kTypeWMALossLess){
+ ALOGV("Bitspersample: %d, wmaformattag: %d,"
+ "advencopt1: %d, advencopt2: %d VirtualPktSize %d", bitspersample,
+ formattag, advencopt1, advencopt2, VirtualPktSize);
+ }
+ status_t err = OK;
+ OMX_INDEXTYPE index;
+ if(version==kTypeWMA) {
+ err = mOMX->getParameter(
+ mNode,OMX_IndexParamAudioWma, &paramWMA, sizeof(paramWMA));
+ } else if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+ mOMX->getExtensionIndex(mNode,"OMX.Qualcomm.index.audio.wma10Pro",&index);
+ err = mOMX->getParameter(
+ mNode, index, &paramWMA10, sizeof(paramWMA10));
+ }
+ CHECK_EQ(err, (status_t)OK);
+ if(version==kTypeWMA) {
+ paramWMA.nChannels = numChannels;
+ paramWMA.nSamplingRate = sampleRate;
+ paramWMA.nEncodeOptions = encodeOptions;
+ paramWMA.nBitRate = bitRate;
+ paramWMA.nBlockAlign = blockAlign;
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamAudioWma, &paramWMA, sizeof(paramWMA));
+ } else if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+ paramWMA10.nChannels = numChannels;
+ paramWMA10.nSamplingRate = sampleRate;
+ paramWMA10.nEncodeOptions = encodeOptions;
+ paramWMA10.nBitRate = bitRate;
+ paramWMA10.nBlockAlign = blockAlign;
+ paramWMA10.advancedEncodeOpt = advencopt1;
+ paramWMA10.advancedEncodeOpt2 = advencopt2;
+ paramWMA10.formatTag = formattag;
+ paramWMA10.validBitsPerSample = bitspersample;
+ paramWMA10.nVirtualPktSize = VirtualPktSize;
+ err = mOMX->setParameter(
+ mNode, index, &paramWMA10, sizeof(paramWMA10));
+ }
+ CHECK_EQ(err, (status_t)OK);
+ int32_t maxInputSize1;
+ if (msg->findInt32("max-input-size", &maxInputSize1)) {
+ setMinBufferSize(kPortIndexInput, (size_t)maxInputSize1);
+ }
+ return err;
+ }
+ }
+#endif
+
status_t err = setComponentRole(encoder /* isEncoder */, mime);
if (err != OK) {
@@ -1482,7 +1586,8 @@ status_t ACodec::setSupportedOutputFormat() {
|| format.eColorFormat == OMX_COLOR_FormatCbYCrY
|| format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
|| format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka);
+ || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
+ || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m );
return mOMX->setParameter(
mNode, OMX_IndexParamVideoPortFormat,
@@ -3146,9 +3251,33 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
AString mime;
+ uint32_t quirks = 0;
+#ifdef QCOM_ENHANCED_AUDIO
+ msg->findString("mime", &mime);
+
+ if(!(strcmp(mime.c_str(),"audio/x-ms-wma"))){
+ mCodec->mQuirks = quirks;
+ mCodec->mOMX = omx;
+
+ mCodec->mPortEOS[kPortIndexInput] =
+ mCodec->mPortEOS[kPortIndexOutput] = false;
+
+ mCodec->mInputEOSResult = OK;
+
+ {
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatComponentAllocated);
+ notify->setString("componentName", mCodec->mComponentName.c_str());
+ notify->post();
+ }
+
+ mCodec->changeState(mCodec->mLoadedState);
+
+ return true;
+ }
+#endif
AString componentName;
- uint32_t quirks = 0;
if (msg->findString("componentName", &componentName)) {
ssize_t index = matchingCodecs.add();
OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
@@ -3173,7 +3302,6 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
0, // flags
&matchingCodecs);
}
-
sp<CodecObserver> observer = new CodecObserver;
IOMX::node_id node = NULL;
@@ -3327,11 +3455,93 @@ bool ACodec::LoadedState::onConfigureComponent(
const sp<AMessage> &msg) {
ALOGV("onConfigureComponent");
- CHECK(mCodec->mNode != NULL);
-
AString mime;
CHECK(msg->findString("mime", &mime));
+#ifdef QCOM_ENHANCED_AUDIO
+ if (!strcasecmp(mime.c_str(), "audio/x-ms-wma")){
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+ sp<IOMX> omx = client.interface();
+ Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
+ AString componentName;
+ uint32_t quirks = 0;
+ int32_t version = -1;
+
+ msg->findInt32("WMA-Version", &version);
+ if(kTypeWMA == version){
+ componentName = "OMX.qcom.audio.decoder.wma";
+ } else if(kTypeWMAPro == version){
+ componentName = "OMX.qcom.audio.decoder.wma10Pro";
+ } else if(kTypeWMALossLess == version){
+ componentName = "OMX.qcom.audio.decoder.wmaLossLess";
+ } else {
+ mCodec->signalError(OMX_ErrorComponentNotFound);
+ return false;
+ }
+
+ int32_t encoder;
+ if (!msg->findInt32("encoder", &encoder)) {
+ encoder = false;
+ }
+
+ OMXCodec::findMatchingCodecs(
+ mime.c_str(),
+ encoder, // createEncoder
+ componentName.c_str(), // matchComponentName
+ 0, // flags
+ &matchingCodecs);
+
+ sp<CodecObserver> observer = new CodecObserver;
+ IOMX::node_id node = NULL;
+
+ for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
+ ++matchIndex) {
+ componentName = matchingCodecs.itemAt(matchIndex).mName.string();
+ quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
+
+ pid_t tid = androidGetTid();
+ int prevPriority = androidGetThreadPriority(tid);
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
+ status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
+ androidSetThreadPriority(tid, prevPriority);
+
+ if (err == OK) {
+ break;
+ }
+ node = NULL;
+ }
+ if (node == NULL) {
+ if (!mime.empty()) {
+ ALOGE("Unable to instantiate a decoder for type '%s'.",
+ mime.c_str());
+ } else {
+ ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
+ }
+
+ mCodec->signalError(OMX_ErrorComponentNotFound);
+ return false;
+ }
+ sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
+ observer->setNotificationMessage(notify);
+
+ mCodec->mComponentName = componentName;
+ mCodec->mFlags = 0;
+
+ if (componentName.endsWith(".secure")) {
+ mCodec->mFlags |= kFlagIsSecure;
+ }
+
+ mCodec->mQuirks = quirks;
+ mCodec->mOMX = omx;
+ mCodec->mNode = node;
+
+ mCodec->mPortEOS[kPortIndexInput] =
+ mCodec->mPortEOS[kPortIndexOutput] = false;
+ }
+#endif
+
+ CHECK(mCodec->mNode != NULL);
status_t err = mCodec->configureCodec(mime.c_str(), msg);
if (err != OK) {
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 193291e..766cf5e 100755
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -92,7 +92,8 @@ LOCAL_SRC_FILES += \
QCMediaDefs.cpp \
QCOMXCodec.cpp \
WAVEWriter.cpp \
- ExtendedExtractor.cpp
+ ExtendedExtractor.cpp \
+ QCUtilityClass.cpp
LOCAL_C_INCLUDES += \
$(TOP)/hardware/qcom/media/mm-core/inc
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index deb6b70..80b64c2 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -500,11 +500,11 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
{
Mutex::Autolock autoLock(mLock);
mNumFramesPlayed += size_done / mFrameSize;
- mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
if (mReachedEOS) {
mPinnedTimeUs = mNumFramesPlayedSysTimeUs;
} else {
+ mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
mPinnedTimeUs = -1ll;
}
}
@@ -535,14 +535,21 @@ int64_t AudioPlayer::getRealTimeUsLocked() const {
// compensate using system time.
int64_t diffUs;
if (mPinnedTimeUs >= 0ll) {
- diffUs = mPinnedTimeUs;
+ if(mReachedEOS)
+ diffUs = ALooper::GetNowUs();
+ else
+ diffUs = mPinnedTimeUs;
+
} else {
diffUs = ALooper::GetNowUs();
}
diffUs -= mNumFramesPlayedSysTimeUs;
- return result + diffUs;
+ if(result + diffUs <= mPositionTimeRealUs)
+ return result + diffUs;
+ else
+ return mPositionTimeRealUs;
}
int64_t AudioPlayer::getMediaTimeUs() {
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index bb2d415..2bb721c 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,8 +29,17 @@
#include <cutils/properties.h>
#include <stdlib.h>
-namespace android {
+#ifdef QCOM_ENHANCED_AUDIO
+#define AMR_FRAMESIZE 32
+#define QCELP_FRAMESIZE 35
+#define EVRC_FRAMESIZE 23
+#define AMR_WB_FRAMESIZE 61
+#endif
+namespace android {
+// Treat time out as an error if we have not received any output
+// buffers after 1 seconds
+const static int64_t WaitLockEventTimeOutNs = 1000000000LL;
static void AudioRecordCallbackFunction(int event, void *user, void *info) {
AudioSource *source = (AudioSource *) user;
switch (event) {
@@ -55,7 +64,13 @@ AudioSource::AudioSource(
mSampleRate(sampleRate),
mPrevSampleTimeUs(0),
mNumFramesReceived(0),
- mNumClientOwnedBuffers(0) {
+ mNumClientOwnedBuffers(0)
+#ifdef QCOM_ENHANCED_AUDIO
+ ,mFormat(AUDIO_FORMAT_PCM_16_BIT),
+ mMime(MEDIA_MIMETYPE_AUDIO_RAW)
+#endif
+{
+
ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount);
CHECK(channelCount == 1 || channelCount == 2 || channelCount == 6);
@@ -64,10 +79,23 @@ AudioSource::AudioSource(
sampleRate,
AUDIO_FORMAT_PCM_16_BIT,
audio_channel_in_mask_from_count(channelCount));
+
+#ifdef QCOM_ENHANCED_AUDIO
+ if ( NO_ERROR != AudioSystem::getInputBufferSize(
+ sampleRate, mFormat, channelCount, (size_t*)&mMaxBufferSize) ) {
+ mMaxBufferSize = kMaxBufferSize;
+ ALOGV("mMaxBufferSize = %d", mMaxBufferSize);
+ }
+#endif
+
if (status == OK) {
// make sure that the AudioRecord callback never returns more than the maximum
// buffer size
+#ifdef QCOM_ENHANCED_AUDIO
+ int frameCount = mMaxBufferSize / sizeof(int16_t) / channelCount;
+#else
int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount;
+#endif
// make sure that the AudioRecord total buffer size is large enough
int bufCount = 2;
@@ -78,7 +106,11 @@ AudioSource::AudioSource(
mRecord = new AudioRecord(
inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
audio_channel_in_mask_from_count(channelCount),
+#ifdef QCOM_ENHANCED_AUDIO
+ 4 * mMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
+#else
bufCount * frameCount,
+#endif
AudioRecordCallbackFunction,
this,
frameCount);
@@ -99,6 +131,62 @@ AudioSource::AudioSource(
}
}
+#ifdef QCOM_ENHANCED_AUDIO
+AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta )
+ : mStarted(false),
+ mPrevSampleTimeUs(0),
+ mNumFramesReceived(0),
+ mNumClientOwnedBuffers(0),
+ mFormat(AUDIO_FORMAT_PCM_16_BIT),
+ mMime(MEDIA_MIMETYPE_AUDIO_RAW) {
+
+ const char * mime;
+ ALOGE("SK: in AudioSource : inputSource: %d", inputSource);
+ CHECK( meta->findCString( kKeyMIMEType, &mime ) );
+ mMime = mime;
+ int32_t sampleRate = 0; //these are the only supported values
+ int32_t channels = 0; //for the below tunnel formats
+ CHECK( meta->findInt32( kKeyChannelCount, &channels ) );
+ CHECK( meta->findInt32( kKeySampleRate, &sampleRate ) );
+ int32_t frameSize = -1;
+ mSampleRate = sampleRate;
+ if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_AMR_NB ) ) {
+ mFormat = AUDIO_FORMAT_AMR_NB;
+ frameSize = AMR_FRAMESIZE;
+ mMaxBufferSize = AMR_FRAMESIZE*10;
+ }
+ else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_QCELP ) ) {
+ mFormat = AUDIO_FORMAT_QCELP;
+ frameSize = QCELP_FRAMESIZE;
+ mMaxBufferSize = QCELP_FRAMESIZE*10;
+ }
+ else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_EVRC ) ) {
+ mFormat = AUDIO_FORMAT_EVRC;
+ frameSize = EVRC_FRAMESIZE;
+ mMaxBufferSize = EVRC_FRAMESIZE*10;
+ }
+ else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_AMR_WB ) ) {
+ mFormat = AUDIO_FORMAT_AMR_WB;
+ frameSize = AMR_WB_FRAMESIZE;
+ mMaxBufferSize = AMR_WB_FRAMESIZE*10;
+ }
+ else {
+ CHECK(0);
+ }
+ mAutoRampStartUs = 0;
+ CHECK(channels == 1 || channels == 2);
+
+ mRecord = new AudioRecord(
+ inputSource, sampleRate, mFormat,
+ channels > 1? AUDIO_CHANNEL_IN_STEREO:
+ AUDIO_CHANNEL_IN_MONO,
+ 4*mMaxBufferSize/channels/frameSize,
+ AudioRecordCallbackFunction,
+ this);
+ mInitCheck = mRecord->initCheck();
+}
+#endif
+
AudioSource::~AudioSource() {
if (mStarted) {
reset();
@@ -184,10 +272,17 @@ sp<MetaData> AudioSource::getFormat() {
}
sp<MetaData> meta = new MetaData;
+#ifdef QCOM_ENHANCED_AUDIO
+ meta->setCString(kKeyMIMEType, mMime);
+ meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
+ meta->setInt32(kKeyChannelCount, mRecord->channelCount());
+ meta->setInt32(kKeyMaxInputSize, mMaxBufferSize);
+#else
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
meta->setInt32(kKeySampleRate, mSampleRate);
meta->setInt32(kKeyChannelCount, mRecord->channelCount());
meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
+#endif
return meta;
}
@@ -234,7 +329,9 @@ status_t AudioSource::read(
}
while (mStarted && mBuffersReceived.empty()) {
- mFrameAvailableCondition.wait(mLock);
+ status_t err = mFrameAvailableCondition.waitRelative(mLock,WaitLockEventTimeOutNs);
+ if(err == -ETIMEDOUT)
+ return (status_t)err;
}
if (!mStarted) {
return OK;
@@ -249,24 +346,33 @@ status_t AudioSource::read(
int64_t timeUs;
CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
int64_t elapsedTimeUs = timeUs - mStartTimeUs;
- if (elapsedTimeUs < mAutoRampStartUs) {
- memset((uint8_t *) buffer->data(), 0, buffer->range_length());
- } else if (elapsedTimeUs < mAutoRampStartUs + kAutoRampDurationUs) {
- int32_t autoRampDurationFrames =
- (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL;
-
- int32_t autoRampStartFrames =
- (mAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL;
-
- int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
- rampVolume(nFrames, autoRampDurationFrames,
- (uint8_t *) buffer->data(), buffer->range_length());
+#ifdef QCOM_ENHANCED_AUDIO
+ if ( mFormat == AUDIO_FORMAT_PCM_16_BIT ) {
+#endif
+ if (elapsedTimeUs < mAutoRampStartUs) {
+ memset((uint8_t *) buffer->data(), 0, buffer->range_length());
+ } else if (elapsedTimeUs < mAutoRampStartUs + kAutoRampDurationUs) {
+ int32_t autoRampDurationFrames =
+ (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL;
+
+ int32_t autoRampStartFrames =
+ (mAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL;
+
+ int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
+ rampVolume(nFrames, autoRampDurationFrames,
+ (uint8_t *) buffer->data(), buffer->range_length());
+ }
+#ifdef QCOM_ENHANCED_AUDIO
}
+#endif
// Track the max recording signal amplitude.
if (mTrackMaxAmplitude) {
- trackMaxAmplitude(
- (int16_t *) buffer->data(), buffer->range_length() >> 1);
+#ifdef QCOM_ENHANCED_AUDIO
+ if (mFormat == AUDIO_FORMAT_PCM_16_BIT)
+#endif
+ trackMaxAmplitude(
+ (int16_t *) buffer->data(), buffer->range_length() >> 1);
}
*out = buffer;
@@ -321,7 +427,9 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
}
CHECK_EQ(numLostBytes & 1, 0u);
+#ifndef QCOM_ENHANCED_AUDIO
CHECK_EQ(audioBuffer.size & 1, 0u);
+#endif
if (numLostBytes > 0) {
// Loss of audio frames should happen rarely; thus the LOGW should
// not cause a logging spam
@@ -359,19 +467,45 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) {
const size_t bufferSize = buffer->range_length();
const size_t frameSize = mRecord->frameSize();
+#ifdef QCOM_ENHANCED_AUDIO
+ int64_t timestampUs = mPrevSampleTimeUs;
+ int64_t recordDurationUs = 0;
+ if ( mFormat == AUDIO_FORMAT_PCM_16_BIT ){
+ recordDurationUs = ((1000000LL * (bufferSize / (2 * mRecord->channelCount()))) +
+ (mSampleRate >> 1)) / mSampleRate;
+ } else {
+ recordDurationUs = bufferDurationUs(bufferSize);
+ }
+ timestampUs += recordDurationUs;
+#else
const int64_t timestampUs =
mPrevSampleTimeUs +
((1000000LL * (bufferSize / frameSize)) +
(mSampleRate >> 1)) / mSampleRate;
+#endif
if (mNumFramesReceived == 0) {
buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
}
buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
- buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
+#ifdef QCOM_ENHANCED_AUDIO
+ if (mFormat == AUDIO_FORMAT_PCM_16_BIT) {
+#endif
+ buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
+#ifdef QCOM_ENHANCED_AUDIO
+ } else {
+ int64_t wallClockTimeUs = timeUs - mInitialReadTimeUs;
+ int64_t mediaTimeUs = mStartTimeUs + mPrevSampleTimeUs;
+ buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
+ }
+#endif
mPrevSampleTimeUs = timestampUs;
+#ifdef QCOM_ENHANCED_AUDIO
+ mNumFramesReceived += buffer->range_length() / sizeof(int16_t);
+#else
mNumFramesReceived += bufferSize / frameSize;
+#endif
mBuffersReceived.push_back(buffer);
mFrameAvailableCondition.signal();
}
@@ -399,4 +533,27 @@ int16_t AudioSource::getMaxAmplitude() {
return value;
}
+#ifdef QCOM_ENHANCED_AUDIO
+int64_t AudioSource::bufferDurationUs( ssize_t n ) {
+
+ int64_t dataDurationMs = 0;
+ if (mFormat == AUDIO_FORMAT_AMR_NB) {
+ dataDurationMs = (n/AMR_FRAMESIZE) * 20; //ms
+ }
+ else if (mFormat == AUDIO_FORMAT_EVRC) {
+ dataDurationMs = (n/EVRC_FRAMESIZE) * 20; //ms
+ }
+ else if (mFormat == AUDIO_FORMAT_QCELP) {
+ dataDurationMs = (n/QCELP_FRAMESIZE) * 20; //ms
+ }
+ else if (mFormat == AUDIO_FORMAT_AMR_WB) {
+ dataDurationMs = (n/AMR_WB_FRAMESIZE) * 20; //ms
+ }
+
+ else
+ CHECK(0);
+
+ return dataDurationMs*1000LL;
+}
+#endif
} // namespace android
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index c68b476..ad221d1 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -57,6 +57,9 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXCodec.h>
+#ifdef QCOM_HARDWARE
+#include "include/QCUtilityClass.h"
+#endif
#include <gui/ISurfaceTexture.h>
#include <gui/SurfaceTextureClient.h>
@@ -255,6 +258,46 @@ AwesomePlayer::~AwesomePlayer() {
mClient.disconnect();
}
+void AwesomePlayer::printStats() {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.debug.sf.statistics", value, "0");
+ if (atoi(value) && mVideoSource != NULL) {
+ ALOGE("===========================\n"
+ " videoDimensions(%d x %d)\n"
+ " Total Video Frames Decoded(%lld)\n"
+ " Total Video Frames Rendered(%lld)\n"
+ " Total Playback Duration(%lld ms)\n"
+ " numVideoFramesDropped(%lld)\n"
+ " Average Frames Per Second(%.4f)\n"
+ " Last Seek To Time(%lld ms)\n"
+ " Last Paused Time(%lld ms)\n"
+ " First Frame Latency (%lld ms)\n"
+ " Number of times AV Sync Lost(%u)\n"
+ " Max Video Ahead Time Delta(%u)\n"
+ " Max Video Behind Time Delta(%u)\n"
+ " Max Time Sync Loss(%u)\n"
+ " EOS(%d)\n"
+ " PLAYING(%d)\n"
+ "===========================\n\n",
+ mStats.mVideoWidth,
+ mStats.mVideoHeight,
+ mStats.mNumVideoFramesDecoded,
+ mStats.mTotalFrames,
+ mStats.mTotalTimeUs/1000,
+ mStats.mNumVideoFramesDropped,
+ mStats.mTotalTimeUs > 0 ? ((double)(mStats.mTotalFrames)*1E6)/((double)mStats.mTotalTimeUs) : 0,
+ mStats.mLastSeekToTimeMs,
+ mStats.mLastPausedTimeMs,
+ mStats.mFirstFrameLatencyUs/1000,
+ mStats.mNumTimesSyncLoss,
+ -mStats.mMaxEarlyDelta/1000,
+ mStats.mMaxLateDelta/1000,
+ mStats.mMaxTimeSyncLoss/1000,
+ (mFlags & VIDEO_AT_EOS) > 0,
+ (mFlags & PLAYING) > 0);
+ }
+}
+
void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
mQueue.cancelEvent(mVideoEvent->eventID());
mVideoEventPending = false;
@@ -448,7 +491,11 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
&mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
stat->mMIME = mime.string();
}
- } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
+ } else if (!haveAudio &&
+#ifdef QCOM_HARDWARE
+ !QCUtilityClass::helper_Awesomeplayer_checkIfAudioDisable() &&
+#endif
+ !strncasecmp(mime.string(), "audio/", 6)) {
setAudioSource(extractor->getTrack(i));
haveAudio = true;
mActiveAudioTrackIndex = i;
@@ -573,6 +620,8 @@ void AwesomePlayer::reset_l() {
mVideoRenderer.clear();
+ modifyFlags(PLAYING, CLEAR);
+ printStats();
if (mVideoSource != NULL) {
shutdownVideoDecoder_l();
}
@@ -1039,7 +1088,7 @@ status_t AwesomePlayer::play_l() {
// We don't want to post an error notification at this point,
// the error returned from MediaPlayer::start() will suffice.
bool sendErrorNotification = false;
-#ifdef IS_TUNNEL_MODE
+#ifdef USE_TUNNEL_MODE
if(mIsTunnelAudio) {
// For tunnel Audio error has to be posted to the client
sendErrorNotification = true;
@@ -1080,6 +1129,7 @@ status_t AwesomePlayer::play_l() {
if (mAudioSource != NULL && mVideoSource != NULL) {
postVideoLagEvent_l();
}
+ printStats();
}
if (mFlags & AT_EOS) {
@@ -1296,9 +1346,10 @@ status_t AwesomePlayer::pause_l(bool at_eos) {
Playback::PAUSE, 0);
}
- if(!(mFlags & AT_EOS)){
+ if(!(mFlags & VIDEO_AT_EOS)){
Mutex::Autolock autoLock(mStatsLock);
mStats.mLastPausedTimeMs = mVideoTimeUs/1000;
+ printStats();
}
uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
@@ -1832,6 +1883,7 @@ void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
mStats.mLastSeekToTimeMs = mSeekTimeUs/1000;
logFirstFrame();
}
+ printStats();
}
void AwesomePlayer::onVideoEvent() {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 9f63ec0..f7d452b 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -30,7 +30,10 @@
#include <gui/Surface.h>
#include <utils/String8.h>
#include <cutils/properties.h>
-
+#ifdef QCOM_HARDWARE
+#include "include/QCUtilityClass.h"
+#include <QCMetaData.h>
+#endif
#ifdef USE_TI_CUSTOM_DOMX
#include <OMX_TI_IVCommon.h>
#endif
@@ -569,6 +572,11 @@ status_t CameraSource::initWithCameraAccess(
mMeta->setInt32(kKeyStride, mVideoSize.width);
mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
mMeta->setInt32(kKeyFrameRate, mVideoFrameRate);
+
+#ifdef QCOM_HARDWARE
+ QCUtilityClass::helper_CameraSource_hfr(params, mMeta);
+#endif
+
return OK;
}
diff --git a/media/libstagefright/LPAPlayerALSA.cpp b/media/libstagefright/LPAPlayerALSA.cpp
index 0aa419c..e2f30ed 100644
--- a/media/libstagefright/LPAPlayerALSA.cpp
+++ b/media/libstagefright/LPAPlayerALSA.cpp
@@ -51,10 +51,9 @@
static const char mName[] = "LPAPlayer";
-#define MEM_PADDING 64
-#define MEM_BUFFER_SIZE (256*1024)
+#define MEM_METADATA_SIZE 64
+#define MEM_BUFFER_SIZE ((256*1024) - MEM_METADATA_SIZE)
#define MEM_BUFFER_COUNT 4
-
#define PCM_FORMAT 2
#define NUM_FDS 2
#define LPA_BUFFER_TIME 1500000
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6d1f8c6..04b508b 100755
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -40,6 +40,10 @@
#include "include/ESDS.h"
+#ifdef QCOM_HARDWARE
+#include "include/QCUtilityClass.h"
+#endif
+
namespace android {
static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
@@ -2161,6 +2165,12 @@ status_t MPEG4Writer::Track::threadEntry() {
meta_data->findInt32(kKeyIsSyncFrame, &isSync);
CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
+#ifdef QCOM_HARDWARE
+ if(!mIsAudio) {
+ QCUtilityClass::helper_MPEG4Writer_hfr(mMeta, timestampUs);
+ }
+#endif
+
////////////////////////////////////////////////////////////////////////////////
if (mStszTableEntries->count() == 0) {
mFirstSampleTimeRealUs = systemTime() / 1000;
@@ -2190,6 +2200,10 @@ status_t MPEG4Writer::Track::threadEntry() {
*/
int64_t decodingTimeUs;
CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
+#ifdef QCOM_HARDWARE
+ QCUtilityClass::helper_MPEG4Writer_hfr(mMeta, decodingTimeUs);
+#endif
+
decodingTimeUs -= previousPausedDurationUs;
cttsOffsetTimeUs =
timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index d24337f..f815ec9 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -28,6 +28,10 @@
#include <libexpat/expat.h>
+#ifdef QCOM_HARDWARE
+#include "include/QCUtilityClass.h"
+#endif
+
namespace android {
static Mutex sInitMutex;
@@ -64,6 +68,14 @@ MediaCodecList::MediaCodecList()
addMediaCodec(
false /* encoder */, "OMX.google.raw.decoder", "audio/raw");
+
+#ifdef QCOM_HARDWARE
+ Vector<AString> QcomAACQuirks;
+ QcomAACQuirks.push(AString("requires-allocate-on-input-ports"));
+ QcomAACQuirks.push(AString("requires-allocate-on-output-ports"));
+ QCUtilityClass::helper_addMediaCodec(mCodecInfos, mTypes, false, "OMX.qcom.audio.decoder.multiaac",
+ "audio/mp4a-latm", QCUtilityClass::helper_getCodecSpecificQuirks(mCodecQuirks, QcomAACQuirks));
+#endif
}
#if 0
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 1eb5c19..33e526a 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -35,6 +35,7 @@
#include "include/AACExtractor.h"
#ifdef QCOM_HARDWARE
#include "include/ExtendedExtractor.h"
+#include "include/QCUtilityClass.h"
#endif
#include "matroska/MatroskaExtractor.h"
@@ -60,7 +61,6 @@ uint32_t MediaExtractor::flags() const {
sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) {
sp<AMessage> meta;
- bool bCheckExtendedExtractor = false;
String8 tmp;
if (mime == NULL) {
@@ -107,9 +107,6 @@ sp<MediaExtractor> MediaExtractor::Create(
} else {
ret = new MPEG4Extractor(source);
}
-#ifdef QCOM_ENHANCED_AUDIO
- bCheckExtendedExtractor = true;
-#endif
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
ret = new MP3Extractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
@@ -147,49 +144,13 @@ sp<MediaExtractor> MediaExtractor::Create(
}
#ifdef QCOM_HARDWARE
- //If default extractor created and flag is not set to check extended extractor,
- // then pass default extractor.
- if (ret && (!bCheckExtendedExtractor) ) {
- ALOGD("returning default extractor");
- return ret;
- }
-
- //Create Extended Extractor only if default extractor are not selected
- ALOGV("Using ExtendedExtractor");
- sp<MediaExtractor> retextParser = ExtendedExtractor::CreateExtractor(source, mime);
- //if we came here, it means we do not have to use the default extractor, if created above.
- bool bUseDefaultExtractor = false;
-
- if(bCheckExtendedExtractor) {
- ALOGV("bCheckExtendedExtractor is true");
- //bCheckExtendedExtractor is true which means default extractor was found
- // but we want to give preference to extended extractor based on certain
- // codec type.Set bUseDefaultExtractor to true if extended extractor
- //does not return specific codec type that we are looking for.
- bUseDefaultExtractor = true;
- ALOGV(" bCheckExtendedExtractor is true..checking extended extractor");
- for (size_t i = 0; (retextParser!=NULL) && (i < retextParser->countTracks()); ++i) {
- sp<MetaData> meta = retextParser->getTrackMetaData(i);
- const char *mime;
- bool success = meta->findCString(kKeyMIMEType, &mime);
- if( (success == true) && !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) {
- ALOGV("Discarding default extractor and using the extended one");
- //We found what we were looking for, set bUseDefaultExtractor to false;
- bUseDefaultExtractor = false;
- if(ret) {
- //delete the default extractor as we will be using extended extractor..
- delete ret;
- }
- break;
- }
- }
- }
- if( (retextParser != NULL) && (!bUseDefaultExtractor) ) {
- ALOGV("returning retextParser");
- return retextParser;
- }
-#endif
+ //ret will get deleted within if replaced
+ return QCUtilityClass::helper_MediaExtractor_CreateIfNeeded(ret,
+ source,
+ mime);
+#else
return ret;
+#endif
}
} // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index b8b3ec4..26cae65 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -52,7 +52,9 @@
#include <QCMetaData.h>
#include <QOMX_AudioExtensions.h>
#include <OMX_QCOMExtns.h>
+#include "include/QCUtilityClass.h"
#endif
+
#include "include/avc_utils.h"
#ifdef USE_SAMSUNG_COLORFORMAT
@@ -415,7 +417,14 @@ sp<MediaSource> OMXCodec::Create(
CHECK(success);
Vector<CodecNameAndQuirks> matchingCodecs;
- findMatchingCodecs(
+
+#ifdef QCOM_HARDWARE
+ if (QCOMXCodec::useHWAACDecoder(mime)) {
+ findMatchingCodecs(mime, createEncoder,
+ "OMX.qcom.audio.decoder.multiaac", flags, &matchingCodecs);
+ } else
+#endif
+ findMatchingCodecs(
mime, createEncoder, matchComponentName, flags, &matchingCodecs);
if (matchingCodecs.isEmpty()) {
@@ -1054,6 +1063,11 @@ void OMXCodec::setVideoInputFormat(
CHECK(success);
CHECK(stride != 0);
+#ifdef QCOM_HARDWARE
+ int32_t newFrameRate = frameRate;
+ QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate);
+#endif
+
OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
compressionFormat = OMX_VIDEO_CodingAVC;
@@ -1288,7 +1302,11 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
h263type.nAllowedPictureTypes =
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
- h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ int32_t newFrameRate = frameRate;
+#ifdef QCOM_HARDWARE
+ QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate);
+#endif
+ h263type.nPFrames = setPFramesSpacing(iFramesInterval, newFrameRate);
if (h263type.nPFrames == 0) {
h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
}
@@ -1339,7 +1357,11 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
mpeg4type.nAllowedPictureTypes =
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
- mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ int32_t newFrameRate = frameRate;
+#ifdef QCOM_HARDWARE
+ QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate);
+#endif
+ mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, newFrameRate);
if (mpeg4type.nPFrames == 0) {
mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
}
@@ -1360,6 +1382,9 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
+#ifdef QCOM_HARDWARE
+ QCUtilityClass::helper_OMXCodec_setBFrames(mpeg4type, mNumBFrames);
+#endif
err = mOMX->setParameter(
mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
CHECK_EQ(err, (status_t)OK);
@@ -1397,7 +1422,12 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
- // XXX
+ int32_t newFrameRate = frameRate;
+#ifdef QCOM_HARDWARE
+ QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate);
+#endif
+
+#ifndef QCOM_HARDWARE
#ifdef USE_TI_DUCATI_H264_PROFILE
if ((strncmp(mComponentName, "OMX.TI.DUCATI1", 14) != 0)
&& (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline)) {
@@ -1405,19 +1435,22 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
#endif
ALOGW("Use baseline profile instead of %d for AVC recording",
- h264type.eProfile);
+ h264type.eProfile);
h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
}
+#endif
if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
h264type.nSliceHeaderSpacing = 0;
h264type.bUseHadamard = OMX_TRUE;
h264type.nRefFrames = 1;
h264type.nBFrames = 0;
+#ifndef QCOM_HARDWARE
h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
if (h264type.nPFrames == 0) {
h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
}
+#endif
h264type.nRefIdx10ActiveMinus1 = 0;
h264type.nRefIdx11ActiveMinus1 = 0;
h264type.bEntropyCodingCABAC = OMX_FALSE;
@@ -1428,6 +1461,12 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
h264type.nCabacInitIdc = 0;
}
+#ifdef QCOM_HARDWARE
+ QCUtilityClass::helper_OMXCodec_setBFrames(h264type,
+ mNumBFrames,
+ iFramesInterval,
+ newFrameRate);
+#endif
if (h264type.nBFrames != 0) {
h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
}
@@ -1509,6 +1548,7 @@ status_t OMXCodec::setVideoOutputFormat(
|| format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
|| format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
|| format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
+ || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m
#ifdef USE_SAMSUNG_COLORFORMAT
|| format.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress
|| format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled
@@ -1653,7 +1693,11 @@ OMXCodec::OMXCodec(
mNativeWindow(
(!strncmp(componentName, "OMX.google.", 11)
|| !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode"))
- ? NULL : nativeWindow) {
+ ? NULL : nativeWindow)
+#ifdef QCOM_HARDWARE
+ ,mNumBFrames(0)
+#endif
+{
mPortStatus[kPortIndexInput] = ENABLED;
mPortStatus[kPortIndexOutput] = ENABLED;
@@ -2152,6 +2196,15 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
return err;
}
+#ifdef QCOM_BSP
+ err = mNativeWindow.get()->perform(mNativeWindow.get(),
+ NATIVE_WINDOW_SET_BUFFERS_SIZE, def.nBufferSize);
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_size failed: %s (%d)", strerror(-err),
+ -err);
+ return err;
+ }
+#endif
CODEC_LOGV("allocating %lu buffers from a native window of size %lu on "
"output port", def.nBufferCountActual, def.nBufferSize);
@@ -3028,13 +3081,30 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) {
mPortStatus[kPortIndexInput] = ENABLED;
mPortStatus[kPortIndexOutput] = ENABLED;
- if ((mFlags & kEnableGrallocUsageProtected) &&
- mNativeWindow != NULL) {
- // We push enough 1x1 blank buffers to ensure that one of
- // them has made it to the display. This allows the OMX
- // component teardown to zero out any protected buffers
- // without the risk of scanning out one of those buffers.
- pushBlankBuffersToNativeWindow();
+ if (mNativeWindow != NULL) {
+#ifdef QCOM_BSP
+ /*
+ * reset buffer size field with SurfaceTexture
+ * back to 0. This will ensure proper size
+ * buffers are allocated if the same SurfaceTexture
+ * is re-used in a different decode session
+ */
+ int err =
+ mNativeWindow.get()->perform(mNativeWindow.get(),
+ NATIVE_WINDOW_SET_BUFFERS_SIZE,
+ 0);
+ if (err != 0) {
+ ALOGE("set_buffers_size failed: %s (%d)", strerror(-err),
+ -err);
+ }
+#endif
+ if (mFlags & kEnableGrallocUsageProtected) {
+ // We push enough 1x1 blank buffers to ensure that one of
+ // them has made it to the display. This allows the OMX
+ // component teardown to zero out any protected buffers
+ // without the risk of scanning out one of those buffers.
+ pushBlankBuffersToNativeWindow();
+ }
}
setState(IDLE_TO_LOADED);
@@ -3305,7 +3375,10 @@ void OMXCodec::drainInputBuffers() {
}
if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
- break;
+#ifdef QCOM_HARDWARE
+ if (i == mNumBFrames)
+#endif
+ break;
}
}
}
@@ -3757,6 +3830,9 @@ void OMXCodec::setRawAudioFormat(
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = portIndex;
+#ifdef QCOM_ENHANCED_AUDIO
+ def.format.audio.cMIMEType = NULL;
+#endif
status_t err = mOMX->getParameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
CHECK_EQ(err, (status_t)OK);
@@ -5235,6 +5311,10 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
if (mNativeWindow != NULL) {
initNativeWindowCrop();
}
+#ifdef QCOM_HARDWARE
+ } else {
+ QCUtilityClass::helper_OMXCodec_hfr(inputFormat, mOutputFormat);
+#endif
}
break;
}
diff --git a/media/libstagefright/QCOMXCodec.cpp b/media/libstagefright/QCOMXCodec.cpp
index fcc57f2..a2f3b35 100644
--- a/media/libstagefright/QCOMXCodec.cpp
+++ b/media/libstagefright/QCOMXCodec.cpp
@@ -30,6 +30,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "QCOMXCodec"
#include <utils/Log.h>
+#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
@@ -593,7 +594,7 @@ void QCOMXCodec::setQCSpecificVideoFormat(const sp<MetaData> &meta, sp<IOMX> OMX
void QCOMXCodec::checkIfInterlaced(const uint8_t *ptr, const sp<MetaData> &meta)
{
uint16_t spsSize = (((uint16_t)ptr[6]) << 8) + (uint16_t)(ptr[7]);
- int32_t width = 0, height = 0, isInterlaced = 0;
+ int32_t width = 0, height = 0, isInterlaced = 1;
const uint8_t *spsStart = &ptr[8];
sp<ABuffer> seqParamSet = new ABuffer(spsSize);
@@ -607,4 +608,14 @@ void QCOMXCodec::checkIfInterlaced(const uint8_t *ptr, const sp<MetaData> &meta)
return;
}
+bool QCOMXCodec::useHWAACDecoder(const char *mime) {
+ char value[PROPERTY_VALUE_MAX];
+ int aaccodectype = property_get("media.aaccodectype", value, NULL);
+ if (!strcmp("0", value) && aaccodectype && !strcmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ ALOGI("Using Hardware AAC Decoder");
+ return true;
+ }
+ return false;
+}
+
}
diff --git a/media/libstagefright/QCUtilityClass.cpp b/media/libstagefright/QCUtilityClass.cpp
new file mode 100644
index 0000000..1efc040
--- /dev/null
+++ b/media/libstagefright/QCUtilityClass.cpp
@@ -0,0 +1,356 @@
+/*Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "QCUtilClass"
+#include <utils/Log.h>
+
+#include <include/QCUtilityClass.h>
+#include "include/ExtendedExtractor.h"
+#include <media/stagefright/MetaData.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/OMXCodec.h>
+
+namespace android {
+
+//-- START :: HFR Related Changes -----
+
+status_t QCUtilityClass::helper_StageFrightRecoder_hfr(sp<MetaData> &meta, sp<MetaData> &enc_meta,
+ int64_t &maxFileDurationUs, int32_t frameRate,
+ video_encoder videoEncoder) {
+ status_t retVal = OK;
+ int32_t hfr = 0;
+
+ if (!meta->findInt32(kKeyHFR, &hfr)) {
+ ALOGW("hfr not found, default to 0");
+ }
+
+ if (hfr && frameRate) {
+ maxFileDurationUs = maxFileDurationUs * (hfr/frameRate);
+ }
+
+ enc_meta->setInt32(kKeyHFR, hfr);
+ int32_t width = 0, height = 0;
+
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ char mDeviceName[100];
+ property_get("ro.board.platform",mDeviceName,"0");
+ if (!strncmp(mDeviceName, "msm7627a", 8)) {
+ if (hfr && (width * height > 432*240)) {
+ ALOGE("HFR mode is supported only upto WQVGA resolution");
+ return INVALID_OPERATION;
+ }
+ } else {
+ if(hfr && ((videoEncoder != VIDEO_ENCODER_H264) || (width * height > 800*480))) {
+ ALOGE("HFR mode is supported only upto WVGA and H264 codec.");
+ return INVALID_OPERATION;
+ }
+ }
+ return retVal;
+}
+
+void QCUtilityClass::helper_CameraSource_hfr(const CameraParameters& params,
+ sp<MetaData> &meta) {
+ const char *hfr_str = params.get("video-hfr");
+ int32_t hfr = -1;
+
+ if (hfr_str != NULL) {
+ hfr = atoi(hfr_str);
+ }
+ if (hfr < 0) {
+ ALOGW("Invalid hfr value(%d) set from app. Disabling HFR.", hfr);
+ hfr = 0;
+ }
+ meta->setInt32(kKeyHFR, hfr);
+}
+
+void QCUtilityClass::helper_MPEG4Writer_hfr(sp<MetaData> &meta,
+ int64_t &timestampUs) {
+ int32_t frameRate = 0, hfr = 0, multiple = 0;
+
+ if (!(meta->findInt32(kKeyFrameRate, &frameRate))) {
+ return;
+ }
+
+ if (!(meta->findInt32(kKeyHFR, &hfr))) {
+ return;
+ }
+
+ multiple = hfr ? (hfr/frameRate) : 1;
+ timestampUs = multiple * timestampUs;
+}
+
+void QCUtilityClass::helper_OMXCodec_hfr(const sp<MetaData> &meta,
+ int32_t &frameRate,
+ int32_t &bitRate,
+ int32_t &newFrameRate) {
+ int32_t hfr = 0, hfrRatio = 0;
+ if (!(meta->findInt32(kKeyHFR, &hfr))) {
+ return;
+ }
+
+ hfrRatio = hfr ? hfr/frameRate : 1;
+ frameRate = hfr?hfr:frameRate;
+ bitRate = hfr ? (hfrRatio*bitRate) : bitRate;
+ newFrameRate = frameRate / hfrRatio;
+}
+
+void QCUtilityClass::helper_OMXCodec_hfr(const sp<MetaData> &inputFormat,
+ sp<MetaData> &outputFormat) {
+ int32_t frameRate = 0, hfr = 0;
+ inputFormat->findInt32(kKeyHFR, &hfr);
+ inputFormat->findInt32(kKeyFrameRate, &frameRate);
+ outputFormat->setInt32(kKeyHFR, hfr);
+ outputFormat->setInt32(kKeyFrameRate, frameRate);
+}
+
+//-- END :: HFR related changes -----
+
+
+//-- START :: AUDIO disable and change in profile base on property -----
+
+bool QCUtilityClass::helper_Awesomeplayer_checkIfAudioDisable() {
+ bool retVal = false;
+ char disableAudio[PROPERTY_VALUE_MAX];
+ property_get("persist.debug.sf.noaudio", disableAudio, "0");
+ if (atoi(disableAudio) == 1) {
+ retVal = true;
+ }
+ return retVal;
+}
+
+bool QCUtilityClass::helper_StagefrightRecoder_checkIfAudioDisable() {
+ bool retVal = false;
+ char disableAudio[PROPERTY_VALUE_MAX];
+ property_get("camcorder.debug.disableaudio", disableAudio, "0");
+ if (atoi(disableAudio) == 1) {
+ retVal = true;
+ }
+ return retVal;
+}
+
+void QCUtilityClass::helper_StagefrightRecoder_setUserprofile(video_encoder &videoEncoder,
+ int32_t &videoEncoderProfile) {
+ char value[PROPERTY_VALUE_MAX];
+ bool customProfile = false;
+ if (!property_get("encoder.video.profile", value, NULL) > 0) {
+ return;
+ }
+
+ switch (videoEncoder) {
+ case VIDEO_ENCODER_H264:
+ if (strncmp("base", value, 4) == 0) {
+ videoEncoderProfile = OMX_VIDEO_AVCProfileBaseline;
+ ALOGI("H264 Baseline Profile");
+ } else if (strncmp("main", value, 4) == 0) {
+ videoEncoderProfile = OMX_VIDEO_AVCProfileMain;
+ ALOGI("H264 Main Profile");
+ } else if (strncmp("high", value, 4) == 0) {
+ videoEncoderProfile = OMX_VIDEO_AVCProfileHigh;
+ ALOGI("H264 High Profile");
+ } else {
+ ALOGW("Unsupported H264 Profile");
+ }
+ break;
+ case VIDEO_ENCODER_MPEG_4_SP:
+ if (strncmp("simple", value, 5) == 0 ) {
+ videoEncoderProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ ALOGI("MPEG4 Simple profile");
+ } else if (strncmp("asp", value, 3) == 0 ) {
+ videoEncoderProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+ ALOGI("MPEG4 Advanced Simple Profile");
+ } else {
+ ALOGW("Unsupported MPEG4 Profile");
+ }
+ break;
+ default:
+ ALOGW("No custom profile support for other codecs");
+ break;
+ }
+}
+
+void QCUtilityClass::helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_MPEG4TYPE &mpeg4type,
+ bool &numBFrames) {
+ if (mpeg4type.eProfile > OMX_VIDEO_MPEG4ProfileSimple) {
+ mpeg4type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
+ mpeg4type.nBFrames = 1;
+ mpeg4type.nPFrames /= (mpeg4type.nBFrames + 1);
+ numBFrames = mpeg4type.nBFrames;
+ }
+ return;
+}
+
+void QCUtilityClass::helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_AVCTYPE &h264type,
+ bool &numBFrames,
+ int32_t iFramesInterval,
+ int32_t frameRate) {
+ OMX_U32 val = 0;
+ if (iFramesInterval < 0) {
+ val = 0xFFFFFFFF;
+ } else if (iFramesInterval == 0) {
+ val = 0;
+ } else {
+ val = frameRate * iFramesInterval - 1;
+ CHECK(val > 1);
+ }
+
+ h264type.nPFrames = val;
+
+ if (h264type.nPFrames == 0) {
+ h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
+
+ if (h264type.eProfile > OMX_VIDEO_AVCProfileBaseline) {
+ h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
+ h264type.nBFrames = 1;
+ h264type.nPFrames /= (h264type.nBFrames + 1);
+ numBFrames = h264type.nBFrames;
+ }
+ return;
+}
+//-- END :: AUDIO disable and change in profile base on property -----
+void QCUtilityClass::helper_addMediaCodec(Vector<MediaCodecList::CodecInfo> &mCodecInfos,
+ KeyedVector<AString, size_t> &mTypes,
+ bool encoder, const char *name,
+ const char *type, uint32_t quirks) {
+ mCodecInfos.push();
+ MediaCodecList::CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
+ info->mName = name;
+ info->mIsEncoder = encoder;
+ ssize_t index = mTypes.indexOfKey(type);
+ uint32_t bit = mTypes.valueAt(index);
+ info->mTypes |= 1ul << bit;
+ info->mQuirks = quirks;
+}
+
+uint32_t QCUtilityClass::helper_getCodecSpecificQuirks(KeyedVector<AString, size_t> &mCodecQuirks,
+ Vector<AString> quirks) {
+ size_t i = 0, numQuirks = quirks.size();
+ uint32_t bit = 0, value = 0;
+ for (i = 0; i < numQuirks; i++)
+ {
+ ssize_t index = mCodecQuirks.indexOfKey(quirks.itemAt(i));
+ bit = mCodecQuirks.valueAt(index);
+ value |= 1ul << bit;
+ }
+ return value;
+}
+
+//- returns NULL if we dont really need a new extractor (or cannot),
+// valid extractor is returned otherwise
+//- caller needs to check for NULL
+// defaultExt - the existing extractor
+// source - file source
+// mime - container mime
+// Note that defaultExt will be deleted in this function if the new parser is taken
+sp<MediaExtractor> QCUtilityClass::helper_MediaExtractor_CreateIfNeeded(sp<MediaExtractor> defaultExt,
+ const sp<DataSource> &source,
+ const char *mime) {
+ bool bCheckExtendedExtractor = false;
+ bool videoOnly = true;
+ bool amrwbAudio = false;
+ if (defaultExt != NULL) {
+ for (size_t i = 0; i < defaultExt->countTracks(); ++i) {
+ sp<MetaData> meta = defaultExt->getTrackMetaData(i);
+ const char *_mime;
+ CHECK(meta->findCString(kKeyMIMEType, &_mime));
+
+ String8 mime = String8(_mime);
+
+ if (!strncasecmp(mime.string(), "audio/", 6)) {
+ videoOnly = false;
+
+ amrwbAudio = !strncasecmp(mime.string(),
+ MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ strlen(MEDIA_MIMETYPE_AUDIO_AMR_WB));
+ if (amrwbAudio) break;
+ }
+ }
+ bCheckExtendedExtractor = videoOnly || amrwbAudio;
+ } else {
+ bCheckExtendedExtractor = true;
+ }
+
+ if (!bCheckExtendedExtractor) {
+ ALOGD("extended extractor not needed, return default");
+ return defaultExt;
+ }
+
+ sp<MediaExtractor> retextParser;
+
+ //Create Extended Extractor only if default extractor are not selected
+ ALOGD("Try creating ExtendedExtractor");
+ retextParser = ExtendedExtractor::CreateExtractor(source, mime);
+
+ if (retextParser == NULL) {
+ ALOGD("Couldn't create the extended extractor, return default one");
+ return defaultExt;
+ }
+
+ if (defaultExt == NULL) {
+ ALOGD("default one is NULL, return extended extractor");
+ return retextParser;
+ }
+
+ //bCheckExtendedExtractor is true which means default extractor was found
+ //but we want to give preference to extended extractor based on certain
+ //conditions.
+
+ //needed to prevent a leak in case both extractors are valid
+ //but we still dont want to use the extended one. we need
+ //to delete the new one
+ bool bUseDefaultExtractor = true;
+
+ for (size_t i = 0; (i < retextParser->countTracks()); ++i) {
+ sp<MetaData> meta = retextParser->getTrackMetaData(i);
+ const char *mime;
+ bool success = meta->findCString(kKeyMIMEType, &mime);
+ if ((success == true) && !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) {
+ ALOGD("Discarding default extractor and using the extended one");
+ bUseDefaultExtractor = false;
+ break;
+ }
+ }
+
+ if (bUseDefaultExtractor) {
+ ALOGD("using default extractor inspite of having a new extractor");
+ retextParser.clear();
+ return defaultExt;
+ } else {
+ defaultExt.clear();
+ return retextParser;
+ }
+}
+
+}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index d9858d7..4a42a70 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -360,8 +360,9 @@ status_t SampleTable::setCompositionTimeToSampleParams(
return ERROR_IO;
}
- if (U32_AT(header) != 0) {
- // Expected version = 0, flags = 0.
+ if (U32_AT(header) != 0 &&
+ U32_AT(header) != 0x01000000) {
+ // Expected version = 0/1, flags = 0.
return ERROR_MALFORMED;
}
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 74e9222..7bd2032 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -28,6 +28,17 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#ifdef QCOM_ENHANCED_AUDIO
+#include <QCMediaDefs.h>
+#include <QCMetaData.h>
+#include <QOMX_AudioExtensions.h>
+#include <OMX_QCOMExtns.h>
+#include "include/avc_utils.h"
+
+#include "include/QCUtilityClass.h"
+#endif
+
+
namespace android {
uint16_t U16_AT(const uint8_t *ptr) {
@@ -111,6 +122,46 @@ status_t convertMetaDataToMessage(
if (meta->findInt32(kKeyIsADTS, &isADTS)) {
msg->setInt32("is-adts", true);
}
+#ifdef QCOM_ENHANCED_AUDIO
+ int32_t keyWMAVersion;
+ if (meta->findInt32(kKeyWMAVersion, &keyWMAVersion)) {
+ msg->setInt32("WMA-Version", keyWMAVersion);
+ }
+ int32_t bitRate;
+ int32_t encodeOptions;
+ int32_t blockAlign;
+ int32_t bitspersample;
+ int32_t formattag;
+ int32_t advencopt1;
+ int32_t advencopt2;
+ int32_t VirtualPktSize;
+
+ if (meta->findInt32(kKeyWMABitspersample, &bitspersample)) {
+ msg->setInt32("bsps", bitspersample);
+ }
+ if (meta->findInt32(kKeyWMAFormatTag, &formattag)) {
+ msg->setInt32("fmtt", formattag);
+ }
+ if (meta->findInt32(kKeyWMAAdvEncOpt1, &advencopt1)) {
+ msg->setInt32("ade1", advencopt1);
+ }
+
+ if (meta->findInt32(kKeyWMAAdvEncOpt2, &advencopt2)) {
+ msg->setInt32("ade2", advencopt2);
+ }
+ if (meta->findInt32(kKeyWMAVirPktSize, &VirtualPktSize)) {
+ msg->setInt32("vpks", VirtualPktSize);
+ }
+ if (meta->findInt32(kKeyBitRate, &bitRate)) {
+ msg->setInt32("brte", bitRate);
+ }
+ if (meta->findInt32(kKeyWMAEncodeOpt, &encodeOptions)) {
+ msg->setInt32("eopt", encodeOptions);
+ }
+ if (meta->findInt32(kKeyWMABlockAlign, &blockAlign)) {
+ msg->setInt32("blka", blockAlign);
+ }
+#endif
}
int32_t maxInputSize;
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index a38400b..2640319 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -192,8 +192,8 @@ status_t WAVExtractor::init() {
mNumChannels = U16_LE_AT(&formatSpec[2]);
if (mWaveFormat != WAVE_FORMAT_EXTENSIBLE) {
- if (mNumChannels != 1 && mNumChannels != 2) {
- ALOGW("More than 2 channels (%d) in non-WAVE_EXT, unknown channel mask",
+ if (mNumChannels != 1 && mNumChannels != 2 && mNumChannels != 4) {
+ ALOGW("More than 4 channels (%d) in non-WAVE_EXT, unknown channel mask",
mNumChannels);
}
} else {
@@ -271,6 +271,10 @@ status_t WAVExtractor::init() {
if (mValidFormat) {
mDataOffset = offset;
mDataSize = chunkSize;
+ off64_t dataSourceSize = 0;
+
+ if (OK == mDataSource->getSize(&dataSourceSize) && mDataSize > (dataSourceSize - offset))
+ mDataSize = dataSourceSize - offset;
mTrackMeta = new MetaData;
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index fbe98f1..7bfa375 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -60,7 +60,11 @@ void FindAVCDimensions(
parseUE(&br); // bit_depth_luma_minus8
parseUE(&br); // bit_depth_chroma_minus8
br.skipBits(1); // qpprime_y_zero_transform_bypass_flag
- CHECK_EQ(br.getBits(1), 0u); // seq_scaling_matrix_present_flag
+ bool seq_scaling_matrix_present = (br.getBits(1) != 0u);
+ if (isInterlaced != NULL && seq_scaling_matrix_present) {
+ return;
+ }
+ CHECK_EQ(seq_scaling_matrix_present, false); // seq_scaling_matrix_present_flag
}
parseUE(&br); // log2_max_frame_num_minus4
@@ -128,11 +132,11 @@ void FindAVCDimensions(
(frame_crop_left_offset + frame_crop_right_offset) * cropUnitX;
*height -=
(frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY;
-
- if (isInterlaced != NULL) {
- *isInterlaced = !frame_mbs_only_flag;
- }
}
+ if (isInterlaced != NULL) {
+ *isInterlaced = !frame_mbs_only_flag;
+ }
+
}
status_t getNextNALUnit(
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index d88813e..606a43d 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -358,9 +358,13 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
inInfo->mOwnedByUs = false;
notifyEmptyBufferDone(inHeader);
- if (!mIsFirst) {
+ if (!mIsFirst || mInputBufferCount) {
// flush out the decoder's delayed data by calling DecodeFrame
// one more time, with the AACDEC_FLUSH flag set
+
+ // for the use case where the first frame in the buffer is EOS,
+ // decode the header to update the sample rate and channel mode
+ // and flush out the buffer.
INT_PCM *outBuffer =
reinterpret_cast<INT_PCM *>(
outHeader->pBuffer + outHeader->nOffset);
@@ -392,6 +396,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
}
outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ outHeader->nTimeStamp =
+ mAnchorTimeUs
+ + (mNumSamplesOutput * 1000000ll) / mStreamInfo->sampleRate;
outQueue.erase(outQueue.begin());
outInfo->mOwnedByUs = false;
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index 07f8b4f..27dea92 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -71,7 +71,7 @@ void SoftAMRNBEncoder::initPorts() {
def.eDir = OMX_DirInput;
def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
+ def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 4;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index 9ccb49c..afd2b32 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -78,7 +78,7 @@ void SoftAMRWBEncoder::initPorts() {
def.eDir = OMX_DirInput;
def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
+ def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 4;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index fb1135c..aade29c 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -110,7 +110,7 @@ void SoftMP3::initPorts() {
void SoftMP3::initDecoder() {
mConfig->equalizerType = flat;
mConfig->crcEnabled = false;
-
+ mConfig->samplingRate = mSamplingRate;
uint32_t memRequirements = pvmp3_decoderMemRequirements();
mDecoderBuf = malloc(memRequirements);
@@ -237,10 +237,13 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) {
if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
&& decoderErr != SIDE_INFO_ERROR) {
ALOGE("mp3 decoder returned error %d", decoderErr);
-
- notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- mSignalledError = true;
- return;
+ if(decoderErr == SYNCH_LOST_ERROR) {
+ mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
+ } else {
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ mSignalledError = true;
+ return;
+ }
}
if (mConfig->outputFrameSize == 0) {
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 8bda7f8..b77cc86 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -308,6 +308,7 @@ private:
void logCatchUp(int64_t ts, int64_t clock, int64_t delta);
void logLate(int64_t ts, int64_t clock, int64_t delta);
void logOnTime(int64_t ts, int64_t clock, int64_t delta);
+ void printStats();
int64_t getTimeOfDayUs();
#ifdef QCOM_HARDWARE
void checkTunnelExceptions();
diff --git a/media/libstagefright/include/QCUtilityClass.h b/media/libstagefright/include/QCUtilityClass.h
new file mode 100644
index 0000000..91b184f
--- /dev/null
+++ b/media/libstagefright/include/QCUtilityClass.h
@@ -0,0 +1,111 @@
+/*Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef QC_UTIL_CLASS_H_
+#define QC_UTIL_CLASS_H_
+
+#include <QCMetaData.h>
+#include <cutils/properties.h>
+#include <QCMediaDefs.h>
+
+#include <media/Metadata.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/MediaCodecList.h>
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <utils/StrongPointer.h>
+
+#include <media/MediaRecorderBase.h>
+#include <camera/CameraParameters.h>
+
+#include <OMX_Video.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+namespace android {
+
+struct QCUtilityClass
+{
+ // helper function to enable Stagefright Recoder to recalculate fileduration
+ // when hfr property is set
+ static status_t helper_StageFrightRecoder_hfr(sp<MetaData> &meta, sp<MetaData> &enc_meta,
+ int64_t &maxFileDurationUs, int32_t frameRate,
+ video_encoder videoEncoder);
+
+ // helper function to enable camera source to set kKeyHFR when video-hfr is enabled
+ static void helper_CameraSource_hfr(const CameraParameters& params, sp<MetaData> &meta);
+
+ // helper function to enable MPEG4Writer to compute timestamp when hfr is enable
+ static void helper_MPEG4Writer_hfr(sp<MetaData> &meta, int64_t &timestampUs);
+
+ // helper function to enable OMXCodec to recalculate frameRate, bitrate when hfr is enable
+ static void helper_OMXCodec_hfr(const sp<MetaData> &meta, int32_t &frameRate,
+ int32_t &bitRate, int32_t &newFrameRate);
+
+ // helper function to enable OMXCodec to set HFR and FrameRate on output format when
+ // present on input format
+ static void helper_OMXCodec_hfr(const sp<MetaData> &inputFormat, sp<MetaData> &outputFormat);
+
+ // helper function to disable audio when decode audio disable prop is set
+ static bool helper_Awesomeplayer_checkIfAudioDisable();
+
+ // helper function to disable audio when encode audio disable prop is set
+ static bool helper_StagefrightRecoder_checkIfAudioDisable();
+
+ //helper function to set encoding profiles
+ static void helper_StagefrightRecoder_setUserprofile(video_encoder &videoEncoder,
+ int32_t &videoEncoderProfile);
+ //helper function to setBframe related info for MPEG4type
+ static void helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_MPEG4TYPE &mpeg4type, bool &numBFrames);
+
+ //helper function to setBframe related info for H264 type
+ static void helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_AVCTYPE &h264type, bool &numBFrames,
+ int32_t iFramesInterval, int32_t frameRate);
+
+ //helper function to add media codecs with specific quirks
+ static void helper_addMediaCodec(Vector<MediaCodecList::CodecInfo> &mCodecInfos,
+ KeyedVector<AString, size_t> &mTypes,
+ bool encoder, const char *name,
+ const char *type, uint32_t quirks);
+
+ //helper function to calculate the value of quirks from strings
+ static uint32_t helper_getCodecSpecificQuirks(KeyedVector<AString, size_t> &mCodecQuirks,
+ Vector<AString> quirks);
+ static sp<MediaExtractor> helper_MediaExtractor_CreateIfNeeded(sp<MediaExtractor> defaultExt,
+ const sp<DataSource> &source,
+ const char *mime);
+};
+
+}
+#endif //QC_UTIL_CLASS
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index bff3def..e41b342 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -599,15 +599,20 @@ status_t OMXNodeInstance::freeBuffer(
OMX_U32 portIndex, OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
- removeActiveBuffer(portIndex, buffer);
-
OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
- delete buffer_meta;
- buffer_meta = NULL;
+ if (err != OMX_ErrorNone) {
+ ALOGW("OMX_FreeBuffer failed w/ err %x, do not remove from active buffer list", err);
+ } else {
+ ALOGI("OMX_FreeBuffer for buffer header %p successful", header);
+ removeActiveBuffer(portIndex, buffer);
+
+ delete buffer_meta;
+ buffer_meta = NULL;
+ }
return StatusFromOMXError(err);
}