From eeffae051aa7d192e909f7d1cb6e3e925774d5cd Mon Sep 17 00:00:00 2001 From: Dilip Gopalakrishna Date: Thu, 8 Oct 2015 16:41:09 -0700 Subject: libcameraservice: Fix ALOG prints in FlashLight. Add missing __FUNCTION__ arguments into log statements. Change-Id: I0256bad626d490fb9360a73c104afaad7a012a97 --- services/camera/libcameraservice/CameraFlashlight.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp index 280bb9d..fd23ef9 100644 --- a/services/camera/libcameraservice/CameraFlashlight.cpp +++ b/services/camera/libcameraservice/CameraFlashlight.cpp @@ -99,7 +99,8 @@ status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) { status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) { if (!mFlashlightMapInitialized) { - ALOGE("%s: findFlashUnits() must be called before this method."); + ALOGE("%s: findFlashUnits() must be called before this method.", + __FUNCTION__); return NO_INIT; } @@ -200,7 +201,8 @@ bool CameraFlashlight::hasFlashUnit(const String8& cameraId) { bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) { if (!mFlashlightMapInitialized) { - ALOGE("%s: findFlashUnits() must be called before this method."); + ALOGE("%s: findFlashUnits() must be called before this method.", + __FUNCTION__); return false; } @@ -219,7 +221,8 @@ status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) { Mutex::Autolock l(mLock); if (!mFlashlightMapInitialized) { - ALOGE("%s: findFlashUnits() must be called before this method."); + ALOGE("%s: findFlashUnits() must be called before this method.", + __FUNCTION__); return NO_INIT; } @@ -256,7 +259,8 @@ status_t CameraFlashlight::deviceClosed(const String8& cameraId) { Mutex::Autolock l(mLock); if (!mFlashlightMapInitialized) { - ALOGE("%s: findFlashUnits() must be called before this method."); + ALOGE("%s: findFlashUnits() must be called before this method.", + __FUNCTION__); return NO_INIT; } -- cgit v1.1 From 31d09de28b6ca2e79c2d157a6412759e3aa88804 Mon Sep 17 00:00:00 2001 From: Ashish Jain Date: Tue, 20 Oct 2015 12:30:49 +0530 Subject: stagefright: Enable QTI FLAC based on feature flag -QTI Flac decoder is used only if QTI_FLAC_DECODER flag is defined. -Enable QTI_FLAC_DECODER flag if respective feature flag is enabled. Change-Id: I192e30af3e53a57f13aa2be5dc92bfbe5f20d096 CRs-Fixed: 927012 --- media/libstagefright/Android.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 03e7e46..b2729af 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -137,6 +137,12 @@ ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) LOCAL_CFLAGS += -DENABLE_STAGEFRIGHT_EXPERIMENTS endif +ifeq ($(call is-vendor-board-platform,QCOM),true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true) + LOCAL_CFLAGS += -DQTI_FLAC_DECODER +endif +endif + LOCAL_CLANG := true LOCAL_MODULE:= libstagefright -- cgit v1.1 From 9be69bd990889cc942a53c22f6f8463f146fd8e7 Mon Sep 17 00:00:00 2001 From: Shivaprasad Hongal Date: Fri, 18 Sep 2015 15:17:14 -0700 Subject: stagefright: Remove additional deep-copy of encoder buffers MPEG4Writer makes a copy of encoded buffer to avoid holding on to the read buffer. This is not needed with MediaCodecSource, as the encoded-output buffer is already copied to a heap buffer. This saves a copy and some power. However, cloning the buffer is still needed for upstream sources that cannot afford to keep the buffers with writer up until they are released. So, pass a hint in buffer's metadata to indicate if it is OK to delay the release and not copy the buffer Change-Id: Ib59ac29ebc6ce4afd6fc272688a8260438ab1517 --- media/libavextensions/stagefright/AVExtensions.h | 3 +++ media/libstagefright/MPEG4Writer.cpp | 26 ++++++++++++++++-------- media/libstagefright/MediaCodecSource.cpp | 2 ++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/media/libavextensions/stagefright/AVExtensions.h b/media/libavextensions/stagefright/AVExtensions.h index 9c712e4..17ea475 100644 --- a/media/libavextensions/stagefright/AVExtensions.h +++ b/media/libavextensions/stagefright/AVExtensions.h @@ -161,6 +161,9 @@ struct AVUtils { virtual bool useQCHWEncoder(const sp &, AString &) { return false; } + virtual bool canDeferRelease(const sp &/*meta*/) { return false; } + virtual void setDeferRelease(sp &/*meta*/) {} + struct HEVCMuxer { virtual bool reassembleHEVCCSD(const AString &mime, sp csd0, sp &meta); diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 94f40b4..cb9df29 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -2284,15 +2284,23 @@ status_t MPEG4Writer::Track::threadEntry() { continue; } - // Make a deep copy of the MediaBuffer and Metadata and release - // the original as soon as we can - MediaBuffer *copy = new MediaBuffer(buffer->range_length()); - memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), - buffer->range_length()); - copy->set_range(0, buffer->range_length()); - meta_data = new MetaData(*buffer->meta_data().get()); - buffer->release(); - buffer = NULL; + MediaBuffer *copy = NULL; + // Check if the upstream source hints it is OK to hold on to the + // buffer without releasing immediately and avoid cloning the buffer + if (AVUtils::get()->canDeferRelease(buffer->meta_data())) { + copy = buffer; + meta_data = new MetaData(*buffer->meta_data().get()); + } else { + // Make a deep copy of the MediaBuffer and Metadata and release + // the original as soon as we can + copy = new MediaBuffer(buffer->range_length()); + memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), + buffer->range_length()); + copy->set_range(0, buffer->range_length()); + meta_data = new MetaData(*buffer->meta_data().get()); + buffer->release(); + buffer = NULL; + } if (mIsAvc || mIsHEVC) StripStartcode(copy); diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp index dbd9cb0..925be14 100644 --- a/media/libstagefright/MediaCodecSource.cpp +++ b/media/libstagefright/MediaCodecSource.cpp @@ -759,6 +759,8 @@ void MediaCodecSource::onMessageReceived(const sp &msg) { MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); memcpy(mbuf->data(), outbuf->data(), outbuf->size()); + sp meta = mbuf->meta_data(); + AVUtils::get()->setDeferRelease(meta); if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { if (mIsVideo) { -- cgit v1.1 From 85ad714b38516807efe40d67da406208d72b0dd0 Mon Sep 17 00:00:00 2001 From: Shalaj Jain Date: Wed, 21 Oct 2015 19:01:59 -0700 Subject: stagefright: Return error for wrong buffer index in MediaCodec Return error if the index passed by client is incorrect rather than returning OK with null buffer. Also add a null buffer check in MPEG4Writer as it shouldn't rely on the source returning the correct error code, just as a precaution. Change-Id: Iaefcd57a545ec3ce4ec0b8d4220bdf41377ff798 --- media/libstagefright/MPEG4Writer.cpp | 4 +++- media/libstagefright/MediaCodec.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 94f40b4..c370260 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -2231,7 +2231,9 @@ status_t MPEG4Writer::Track::threadEntry() { MediaBuffer *buffer; const char *trackName = mIsAudio ? "Audio" : "Video"; while (!mDone && (err = mSource->read(&buffer)) == OK) { - if (buffer->range_length() == 0) { + if (buffer == NULL) { + continue; + } else if (buffer->range_length() == 0) { buffer->release(); buffer = NULL; ++nZeroLengthFrames; diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 7f7c7fa..c6ba76e 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -871,6 +871,8 @@ status_t MediaCodec::getBufferAndFormat( } *format = info.mFormat; } + } else { + return BAD_INDEX; } return OK; } -- cgit v1.1 From d4c3afbb613f7201ece31ad2230ec22289422680 Mon Sep 17 00:00:00 2001 From: Sidipotu Ashok Date: Fri, 16 Oct 2015 06:16:13 +0530 Subject: NuPlayer: use a generic funtion to get flags Use a generic function to get flags while creating extractor, so that there is no restriction to a particular usecase. CRs-Fixed: 911338 Change-Id: I8520d2ea9b25ab564b7eee6610744fcaa364fe87 --- media/libavextensions/mediaplayerservice/AVNuExtensions.h | 2 +- media/libavextensions/mediaplayerservice/AVNuUtils.cpp | 2 +- media/libmediaplayerservice/nuplayer/GenericSource.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/media/libavextensions/mediaplayerservice/AVNuExtensions.h b/media/libavextensions/mediaplayerservice/AVNuExtensions.h index c6aba71..7aeb5c3 100644 --- a/media/libavextensions/mediaplayerservice/AVNuExtensions.h +++ b/media/libavextensions/mediaplayerservice/AVNuExtensions.h @@ -80,7 +80,7 @@ struct AVNuUtils { virtual void setDecodedPCMFormat(const sp &); virtual status_t convertToSinkFormatIfNeeded(const sp &, sp &, audio_format_t sinkFormat, bool isOffload); - virtual uint32_t getUseSetBuffersFlag(); + virtual uint32_t getFlags(); virtual bool canUseSetBuffers(const sp &Meta); virtual void printFileName(int fd); diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp index c254a70..51c4a37 100644 --- a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp +++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp @@ -104,7 +104,7 @@ void AVNuUtils::checkFormatChange(bool * /*formatChange*/, const sp & /*accessUnit*/) { } -uint32_t AVNuUtils::getUseSetBuffersFlag() { +uint32_t AVNuUtils::getFlags() { return 0; } diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index efdf096..5c68e81 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -175,7 +175,7 @@ status_t NuPlayer::GenericSource::initFromDataSource() { } else { extractor = MediaExtractor::Create(mDataSource, mimeType.isEmpty() ? NULL : mimeType.string(), - mIsStreaming ? 0 : AVNuUtils::get()->getUseSetBuffersFlag()); + mIsStreaming ? 0 : AVNuUtils::get()->getFlags()); } if (extractor == NULL) { -- cgit v1.1 From bbb9b1da50edbbed193b342be19b62e232254f27 Mon Sep 17 00:00:00 2001 From: Praveen Chavan Date: Mon, 19 Oct 2015 14:44:52 -0700 Subject: GenericSource: Synchronize access to dataSource DataSource and HTTPSource can be accessed/modified by GenericSource's looper and Client's thread which can lead to race conditions when copying the sp<>. Add a Mutex lock to synchronize such accesses and avoid race conditions. CRs-Fixed: 906899 Change-Id: I2fb4b4a7079e638e151f4fe67a780007a4011652 --- .../nuplayer/GenericSource.cpp | 22 +++++++++++++++++----- .../libmediaplayerservice/nuplayer/GenericSource.h | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index 6957a90..6406971 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -126,6 +126,7 @@ status_t NuPlayer::GenericSource::setDataSource( status_t NuPlayer::GenericSource::setDataSource(const sp& source) { resetDataSource(); + Mutex::Autolock _l(mSourceLock); mDataSource = source; return OK; } @@ -372,6 +373,7 @@ void NuPlayer::GenericSource::onPrepareAsync() { } } + Mutex::Autolock _l(mSourceLock); mDataSource = DataSource::CreateFromURI( mHTTPService, uri, &mUriHeaders, &contentType, static_cast(mHttpSource.get()), @@ -379,6 +381,7 @@ void NuPlayer::GenericSource::onPrepareAsync() { } else { mIsWidevine = false; + Mutex::Autolock _l(mSourceLock); mDataSource = new FileSource(mFd, mOffset, mLength); mFd = -1; } @@ -468,6 +471,7 @@ void NuPlayer::GenericSource::finishPrepareAsync() { void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { if (err != OK) { + Mutex::Autolock _l(mSourceLock); mDataSource.clear(); mCachedSource.clear(); mHttpSource.clear(); @@ -523,13 +527,21 @@ void NuPlayer::GenericSource::resume() { } void NuPlayer::GenericSource::disconnect() { - if (mDataSource != NULL) { + + sp dataSource; + sp httpSource; + { + Mutex::Autolock _l(mSourceLock); + dataSource = mDataSource; + httpSource = mHttpSource; + } + if (dataSource != NULL) { // disconnect data source - if (mDataSource->flags() & DataSource::kIsCachingDataSource) { - static_cast(mDataSource.get())->disconnect(); + if (dataSource->flags() & DataSource::kIsCachingDataSource) { + static_cast(dataSource.get())->disconnect(); } - } else if (mHttpSource != NULL) { - static_cast(mHttpSource.get())->disconnect(); + } else if (httpSource != NULL) { + static_cast(httpSource.get())->disconnect(); } } diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h index 0181947..beaee9a 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.h +++ b/media/libmediaplayerservice/nuplayer/GenericSource.h @@ -136,6 +136,7 @@ protected: int64_t mOffset; int64_t mLength; + Mutex mSourceLock; sp mDataSource; sp mCachedSource; sp mHttpSource; -- cgit v1.1 From 1dafcd15418346edb5b0fd1a925a29ea90b5c3c2 Mon Sep 17 00:00:00 2001 From: Shivaprasad Hongal Date: Fri, 23 Oct 2015 11:43:19 -0700 Subject: GenericSource: Hold an additional reference to dataSource. mDataSource can be deleted by client thread while GenericSource looper is accessing dataSource in sniff functions, which can lead to race condition. Add local sp<> to hold an additional reference to dataSource. Change-Id: I9e51f75f3c2bd703e381230dd93cb4d3f6621dab CRs-Fixed: 923729 --- media/libmediaplayerservice/nuplayer/GenericSource.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index 6406971..b9cb1ca 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -154,7 +154,12 @@ status_t NuPlayer::GenericSource::initFromDataSource() { return UNKNOWN_ERROR; } } else if (mIsStreaming) { - if (!mDataSource->sniff(&mimeType, &confidence, &dummy)) { + sp dataSource; + { + Mutex::Autolock _l(mSourceLock); + dataSource = mDataSource; + } + if (!dataSource->sniff(&mimeType, &confidence, &dummy)) { return UNKNOWN_ERROR; } isWidevineStreaming = !strcasecmp( -- cgit v1.1 From a729f437f5f46efbd366721d7d4f398186ce77cd Mon Sep 17 00:00:00 2001 From: Shalaj Jain Date: Tue, 13 Oct 2015 17:56:23 -0700 Subject: nuplayer: Drop frames with DATACORRUPT flag Drop frames in NuplayerDecoder if the corresponding OMX_BUFFERFLAG_DATACORRUPT is set from OMX. Add a util function to easily switch off this feature. Do not declare MediaSource explicitly. Change-Id: I97bd238d52d660e1ab61eac222cdff28334cc5cc --- include/media/stagefright/MediaCodec.h | 1 + media/libavextensions/mediaplayerservice/AVNuExtensions.h | 1 + media/libavextensions/mediaplayerservice/AVNuUtils.cpp | 2 ++ media/libavextensions/stagefright/AVExtensions.h | 1 - media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp | 8 ++++++++ media/libstagefright/MediaCodec.cpp | 6 ++++++ 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index b0ae83b..9c489e5 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -52,6 +52,7 @@ struct MediaCodec : public AHandler { BUFFER_FLAG_CODECCONFIG = 2, BUFFER_FLAG_EOS = 4, BUFFER_FLAG_EXTRADATA = 0x1000, + BUFFER_FLAG_DATACORRUPT = 0x2000, }; enum { diff --git a/media/libavextensions/mediaplayerservice/AVNuExtensions.h b/media/libavextensions/mediaplayerservice/AVNuExtensions.h index 7aeb5c3..1d45c00 100644 --- a/media/libavextensions/mediaplayerservice/AVNuExtensions.h +++ b/media/libavextensions/mediaplayerservice/AVNuExtensions.h @@ -85,6 +85,7 @@ struct AVNuUtils { virtual void printFileName(int fd); virtual void checkFormatChange(bool *formatChange, const sp &accessUnit); + virtual bool dropCorruptFrame(); // ----- NO TRESSPASSING BEYOND THIS LINE ------ DECLARE_LOADABLE_SINGLETON(AVNuUtils); diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp index 51c4a37..95f6454 100644 --- a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp +++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp @@ -112,6 +112,8 @@ bool AVNuUtils::canUseSetBuffers(const sp &/*Meta*/) { return false; } +bool AVNuUtils::dropCorruptFrame() { return false; } + // ----- NO TRESSPASSING BEYOND THIS LINE ------ AVNuUtils::AVNuUtils() {} diff --git a/media/libavextensions/stagefright/AVExtensions.h b/media/libavextensions/stagefright/AVExtensions.h index b45c051..891c7f8 100644 --- a/media/libavextensions/stagefright/AVExtensions.h +++ b/media/libavextensions/stagefright/AVExtensions.h @@ -47,7 +47,6 @@ struct ACodec; struct ALooper; struct IMediaHTTPConnection; struct MediaCodec; -struct MediaSource; struct MediaHTTP; struct NuCachedSource2; class CameraParameters; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index f83eaf6..997920b 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -590,6 +590,14 @@ bool NuPlayer::Decoder::handleAnOutputBuffer( reply->setSize("buffer-ix", index); reply->setInt32("generation", mBufferGeneration); + if ((flags & MediaCodec::BUFFER_FLAG_DATACORRUPT) && + AVNuUtils::get()->dropCorruptFrame()) { + ALOGV("[%s] dropping corrupt buffer at time %lld as requested.", + mComponentName.c_str(), (long long)timeUs); + reply->post(); + return true; + } + if (eos) { ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video"); diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 7f7c7fa..3ae2056 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -987,6 +987,9 @@ bool MediaCodec::handleDequeueOutputBuffer(const sp &replyID, bool if (omxFlags & OMX_BUFFERFLAG_EXTRADATA) { flags |= BUFFER_FLAG_EXTRADATA; } + if (omxFlags & OMX_BUFFERFLAG_DATACORRUPT) { + flags |= BUFFER_FLAG_DATACORRUPT; + } response->setInt32("flags", flags); response->postReply(replyID); @@ -2631,6 +2634,9 @@ void MediaCodec::onOutputBufferAvailable() { if (omxFlags & OMX_BUFFERFLAG_EOS) { flags |= BUFFER_FLAG_EOS; } + if (omxFlags & OMX_BUFFERFLAG_DATACORRUPT) { + flags |= BUFFER_FLAG_DATACORRUPT; + } msg->setInt32("flags", flags); -- cgit v1.1 From 4f33629b62ad90687973c8496d9b60f4f18e26b1 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Fri, 4 Sep 2015 14:15:58 -0700 Subject: DO NOT MERGE: CameraService: Link to client binder death at end of connect If, within a binder Looper thread, a Binder object death notifier is registered, and then a nested Binder transaction is begun, that transaction may process a death notification callback for the just-registered object, if it was dead at the time of registration. This can lead to an unexpected nested call into the service, and cause deadlock. To avoid this, move the death notifier registration to the end of handling the connect transaction. Also remove one extra bit of disconnect logging. Bug: 23525545 Change-Id: If01cbaf42704f55134118afefc9a8f7bdb014e09 --- services/camera/libcameraservice/CameraService.cpp | 14 +++++++++++--- services/camera/libcameraservice/CameraService.h | 5 ----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 9a1101a..e4f792d 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -935,6 +935,16 @@ void CameraService::finishConnectLocked(const sp& client, LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, clients not evicted properly", __FUNCTION__); } + + // And register a death notification for the client callback. Do + // this last to avoid Binder policy where a nested Binder + // transaction might be pre-empted to service the client death + // notification if the client process dies before linkToDeath is + // invoked. + sp remoteCallback = client->getRemote(); + if (remoteCallback != nullptr) { + remoteCallback->linkToDeath(this); + } } status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid, @@ -1874,11 +1884,9 @@ CameraService::BasicClient::~BasicClient() { void CameraService::BasicClient::disconnect() { if (mDisconnected) { - ALOGE("%s: Disconnect called on already disconnected client for device %d", __FUNCTION__, - mCameraId); return; } - mDisconnected = true;; + mDisconnected = true; mCameraService->removeByClient(this); mCameraService->logDisconnected(String8::format("%d", mCameraId), mClientPid, diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index b56c161..b29317e 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -861,11 +861,6 @@ status_t CameraService::connectHelper(const sp& cameraCb, const String return ret; } - sp remoteCallback = client->getRemote(); - if (remoteCallback != nullptr) { - remoteCallback->linkToDeath(this); - } - // Update shim paremeters for legacy clients if (effectiveApiLevel == API_1) { // Assume we have always received a Client subclass for API1 -- cgit v1.1 From f72f7d57142cd3415bc189a8a9dee39674117167 Mon Sep 17 00:00:00 2001 From: Susmitha Gummalla Date: Thu, 8 Oct 2015 16:00:33 -0700 Subject: Camera: frameworks: Add NULL check for callback --Added NULL check for mRemoteCallback Change-Id: Ib88a128a52e81b8ec1052e3222b6d8b9e494afcc --- services/camera/libcameraservice/CameraService.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 9a1101a..26c8007 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -2024,7 +2024,11 @@ sp CameraService::Client::getClientFromCookie(void* user) void CameraService::Client::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode, const CaptureResultExtras& resultExtras) { - mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0); + if (mRemoteCallback != NULL) { + mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0); + } else { + ALOGE("mRemoteCallback is NULL!!"); + } } // NOTE: function is idempotent -- cgit v1.1 From 1fb6c97d6cf1ae3264605d912b4e034809e2103a Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Mon, 26 Oct 2015 18:22:13 -0700 Subject: AudioPolicyService: Synchronize access to AudioPolicyManager Synchronize access to APM when getDevicesForStream is called on APM. CRs-Fixed: 913227 Change-Id: I2ba6922341f035375270b02000ef5a7e078f6b5a --- services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 793c26a..58ecb11 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -459,6 +459,7 @@ audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stre if (mAudioPolicyManager == NULL) { return AUDIO_DEVICE_NONE; } + Mutex::Autolock _l(mLock); return mAudioPolicyManager->getDevicesForStream(stream); } -- cgit v1.1 From f17204ea09e5629f3f9d9eba2e66d9fb6ce72357 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 23 Sep 2015 10:25:31 -0700 Subject: AudioPolicyService: fix race in AudioCommandThread Fixe race condition in AudioCommandThread::threadLoop() where a command can be inserted in first position in the queue after the sleep time has been calculated causing a longer delay than expected. Also fix a failure to hold a wake lock while commands are still in the queue. Bug: 22707905. Change-Id: I813626986677bf00106acb37ee20d3dd75d5cf33 --- .../audiopolicy/service/AudioPolicyService.cpp | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index d689065..41dd40c 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -577,22 +577,28 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() } } waitTime = INT64_MAX; + // release mLock before releasing strong reference on the service as + // AudioPolicyService destructor calls AudioCommandThread::exit() which + // acquires mLock. + mLock.unlock(); + svc.clear(); + mLock.lock(); } else { waitTime = mAudioCommands[0]->mTime - curTime; break; } } - // release mLock before releasing strong reference on the service as - // AudioPolicyService destructor calls AudioCommandThread::exit() which acquires mLock. - mLock.unlock(); - svc.clear(); - mLock.lock(); - if (!exitPending() && (mAudioCommands.isEmpty() || waitTime != INT64_MAX)) { - // release delayed commands wake lock + + // release delayed commands wake lock if the queue is empty + if (mAudioCommands.isEmpty()) { release_wake_lock(mName.string()); + } + + // At this stage we have either an empty command queue or the first command in the queue + // has a finite delay. So unless we are exiting it is safe to wait. + if (!exitPending()) { ALOGV("AudioCommandThread() going to sleep"); mWaitWorkCV.waitRelative(mLock, waitTime); - ALOGV("AudioCommandThread() waking up"); } } // release delayed commands wake lock before quitting @@ -1005,6 +1011,8 @@ void AudioPolicyService::AudioCommandThread::exit() requestExit(); mWaitWorkCV.signal(); } + // Note that we can call it from the thread loop if all other references have been released + // but it will safely return WOULD_BLOCK in this case requestExitAndWait(); } -- cgit v1.1 From 14896d6fa21cb76e50b1d6a80527f52067c3a99b Mon Sep 17 00:00:00 2001 From: Sharad Sangle Date: Thu, 8 Oct 2015 23:59:08 +0530 Subject: audio: use QTI flac decoder based on flag While setting up the component for flac, current design is if encoder then don't use QTI flac component otherwise use QTI flac component, so if QTI flac is not being used then this might be wrong. So enhance the design to use QTI flac component only when it is enabled, otherwise use default flac component Change-Id: I57454841611885ae7cdf75896f8297ef8132292e CRs-Fixed: 916650 --- media/libstagefright/ACodec.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 3c80d03..f40a3c4 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -2073,7 +2073,11 @@ status_t ACodec::configureCodec( } err = setupG711Codec(encoder, sampleRate, numChannels); } +#ifdef QTI_FLAC_DECODER } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) && encoder) { +#else + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { +#endif int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1; if (encoder && (!msg->findInt32("channel-count", &numChannels) -- cgit v1.1 From b987753ada64c5824672ea70f92fe603f849d4b6 Mon Sep 17 00:00:00 2001 From: Manoj Kumar AVM Date: Thu, 30 Apr 2015 10:24:11 -0700 Subject: stagefright: Add null check before passing meta data buffer Add necessary null checks to GraphicBuffer before passing it onto Metadatabuffer. Change-Id: I5cf09da4bd316e5c1733023746aa54960a36d8c9 --- media/libstagefright/SurfaceMediaSource.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index e8abf48..7da5a9f 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -360,7 +360,11 @@ status_t SurfaceMediaSource::read( mNumFramesEncoded++; // Pass the data to the MediaBuffer. Pass in only the metadata - + if (mSlots[mCurrentSlot].mGraphicBuffer == NULL) { + ALOGV("Read: SurfaceMediaSource mGraphicBuffer is null. Returning" + "ERROR_END_OF_STREAM."); + return ERROR_END_OF_STREAM; + } passMetadataBuffer(buffer, mSlots[mCurrentSlot].mGraphicBuffer->handle); (*buffer)->setObserver(this); -- cgit v1.1 From 262a62c19e8b09c4e6b271c9522e7eb318e0d574 Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Wed, 2 Jul 2014 19:09:04 -0700 Subject: libstagefright: Add WFD specific flags to consumer usage flags Add the GRALLOC_USAGE_PRIVATE_WFD flag to the consumer usage flags to allow the display framework to distinguish WFD from other virtual display connections. Change-Id: I7cdbac3716fb5c18d1691701accb8e66f388de86 --- media/libstagefright/Android.mk | 5 +++++ media/libstagefright/SurfaceMediaSource.cpp | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index b2729af..9687c7d 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -132,6 +132,11 @@ LOCAL_SHARED_LIBRARIES += \ LOCAL_CFLAGS += -Wno-multichar -Werror -Wno-error=deprecated-declarations -Wall +ifeq ($(TARGET_USES_QCOM_BSP), true) + LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc + LOCAL_CFLAGS += -DQTI_BSP +endif + # enable experiments only in userdebug and eng builds ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) LOCAL_CFLAGS += -DENABLE_STAGEFRIGHT_EXPERIMENTS diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index e8abf48..a0d55f5 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -35,6 +35,9 @@ #include #include +#if QTI_BSP +#include +#endif namespace android { @@ -59,8 +62,12 @@ SurfaceMediaSource::SurfaceMediaSource(uint32_t bufferWidth, uint32_t bufferHeig BufferQueue::createBufferQueue(&mProducer, &mConsumer); mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight); - mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER | - GRALLOC_USAGE_HW_TEXTURE); + mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER + | GRALLOC_USAGE_HW_TEXTURE +#if QTI_BSP + | GRALLOC_USAGE_PRIVATE_WFD +#endif + ); sp composer(ComposerService::getComposerService()); -- cgit v1.1 From 5918d3601f5711671a6fb5ccc2f65a931aae33eb Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Fri, 30 Oct 2015 18:41:06 -0700 Subject: libstagefright: omx: Prevent assertion due to state mismatches Instead handle them a bit better. Since the assertions dealt with in this patchset can only happen if the OMX IL client died while de-init'ing the component, it is impossible to deal with all possible cases gracefully. Hence take an aggressive approach by moving state of the component to OMX_StateInvalid. This looks okay as per the spec, but might not be the best approach. Change-Id: I3f23f5e3853523fe1a7fb3aaf38b46595fa91732 --- .../include/SimpleSoftOMXComponent.h | 1 + .../libstagefright/omx/SimpleSoftOMXComponent.cpp | 44 ++++++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/media/libstagefright/include/SimpleSoftOMXComponent.h b/media/libstagefright/include/SimpleSoftOMXComponent.h index 591b38e..6a0a958 100644 --- a/media/libstagefright/include/SimpleSoftOMXComponent.h +++ b/media/libstagefright/include/SimpleSoftOMXComponent.h @@ -140,6 +140,7 @@ private: void onPortFlush(OMX_U32 portIndex, bool sendFlushComplete); void checkTransitions(); + void onTransitionError(); DISALLOW_EVIL_CONSTRUCTORS(SimpleSoftOMXComponent); }; diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp index e6a0c49..1fd0641 100644 --- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp +++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp @@ -417,16 +417,43 @@ void SimpleSoftOMXComponent::onSendCommand( } } +void SimpleSoftOMXComponent::onTransitionError() { + mState = OMX_StateInvalid; + mTargetState = OMX_StateInvalid; + notify(OMX_EventError, OMX_CommandStateSet, OMX_StateInvalid, 0); +} + void SimpleSoftOMXComponent::onChangeState(OMX_STATETYPE state) { + bool skipTransitions = false; + // We shouldn't be in a state transition already. - CHECK_EQ((int)mState, (int)mTargetState); + if (mState != mTargetState) { + // Workaround to prevent assertion + // XXX CHECK_EQ((int)mState, (int)mTargetState); + ALOGW("mState %d != mTargetState %d", mState, mTargetState); + skipTransitions = true; + onTransitionError(); + } switch (mState) { case OMX_StateLoaded: - CHECK_EQ((int)state, (int)OMX_StateIdle); + if (state != OMX_StateIdle) { + // Workaround to prevent assertion + // XXX CHECK_EQ((int)state, (int)OMX_StateIdle); + ALOGW("In OMX_StateLoaded, state %d != OMX_StateIdle", state); + skipTransitions = true; + onTransitionError(); + } break; case OMX_StateIdle: - CHECK(state == OMX_StateLoaded || state == OMX_StateExecuting); + if (!(state == OMX_StateLoaded || state == OMX_StateExecuting)) { + // Workaround to prevent assertion + // XXX CHECK(state == OMX_StateLoaded || state == OMX_StateExecuting); + ALOGW("In OMX_StateIdle, state %d != OMX_StateLoaded||OMX_StateExecuting", + state); + skipTransitions = true; + onTransitionError(); + } break; case OMX_StateExecuting: { @@ -440,11 +467,20 @@ void SimpleSoftOMXComponent::onChangeState(OMX_STATETYPE state) { notify(OMX_EventCmdComplete, OMX_CommandStateSet, state, NULL); break; } - + case OMX_StateInvalid: { + ALOGW("In OMX_StateInvalid, ignore state transition to %d", state); + skipTransitions = true; + onTransitionError(); + break; + } default: TRESPASS(); } + if (skipTransitions) { + return; + } + mTargetState = state; checkTransitions(); -- cgit v1.1 From 614ee35203329c5a617d0c5cfca9cd08446c3af5 Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Fri, 30 Oct 2015 15:29:47 -0700 Subject: audiopolicy: Add synchronization to EffectDescriptorCollection Synchronize public APIs of EffectDescriptorCollection CRs-Fixed: 920103 Change-Id: I04ccac526c6f99e61e43288776653d6b7ff325c4 --- .../audiopolicy/common/managerdefinitions/include/EffectDescriptor.h | 3 +++ .../audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h index c9783a1..396541b 100644 --- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace android { @@ -66,6 +67,8 @@ private: * Maximum memory allocated to audio effects in KB */ static const uint32_t MAX_EFFECTS_MEMORY = 512; + + Mutex mLock; }; }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp index 33d838d..6a0d079 100644 --- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp @@ -56,6 +56,7 @@ status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *d int session, int id) { + Mutex::Autolock _l(mLock); if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) { ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB", desc->name, desc->memoryUsage); @@ -80,6 +81,7 @@ status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *d status_t EffectDescriptorCollection::unregisterEffect(int id) { + Mutex::Autolock _l(mLock); ssize_t index = indexOfKey(id); if (index < 0) { ALOGW("unregisterEffect() unknown effect ID %d", id); @@ -106,6 +108,7 @@ status_t EffectDescriptorCollection::unregisterEffect(int id) status_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled) { + Mutex::Autolock _l(mLock); ssize_t index = indexOfKey(id); if (index < 0) { ALOGW("unregisterEffect() unknown effect ID %d", id); @@ -148,6 +151,7 @@ status_t EffectDescriptorCollection::setEffectEnabled(const sp bool EffectDescriptorCollection::isNonOffloadableEffectEnabled() { + Mutex::Autolock _l(mLock); for (size_t i = 0; i < size(); i++) { sp effectDesc = valueAt(i); if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) && @@ -172,6 +176,7 @@ uint32_t EffectDescriptorCollection::getMaxEffectsMemory() const status_t EffectDescriptorCollection::dump(int fd) { + Mutex::Autolock _l(mLock); const size_t SIZE = 256; char buffer[SIZE]; -- cgit v1.1