diff options
-rw-r--r-- | include/media/stagefright/MediaDefs.h | 1 | ||||
-rw-r--r-- | include/media/stagefright/QCOMXCodec.h | 3 | ||||
-rw-r--r-- | include/media/stagefright/TunnelPlayer.h | 5 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 2 | ||||
-rw-r--r-- | media/libstagefright/AudioSource.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 21 | ||||
-rw-r--r-- | media/libstagefright/LPAPlayerALSA.cpp | 2 | ||||
-rw-r--r-- | media/libstagefright/MediaExtractor.cpp | 56 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 4 | ||||
-rw-r--r-- | media/libstagefright/QCOMXCodec.cpp | 44 | ||||
-rw-r--r-- | media/libstagefright/TunnelPlayer.cpp | 87 |
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(×tamp); - 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(); |