summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/MediaCodec.h5
-rw-r--r--include/media/stagefright/MediaCodecList.h4
-rw-r--r--media/libmedia/AudioTrack.cpp6
-rw-r--r--media/libmedia/AudioTrackShared.cpp6
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.cpp2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp6
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp5
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp27
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h1
-rw-r--r--media/libstagefright/MediaCodec.cpp49
-rw-r--r--media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp1
-rw-r--r--media/libstagefright/codecs/hevcdec/SoftHEVC.cpp333
-rw-r--r--media/libstagefright/codecs/hevcdec/SoftHEVC.h13
-rw-r--r--media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp3
-rw-r--r--media/libstagefright/foundation/ALooper.cpp10
-rw-r--r--services/audioflinger/AudioFlinger.cpp9
-rw-r--r--services/audioflinger/AudioFlinger.h8
-rw-r--r--services/audioflinger/FastCapture.cpp4
-rw-r--r--services/audioflinger/Threads.cpp5
-rw-r--r--services/audioflinger/Tracks.cpp1
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.cpp33
-rw-r--r--services/camera/libcameraservice/CameraService.cpp16
-rw-r--r--services/camera/libcameraservice/CameraService.h3
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.cpp6
-rw-r--r--services/camera/libcameraservice/api1/CameraClient.cpp6
-rw-r--r--services/mediaresourcemanager/ResourceManagerService.cpp37
-rw-r--r--soundtrigger/ISoundTrigger.cpp14
-rw-r--r--soundtrigger/ISoundTriggerHwService.cpp7
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 &params, 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());
}