summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/MediaDefs.h1
-rw-r--r--include/media/stagefright/QCOMXCodec.h3
-rw-r--r--include/media/stagefright/TunnelPlayer.h5
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp2
-rw-r--r--media/libstagefright/AudioSource.cpp3
-rw-r--r--media/libstagefright/AwesomePlayer.cpp21
-rw-r--r--media/libstagefright/LPAPlayerALSA.cpp2
-rw-r--r--media/libstagefright/MediaExtractor.cpp56
-rw-r--r--media/libstagefright/OMXCodec.cpp4
-rw-r--r--media/libstagefright/QCOMXCodec.cpp44
-rw-r--r--media/libstagefright/TunnelPlayer.cpp87
11 files changed, 175 insertions, 53 deletions
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 457d5d7..f63926c 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -31,6 +31,7 @@ extern const char *MEDIA_MIMETYPE_VIDEO_RAW;
extern const char *MEDIA_MIMETYPE_AUDIO_AMR_NB;
extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB;
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS;
extern const char *MEDIA_MIMETYPE_AUDIO_MPEG; // layer III
extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I;
extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
diff --git a/include/media/stagefright/QCOMXCodec.h b/include/media/stagefright/QCOMXCodec.h
index 7259af9..485c187 100644
--- a/include/media/stagefright/QCOMXCodec.h
+++ b/include/media/stagefright/QCOMXCodec.h
@@ -91,6 +91,9 @@ struct QCOMXCodec {
static void checkQCRole(const sp<IOMX> &omx, IOMX::node_id node,
bool isEncoder,const char *mime);
+ static void setQCSpecificVideoFormat(const sp<MetaData> &meta, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID, char* componentName );
+
};
}
diff --git a/include/media/stagefright/TunnelPlayer.h b/include/media/stagefright/TunnelPlayer.h
index 71c4f10..04cc750 100644
--- a/include/media/stagefright/TunnelPlayer.h
+++ b/include/media/stagefright/TunnelPlayer.h
@@ -212,12 +212,11 @@ private:
A2DP_DISCONNECT
};
- int64_t getTimeStamp(A2DPState state);
+ void getPlayedTimeFromDSP_l(int64_t *timeStamp);
+ void getOffsetRealTime_l(int64_t *offsetTime);
size_t fillBuffer(void *data, size_t size);
- int64_t getRealTimeUsLocked();
-
void reset();
TunnelPlayer(const TunnelPlayer &);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index aa25eff..335dd43 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -355,7 +355,7 @@ status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
ALOGV("setParamAudioNumberOfChannels: %d", channels);
- if (channels <= 0 || channels >= 3) {
+ if (channels != 1 && channels != 2 && channels != 6) {
ALOGE("Invalid number of audio channels: %d", channels);
return BAD_VALUE;
}
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 861aebe..8e3811b 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
+ * Copyright (c) 2012, 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.
@@ -56,7 +57,7 @@ AudioSource::AudioSource(
mNumFramesReceived(0),
mNumClientOwnedBuffers(0) {
ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount);
- CHECK(channelCount == 1 || channelCount == 2);
+ CHECK(channelCount == 1 || channelCount == 2 || channelCount == 6);
int minFrameCount;
status_t status = AudioRecord::getMinFrameCount(&minFrameCount,
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 5cffad8..9c0e799 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -967,9 +967,18 @@ status_t AwesomePlayer::play_l() {
}
tunnelObjectsAlive = (TunnelPlayer::mTunnelObjectsAlive);
#endif
+ int32_t nchannels = 0;
+ if(mAudioTrack != NULL) {
+ sp<MetaData> format = mAudioTrack->getFormat();
+ if(format != NULL) {
+ format->findInt32( kKeyChannelCount, &nchannels );
+ ALOGV("nchannels %d;LPA will be skipped if nchannels is > 2 or nchannels == 0",nchannels);
+ }
+ }
char lpaDecode[128];
property_get("lpa.decode",lpaDecode,"0");
- if((strcmp("true",lpaDecode) == 0) && (mAudioPlayer == NULL) && tunnelObjectsAlive==0 )
+ if((strcmp("true",lpaDecode) == 0) && (mAudioPlayer == NULL) &&
+ (tunnelObjectsAlive==0) && (nchannels && (nchannels <= 2)))
{
ALOGV("LPAPlayer::getObjectsAlive() %d",LPAPlayer::objectsAlive);
if ( mDurationUs > 60000000
@@ -1486,6 +1495,11 @@ status_t AwesomePlayer::initAudioDecoder() {
const char *mime;
CHECK(meta->findCString(kKeyMIMEType, &mime));
#ifdef QCOM_ENHANCED_AUDIO
+ int32_t nchannels = 0;
+ meta->findInt32( kKeyChannelCount, &nchannels );
+ ALOGV("nchannels %d;LPA will be skipped if nchannels is > 2 or nchannels == 0",
+ nchannels);
+
#ifdef USE_TUNNEL_MODE
char value[PROPERTY_VALUE_MAX];
char tunnelDecode[128];
@@ -1498,6 +1512,8 @@ status_t AwesomePlayer::initAudioDecoder() {
(TunnelPlayer::mTunnelObjectsAlive == 0) &&
mTunnelAliveAP == 0 &&
((!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) ||
+ (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) ||
+ (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) ||
(!strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_AAC)))) {
if(mVideoSource != NULL) {
@@ -1542,7 +1558,8 @@ status_t AwesomePlayer::initAudioDecoder() {
}
if ( mDurationUs > 60000000
&& (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG) || !strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_AAC))
- && LPAPlayer::objectsAlive == 0 && mVideoSource == NULL && (strcmp("true",lpaDecode) == 0)) {
+ && LPAPlayer::objectsAlive == 0 && mVideoSource == NULL && (strcmp("true",lpaDecode) == 0)
+ && (nchannels && (nchannels <= 2)) ) {
char nonOMXDecoder[128];
if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
ALOGD("matchComponentName is set to MP3Decoder %lld, mime %s",mDurationUs,mime);
diff --git a/media/libstagefright/LPAPlayerALSA.cpp b/media/libstagefright/LPAPlayerALSA.cpp
index bec02d4..38d6bac 100644
--- a/media/libstagefright/LPAPlayerALSA.cpp
+++ b/media/libstagefright/LPAPlayerALSA.cpp
@@ -782,6 +782,8 @@ void LPAPlayer::onPauseTimeOut() {
}
ALOGV("newseek time = %lld ", mSeekTimeUs);
// 2.) Close routing Session
+ mAudioSink->flush();
+ mAudioSink->stop();
mAudioSink->close();
mIsAudioRouted = false;
}
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index cca49fe..833084a 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaExtractor"
#include <utils/Log.h>
+#include <cutils/properties.h>
#include "include/AMRExtractor.h"
#include "include/MP3Extractor.h"
@@ -57,6 +58,7 @@ 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) {
@@ -103,6 +105,15 @@ sp<MediaExtractor> MediaExtractor::Create(
} else {
ret = new MPEG4Extractor(source);
}
+#ifdef QCOM_ENHANCED_AUDIO
+ char tunnelDecode[PROPERTY_VALUE_MAX];
+ ALOGV("MediaExtractor::Create checking tunnel.decode");
+ property_get("tunnel.decode",tunnelDecode,"0");
+ if( (strncmp("true",tunnelDecode,4) == 0) || (atoi(tunnelDecode)) ) {
+ bCheckExtendedExtractor = true;
+ ALOGV("MediaExtractor::Create detected tunnel.decode as true...");
+ }
+#endif
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
ret = new MP3Extractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
@@ -136,13 +147,48 @@ sp<MediaExtractor> MediaExtractor::Create(
}
#ifdef QCOM_HARDWARE
- if(ret == NULL) {
- //Create Extended Extractor only if default extractor are not selected
- ALOGV("Using ExtendedExtractor\n");
- ret = ExtendedExtractor::CreateExtractor(source, mime);
+ //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;
}
-#endif
+ //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
return ret;
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4e6c395..1992533 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -705,6 +705,10 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
if (err != OK) {
return err;
}
+
+#ifdef QCOM_HARDWARE
+ QCOMXCodec::setQCSpecificVideoFormat(meta,mOMX,mNode,mComponentName );
+#endif
}
}
diff --git a/media/libstagefright/QCOMXCodec.cpp b/media/libstagefright/QCOMXCodec.cpp
index 1b24c8b..0d5768a 100644
--- a/media/libstagefright/QCOMXCodec.cpp
+++ b/media/libstagefright/QCOMXCodec.cpp
@@ -545,4 +545,48 @@ status_t QCOMXCodec::checkQCFormats(int format, AString* meta){
return retVal;
}
+void QCOMXCodec::setQCSpecificVideoFormat(const sp<MetaData> &meta, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID, char* componentName ) {
+ int32_t arbitraryMode = 1;
+ bool success = meta->findInt32(kKeyUseArbitraryMode, &arbitraryMode);
+ bool useArbitraryMode = true;
+ if (success) {
+ useArbitraryMode = arbitraryMode ? true : false;
+ }
+
+ if (useArbitraryMode) {
+ ALOGI("Decoder should be in arbitrary mode");
+ // Is it required to set OMX_QCOM_FramePacking_Arbitrary ??
+ } else{
+ ALOGI("Enable frame by frame mode");
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE portFmt;
+ portFmt.nPortIndex = OMXCodec::kPortIndexInput;
+ portFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame;
+ status_t err = OMXhandle->setParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_QcomIndexPortDefn, (void *)&portFmt, sizeof(portFmt));
+ if(err != OK) {
+ ALOGW("Failed to set frame packing format on component");
+ }
+ }
+
+ // Enable timestamp reordering only for AVI/mpeg4 and vc1 clips
+ const char *fileFormat;
+ success = meta->findCString(kKeyFileFormat, &fileFormat);
+ if (!strcmp(componentName, "OMX.qcom.video.decoder.vc1") ||
+ (success && !strncmp(fileFormat, "video/avi", 9))) {
+ ALOGI("Enabling timestamp reordering");
+ QOMX_INDEXTIMESTAMPREORDER reorder;
+ InitOMXParams(&reorder);
+ reorder.nPortIndex = OMXCodec::kPortIndexOutput;
+ reorder.bEnable = OMX_TRUE;
+ status_t err = OMXhandle->setParameter(nodeID,
+ (OMX_INDEXTYPE)OMX_QcomIndexParamEnableTimeStampReorder,
+ (void *)&reorder, sizeof(reorder));
+
+ if(err != OK) {
+ ALOGW("Failed to enable timestamp reordering");
+ }
+ }
+}
+
}
diff --git a/media/libstagefright/TunnelPlayer.cpp b/media/libstagefright/TunnelPlayer.cpp
index 34c260f..fa2dc06 100644
--- a/media/libstagefright/TunnelPlayer.cpp
+++ b/media/libstagefright/TunnelPlayer.cpp
@@ -18,8 +18,8 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
//#define LOG_NDDEBUG 0
-#define LOG_NDEBUG 0
#define LOG_TAG "TunnelPlayer"
#include <utils/Log.h>
#include <utils/threads.h>
@@ -313,10 +313,10 @@ status_t TunnelPlayer::start(bool sourceAlreadyStarted) {
mFormat = AUDIO_FORMAT_AMR_WB;
ALOGV("TunnelPlayer::start AUDIO_FORMAT_AMR_WB");
}
-// if (!strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) {
-// mFormat = AUDIO_FORMAT_AMR_WB_PLUS;
-// ALOGV("TunnelPlayer::start AUDIO_FORMAT_AMR_WB_PLUS");
-// }
+ if (!strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) {
+ mFormat = AUDIO_FORMAT_AMR_WB_PLUS;
+ ALOGV("TunnelPlayer::start AUDIO_FORMAT_AMR_WB_PLUS");
+ }
CHECK(success);
@@ -389,15 +389,17 @@ void TunnelPlayer::pause(bool playPendingSamples) {
if (mPaused) {
return;
}
+ Mutex::Autolock autoLock(mLock);
ALOGV("pause: playPendingSamples %d", playPendingSamples);
mPaused = true;
- A2DPState state;
+ int64_t playedTime = 0;
if(!mPauseEventPending) {
ALOGV("Posting an event for Pause timeout");
mQueue.postEventWithDelay(mPauseEvent, TUNNEL_PAUSE_TIMEOUT_USEC);
mPauseEventPending = true;
}
- mPauseTime = mSeekTimeUs + getTimeStamp(A2DP_DISABLED);
+ getPlayedTimeFromDSP_l(&playedTime);
+ mPauseTime = mSeekTimeUs + playedTime;
if (mAudioSink.get() != NULL) {
ALOGV("AudioSink pause");
mAudioSink->pause();
@@ -460,8 +462,11 @@ void TunnelPlayer::reset() {
requestAndWaitForExtractorThreadExit();
// Close the audiosink after all the threads exited to make sure
- mAudioSink->stop();
- mAudioSink->close();
+ if (mIsAudioRouted) {
+ mAudioSink->stop();
+ mAudioSink->close();
+ mIsAudioRouted = false;
+ }
//TODO: Release Wake lock
// Make sure to release any buffer we hold onto so that the
@@ -696,43 +701,33 @@ size_t TunnelPlayer::fillBuffer(void *data, size_t size) {
int64_t TunnelPlayer::getRealTimeUs() {
Mutex::Autolock autoLock(mLock);
- return getRealTimeUsLocked();
+ getOffsetRealTime_l(&mPositionTimeRealUs);
+ //update media time too
+ mPositionTimeMediaUs = mPositionTimeRealUs;
+ return mPositionTimeRealUs;
}
-
-int64_t TunnelPlayer::getRealTimeUsLocked(){
- //Used for AV sync: irrelevant API for Tunnel.
- return 0;
+void TunnelPlayer::getPlayedTimeFromDSP_l(int64_t* timeStamp ) {
+ mAudioSink->getTimeStamp((uint64_t*)timeStamp);
+ ALOGV("timestamp returned from DSP %lld ", (*timeStamp));
+ return;
}
-int64_t TunnelPlayer::getTimeStamp(A2DPState state) {
- uint64_t timestamp = 0;
- switch (state) {
- case A2DP_ENABLED:
- case A2DP_DISCONNECT:
- ALOGV("Get timestamp for A2DP");
- break;
- case A2DP_DISABLED:
- case A2DP_CONNECT: {
- mAudioSink->getTimeStamp(&timestamp);
- break;
- }
- default:
- break;
+//offset with pause and seek time
+void TunnelPlayer::getOffsetRealTime_l(int64_t* offsetTime) {
+ if (mPaused) {
+ *offsetTime = mPauseTime;
+ ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld", mPaused, mSeekTimeUs, mPauseTime );
+ } else {
+ getPlayedTimeFromDSP_l(offsetTime);
+ ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld, timeStamp %lld", mPaused, mSeekTimeUs, mPauseTime, *offsetTime);
+ *offsetTime = mSeekTimeUs + *offsetTime;
}
- ALOGV("timestamp %lld ", timestamp);
- return timestamp;
}
int64_t TunnelPlayer::getMediaTimeUs() {
- Mutex::Autolock autoLock(mLock);
- ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld", mPaused, mSeekTimeUs, mPauseTime);
- if (mPaused) {
- return mPauseTime;
- } else {
- A2DPState state = mIsA2DPEnabled ? A2DP_ENABLED : A2DP_DISABLED;
- return (mSeekTimeUs + getTimeStamp(state));
- }
+ //essentially there is only one time, the real time
+ return getRealTimeUs();
}
bool TunnelPlayer::getMediaTimeMapping(
@@ -749,7 +744,8 @@ void TunnelPlayer::requestAndWaitForExtractorThreadExit() {
if (!extractorThreadAlive)
return;
- mAudioSink->flush();
+ if (mIsAudioRouted)
+ mAudioSink->flush();
killExtractorThread = true;
pthread_cond_signal(&extractor_cv);
pthread_join(extractorThread,NULL);
@@ -757,6 +753,7 @@ void TunnelPlayer::requestAndWaitForExtractorThreadExit() {
}
void TunnelPlayer::onPauseTimeOut() {
+ int64_t playedTime = 0;
ALOGV("onPauseTimeOut");
if (!mPauseEventPending) {
return;
@@ -766,8 +763,16 @@ void TunnelPlayer::onPauseTimeOut() {
// 1.) Set seek flags
mReachedEOS = false;
mReachedOutputEOS = false;
- mSeekTimeUs += getTimeStamp(A2DP_DISABLED);
- mInternalSeeking = true;
+
+ if(mSeeking == false) {
+ mInternalSeeking = true;
+ mLock.lock();
+ getPlayedTimeFromDSP_l(&playedTime);
+ mLock.unlock();
+ mSeekTimeUs += playedTime;
+ } else {
+ ALOGV("Do not update seek time if it was seeked before onpause timeout");
+ }
// 2.) Close routing Session
mAudioSink->close();