diff options
author | Steve Kondik <steve@cyngn.com> | 2015-12-07 18:45:35 -0800 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-12-07 18:45:35 -0800 |
commit | 697a7ab8c538ca84a92b605e50824da1cbf9b466 (patch) | |
tree | fe32b5c0b8e0fa115cd6358c5428b8a48e285dec | |
parent | 7f8512331f105565054202486fa0a6094ad693c1 (diff) | |
parent | 5dc9ffe50ef517591b8ffad66c7e4d6ec82b8b4b (diff) | |
download | frameworks_av-697a7ab8c538ca84a92b605e50824da1cbf9b466.zip frameworks_av-697a7ab8c538ca84a92b605e50824da1cbf9b466.tar.gz frameworks_av-697a7ab8c538ca84a92b605e50824da1cbf9b466.tar.bz2 |
Merge tag 'android-6.0.1_r3' of https://android.googlesource.com/platform/frameworks/av into cm-13.0
Android 6.0.1 release 3
Change-Id: I2f2a1fe1b58c828e8341556996211562d6e195ab
29 files changed, 315 insertions, 307 deletions
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index 9c489e5..e2588a4 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -178,7 +178,7 @@ protected: private: // used by ResourceManagerClient - status_t reclaim(); + status_t reclaim(bool force = false); friend struct ResourceManagerClient; private: @@ -387,6 +387,9 @@ private: uint64_t getGraphicBufferSize(); void addResource(const String8 &type, const String8 &subtype, uint64_t value); + bool hasPendingBuffer(int portIndex); + bool hasPendingBuffer(); + /* called to get the last codec error when the sticky flag is set. * if no such codec error is found, returns UNKNOWN_ERROR. */ diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h index 3aaa032..bf4db87 100644 --- a/include/media/stagefright/MediaCodecList.h +++ b/include/media/stagefright/MediaCodecList.h @@ -47,6 +47,10 @@ struct MediaCodecList : public BnMediaCodecList { virtual size_t countCodecs() const; virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const { + if (index >= mCodecInfos.size()) { + ALOGE("b/24445127"); + return NULL; + } return mCodecInfos.itemAt(index); } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 8c47268..ff57b44 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1922,7 +1922,11 @@ nsecs_t AudioTrack::processAudioBuffer() return 0; } } - mCbf(EVENT_STREAM_END, mUserData, NULL); + if (status != DEAD_OBJECT) { + // for DEAD_OBJECT, we do not send a EVENT_STREAM_END after stop(); + // instead, the application should handle the EVENT_NEW_IAUDIOTRACK. + mCbf(EVENT_STREAM_END, mUserData, NULL); + } { AutoMutex lock(mLock); // The previously assigned value of waitStreamEnd is no longer valid, diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 0f8e6d6..7148743 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -932,7 +932,7 @@ ssize_t StaticAudioTrackServerProxy::pollPosition() return (ssize_t) mState.mPosition; } -status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush __unused) +status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) { if (mIsShutdown) { buffer->mFrameCount = 0; @@ -970,7 +970,9 @@ status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush // it is always larger or equal to avail. LOG_ALWAYS_FATAL_IF(mFramesReady < (int64_t) avail); buffer->mNonContig = mFramesReady == INT64_MAX ? SIZE_MAX : clampToSize(mFramesReady - avail); - mUnreleased = avail; + if (!ackFlush) { + mUnreleased = avail; + } return NO_ERROR; } diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index 056c85f..3ffb0f9 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -503,6 +503,8 @@ void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { { Mutex::Autolock _l(mDisconnectLock); mDataSource.clear(); + mDecryptHandle = NULL; + mDrmManagerClient = NULL; mCachedSource.clear(); mHttpSource.clear(); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index a494e87..de507f1 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1094,6 +1094,12 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { int32_t audio; CHECK(msg->findInt32("audio", &audio)); + if (audio) { + mAudioEOS = false; + } else { + mVideoEOS = false; + } + ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); if (audio && (mFlushingAudio == NONE || mFlushingAudio == FLUSHED || mFlushingAudio == SHUT_DOWN)) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 1710076..d23a9e2 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -674,8 +674,11 @@ void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) { flags = AUDIO_OUTPUT_FLAG_NONE; } - mRenderer->openAudioSink( + status_t err = mRenderer->openAudioSink( format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */, mSource->isStreaming()); + if (err != OK) { + handleError(err); + } } } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 8727907..716c353 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -366,9 +366,9 @@ bool NuPlayerDriver::isPlaying() { } status_t NuPlayerDriver::setPlaybackSettings(const AudioPlaybackRate &rate) { - Mutex::Autolock autoLock(mLock); status_t err = mPlayer->setPlaybackSettings(rate); if (err == OK) { + Mutex::Autolock autoLock(mLock); if (rate.mSpeed == 0.f && mState == STATE_RUNNING) { mState = STATE_PAUSED; // try to update position diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 6b2c072..049b79d 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -125,6 +125,7 @@ NuPlayer::Renderer::Renderer( mVideoRenderingStarted(false), mVideoRenderingStartGeneration(0), mAudioRenderingStartGeneration(0), + mRenderingDataDelivered(false), mAudioOffloadPauseTimeoutGeneration(0), mAudioTornDown(false), mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), @@ -670,11 +671,16 @@ void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) { void NuPlayer::Renderer::prepareForMediaRenderingStart_l() { mAudioRenderingStartGeneration = mAudioDrainGeneration; mVideoRenderingStartGeneration = mVideoDrainGeneration; + mRenderingDataDelivered = false; } void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() { if (mVideoRenderingStartGeneration == mVideoDrainGeneration && mAudioRenderingStartGeneration == mAudioDrainGeneration) { + mRenderingDataDelivered = true; + if (mPaused) { + return; + } mVideoRenderingStartGeneration = -1; mAudioRenderingStartGeneration = -1; @@ -932,6 +938,13 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { { Mutex::Autolock autoLock(mLock); + int64_t maxTimeMedia; + maxTimeMedia = + mAnchorTimeMediaUs + + (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL) + * 1000LL * mAudioSink->msecsPerFrame()); + mMediaClock->updateMaxTimeMedia(maxTimeMedia); + notifyIfMediaRenderingStarted_l(); } @@ -958,15 +971,6 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { break; } } - int64_t maxTimeMedia; - { - Mutex::Autolock autoLock(mLock); - maxTimeMedia = - mAnchorTimeMediaUs + - (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL) - * 1000LL * mAudioSink->msecsPerFrame()); - } - mMediaClock->updateMaxTimeMedia(maxTimeMedia); // calculate whether we need to reschedule another write. bool reschedule = !mAudioQueue.empty() @@ -1545,7 +1549,10 @@ void NuPlayer::Renderer::onResume() { { Mutex::Autolock autoLock(mLock); mPaused = false; - + // rendering started message may have been delayed if we were paused. + if (mRenderingDataDelivered) { + notifyIfMediaRenderingStarted_l(); + } // configure audiosink as we did not do it when pausing if (mAudioSink != NULL && mAudioSink->ready()) { mAudioSink->setPlaybackRate(mPlaybackSettings); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 50bd0a9..e872227 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -179,6 +179,7 @@ protected: bool mVideoRenderingStarted; int32_t mVideoRenderingStartGeneration; int32_t mAudioRenderingStartGeneration; + bool mRenderingDataDelivered; int64_t mLastPositionUpdateUs; diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 83b378f..54c57ee 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -64,6 +64,7 @@ static bool isResourceError(status_t err) { } static const int kMaxRetry = 2; +static const int kMaxReclaimWaitTimeInUs = 500000; // 0.5s struct ResourceManagerClient : public BnResourceManagerClient { ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {} @@ -75,6 +76,12 @@ struct ResourceManagerClient : public BnResourceManagerClient { return true; } status_t err = codec->reclaim(); + if (err == WOULD_BLOCK) { + ALOGD("Wait for the client to release codec."); + usleep(kMaxReclaimWaitTimeInUs); + ALOGD("Try to reclaim again."); + err = codec->reclaim(true /* force */); + } if (err != OK) { ALOGW("ResourceManagerClient failed to release codec with err %d", err); } @@ -572,13 +579,34 @@ status_t MediaCodec::stop() { return PostAndAwaitResponse(msg, &response); } -status_t MediaCodec::reclaim() { +bool MediaCodec::hasPendingBuffer(int portIndex) { + const Vector<BufferInfo> &buffers = mPortBuffers[portIndex]; + for (size_t i = 0; i < buffers.size(); ++i) { + const BufferInfo &info = buffers.itemAt(i); + if (info.mOwnedByClient) { + return true; + } + } + return false; +} + +bool MediaCodec::hasPendingBuffer() { + return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput); +} + +status_t MediaCodec::reclaim(bool force) { ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str()); sp<AMessage> msg = new AMessage(kWhatRelease, this); msg->setInt32("reclaimed", 1); + msg->setInt32("force", force ? 1 : 0); sp<AMessage> response; - return PostAndAwaitResponse(msg, &response); + status_t ret = PostAndAwaitResponse(msg, &response); + if (ret == -ENOENT) { + ALOGD("MediaCodec looper is gone, skip reclaim"); + ret = OK; + } + return ret; } status_t MediaCodec::release() { @@ -1798,6 +1826,23 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { msg->findInt32("reclaimed", &reclaimed); if (reclaimed) { mReleasedByResourceManager = true; + + int32_t force = 0; + msg->findInt32("force", &force); + if (!force && hasPendingBuffer()) { + ALOGW("Can't reclaim codec right now due to pending buffers."); + + // return WOULD_BLOCK to ask resource manager to retry later. + sp<AMessage> response = new AMessage; + response->setInt32("err", WOULD_BLOCK); + response->postReply(replyID); + + // notify the async client + if (mFlags & kFlagIsAsync) { + onError(DEAD_OBJECT, ACTION_CODE_FATAL); + } + break; + } } if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1 diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp index 6e55034..387d17d 100644 --- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp +++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp @@ -637,6 +637,7 @@ OMX_ERRORTYPE SoftAVC::initEncoder() { for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) { if (mConversionBuffers[i] != NULL) { free(mConversionBuffers[i]); + mConversionBuffers[i] = 0; } if (((uint64_t)mStride * mHeight) > ((uint64_t)INT32_MAX / 3)) { diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp index 4b2ec1c..e601125 100644 --- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp +++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp @@ -37,10 +37,10 @@ namespace android { /** Function and structure definitions to keep code similar for each codec */ #define ivdec_api_function ihevcd_cxa_api_function -#define ivdext_init_ip_t ihevcd_cxa_init_ip_t -#define ivdext_init_op_t ihevcd_cxa_init_op_t -#define ivdext_fill_mem_rec_ip_t ihevcd_cxa_fill_mem_rec_ip_t -#define ivdext_fill_mem_rec_op_t ihevcd_cxa_fill_mem_rec_op_t +#define ivdext_create_ip_t ihevcd_cxa_create_ip_t +#define ivdext_create_op_t ihevcd_cxa_create_op_t +#define ivdext_delete_ip_t ihevcd_cxa_delete_ip_t +#define ivdext_delete_op_t ihevcd_cxa_delete_op_t #define ivdext_ctl_set_num_cores_ip_t ihevcd_cxa_ctl_set_num_cores_ip_t #define ivdext_ctl_set_num_cores_op_t ihevcd_cxa_ctl_set_num_cores_op_t @@ -68,13 +68,13 @@ SoftHEVC::SoftHEVC( kProfileLevels, ARRAY_SIZE(kProfileLevels), 320 /* width */, 240 /* height */, callbacks, appData, component), - mMemRecords(NULL), + mCodecCtx(NULL), mFlushOutBuffer(NULL), mOmxColorFormat(OMX_COLOR_FormatYUV420Planar), mIvColorFormat(IV_YUV_420P), - mNewWidth(mWidth), - mNewHeight(mHeight), - mChangingResolution(false) { + mChangingResolution(false), + mSignalledError(false), + mStride(mWidth) { const size_t kMinCompressionRatio = 4 /* compressionRatio (for Level 4+) */; const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; // INPUT_BUF_SIZE is given by HEVC codec as minimum input size @@ -88,10 +88,21 @@ status_t SoftHEVC::init() { } SoftHEVC::~SoftHEVC() { - ALOGD("In SoftHEVC::~SoftHEVC"); + ALOGV("In SoftHEVC::~SoftHEVC"); CHECK_EQ(deInitDecoder(), (status_t)OK); } +static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) { + UNUSED(ctxt); + return memalign(alignment, size); +} + +static void ivd_aligned_free(void *ctxt, void *buf) { + UNUSED(ctxt); + free(buf); + return; +} + static size_t GetCPUCoreCount() { long cpuCoreCount = 1; #if defined(_SC_NPROCESSORS_ONLN) @@ -101,7 +112,7 @@ static size_t GetCPUCoreCount() { cpuCoreCount = sysconf(_SC_NPROC_ONLN); #endif CHECK(cpuCoreCount >= 1); - ALOGD("Number of CPU cores: %ld", cpuCoreCount); + ALOGV("Number of CPU cores: %ld", cpuCoreCount); return (size_t)cpuCoreCount; } @@ -125,7 +136,7 @@ void SoftHEVC::logVersion() { ALOGE("Error in getting version number: 0x%x", s_ctl_op.u4_error_code); } else { - ALOGD("Ittiam decoder version number: %s", + ALOGV("Ittiam decoder version number: %s", (char *)s_ctl_ip.pv_version_buffer); } return; @@ -187,13 +198,12 @@ status_t SoftHEVC::resetDecoder() { ALOGE("Error in reset: 0x%x", s_ctl_op.u4_error_code); return UNKNOWN_ERROR; } - - /* Set the run-time (dynamic) parameters */ - setParams(outputBufferWidth()); + mSignalledError = false; /* Set number of cores/threads to be used by the codec */ setNumCores(); + mStride = 0; return OK; } @@ -206,7 +216,7 @@ status_t SoftHEVC::setNumCores() { s_set_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_NUM_CORES); s_set_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t); s_set_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t); - ALOGD("Set number of cores to %u", s_set_cores_ip.u4_num_cores); + ALOGV("Set number of cores to %u", s_set_cores_ip.u4_num_cores); status = ivdec_api_function(mCodecCtx, (void *)&s_set_cores_ip, (void *)&s_set_cores_op); if (IV_SUCCESS != status) { @@ -226,7 +236,7 @@ status_t SoftHEVC::setFlushMode() { s_video_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; s_video_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); s_video_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t); - ALOGD("Set the decoder in flush mode "); + ALOGV("Set the decoder in flush mode "); /* Set the decoder in Flush mode, subsequent decode() calls will flush */ status = ivdec_api_function(mCodecCtx, (void *)&s_video_flush_ip, @@ -245,151 +255,38 @@ status_t SoftHEVC::setFlushMode() { status_t SoftHEVC::initDecoder() { IV_API_CALL_STATUS_T status; - UWORD32 u4_num_reorder_frames; - UWORD32 u4_num_ref_frames; - UWORD32 u4_share_disp_buf; - WORD32 i4_level; - mNumCores = GetCPUCoreCount(); + mCodecCtx = NULL; - /* Initialize number of ref and reorder modes (for HEVC) */ - u4_num_reorder_frames = 16; - u4_num_ref_frames = 16; - u4_share_disp_buf = 0; - - uint32_t displayStride = outputBufferWidth(); - uint32_t displayHeight = outputBufferHeight(); - uint32_t displaySizeY = displayStride * displayHeight; - - if (displaySizeY > (1920 * 1088)) { - i4_level = 50; - } else if (displaySizeY > (1280 * 720)) { - i4_level = 40; - } else if (displaySizeY > (960 * 540)) { - i4_level = 31; - } else if (displaySizeY > (640 * 360)) { - i4_level = 30; - } else if (displaySizeY > (352 * 288)) { - i4_level = 21; - } else { - i4_level = 20; - } - { - iv_num_mem_rec_ip_t s_num_mem_rec_ip; - iv_num_mem_rec_op_t s_num_mem_rec_op; - - s_num_mem_rec_ip.u4_size = sizeof(s_num_mem_rec_ip); - s_num_mem_rec_op.u4_size = sizeof(s_num_mem_rec_op); - s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC; - - ALOGV("Get number of mem records"); - status = ivdec_api_function(mCodecCtx, (void*)&s_num_mem_rec_ip, - (void*)&s_num_mem_rec_op); - if (IV_SUCCESS != status) { - ALOGE("Error in getting mem records: 0x%x", - s_num_mem_rec_op.u4_error_code); - return UNKNOWN_ERROR; - } - - mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec; - } - - mMemRecords = (iv_mem_rec_t*)ivd_aligned_malloc( - 128, mNumMemRecords * sizeof(iv_mem_rec_t)); - if (mMemRecords == NULL) { - ALOGE("Allocation failure"); - return NO_MEMORY; - } - - memset(mMemRecords, 0, mNumMemRecords * sizeof(iv_mem_rec_t)); - - { - size_t i; - ivdext_fill_mem_rec_ip_t s_fill_mem_ip; - ivdext_fill_mem_rec_op_t s_fill_mem_op; - iv_mem_rec_t *ps_mem_rec; - - s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_size = - sizeof(ivdext_fill_mem_rec_ip_t); - s_fill_mem_ip.i4_level = i4_level; - s_fill_mem_ip.u4_num_reorder_frames = u4_num_reorder_frames; - s_fill_mem_ip.u4_num_ref_frames = u4_num_ref_frames; - s_fill_mem_ip.u4_share_disp_buf = u4_share_disp_buf; - s_fill_mem_ip.u4_num_extra_disp_buf = 0; - s_fill_mem_ip.e_output_format = mIvColorFormat; - - s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC; - s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = mMemRecords; - s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = displayStride; - s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = displayHeight; - s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_size = - sizeof(ivdext_fill_mem_rec_op_t); - - ps_mem_rec = mMemRecords; - for (i = 0; i < mNumMemRecords; i++) - ps_mem_rec[i].u4_size = sizeof(iv_mem_rec_t); - - status = ivdec_api_function(mCodecCtx, (void *)&s_fill_mem_ip, - (void *)&s_fill_mem_op); - - if (IV_SUCCESS != status) { - ALOGE("Error in filling mem records: 0x%x", - s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_error_code); - return UNKNOWN_ERROR; - } - mNumMemRecords = - s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_num_mem_rec_filled; - - ps_mem_rec = mMemRecords; - - for (i = 0; i < mNumMemRecords; i++) { - ps_mem_rec->pv_base = ivd_aligned_malloc( - ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size); - if (ps_mem_rec->pv_base == NULL) { - ALOGE("Allocation failure for memory record #%zu of size %u", - i, ps_mem_rec->u4_mem_size); - status = IV_FAIL; - return NO_MEMORY; - } - - ps_mem_rec++; - } - } + mStride = outputBufferWidth(); /* Initialize the decoder */ { - ivdext_init_ip_t s_init_ip; - ivdext_init_op_t s_init_op; + ivdext_create_ip_t s_create_ip; + ivdext_create_op_t s_create_op; void *dec_fxns = (void *)ivdec_api_function; - s_init_ip.s_ivd_init_ip_t.u4_size = sizeof(ivdext_init_ip_t); - s_init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT; - s_init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mMemRecords; - s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = displayStride; - s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = displayHeight; - - s_init_ip.i4_level = i4_level; - s_init_ip.u4_num_reorder_frames = u4_num_reorder_frames; - s_init_ip.u4_num_ref_frames = u4_num_ref_frames; - s_init_ip.u4_share_disp_buf = u4_share_disp_buf; - s_init_ip.u4_num_extra_disp_buf = 0; - - s_init_op.s_ivd_init_op_t.u4_size = sizeof(s_init_op); + s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t); + s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE; + s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0; + s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t); + s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorFormat; + s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc; + s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free; + s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL; - s_init_ip.s_ivd_init_ip_t.u4_num_mem_rec = mNumMemRecords; - s_init_ip.s_ivd_init_ip_t.e_output_format = mIvColorFormat; + status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op); - mCodecCtx = (iv_obj_t*)mMemRecords[0].pv_base; + mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle; mCodecCtx->pv_fxns = dec_fxns; mCodecCtx->u4_size = sizeof(iv_obj_t); - ALOGD("Initializing decoder"); - status = ivdec_api_function(mCodecCtx, (void *)&s_init_ip, - (void *)&s_init_op); if (status != IV_SUCCESS) { - ALOGE("Error in init: 0x%x", - s_init_op.s_ivd_init_op_t.u4_error_code); + ALOGE("Error in create: 0x%x", + s_create_op.s_ivd_create_op_t.u4_error_code); + deInitDecoder(); + mCodecCtx = NULL; return UNKNOWN_ERROR; } } @@ -398,7 +295,7 @@ status_t SoftHEVC::initDecoder() { resetPlugin(); /* Set the run time (dynamic) parameters */ - setParams(displayStride); + setParams(mStride); /* Set number of cores/threads to be used by the codec */ setNumCores(); @@ -406,80 +303,46 @@ status_t SoftHEVC::initDecoder() { /* Get codec version */ logVersion(); - /* Allocate internal picture buffer */ - uint32_t bufferSize = displaySizeY * 3 / 2; - mFlushOutBuffer = (uint8_t *)ivd_aligned_malloc(128, bufferSize); - if (NULL == mFlushOutBuffer) { - ALOGE("Could not allocate flushOutputBuffer of size %u", bufferSize); - return NO_MEMORY; - } - - mInitNeeded = false; mFlushNeeded = false; return OK; } status_t SoftHEVC::deInitDecoder() { size_t i; + IV_API_CALL_STATUS_T status; - if (mMemRecords) { - iv_mem_rec_t *ps_mem_rec; + if (mCodecCtx) { + ivdext_delete_ip_t s_delete_ip; + ivdext_delete_op_t s_delete_op; - ps_mem_rec = mMemRecords; - ALOGD("Freeing codec memory"); - for (i = 0; i < mNumMemRecords; i++) { - if(ps_mem_rec->pv_base) { - ivd_aligned_free(ps_mem_rec->pv_base); - } - ps_mem_rec++; + s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t); + s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE; + + s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t); + + status = ivdec_api_function(mCodecCtx, (void *)&s_delete_ip, (void *)&s_delete_op); + if (status != IV_SUCCESS) { + ALOGE("Error in delete: 0x%x", + s_delete_op.s_ivd_delete_op_t.u4_error_code); + return UNKNOWN_ERROR; } - ivd_aligned_free(mMemRecords); - mMemRecords = NULL; } - if(mFlushOutBuffer) { - ivd_aligned_free(mFlushOutBuffer); - mFlushOutBuffer = NULL; - } - mInitNeeded = true; mChangingResolution = false; return OK; } -status_t SoftHEVC::reInitDecoder() { - status_t ret; - - deInitDecoder(); - - ret = initDecoder(); - if (OK != ret) { - ALOGE("Create failure"); - deInitDecoder(); - return NO_MEMORY; - } - return OK; -} - void SoftHEVC::onReset() { - ALOGD("onReset called"); + ALOGV("onReset called"); SoftVideoDecoderOMXComponent::onReset(); + mSignalledError = false; resetDecoder(); resetPlugin(); } -OMX_ERRORTYPE SoftHEVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) { - const uint32_t oldWidth = mWidth; - const uint32_t oldHeight = mHeight; - OMX_ERRORTYPE ret = SoftVideoDecoderOMXComponent::internalSetParameter(index, params); - if (mWidth != oldWidth || mHeight != oldHeight) { - reInitDecoder(); - } - return ret; -} - void SoftHEVC::setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip, ivd_video_decode_op_t *ps_dec_op, OMX_BUFFERHEADERTYPE *inHeader, @@ -529,6 +392,17 @@ void SoftHEVC::onPortFlushCompleted(OMX_U32 portIndex) { if (kOutputPortIndex == portIndex) { setFlushMode(); + /* Allocate a picture buffer to flushed data */ + uint32_t displayStride = outputBufferWidth(); + uint32_t displayHeight = outputBufferHeight(); + + uint32_t bufferSize = displayStride * displayHeight * 3 / 2; + mFlushOutBuffer = (uint8_t *)memalign(128, bufferSize); + if (NULL == mFlushOutBuffer) { + ALOGE("Could not allocate flushOutputBuffer of size %zu", bufferSize); + return; + } + while (true) { ivd_video_decode_ip_t s_dec_ip; ivd_video_decode_op_t s_dec_op; @@ -544,16 +418,36 @@ void SoftHEVC::onPortFlushCompleted(OMX_U32 portIndex) { break; } } + + if (mFlushOutBuffer) { + free(mFlushOutBuffer); + mFlushOutBuffer = NULL; + } + } } void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { UNUSED(portIndex); + if (mSignalledError) { + return; + } if (mOutputPortSettingsChange != NONE) { return; } + if (NULL == mCodecCtx) { + if (OK != initDecoder()) { + return; + } + } + if (outputBufferWidth() != mStride) { + /* Set the run-time (dynamic) parameters */ + mStride = outputBufferWidth(); + setParams(mStride); + } + List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex); List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); @@ -594,7 +488,6 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { outHeader->nOffset = 0; if (inHeader != NULL && (inHeader->nFlags & OMX_BUFFERFLAG_EOS)) { - ALOGD("EOS seen on input"); mReceivedEOS = true; if (inHeader->nFilledLen == 0) { inQueue.erase(inQueue.begin()); @@ -605,16 +498,6 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { } } - // When there is an init required and the decoder is not in flush mode, - // update output port's definition and reinitialize decoder. - if (mInitNeeded && !mIsInFlush) { - bool portWillReset = false; - handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight); - - CHECK_EQ(reInitDecoder(), (status_t)OK); - return; - } - /* Get a free slot in timestamp array to hold input timestamp */ { size_t i; @@ -646,13 +529,7 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { IV_API_CALL_STATUS_T status; status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op); - // FIXME: Compare |status| to IHEVCD_UNSUPPORTED_DIMENSIONS, which is not one of the - // IV_API_CALL_STATUS_T, seems be wrong. But this is what the decoder returns right now. - // The decoder should be fixed so that |u4_error_code| instead of |status| returns - // IHEVCD_UNSUPPORTED_DIMENSIONS. - bool unsupportedDimensions = - ((IHEVCD_UNSUPPORTED_DIMENSIONS == (IHEVCD_CXA_ERROR_CODES_T)status) - || (IHEVCD_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code)); + bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF)); GETTIME(&mTimeEnd, NULL); @@ -671,20 +548,6 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { mTimeStampsValid[timeStampIx] = false; } - // This is needed to handle CTS DecoderTest testCodecResetsHEVCWithoutSurface, - // which is not sending SPS/PPS after port reconfiguration and flush to the codec. - if (unsupportedDimensions && !mFlushNeeded) { - bool portWillReset = false; - handlePortSettingsChange(&portWillReset, s_dec_op.u4_pic_wd, s_dec_op.u4_pic_ht); - - CHECK_EQ(reInitDecoder(), (status_t)OK); - - setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx); - - ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op); - return; - } - // If the decoder is in the changing resolution mode and there is no output present, // that means the switching is done and it's ready to reset the decoder and the plugin. if (mChangingResolution && !s_dec_op.u4_output_present) { @@ -694,17 +557,11 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { continue; } - if (unsupportedDimensions || resChanged) { + if (resChanged) { mChangingResolution = true; if (mFlushNeeded) { setFlushMode(); } - - if (unsupportedDimensions) { - mNewWidth = s_dec_op.u4_pic_wd; - mNewHeight = s_dec_op.u4_pic_ht; - mInitNeeded = true; - } continue; } @@ -721,7 +578,7 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { } if (s_dec_op.u4_output_present) { - outHeader->nFilledLen = (mWidth * mHeight * 3) / 2; + outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2; outHeader->nTimeStamp = mTimeStamps[s_dec_op.u4_ts]; mTimeStampsValid[s_dec_op.u4_ts] = false; diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.h b/media/libstagefright/codecs/hevcdec/SoftHEVC.h index c6344cf..21bb99e 100644 --- a/media/libstagefright/codecs/hevcdec/SoftHEVC.h +++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.h @@ -23,9 +23,6 @@ namespace android { -#define ivd_aligned_malloc(alignment, size) memalign(alignment, size) -#define ivd_aligned_free(buf) free(buf) - /** Number of entries in the time-stamp array */ #define MAX_TIME_STAMPS 64 @@ -64,7 +61,6 @@ protected: virtual void onQueueFilled(OMX_U32 portIndex); virtual void onPortFlushCompleted(OMX_U32 portIndex); virtual void onReset(); - virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params); private: // Number of input and output buffers enum { @@ -72,8 +68,6 @@ private: }; iv_obj_t *mCodecCtx; // Codec context - iv_mem_rec_t *mMemRecords; // Memory records requested by the codec - size_t mNumMemRecords; // Number of memory records requested by the codec size_t mNumCores; // Number of cores to be uesd by the codec @@ -95,13 +89,13 @@ private: bool mIsInFlush; // codec is flush mode bool mReceivedEOS; // EOS is receieved on input port - bool mInitNeeded; - uint32_t mNewWidth; - uint32_t mNewHeight; + // The input stream has changed to a different resolution, which is still supported by the // codec. So the codec is switching to decode the new resolution. bool mChangingResolution; bool mFlushNeeded; + bool mSignalledError; + size_t mStride; status_t initDecoder(); status_t deInitDecoder(); @@ -111,7 +105,6 @@ private: status_t setNumCores(); status_t resetDecoder(); status_t resetPlugin(); - status_t reInitDecoder(); void setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip, ivd_video_decode_op_t *ps_dec_op, diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp index 32e5da7..4307c4e 100644 --- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp +++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp @@ -307,7 +307,7 @@ status_t SoftMPEG2::initDecoder() { s_fill_mem_ip.u4_share_disp_buf = u4_share_disp_buf; s_fill_mem_ip.e_output_format = mIvColorFormat; - + s_fill_mem_ip.u4_deinterlace = 1; s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC; s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = mMemRecords; s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = displayStride; @@ -361,6 +361,7 @@ status_t SoftMPEG2::initDecoder() { s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = displayHeight; s_init_ip.u4_share_disp_buf = u4_share_disp_buf; + s_init_ip.u4_deinterlace = 1; s_init_op.s_ivd_init_op_t.u4_size = sizeof(s_init_op); diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp index 90b5f68..9921636 100644 --- a/media/libstagefright/foundation/ALooper.cpp +++ b/media/libstagefright/foundation/ALooper.cpp @@ -151,6 +151,10 @@ status_t ALooper::stop() { } mQueueChangedCondition.signal(); + { + Mutex::Autolock autoLock(mRepliesLock); + mRepliesCondition.broadcast(); + } if (!runningLocally && !thread->isCurrentThread()) { // If not running locally and this thread _is_ the looper thread, @@ -234,6 +238,12 @@ status_t ALooper::awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> Mutex::Autolock autoLock(mRepliesLock); CHECK(replyToken != NULL); while (!replyToken->retrieveReply(response)) { + { + Mutex::Autolock autoLock(mLock); + if (mThread == NULL) { + return -ENOENT; + } + } mRepliesCondition.wait(mRepliesLock); } return OK; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index d7af22c..1acfaad 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1375,11 +1375,16 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(int sessionId, AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) : RefBase(), mAudioFlinger(audioFlinger), - // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below - mMemoryDealer(new MemoryDealer(4100*1024, "AudioFlinger::Client")), //4MB + 1 more 4k page mPid(pid), mTimedTrackCount(0) { + size_t heapSize = kClientSharedHeapSizeBytes; + // Increase heap size on non low ram devices to limit risk of reconnection failure for + // invalidated tracks + if (!audioFlinger->isLowRamDevice()) { + heapSize *= kClientSharedHeapSizeMultiplier; + } + mMemoryDealer = new MemoryDealer(heapSize, "AudioFlinger::Client"); } // Client destructor must be called with AudioFlinger::mClientLock held diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 20c34ef..08fa70d 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -88,6 +88,12 @@ class ServerProxy; static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3); + +// Max shared memory size for audio tracks and audio records per client process +static const size_t kClientSharedHeapSizeBytes = 1024*1024; +// Shared memory size multiplier for non low ram devices +static const size_t kClientSharedHeapSizeMultiplier = 4; + #define INCLUDING_FROM_AUDIOFLINGER_H class AudioFlinger : @@ -423,7 +429,7 @@ private: Client(const Client&); Client& operator = (const Client&); const sp<AudioFlinger> mAudioFlinger; - const sp<MemoryDealer> mMemoryDealer; + sp<MemoryDealer> mMemoryDealer; const pid_t mPid; Mutex mTimedTrackLock; diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp index 04ed08f..2493fb7 100644 --- a/services/audioflinger/FastCapture.cpp +++ b/services/audioflinger/FastCapture.cpp @@ -131,7 +131,9 @@ void FastCapture::onStateChange() // FIXME new may block for unbounded time at internal mutex of the heap // implementation; it would be better to have normal capture thread allocate for // us to avoid blocking here and to prevent possible priority inversion - (void)posix_memalign(&mReadBuffer, 32, frameCount * Format_frameSize(mFormat)); + size_t bufferSize = frameCount * Format_frameSize(mFormat); + (void)posix_memalign(&mReadBuffer, 32, bufferSize); + memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here. mPeriodNs = (frameCount * 1000000000LL) / mSampleRate; // 1.00 mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate; // 1.75 mOverrunNs = (frameCount * 500000000LL) / mSampleRate; // 0.50 diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 680ff13..e80221e 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -6962,6 +6962,7 @@ void AudioFlinger::RecordThread::readInputParameters_l() mRsmpInFrames = mFrameCount * 7; mRsmpInFramesP2 = roundup(mRsmpInFrames); free(mRsmpInBuffer); + mRsmpInBuffer = NULL; // TODO optimize audio capture buffer sizes ... // Here we calculate the size of the sliding buffer used as a source @@ -6971,7 +6972,9 @@ void AudioFlinger::RecordThread::readInputParameters_l() // The current value is higher than necessary. However it should not add to latency. // Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer - (void)posix_memalign(&mRsmpInBuffer, 32, (mRsmpInFramesP2 + mFrameCount - 1) * mFrameSize); + size_t bufferSize = (mRsmpInFramesP2 + mFrameCount - 1) * mFrameSize; + (void)posix_memalign(&mRsmpInBuffer, 32, bufferSize); + memset(mRsmpInBuffer, 0, bufferSize); // if posix_memalign fails, will segv here. // AudioRecord mSampleRate and mChannelCount are constant due to AudioRecord API constraints. // But if thread's mSampleRate or mChannelCount changes, how will that affect active tracks? diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 4eb13dc..f3b5375 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -717,6 +717,7 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev // But in this case we know the mixer thread (whether normal mixer or fast mixer) // isn't looking at this track yet: we still hold the normal mixer thread lock, // and for fast tracks the track is not yet in the fast mixer thread's active set. + // For static tracks, this is used to acknowledge change in position or loop. ServerProxy::Buffer buffer; buffer.mFrameCount = 1; (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/); diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 45efbe1..598edfc 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -442,6 +442,20 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs patch.num_sources = 2; } + // terminate active capture if on the same HW module as the call TX source device + // FIXME: would be better to refine to only inputs whose profile connects to the + // call TX device but this information is not in the audio patch and logic here must be + // symmetric to the one in startInput() + audio_io_handle_t activeInput = mInputs.getActiveInput(); + if (activeInput != 0) { + sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput); + if (activeDesc->getModuleHandle() == txSourceDeviceDesc->getModuleHandle()) { + audio_session_t activeSession = activeDesc->mSessions.itemAt(0); + stopInput(activeInput, activeSession); + releaseInput(activeInput, activeSession); + } + } + afPatchHandle = AUDIO_PATCH_HANDLE_NONE; status = mpClientInterface->createAudioPatch(&patch, &afPatchHandle, 0); ALOGW_IF(status != NO_ERROR, "setPhoneState() error %d creating TX audio patch", @@ -606,9 +620,15 @@ void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage, audio_io_handle_t activeInput = mInputs.getActiveInput(); if (activeInput != 0) { - setInputDevice(activeInput, getNewInputDevice(activeInput)); + sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput); + audio_devices_t newDevice = getNewInputDevice(activeInput); + // Force new input selection if the new device can not be reached via current input + if (activeDesc->mProfile->mSupportedDevices.types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) { + setInputDevice(activeInput, newDevice); + } else { + closeInput(activeInput); + } } - } void AudioPolicyManager::setSystemProperty(const char* property, const char* value) @@ -1547,6 +1567,15 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input, return INVALID_OPERATION; } } + + // Do not allow capture if an active voice call is using a software patch and + // the call TX source device is on the same HW module. + // FIXME: would be better to refine to only inputs whose profile connects to the + // call TX device but this information is not in the audio patch + if (mCallTxPatch != 0 && + inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) { + return INVALID_OPERATION; + } } // Routing? diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 861e519..3deb396 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -173,6 +173,13 @@ void CameraService::onFirstRef() mNumberOfCameras = mModule->getNumberOfCameras(); mNumberOfNormalCameras = mNumberOfCameras; + // Setup vendor tags before we call get_camera_info the first time + // because HAL might need to setup static vendor keys in get_camera_info + VendorTagDescriptor::clearGlobalVendorTagDescriptor(); + if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) { + setUpVendorTags(); + } + mFlashlight = new CameraFlashlight(*mModule, *this); status_t res = mFlashlight->findFlashUnits(); if (res) { @@ -239,12 +246,6 @@ void CameraService::onFirstRef() mModule->setCallbacks(this); } - VendorTagDescriptor::clearGlobalVendorTagDescriptor(); - - if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) { - setUpVendorTags(); - } - CameraDeviceFactory::registerService(this); CameraService::pingCameraServiceProxy(); @@ -1833,7 +1834,8 @@ void CameraService::loadSound() { if (mSoundRef++) return; mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg"); - mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg"); + mSoundPlayer[SOUND_RECORDING_START] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg"); + mSoundPlayer[SOUND_RECORDING_STOP] = newMediaPlayer("/system/media/audio/ui/VideoStop.ogg"); } void CameraService::releaseSound() { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index b3903d4..ce026b9 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -163,7 +163,8 @@ public: enum sound_kind { SOUND_SHUTTER = 0, - SOUND_RECORDING = 1, + SOUND_RECORDING_START = 1, + SOUND_RECORDING_STOP = 2, NUM_SOUNDS }; diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index 48b5a26..4338d64 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -1040,7 +1040,7 @@ status_t Camera2Client::startRecordingL(Parameters ¶ms, bool restart) { } if (!restart) { - mCameraService->playSound(CameraService::SOUND_RECORDING); + mCameraService->playSound(CameraService::SOUND_RECORDING_START); mStreamingProcessor->updateRecordingRequest(params); if (res != OK) { ALOGE("%s: Camera %d: Unable to update recording request: %s (%d)", @@ -1212,7 +1212,7 @@ void Camera2Client::stopRecording() { return; }; - mCameraService->playSound(CameraService::SOUND_RECORDING); + mCameraService->playSound(CameraService::SOUND_RECORDING_STOP); // Remove recording stream to prevent it from slowing down takePicture later if (!l.mParameters.recordingHint && l.mParameters.isJpegSizeOverridden()) { @@ -1638,7 +1638,7 @@ status_t Camera2Client::commandEnableShutterSoundL(bool enable) { } status_t Camera2Client::commandPlayRecordingSoundL() { - mCameraService->playSound(CameraService::SOUND_RECORDING); + mCameraService->playSound(CameraService::SOUND_RECORDING_START); return OK; } diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp index 1bb2910..af0d680 100644 --- a/services/camera/libcameraservice/api1/CameraClient.cpp +++ b/services/camera/libcameraservice/api1/CameraClient.cpp @@ -443,7 +443,7 @@ status_t CameraClient::startRecordingMode() { // start recording mode enableMsgType(CAMERA_MSG_VIDEO_FRAME); - mCameraService->playSound(CameraService::SOUND_RECORDING); + mCameraService->playSound(CameraService::SOUND_RECORDING_START); result = mHardware->startRecording(); if (result != NO_ERROR) { ALOGE("mHardware->startRecording() failed with status %d", result); @@ -474,7 +474,7 @@ void CameraClient::stopRecording() { disableMsgType(CAMERA_MSG_VIDEO_FRAME); mHardware->stopRecording(); - mCameraService->playSound(CameraService::SOUND_RECORDING); + mCameraService->playSound(CameraService::SOUND_RECORDING_STOP); mPreviewBuffer.clear(); } @@ -656,7 +656,7 @@ status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { } return OK; } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) { - mCameraService->playSound(CameraService::SOUND_RECORDING); + mCameraService->playSound(CameraService::SOUND_RECORDING_START); } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) { // Silently ignore this command return INVALID_OPERATION; diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp index 4790754..6781a36 100644 --- a/services/mediaresourcemanager/ResourceManagerService.cpp +++ b/services/mediaresourcemanager/ResourceManagerService.cpp @@ -90,11 +90,7 @@ static ResourceInfo& getResourceInfoForEdit( } status_t ResourceManagerService::dump(int fd, const Vector<String16>& /* args */) { - Mutex::Autolock lock(mLock); - String8 result; - const size_t SIZE = 256; - char buffer[SIZE]; if (checkCallingPermission(String16("android.permission.DUMP")) == false) { result.format("Permission Denial: " @@ -105,20 +101,35 @@ status_t ResourceManagerService::dump(int fd, const Vector<String16>& /* args */ return PERMISSION_DENIED; } + PidResourceInfosMap mapCopy; + bool supportsMultipleSecureCodecs; + bool supportsSecureWithNonSecureCodec; + String8 serviceLog; + { + Mutex::Autolock lock(mLock); + mapCopy = mMap; // Shadow copy, real copy will happen on write. + supportsMultipleSecureCodecs = mSupportsMultipleSecureCodecs; + supportsSecureWithNonSecureCodec = mSupportsSecureWithNonSecureCodec; + serviceLog = mServiceLog->toString(" " /* linePrefix */); + } + + const size_t SIZE = 256; + char buffer[SIZE]; snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this); result.append(buffer); result.append(" Policies:\n"); - snprintf(buffer, SIZE, " SupportsMultipleSecureCodecs: %d\n", mSupportsMultipleSecureCodecs); + snprintf(buffer, SIZE, " SupportsMultipleSecureCodecs: %d\n", supportsMultipleSecureCodecs); result.append(buffer); - snprintf(buffer, SIZE, " SupportsSecureWithNonSecureCodec: %d\n", mSupportsSecureWithNonSecureCodec); + snprintf(buffer, SIZE, " SupportsSecureWithNonSecureCodec: %d\n", + supportsSecureWithNonSecureCodec); result.append(buffer); result.append(" Processes:\n"); - for (size_t i = 0; i < mMap.size(); ++i) { - snprintf(buffer, SIZE, " Pid: %d\n", mMap.keyAt(i)); + for (size_t i = 0; i < mapCopy.size(); ++i) { + snprintf(buffer, SIZE, " Pid: %d\n", mapCopy.keyAt(i)); result.append(buffer); - const ResourceInfos &infos = mMap.valueAt(i); + const ResourceInfos &infos = mapCopy.valueAt(i); for (size_t j = 0; j < infos.size(); ++j) { result.append(" Client:\n"); snprintf(buffer, SIZE, " Id: %lld\n", (long long)infos[j].clientId); @@ -136,7 +147,7 @@ status_t ResourceManagerService::dump(int fd, const Vector<String16>& /* args */ } } result.append(" Events logs (most recent at top):\n"); - result.append(mServiceLog->toString(" " /* linePrefix */)); + result.append(serviceLog); write(fd, result.string(), result.size()); return OK; @@ -307,6 +318,10 @@ bool ResourceManagerService::reclaimResource( } } + if (failedClient == NULL) { + return true; + } + { Mutex::Autolock lock(mLock); bool found = false; @@ -329,7 +344,7 @@ bool ResourceManagerService::reclaimResource( } } - return (failedClient == NULL); + return false; } bool ResourceManagerService::getAllClients_l( diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp index eecc1ea..4df2068 100644 --- a/soundtrigger/ISoundTrigger.cpp +++ b/soundtrigger/ISoundTrigger.cpp @@ -60,11 +60,13 @@ public: data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor()); data.writeStrongBinder(IInterface::asBinder(modelMemory)); status_t status = remote()->transact(LOAD_SOUND_MODEL, data, &reply); - if (status != NO_ERROR || - (status = (status_t)reply.readInt32()) != NO_ERROR) { + if (status != NO_ERROR) { return status; } - reply.read(handle, sizeof(sound_model_handle_t)); + status = (status_t)reply.readInt32(); + if (status == NO_ERROR) { + reply.read(handle, sizeof(sound_model_handle_t)); + } return status; } @@ -74,7 +76,7 @@ public: data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor()); data.write(&handle, sizeof(sound_model_handle_t)); status_t status = remote()->transact(UNLOAD_SOUND_MODEL, data, &reply); - if (status != NO_ERROR) { + if (status == NO_ERROR) { status = (status_t)reply.readInt32(); } return status; @@ -93,7 +95,7 @@ public: } data.writeStrongBinder(IInterface::asBinder(dataMemory)); status_t status = remote()->transact(START_RECOGNITION, data, &reply); - if (status != NO_ERROR) { + if (status == NO_ERROR) { status = (status_t)reply.readInt32(); } return status; @@ -105,7 +107,7 @@ public: data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor()); data.write(&handle, sizeof(sound_model_handle_t)); status_t status = remote()->transact(STOP_RECOGNITION, data, &reply); - if (status != NO_ERROR) { + if (status == NO_ERROR) { status = (status_t)reply.readInt32(); } return status; diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp index e14a771..e37bae3 100644 --- a/soundtrigger/ISoundTriggerHwService.cpp +++ b/soundtrigger/ISoundTriggerHwService.cpp @@ -85,8 +85,11 @@ public: data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor()); data.write(&handle, sizeof(sound_trigger_module_handle_t)); data.writeStrongBinder(IInterface::asBinder(client)); - remote()->transact(ATTACH, data, &reply); - status_t status = reply.readInt32(); + status_t status = remote()->transact(ATTACH, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = reply.readInt32(); if (reply.readInt32() != 0) { module = interface_cast<ISoundTrigger>(reply.readStrongBinder()); } |