From b49c385232adfc7f82d7194c7b19b5966499f66b Mon Sep 17 00:00:00 2001 From: Ronghua Wu Date: Mon, 26 Oct 2015 10:17:37 -0700 Subject: ALooper::awaitResponse gets reply and returns immediately if the looper is stopped. Bug: 25088488 Change-Id: Id33d5d75f1173db52d00f4ff71d4c2c4f27f72f5 --- media/libstagefright/foundation/ALooper.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'media') diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp index 5c2e9f9..9921636 100644 --- a/media/libstagefright/foundation/ALooper.cpp +++ b/media/libstagefright/foundation/ALooper.cpp @@ -234,31 +234,19 @@ sp ALooper::createReplyToken() { // to be called by AMessage::postAndAwaitResponse only status_t ALooper::awaitResponse(const sp &replyToken, sp *response) { - { - Mutex::Autolock autoLock(mLock); - if (mThread == NULL) { - return -ENOENT; - } - } - // return status in case we want to handle an interrupted wait Mutex::Autolock autoLock(mRepliesLock); CHECK(replyToken != NULL); - bool gotReply; - bool shouldContinue = true; - while (!(gotReply = replyToken->retrieveReply(response)) && shouldContinue) { - mRepliesCondition.wait(mRepliesLock); - + while (!replyToken->retrieveReply(response)) { { Mutex::Autolock autoLock(mLock); if (mThread == NULL) { - shouldContinue = false; - // continue and try to get potential reply one more time before break the loop + return -ENOENT; } } + mRepliesCondition.wait(mRepliesLock); } - - return gotReply ? OK : -ENOENT; + return OK; } status_t ALooper::postReply(const sp &replyToken, const sp &reply) { -- cgit v1.1 From 7845a1f0790a1de9e26e99578f6ce3219cf8efc3 Mon Sep 17 00:00:00 2001 From: Erik Wolsheimer Date: Fri, 30 Oct 2015 12:07:52 -0700 Subject: fix deadlock in MediaPlayerService BUG: 25263909 Change-Id: I3f08c02a851b67ab269e9aef7b2fb17eda09ea5d --- media/libmediaplayerservice/MediaPlayerService.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'media') diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index bcfd83a..f0baf69 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1894,8 +1894,13 @@ void MediaPlayerService::AudioOutput::pause() void MediaPlayerService::AudioOutput::close() { ALOGV("close"); - Mutex::Autolock lock(mLock); - close_l(); + sp track; + { + Mutex::Autolock lock(mLock); + track = mTrack; + close_l(); // clears mTrack + } + // destruction of the track occurs outside of mutex. } void MediaPlayerService::AudioOutput::setVolume(float left, float right) -- cgit v1.1 From 87f8cbb223ee516803dbb99699320c2484cbf3ba Mon Sep 17 00:00:00 2001 From: Wei Jia Date: Fri, 20 Nov 2015 10:34:35 -0800 Subject: libstagefright: check requested memory size before allocation for SoftMPEG4Encoder and SoftVPXEncoder. Bug: 25812794 Change-Id: I96dc74734380d462583f6efa33d09946f9532809 --- media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp | 9 +++++++++ media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 9 +++++++++ 2 files changed, 18 insertions(+) (limited to 'media') diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index 8240f83..f2a4e65 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -37,6 +37,10 @@ #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -137,6 +141,11 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { // Color conversion is needed. free(mInputFrameData); + mInputFrameData = NULL; + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return OMX_ErrorBadParameter; + } mInputFrameData = (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1); CHECK(mInputFrameData != NULL); diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index e654843..410f9d0 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -26,6 +26,10 @@ #include #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -315,6 +319,11 @@ status_t SoftVPXEncoder::initEncoder() { if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { free(mConversionBuffer); + mConversionBuffer = NULL; + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return UNKNOWN_ERROR; + } mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); if (mConversionBuffer == NULL) { ALOGE("Allocating conversion buffer failed."); -- cgit v1.1 From 701cac1716d5ddb867a5444ea152d26741f3b397 Mon Sep 17 00:00:00 2001 From: Sridhar Vashist Date: Thu, 23 Jul 2015 13:48:54 -0500 Subject: AwesomePlayer: Stop posting buffering events once at EOS Stop posting buffering events once at end of stream to avoid perpetually holding the 'TimedEventQueue' wakelock in libstagefright. Change-Id: I3b8012886f2c27e830ce215b14090c35825635cd Signed-off-by: Sridhar Vashist --- media/libstagefright/AwesomePlayer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 3cd0b0e..d7be07d 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -828,7 +828,8 @@ void AwesomePlayer::onBufferingUpdate() { } } - if (mFlags & (PLAYING | PREPARING | CACHE_UNDERRUN)) { + if ( ((mFlags & PLAYING) && !eos) || + (mFlags & (PREPARING | CACHE_UNDERRUN)) ) { postBufferingEvent_l(); } } -- cgit v1.1 From ddbebb92f831784dc143d2cd8492ce690e238744 Mon Sep 17 00:00:00 2001 From: Sridhar Vashist Date: Thu, 23 Jul 2015 16:43:10 -0500 Subject: AwesomePlayer: Separate cache buffer watermarks for offload audio - Using normal playback cache watermarks for offload playback leads to cache underruns & buffering pauses resulting in choppy audio. - Add new properties to define cache hi/low watermarks for offload audio. - Calculate cache buffer levels only based on size for offload audio. Change-Id: Idb8c1be351678d57490939187079f452a65aebc3 Signed-off-by: Sridhar Vashist --- media/libstagefright/AwesomePlayer.cpp | 39 +++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'media') diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index d7be07d..15506ef 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -65,6 +65,8 @@ #define USE_SURFACE_ALLOC 1 #define FRAME_DROP_FREQ 0 +#define PROPERTY_OFFLOAD_HIWATERMARK "audio.offload.hiwatermark" +#define PROPERTY_OFFLOAD_LOWATERMARK "audio.offload.lowatermark" namespace android { @@ -72,7 +74,8 @@ static int64_t kLowWaterMarkUs = 2000000ll; // 2secs static int64_t kHighWaterMarkUs = 5000000ll; // 5secs static const size_t kLowWaterMarkBytes = 40000; static const size_t kHighWaterMarkBytes = 200000; - +static size_t kOffloadLowWaterMarkBytes = kLowWaterMarkBytes; +static size_t kOffloadHighWaterMarkBytes = kHighWaterMarkBytes; // maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer // is destroyed to allow the audio DSP to power down. static int64_t kOffloadPauseMaxUs = 10000000ll; @@ -638,6 +641,11 @@ void AwesomePlayer::reset_l() { mMediaRenderingStartGeneration = 0; mStartGeneration = 0; + + kOffloadLowWaterMarkBytes = + property_get_int32(PROPERTY_OFFLOAD_LOWATERMARK, kLowWaterMarkBytes); + kOffloadHighWaterMarkBytes = + property_get_int32(PROPERTY_OFFLOAD_HIWATERMARK, kHighWaterMarkBytes); } void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { @@ -728,6 +736,7 @@ void AwesomePlayer::onBufferingUpdate() { size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); bool eos = (finalStatus != OK); + ALOGV("cachedDataRemaining = %zu b, eos=%d", cachedDataRemaining, eos); if (eos) { if (finalStatus == ERROR_END_OF_STREAM) { notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); @@ -738,36 +747,42 @@ void AwesomePlayer::onBufferingUpdate() { } } else { bool eos2; + bool knownDuration = false; int64_t cachedDurationUs; if (getCachedDuration_l(&cachedDurationUs, &eos2) && mDurationUs > 0) { + knownDuration = true; int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; if (percentage > 100) { percentage = 100; } notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); - } else { - // We don't know the bitrate/duration of the stream, use absolute size - // limits to maintain the cache. + } + if (!knownDuration || mOffloadAudio) { + // If we don't know the bitrate/duration of the stream, or are offloading + // decode, use absolute size limits to maintain the cache. + + size_t lowWatermark = + mOffloadAudio ? kOffloadLowWaterMarkBytes : kLowWaterMarkBytes; + size_t highWatermark = + mOffloadAudio ? kOffloadHighWaterMarkBytes : kHighWaterMarkBytes; - if ((mFlags & PLAYING) && !eos - && (cachedDataRemaining < kLowWaterMarkBytes)) { - ALOGI("cache is running low (< %zu) , pausing.", - kLowWaterMarkBytes); + if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) { + ALOGI("cache is running low (< %zu) , pausing.", lowWatermark); modifyFlags(CACHE_UNDERRUN, SET); pause_l(); ensureCacheIsFetching_l(); sendCacheStats(); notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); - } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { + } else if (eos || cachedDataRemaining > highWatermark) { if (mFlags & CACHE_UNDERRUN) { ALOGI("cache has filled up (> %zu), resuming.", - kHighWaterMarkBytes); + highWatermark); modifyFlags(CACHE_UNDERRUN, CLEAR); play_l(); } else if (mFlags & PREPARING) { ALOGV("cache has filled up (> %zu), prepare is done", - kHighWaterMarkBytes); + highWatermark); finishAsyncPrepare_l(); } } @@ -801,7 +816,7 @@ void AwesomePlayer::onBufferingUpdate() { int64_t cachedDurationUs; bool eos; - if (getCachedDuration_l(&cachedDurationUs, &eos)) { + if (!mOffloadAudio && getCachedDuration_l(&cachedDurationUs, &eos)) { ALOGV("cachedDurationUs = %.2f secs, eos=%d", cachedDurationUs / 1E6, eos); -- cgit v1.1 From 92e41514344227f0c0cf09e9a989b455c8490fda Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Wed, 2 Dec 2015 13:22:51 -0800 Subject: DO NOT MERGE Revert "AwesomePlayer: Stop posting buffering events once at EOS" This reverts commit 701cac1716d5ddb867a5444ea152d26741f3b397. --- media/libstagefright/AwesomePlayer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'media') diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 15506ef..9a2c7a7 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -843,8 +843,7 @@ void AwesomePlayer::onBufferingUpdate() { } } - if ( ((mFlags & PLAYING) && !eos) || - (mFlags & (PREPARING | CACHE_UNDERRUN)) ) { + if (mFlags & (PLAYING | PREPARING | CACHE_UNDERRUN)) { postBufferingEvent_l(); } } -- cgit v1.1 From 35997452876b7ec164534b5267535076597495cd Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Wed, 2 Dec 2015 13:24:15 -0800 Subject: DO NOT MERGE Revert "AwesomePlayer: Separate cache buffer watermarks for offload audio" This reverts commit ddbebb92f831784dc143d2cd8492ce690e238744. --- media/libstagefright/AwesomePlayer.cpp | 39 +++++++++++----------------------- 1 file changed, 12 insertions(+), 27 deletions(-) (limited to 'media') diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 9a2c7a7..3cd0b0e 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -65,8 +65,6 @@ #define USE_SURFACE_ALLOC 1 #define FRAME_DROP_FREQ 0 -#define PROPERTY_OFFLOAD_HIWATERMARK "audio.offload.hiwatermark" -#define PROPERTY_OFFLOAD_LOWATERMARK "audio.offload.lowatermark" namespace android { @@ -74,8 +72,7 @@ static int64_t kLowWaterMarkUs = 2000000ll; // 2secs static int64_t kHighWaterMarkUs = 5000000ll; // 5secs static const size_t kLowWaterMarkBytes = 40000; static const size_t kHighWaterMarkBytes = 200000; -static size_t kOffloadLowWaterMarkBytes = kLowWaterMarkBytes; -static size_t kOffloadHighWaterMarkBytes = kHighWaterMarkBytes; + // maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer // is destroyed to allow the audio DSP to power down. static int64_t kOffloadPauseMaxUs = 10000000ll; @@ -641,11 +638,6 @@ void AwesomePlayer::reset_l() { mMediaRenderingStartGeneration = 0; mStartGeneration = 0; - - kOffloadLowWaterMarkBytes = - property_get_int32(PROPERTY_OFFLOAD_LOWATERMARK, kLowWaterMarkBytes); - kOffloadHighWaterMarkBytes = - property_get_int32(PROPERTY_OFFLOAD_HIWATERMARK, kHighWaterMarkBytes); } void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { @@ -736,7 +728,6 @@ void AwesomePlayer::onBufferingUpdate() { size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); bool eos = (finalStatus != OK); - ALOGV("cachedDataRemaining = %zu b, eos=%d", cachedDataRemaining, eos); if (eos) { if (finalStatus == ERROR_END_OF_STREAM) { notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); @@ -747,42 +738,36 @@ void AwesomePlayer::onBufferingUpdate() { } } else { bool eos2; - bool knownDuration = false; int64_t cachedDurationUs; if (getCachedDuration_l(&cachedDurationUs, &eos2) && mDurationUs > 0) { - knownDuration = true; int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; if (percentage > 100) { percentage = 100; } notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); - } - if (!knownDuration || mOffloadAudio) { - // If we don't know the bitrate/duration of the stream, or are offloading - // decode, use absolute size limits to maintain the cache. - - size_t lowWatermark = - mOffloadAudio ? kOffloadLowWaterMarkBytes : kLowWaterMarkBytes; - size_t highWatermark = - mOffloadAudio ? kOffloadHighWaterMarkBytes : kHighWaterMarkBytes; + } else { + // We don't know the bitrate/duration of the stream, use absolute size + // limits to maintain the cache. - if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) { - ALOGI("cache is running low (< %zu) , pausing.", lowWatermark); + if ((mFlags & PLAYING) && !eos + && (cachedDataRemaining < kLowWaterMarkBytes)) { + ALOGI("cache is running low (< %zu) , pausing.", + kLowWaterMarkBytes); modifyFlags(CACHE_UNDERRUN, SET); pause_l(); ensureCacheIsFetching_l(); sendCacheStats(); notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); - } else if (eos || cachedDataRemaining > highWatermark) { + } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { if (mFlags & CACHE_UNDERRUN) { ALOGI("cache has filled up (> %zu), resuming.", - highWatermark); + kHighWaterMarkBytes); modifyFlags(CACHE_UNDERRUN, CLEAR); play_l(); } else if (mFlags & PREPARING) { ALOGV("cache has filled up (> %zu), prepare is done", - highWatermark); + kHighWaterMarkBytes); finishAsyncPrepare_l(); } } @@ -816,7 +801,7 @@ void AwesomePlayer::onBufferingUpdate() { int64_t cachedDurationUs; bool eos; - if (!mOffloadAudio && getCachedDuration_l(&cachedDurationUs, &eos)) { + if (getCachedDuration_l(&cachedDurationUs, &eos)) { ALOGV("cachedDurationUs = %.2f secs, eos=%d", cachedDurationUs / 1E6, eos); -- cgit v1.1 From 19c47afbc402542720ddd280e1bbde3b2277b586 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Wed, 2 Dec 2015 15:55:23 -0800 Subject: DO NOT MERGE SoundPool: add lock for findSample access from SoundPoolThread Sample decoding still occurs in SoundPoolThread without holding the SoundPool lock. Bug: 25781119 Change-Id: I11fde005aa9cf5438e0390a0d2dfe0ec1dd282e8 --- media/libmedia/SoundPool.cpp | 61 ++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 19 deletions(-) (limited to 'media') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index d2e381b..29ad7ea 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -183,6 +183,17 @@ bool SoundPool::startThreads() return mDecodeThread != NULL; } +sp SoundPool::findSample(int sampleID) +{ + Mutex::Autolock lock(&mLock); + return findSample_l(sampleID); +} + +sp SoundPool::findSample_l(int sampleID) +{ + return mSamples.valueFor(sampleID); +} + SoundChannel* SoundPool::findChannel(int channelID) { for (int i = 0; i < mMaxChannels; ++i) { @@ -206,29 +217,42 @@ SoundChannel* SoundPool::findNextChannel(int channelID) int SoundPool::load(const char* path, int priority __unused) { ALOGV("load: path=%s, priority=%d", path, priority); - Mutex::Autolock lock(&mLock); - sp sample = new Sample(++mNextSampleID, path); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); + int sampleID; + { + Mutex::Autolock lock(&mLock); + sampleID = ++mNextSampleID; + sp sample = new Sample(sampleID, path); + mSamples.add(sampleID, sample); + sample->startLoad(); + } + // mDecodeThread->loadSample() must be called outside of mLock. + // mDecodeThread->loadSample() may block on mDecodeThread message queue space; + // the message queue emptying may block on SoundPool::findSample(). + // + // It theoretically possible that sample loads might decode out-of-order. + mDecodeThread->loadSample(sampleID); + return sampleID; } int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused) { ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d", fd, offset, length, priority); - Mutex::Autolock lock(&mLock); - sp sample = new Sample(++mNextSampleID, fd, offset, length); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); -} - -void SoundPool::doLoad(sp& sample) -{ - ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); - sample->startLoad(); - mDecodeThread->loadSample(sample->sampleID()); + int sampleID; + { + Mutex::Autolock lock(&mLock); + sampleID = ++mNextSampleID; + sp sample = new Sample(sampleID, fd, offset, length); + mSamples.add(sampleID, sample); + sample->startLoad(); + } + // mDecodeThread->loadSample() must be called outside of mLock. + // mDecodeThread->loadSample() may block on mDecodeThread message queue space; + // the message queue emptying may block on SoundPool::findSample(). + // + // It theoretically possible that sample loads might decode out-of-order. + mDecodeThread->loadSample(sampleID); + return sampleID; } bool SoundPool::unload(int sampleID) @@ -243,7 +267,6 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, { ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", sampleID, leftVolume, rightVolume, priority, loop, rate); - sp sample; SoundChannel* channel; int channelID; @@ -253,7 +276,7 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, return 0; } // is sample ready? - sample = findSample(sampleID); + sp sample(findSample_l(sampleID)); if ((sample == 0) || (sample->state() != Sample::READY)) { ALOGW(" sample %d not READY", sampleID); return 0; -- cgit v1.1 From 69bd1cf225328e64a5b4ae6935d2b7fe0b7b6400 Mon Sep 17 00:00:00 2001 From: Wei Jia Date: Fri, 20 Nov 2015 10:34:35 -0800 Subject: libstagefright: check requested memory size before allocation for SoftMPEG4Encoder and SoftVPXEncoder. Bug: 25812794 Change-Id: I96dc74734380d462583f6efa33d09946f9532809 (cherry picked from commit 87f8cbb223ee516803dbb99699320c2484cbf3ba) --- media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp | 9 +++++++++ media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 9 +++++++++ 2 files changed, 18 insertions(+) (limited to 'media') diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index 8240f83..f2a4e65 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -37,6 +37,10 @@ #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -137,6 +141,11 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { // Color conversion is needed. free(mInputFrameData); + mInputFrameData = NULL; + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return OMX_ErrorBadParameter; + } mInputFrameData = (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1); CHECK(mInputFrameData != NULL); diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index e654843..410f9d0 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -26,6 +26,10 @@ #include #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -315,6 +319,11 @@ status_t SoftVPXEncoder::initEncoder() { if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { free(mConversionBuffer); + mConversionBuffer = NULL; + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return UNKNOWN_ERROR; + } mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); if (mConversionBuffer == NULL) { ALOGE("Allocating conversion buffer failed."); -- cgit v1.1 From 0462975291796e414891e04bcec9da993914e458 Mon Sep 17 00:00:00 2001 From: Wei Jia Date: Fri, 20 Nov 2015 10:34:35 -0800 Subject: DO NOT MERGE - libstagefright: check requested memory size before allocation for SoftMPEG4Encoder and SoftVPXEncoder. Bug: 25812794 Change-Id: I96dc74734380d462583f6efa33d09946f9532809 (cherry picked from commit 87f8cbb223ee516803dbb99699320c2484cbf3ba) --- media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp | 9 +++++++++ media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 9 +++++++++ 2 files changed, 18 insertions(+) (limited to 'media') diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index c87d19c..d68c682 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -35,6 +35,10 @@ #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -123,6 +127,11 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { || mStoreMetaDataInBuffers) { // Color conversion is needed. free(mInputFrameData); + mInputFrameData = NULL; + if (((uint64_t)mVideoWidth * mVideoHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return OMX_ErrorBadParameter; + } mInputFrameData = (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1); CHECK(mInputFrameData != NULL); diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index eb621d5..43f99d4 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -25,6 +25,10 @@ #include #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -369,6 +373,11 @@ status_t SoftVPXEncoder::initEncoder() { if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { free(mConversionBuffer); + mConversionBuffer = NULL; + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return UNKNOWN_ERROR; + } mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); if (mConversionBuffer == NULL) { ALOGE("Allocating conversion buffer failed."); -- cgit v1.1 From 6afc659b00c3f4a83b9f5f3c744b7119b33340b4 Mon Sep 17 00:00:00 2001 From: Wei Jia Date: Fri, 20 Nov 2015 10:34:35 -0800 Subject: DO NOT MERGE - libstagefright: check requested memory size before allocation for SoftMPEG4Encoder and SoftVPXEncoder. Bug: 25812794 Change-Id: I96dc74734380d462583f6efa33d09946f9532809 (cherry picked from commit 87f8cbb223ee516803dbb99699320c2484cbf3ba) --- media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp | 11 ++++++++++- media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index e02af90..9f03502 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -33,6 +33,10 @@ #include "SoftMPEG4Encoder.h" +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -149,7 +153,12 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { if (mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { // Color conversion is needed. - CHECK(mInputFrameData == NULL); + free(mInputFrameData); + mInputFrameData = NULL; + if (((uint64_t)mVideoWidth * mVideoHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return OMX_ErrorBadParameter; + } mInputFrameData = (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1); CHECK(mInputFrameData != NULL); diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 8375cac..50eb6bf 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -25,6 +25,10 @@ #include #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { @@ -300,6 +304,10 @@ status_t SoftVPXEncoder::initEncoder() { if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || mInputDataIsMeta) { if (mConversionBuffer == NULL) { + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return UNKNOWN_ERROR; + } mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); if (mConversionBuffer == NULL) { ALOGE("Allocating conversion buffer failed."); -- cgit v1.1 From 3d6a7149802928ecf3f58b7218b0e82699b492df Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Wed, 2 Dec 2015 15:55:23 -0800 Subject: DO NOT MERGE SoundPool: add lock for findSample access from SoundPoolThread Sample decoding still occurs in SoundPoolThread without holding the SoundPool lock. Bug: 25781119 Change-Id: I11fde005aa9cf5438e0390a0d2dfe0ec1dd282e8 --- media/libmedia/SoundPool.cpp | 61 ++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 19 deletions(-) (limited to 'media') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 22e9fad..a2b5e30 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -179,6 +179,17 @@ bool SoundPool::startThreads() return mDecodeThread != NULL; } +sp SoundPool::findSample(int sampleID) +{ + Mutex::Autolock lock(&mLock); + return findSample_l(sampleID); +} + +sp SoundPool::findSample_l(int sampleID) +{ + return mSamples.valueFor(sampleID); +} + SoundChannel* SoundPool::findChannel(int channelID) { for (int i = 0; i < mMaxChannels; ++i) { @@ -202,29 +213,42 @@ SoundChannel* SoundPool::findNextChannel(int channelID) int SoundPool::load(const char* path, int priority) { ALOGV("load: path=%s, priority=%d", path, priority); - Mutex::Autolock lock(&mLock); - sp sample = new Sample(++mNextSampleID, path); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); + int sampleID; + { + Mutex::Autolock lock(&mLock); + sampleID = ++mNextSampleID; + sp sample = new Sample(sampleID, path); + mSamples.add(sampleID, sample); + sample->startLoad(); + } + // mDecodeThread->loadSample() must be called outside of mLock. + // mDecodeThread->loadSample() may block on mDecodeThread message queue space; + // the message queue emptying may block on SoundPool::findSample(). + // + // It theoretically possible that sample loads might decode out-of-order. + mDecodeThread->loadSample(sampleID); + return sampleID; } int SoundPool::load(int fd, int64_t offset, int64_t length, int priority) { ALOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d", fd, offset, length, priority); - Mutex::Autolock lock(&mLock); - sp sample = new Sample(++mNextSampleID, fd, offset, length); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); -} - -void SoundPool::doLoad(sp& sample) -{ - ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); - sample->startLoad(); - mDecodeThread->loadSample(sample->sampleID()); + int sampleID; + { + Mutex::Autolock lock(&mLock); + sampleID = ++mNextSampleID; + sp sample = new Sample(sampleID, fd, offset, length); + mSamples.add(sampleID, sample); + sample->startLoad(); + } + // mDecodeThread->loadSample() must be called outside of mLock. + // mDecodeThread->loadSample() may block on mDecodeThread message queue space; + // the message queue emptying may block on SoundPool::findSample(). + // + // It theoretically possible that sample loads might decode out-of-order. + mDecodeThread->loadSample(sampleID); + return sampleID; } bool SoundPool::unload(int sampleID) @@ -239,7 +263,6 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, { ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", sampleID, leftVolume, rightVolume, priority, loop, rate); - sp sample; SoundChannel* channel; int channelID; @@ -249,7 +272,7 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, return 0; } // is sample ready? - sample = findSample(sampleID); + sp sample(findSample_l(sampleID)); if ((sample == 0) || (sample->state() != Sample::READY)) { ALOGW(" sample %d not READY", sampleID); return 0; -- cgit v1.1 From 91a23ed95cda558a3c31e8ef34f420924f4d6d7d Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Thu, 19 Feb 2015 16:39:59 -0800 Subject: DO NOT MERGE nuplayer: do not use cached source for wvm content bug: 18730095, 25563255 Change-Id: Ibd4f54907949daae1d095fa0922050310d16698f (cherry picked from commit fc6cfd8343ae8919e85ec22efed9df626fe8854b) --- .../nuplayer/GenericSource.cpp | 55 +++++++++++++--------- 1 file changed, 32 insertions(+), 23 deletions(-) (limited to 'media') diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index cdd2670..7c38edb 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -130,23 +130,37 @@ sp NuPlayer::GenericSource::getFileFormatMeta() const { status_t NuPlayer::GenericSource::initFromDataSource() { sp extractor; + String8 mimeType; + float confidence; + sp dummy; + bool isWidevineStreaming = false; CHECK(mDataSource != NULL); if (mIsWidevine) { - String8 mimeType; - float confidence; - sp dummy; - bool success; - - success = SniffWVM(mDataSource, &mimeType, &confidence, &dummy); - if (!success - || strcasecmp( + isWidevineStreaming = SniffWVM( + mDataSource, &mimeType, &confidence, &dummy); + if (!isWidevineStreaming || + strcasecmp( mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { ALOGE("unsupported widevine mime: %s", mimeType.string()); return UNKNOWN_ERROR; } + } else if (mIsStreaming) { + if (mSniffedMIME.empty()) { + if (!mDataSource->sniff(&mimeType, &confidence, &dummy)) { + return UNKNOWN_ERROR; + } + mSniffedMIME = mimeType.string(); + } + isWidevineStreaming = !strcasecmp( + mSniffedMIME.c_str(), MEDIA_MIMETYPE_CONTAINER_WVM); + } + if (isWidevineStreaming) { + // we don't want cached source for widevine streaming. + mCachedSource.clear(); + mDataSource = mHttpSource; mWVMExtractor = new WVMExtractor(mDataSource); mWVMExtractor->setAdaptiveStreamingMode(true); if (mUIDValid) { @@ -181,14 +195,6 @@ status_t NuPlayer::GenericSource::initFromDataSource() { if (mFileMeta->findCString(kKeyMIMEType, &fileMime) && !strncasecmp(fileMime, "video/wvm", 9)) { mIsWidevine = true; - if (!mUri.empty()) { - // streaming, but the app forgot to specify widevine:// url - mWVMExtractor = static_cast(extractor.get()); - mWVMExtractor->setAdaptiveStreamingMode(true); - if (mUIDValid) { - mWVMExtractor->setUID(mUID); - } - } } } } @@ -704,10 +710,10 @@ void NuPlayer::GenericSource::sendCacheStats() { int32_t kbps = 0; status_t err = UNKNOWN_ERROR; - if (mCachedSource != NULL) { - err = mCachedSource->getEstimatedBandwidthKbps(&kbps); - } else if (mWVMExtractor != NULL) { + if (mWVMExtractor != NULL) { err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps); + } else if (mCachedSource != NULL) { + err = mCachedSource->getEstimatedBandwidthKbps(&kbps); } if (err == OK) { @@ -729,7 +735,13 @@ void NuPlayer::GenericSource::onPollBuffering() { int64_t cachedDurationUs = -1ll; ssize_t cachedDataRemaining = -1; - if (mCachedSource != NULL) { + ALOGW_IF(mWVMExtractor != NULL && mCachedSource != NULL, + "WVMExtractor and NuCachedSource both present"); + + if (mWVMExtractor != NULL) { + cachedDurationUs = + mWVMExtractor->getCachedDurationUs(&finalStatus); + } else if (mCachedSource != NULL) { cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); @@ -745,9 +757,6 @@ void NuPlayer::GenericSource::onPollBuffering() { cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate; } } - } else if (mWVMExtractor != NULL) { - cachedDurationUs - = mWVMExtractor->getCachedDurationUs(&finalStatus); } if (finalStatus != OK) { -- cgit v1.1 From 22f824feac43d5758f9a70b77f2aca840ba62c3b Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Fri, 4 Dec 2015 16:29:16 -0800 Subject: Fix security vulnerability in ICrypto DO NOT MERGE b/25800375 Change-Id: I03c9395f7c7de4ac5813a1207452aac57aa39484 --- media/libmedia/ICrypto.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp index a398ff7..22f8af7 100644 --- a/media/libmedia/ICrypto.cpp +++ b/media/libmedia/ICrypto.cpp @@ -321,7 +321,9 @@ status_t BnCrypto::onTransact( if (overflow || sumSubsampleSizes != totalSize) { result = -EINVAL; - } else if (offset + totalSize > sharedBuffer->size()) { + } else if (totalSize > sharedBuffer->size()) { + result = -EINVAL; + } else if ((size_t)offset > sharedBuffer->size() - totalSize) { result = -EINVAL; } else { result = decrypt( -- cgit v1.1 From 50270d98e26fa18b20ca88216c3526667b724ba7 Mon Sep 17 00:00:00 2001 From: Wei Jia Date: Fri, 20 Nov 2015 10:34:35 -0800 Subject: DO NOT MERGE - libstagefright: check requested memory size before allocation for SoftMPEG4Encoder and SoftVPXEncoder. Bug: 25812794 Change-Id: I96dc74734380d462583f6efa33d09946f9532809 (cherry picked from commit 87f8cbb223ee516803dbb99699320c2484cbf3ba) (cherry picked from commit 0462975291796e414891e04bcec9da993914e458) --- media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp | 9 +++++++++ media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 9 +++++++++ 2 files changed, 18 insertions(+) (limited to 'media') diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index fa3486c..bd4d623 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -37,6 +37,10 @@ #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -137,6 +141,11 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { // Color conversion is needed. free(mInputFrameData); + mInputFrameData = NULL; + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return OMX_ErrorBadParameter; + } mInputFrameData = (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1); CHECK(mInputFrameData != NULL); diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 970acf3..ef94946 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -26,6 +26,10 @@ #include #include +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + namespace android { template @@ -315,6 +319,11 @@ status_t SoftVPXEncoder::initEncoder() { if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { free(mConversionBuffer); + mConversionBuffer = NULL; + if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { + ALOGE("b/25812794, Buffer size is too big."); + return UNKNOWN_ERROR; + } mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); if (mConversionBuffer == NULL) { ALOGE("Allocating conversion buffer failed."); -- cgit v1.1 From 9e29523b9537983b4c4b205ff868d0b3bca0383b Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 8 Jan 2016 10:52:38 -0800 Subject: fix possible overflow in effect wrappers. Add checks on parameter size field in effect command handlers to avoid overflow leading to invalid comparison with min allowed size for command and reply buffers. Bug: 26347509. Change-Id: I20e6a9b6de8e5172b957caa1ac9410b9752efa4d (cherry picked from commit ad1bd92a49d78df6bc6e75bee68c517c1326f3cf) --- media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp | 5 ++++- media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'media') diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index 9fcfba3..5befff8 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -2809,7 +2809,10 @@ int Effect_command(effect_handle_t self, //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - + if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { + android_errorWriteLog(0x534e4554, "26347509"); + return -EINVAL; + } if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index 2e22532..7ab16a1 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -1953,7 +1953,10 @@ int Reverb_command(effect_handle_t self, //ALOGV("\tReverb_command cmdCode Case: " // "EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - + if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { + android_errorWriteLog(0x534e4554, "26347509"); + return -EINVAL; + } if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || -- cgit v1.1 From 9cebd7cfba272117522617661cf9d4985880921e Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 12 Jan 2016 18:03:24 +0000 Subject: DO NOT MERGE ANYWHERE Revert "fix possible overflow in effect wrappers." This reverts commit 9e29523b9537983b4c4b205ff868d0b3bca0383b. Change-Id: Ic9a97d1a98165500dd444b97629349cf082ced94 --- media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp | 5 +---- media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'media') diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index 86ce27a..40c7fef 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -3053,10 +3053,7 @@ int Effect_command(effect_handle_t self, //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { - android_errorWriteLog(0x534e4554, "26347509"); - return -EINVAL; - } + if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index 4dc8b45..a48a4e3 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -1956,10 +1956,7 @@ int Reverb_command(effect_handle_t self, //ALOGV("\tReverb_command cmdCode Case: " // "EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { - android_errorWriteLog(0x534e4554, "26347509"); - return -EINVAL; - } + if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || -- cgit v1.1 From 5403587a74aee2fb57076528c3927851531c8afb Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Tue, 12 Jan 2016 12:37:36 -0800 Subject: Fix out-of-bounds write Bug: 26365349 Change-Id: Ia363d9f8c231cf255dea852e0bbf5ca466c7990b --- media/libstagefright/MPEG4Extractor.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index f0988eb..5d8be84 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -3682,7 +3682,15 @@ status_t MPEG4Source::fragmentedRead( continue; } - CHECK(dstOffset + 4 <= mBuffer->size()); + if (dstOffset > SIZE_MAX - 4 || + dstOffset + 4 > SIZE_MAX - nalLength || + dstOffset + 4 + nalLength > mBuffer->size()) { + ALOGE("b/26365349 : %zu %zu", dstOffset, mBuffer->size()); + android_errorWriteLog(0x534e4554, "26365349"); + mBuffer->release(); + mBuffer = NULL; + return ERROR_MALFORMED; + } dstData[dstOffset++] = 0; dstData[dstOffset++] = 0; -- cgit v1.1 From 349169847c86cd1154a3b401d4cab6f0a410b192 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 8 Jan 2016 10:52:38 -0800 Subject: fix possible overflow in effect wrappers. Add checks on parameter size field in effect command handlers to avoid overflow leading to invalid comparison with min allowed size for command and reply buffers. Bug: 26347509. Change-Id: I20e6a9b6de8e5172b957caa1ac9410b9752efa4d (cherry picked from commit ad1bd92a49d78df6bc6e75bee68c517c1326f3cf) --- media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp | 5 ++++- media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'media') diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index af904a6..14a1a74 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -3091,7 +3091,10 @@ int Effect_command(effect_handle_t self, //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - + if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { + android_errorWriteLog(0x534e4554, "26347509"); + return -EINVAL; + } if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index a48a4e3..4dc8b45 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -1956,7 +1956,10 @@ int Reverb_command(effect_handle_t self, //ALOGV("\tReverb_command cmdCode Case: " // "EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - + if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { + android_errorWriteLog(0x534e4554, "26347509"); + return -EINVAL; + } if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || -- cgit v1.1 From d7640491ba0cf2ef8424734a942f38f80535591b Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Tue, 12 Jan 2016 12:37:36 -0800 Subject: Fix out-of-bounds write Bug: 26365349 Change-Id: Ia363d9f8c231cf255dea852e0bbf5ca466c7990b --- media/libstagefright/MPEG4Extractor.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index bfdff38..e4f8384 100755 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -4545,7 +4545,15 @@ status_t MPEG4Source::fragmentedRead( continue; } - CHECK(dstOffset + 4 <= mBuffer->size()); + if (dstOffset > SIZE_MAX - 4 || + dstOffset + 4 > SIZE_MAX - nalLength || + dstOffset + 4 + nalLength > mBuffer->size()) { + ALOGE("b/26365349 : %zu %zu", dstOffset, mBuffer->size()); + android_errorWriteLog(0x534e4554, "26365349"); + mBuffer->release(); + mBuffer = NULL; + return ERROR_MALFORMED; + } dstData[dstOffset++] = 0; dstData[dstOffset++] = 0; -- cgit v1.1 From c5fa90a809c9e7a98e32373a4dea6b3e46a0e92c Mon Sep 17 00:00:00 2001 From: Weiyin Jiang Date: Thu, 13 Nov 2014 12:56:05 +0800 Subject: audio: omx encoder isn't expected for raw recording Raw recording doesn't require any encoder, so no OMX encoder will be created and audio source will be directly used as media source. UNKNOWN_ERROR error will be threwn if call AudioSource::start() continuously, so we should avoid omx encoder operations if it's not created for raw recording. CYNGNOS-1679 Change-Id: Ib38c4e42b7667e9bf882cddb15422d0dd598b60e CRs-Fixed: 752419 (cherry picked from commit 587267232a2829936510bbe46591863403782d1a) --- .../libmediaplayerservice/StagefrightRecorder.cpp | 28 +++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'media') diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index c4c5741..709e653 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -2044,10 +2044,16 @@ status_t StagefrightRecorder::setSourcePause(bool pause) { } } if (mAudioEncoderOMX != NULL) { - err = mAudioEncoderOMX->pause(); - if (err != OK) { - ALOGE("OMX AudioEncoder pause failed"); - return err; + if (mAudioEncoderOMX != mAudioSourceNode) { + err = mAudioEncoderOMX->pause(); + if (err != OK) { + ALOGE("OMX AudioEncoder pause failed"); + return err; + } + } else { + // If AudioSource is the same as MediaSource(as in LPCM), + // bypass omx encoder pause() call. + ALOGV("OMX AudioEncoder->pause() bypassed"); } } if (mVideoSourceNode != NULL) { @@ -2087,10 +2093,16 @@ status_t StagefrightRecorder::setSourcePause(bool pause) { } } if (mAudioEncoderOMX != NULL) { - err = mAudioEncoderOMX->start(); - if (err != OK) { - ALOGE("OMX AudioEncoder start failed"); - return err; + if (mAudioEncoderOMX != mAudioSourceNode) { + err = mAudioEncoderOMX->start(); + if (err != OK) { + ALOGE("OMX AudioEncoder start failed"); + return err; + } + } else { + // If AudioSource is the same as MediaSource(as in LPCM), + // bypass omx encoder start() call. + ALOGV("OMX AudioEncoder->start() bypassed"); } } } -- cgit v1.1 From 808632f7bf0a897fb55cc38170ad6c1b2fd86ba2 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Mon, 29 Feb 2016 17:32:19 -0800 Subject: stagefright: Don't crash on invalid / null AVCC atoms in MKV * Seen in the wild. If a file contains an invalid track, skip it. * Also correct AVCC atom size check in Matroska extractor. REF: CYNGNOS-2168 Change-Id: I589aadbd689c9a00e1dca613e61fcec5b06ed69a --- media/libstagefright/MPEG4Extractor.cpp | 12 +++++++----- media/libstagefright/matroska/MatroskaExtractor.cpp | 13 +++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'media') diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index c928495..3baf6b6 100755 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -3325,11 +3325,13 @@ MPEG4Source::MPEG4Source( const uint8_t *ptr = (const uint8_t *)data; - CHECK(size >= 7); - CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 - - // The number of bytes used to encode the length of a NAL unit. - mNALLengthSize = 1 + (ptr[4] & 3); + if (size < 7 || ptr[0] != 1) { + ALOGE("Invalid AVCC atom, size %zu, configurationVersion: %d", + size, ptr[0]); + } else { + // The number of bytes used to encode the length of a NAL unit. + mNALLengthSize = 1 + (ptr[4] & 3); + } } else if (mIsHEVC) { uint32_t type; const void *data; diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index c1fa240..b2463e7 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -224,18 +224,19 @@ MatroskaSource::MatroskaSource( mIsAudio = !strncasecmp("audio/", mime, 6); if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { - mType = AVC; - uint32_t dummy; const uint8_t *avcc; size_t avccSize; CHECK(meta->findData( kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)); - CHECK_GE(avccSize, 5u); - - mNALSizeLen = 1 + (avcc[4] & 3); - ALOGV("mNALSizeLen = %zu", mNALSizeLen); + if (avccSize < 7) { + ALOGW("Invalid AVCC atom in track, size %zu", avccSize); + } else { + mNALSizeLen = 1 + (avcc[4] & 3); + ALOGV("mNALSizeLen = %zu", mNALSizeLen); + mType = AVC; + } } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { mType = HEVC; -- cgit v1.1 From 51aee1e55bee9cf8e4fd30ecf19fccd7ab7bfc15 Mon Sep 17 00:00:00 2001 From: Keith Mok Date: Mon, 7 Mar 2016 15:22:22 -0800 Subject: stagefright: Support audio in slow motion We need to query AVUtil for slow motion recording to support audio in slow motion recording instead of using mCaptureFps and mCaptureFpsEnable, since qcom camera1 HAL don't call setCaptureRate for slow motion recording. CYNGNOS-2196 Change-Id: I7b75ab44499ed13cb1e4e6f527103ec0f09ffcc8 --- .../libmediaplayerservice/StagefrightRecorder.cpp | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'media') diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 709e653..d182a68 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -963,6 +963,30 @@ sp StagefrightRecorder::createAudioSource() { } } + // If using QCOM extension (Camera 1 HAL) for slow motion recording + // mCaptureFpsEnable and mCaptureFps will not be set via setCaptureRate + // We need to query from AVUtil, in order to support slow motion audio recording + if (mVideoSourceNode != NULL) { + int hfrRatio = AVUtils::get()->HFRUtils().getHFRRatio(mVideoSourceNode->getFormat()); + if (hfrRatio != 1) { + // Upscale the sample rate for slow motion recording. + // Fail audio source creation if source sample rate is too high, as it could + // cause out-of-memory due to large input buffer size. And audio recording + // probably doesn't make sense in the scenario, since the slow-down factor + // is probably huge (eg. mSampleRate=48K, hfrRatio=240, mFrameRate=1). + const static int32_t SAMPLE_RATE_HZ_MAX = 192000; + sourceSampleRate = + (mSampleRate * hfrRatio + mFrameRate / 2) / mFrameRate; + if (sourceSampleRate < mSampleRate || sourceSampleRate > SAMPLE_RATE_HZ_MAX) { + ALOGE("source sample rate out of range! " + "(mSampleRate %d, hfrRatio %d, mFrameRate %d", + mSampleRate, hfrRatio, mFrameRate); + return NULL; + } + } + } + + sp audioSource = AVFactory::get()->createAudioSource( mAudioSource, mOpPackageName, -- cgit v1.1 From 0479d7c79a7fd6f112e8dc7e45c009cf6602dbaa Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Thu, 14 Jan 2016 02:46:40 -0800 Subject: audiopolicy: Add notification when default effects are updated * In M, we now have the ability to define a default set of audio effect on a per-stream basis. This allows us to get around the problem of apps not sending the control intents so we can implement smart global effects for specific media types. * We still need a session id in order to get a handle and configure them from an app like AudioFX, so we'll need to add some plumbing in order to send an event to interested applications. * This patch implements the native side of this. The Java layer will call down thru AudioSystem and register a callback which will be invoked by the audio policy when default effects are updated on a stream. This callback will receive both the stream type as well as the session id. * Attaching this listener requires that the caller hold the MODIFY_AUDIO_ROUTING permission. Change-Id: I142b15f2585ffca6a953c3e828e2a7c07b24f56c --- media/libmedia/AudioSystem.cpp | 32 +++++++++++++++++++++++++++- media/libmedia/IAudioPolicyService.cpp | 20 +++++++++++++++++ media/libmedia/IAudioPolicyServiceClient.cpp | 22 ++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) (limited to 'media') diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 9d645f0..10ec495 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -37,7 +37,7 @@ sp AudioSystem::gAudioFlinger; sp AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL; - +effect_session_callback AudioSystem::gEffectSessionCallback = NULL; // establish binder interface to AudioFlinger service const sp AudioSystem::get_audio_flinger() @@ -652,6 +652,21 @@ status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( gDynPolicyCallback = cb; } +/*static*/ status_t AudioSystem::setEffectSessionCallback(effect_session_callback cb) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + + Mutex::Autolock _l(gLock); + gEffectSessionCallback = cb; + + status_t status = aps->setEffectSessionCallbacksEnabled(cb != NULL); + if (status != OK) { + gEffectSessionCallback = NULL; + } + return status; +} + // client singleton for AudioPolicyService binder interface // protected by gLockAPS sp AudioSystem::gAudioPolicyService; @@ -1223,6 +1238,21 @@ void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate( } } +void AudioSystem::AudioPolicyServiceClient::onOutputSessionEffectsUpdate( + audio_stream_type_t stream, audio_unique_id_t sessionId, bool added) +{ + ALOGV("AudioPolicyServiceClient::onOutputSessionEffectsUpdate(%d, %d, %d)", stream, sessionId, added); + effect_session_callback cb = NULL; + { + Mutex::Autolock _l(AudioSystem::gLock); + cb = gEffectSessionCallback; + } + + if (cb != NULL) { + cb(AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE, stream, sessionId, added); + } +} + void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) { { diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 76b5924..6ff8149 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -74,6 +74,7 @@ enum { START_AUDIO_SOURCE, STOP_AUDIO_SOURCE, SET_AUDIO_PORT_CALLBACK_ENABLED, + SET_EFFECT_SESSION_CALLBACK_ENABLED, }; #define MAX_ITEMS_PER_LIST 1024 @@ -655,6 +656,18 @@ public: remote()->transact(SET_AUDIO_PORT_CALLBACK_ENABLED, data, &reply); } + virtual status_t setEffectSessionCallbacksEnabled(bool enabled) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(enabled ? 1 : 0); + status_t status = remote()->transact(SET_EFFECT_SESSION_CALLBACK_ENABLED, data, &reply); + if (status != NO_ERROR) { + return status; + } + return (status_t)reply.readInt32(); + } + virtual status_t acquireSoundTriggerSession(audio_session_t *session, audio_io_handle_t *ioHandle, audio_devices_t *device) @@ -1238,6 +1251,13 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case SET_EFFECT_SESSION_CALLBACK_ENABLED: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + status_t status = setEffectSessionCallbacksEnabled(data.readInt32() == 1); + reply->writeInt32(status); + return NO_ERROR; + } break; + case ACQUIRE_SOUNDTRIGGER_SESSION: { CHECK_INTERFACE(IAudioPolicyService, data, reply); sp client = interface_cast( diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp index 65cc7d6..d6207ce 100644 --- a/media/libmedia/IAudioPolicyServiceClient.cpp +++ b/media/libmedia/IAudioPolicyServiceClient.cpp @@ -30,7 +30,8 @@ namespace android { enum { PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION, PATCH_LIST_UPDATE, - MIX_STATE_UPDATE + MIX_STATE_UPDATE, + OUTPUT_SESSION_EFFECTS_UPDATE }; class BpAudioPolicyServiceClient : public BpInterface @@ -63,6 +64,17 @@ public: data.writeInt32(state); remote()->transact(MIX_STATE_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); } + + void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); + data.writeInt32(stream); + data.writeInt32(sessionId); + data.writeInt32(added ? 1 : 0); + remote()->transact(OUTPUT_SESSION_EFFECTS_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient"); @@ -90,6 +102,14 @@ status_t BnAudioPolicyServiceClient::onTransact( onDynamicPolicyMixStateUpdate(regId, state); return NO_ERROR; } + case OUTPUT_SESSION_EFFECTS_UPDATE: { + CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); + audio_stream_type_t stream = static_cast(data.readInt32()); + audio_unique_id_t sessionId = static_cast(data.readInt32()); + bool added = data.readInt32() > 0; + onOutputSessionEffectsUpdate(stream, sessionId, added); + return NO_ERROR; + } default: return BBinder::onTransact(code, data, reply, flags); } -- cgit v1.1 From 41d4ad503757189ad401fa82d7572502de0712fa Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Wed, 6 Jan 2016 17:03:22 -0800 Subject: SoftVorbis: memory access check Check for valid input buffer header before reading from it. This seems to be manifested only when memory map of an input buffer sent from a remote process fails in mediaserver context. CRs-Fixed: 916568 Change-Id: I4ee16e7104c2d8bf579f80201864009e51cd1b25 --- media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp | 14 +++++++++++++- media/libstagefright/codecs/vorbis/dec/SoftVorbis.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp index 3dc549e..08200c1 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp @@ -56,7 +56,8 @@ SoftVorbis::SoftVorbis( mNumFramesLeftOnPage(-1), mSawInputEos(false), mSignalledOutputEos(false), - mOutputPortSettingsChange(NONE) { + mOutputPortSettingsChange(NONE), + mSignalledError(false) { initPorts(); CHECK_EQ(initDecoder(), (status_t)OK); } @@ -251,10 +252,21 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) { return; } + if (mSignalledError) { + return; + } + if (portIndex == 0 && mInputBufferCount < 2) { BufferInfo *info = *inQueue.begin(); OMX_BUFFERHEADERTYPE *header = info->mHeader; + if (!header || !header->pBuffer) { + ALOGE("b/25727575 has happened. report error"); + notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); + mSignalledError = true; + return; + } + const uint8_t *data = header->pBuffer + header->nOffset; size_t size = header->nFilledLen; diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h index 1d00816..7decc5a 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h @@ -68,6 +68,8 @@ private: AWAITING_ENABLED } mOutputPortSettingsChange; + bool mSignalledError; + void initPorts(); status_t initDecoder(); bool isConfigured() const; -- cgit v1.1 From 97fc248733b43731e1e2d98de5dad47a490dbbc2 Mon Sep 17 00:00:00 2001 From: Santhosh Behara Date: Thu, 26 Nov 2015 15:27:50 +0530 Subject: ACodec: update the right size and crop in smooth streaming case In smooth streaming enabled case, the max width and max height sizes should be updated in native window. And the crop rectangle should also be updated. Change-Id: I4a15aa24a51b495141001dd43adec7005ab0c742 --- media/libstagefright/ACodec.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'media') diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 4807b65..7351d3e 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -925,10 +925,24 @@ status_t ACodec::setupNativeWindowSizeFormatAndUsage( #endif ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage); + int32_t width = 0, height = 0; + int32_t isAdaptivePlayback = 0; + + if (mInputFormat->findInt32("adaptive-playback", &isAdaptivePlayback) + && isAdaptivePlayback + && mInputFormat->findInt32("max-width", &width) + && mInputFormat->findInt32("max-height", &height)) { + width = max(width, (int32_t)def.format.video.nFrameWidth); + height = max(height, (int32_t)def.format.video.nFrameHeight); + ALOGV("Adaptive playback width = %d, height = %d", width, height); + } else { + width = def.format.video.nFrameWidth; + height = def.format.video.nFrameHeight; + } err = setNativeWindowSizeFormatAndUsage( nativeWindow, - def.format.video.nFrameWidth, - def.format.video.nFrameHeight, + width, + height, #ifdef USE_SAMSUNG_COLORFORMAT eNativeColorFormat, #else -- cgit v1.1 From 1aedff94c6f52223f8720edbce16c80ad1b57b00 Mon Sep 17 00:00:00 2001 From: Li Sun Date: Wed, 9 Dec 2015 18:28:10 +0530 Subject: Nuplayer: Flush the decoder if seamless format change is supported In smooth streaming enabled case, flush the decoder if seamless format change is supported. Otherwise,ramdomly video frames with old resolution are queued to the new surface and results in green frames. Calling flush ensures that all the old video frames are cleared. Change-Id: Ia020a01fd0eaa8af8e48b6edb526a3f53875b068 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 15 ++++++++++++-- .../nuplayer/NuPlayerDecoder.cpp | 23 +++++++++++++++++++--- .../nuplayer/NuPlayerDecoder.h | 1 + 3 files changed, 34 insertions(+), 5 deletions(-) (limited to 'media') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index c87208c..caac70b 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -932,10 +932,21 @@ void NuPlayer::onMessageReceived(const sp &msg) { audio ? "audio" : "video", formatChange); if (formatChange) { - mDeferredActions.push_back( - new FlushDecoderAction( + int32_t seamlessChange = 0; + if (msg->findInt32("video-seamlessChange", &seamlessChange) && seamlessChange) { + ALOGE("video decoder seamlessChange in smooth streaming mode, " + "flush the video decoder"); + mDeferredActions.push_back( + new FlushDecoderAction(FLUSH_CMD_NONE, FLUSH_CMD_FLUSH)); + mDeferredActions.push_back(new ResumeDecoderAction(false)); + processDeferredActions(); + break; + } else { + mDeferredActions.push_back( + new FlushDecoderAction( audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE, audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN)); + } } mDeferredActions.push_back( diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index c505096..a18e1da 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -73,6 +73,7 @@ NuPlayer::Decoder::Decoder( mIsSecure(false), mFormatChangePending(false), mTimeChangePending(false), + mVideoFormatChangeDoFlushOnly(false), mResumePending(false), mComponentName("decoder") { mCodecLooper = new ALooper; @@ -243,6 +244,7 @@ void NuPlayer::Decoder::onConfigure(const sp &format) { mFormatChangePending = false; mTimeChangePending = false; + mVideoFormatChangeDoFlushOnly = false; ++mBufferGeneration; @@ -759,9 +761,20 @@ status_t NuPlayer::Decoder::fetchInputData(sp &reply) { mTimeChangePending = true; err = ERROR_END_OF_STREAM; } else if (seamlessFormatChange) { - // reuse existing decoder and don't flush - rememberCodecSpecificData(newFormat); - continue; + if (!mIsAudio && + newFormat != NULL && + newFormat->contains("prefer-adaptive-playback")) { + ALOGV("in smooth streaming mode, " + "do video flush in video seamless format change"); + mFormatChangePending = true; + mVideoFormatChangeDoFlushOnly = true; + err = ERROR_END_OF_STREAM; + } else { + // reuse existing decoder and don't flush + rememberCodecSpecificData(newFormat); + continue; + } + } else { // This stream is unaffected by the discontinuity return -EWOULDBLOCK; @@ -989,10 +1002,14 @@ void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) { sp msg = mNotify->dup(); msg->setInt32("what", kWhatInputDiscontinuity); msg->setInt32("formatChange", mFormatChangePending); + if (mVideoFormatChangeDoFlushOnly) { + msg->setInt32("video-seamlessChange", mVideoFormatChangeDoFlushOnly); + } msg->post(); mFormatChangePending = false; mTimeChangePending = false; + mVideoFormatChangeDoFlushOnly = false; } bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange( diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h index 6e2b9d0..1fbefda 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h @@ -95,6 +95,7 @@ protected: bool mIsSecure; bool mFormatChangePending; bool mTimeChangePending; + bool mVideoFormatChangeDoFlushOnly; bool mResumePending; AString mComponentName; -- cgit v1.1 From 69714d42dc65906f2a94a5e47bea6219ead6fe23 Mon Sep 17 00:00:00 2001 From: Surajit Podder Date: Wed, 13 Jan 2016 12:42:43 +0530 Subject: video: Add support to push blank buffers on surface switch Add support to push blank buffers only on surface switch. Setting "push-blank-buffers-on-switch" key with value 1 will enable this feature. Change-Id: I4a0fc48fe24c09a6b8d0e2e0fc4dc2e96d3178bf --- media/libstagefright/ACodec.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 7351d3e..8cf38ef 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -767,7 +767,8 @@ status_t ACodec::handleSetSurface(const sp &surface) { } // push blank buffers to previous window if requested - if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) { + if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown || + mFlags & kFlagPushBlankBuffersToNativeWindowOnSwitch) { pushBlankBuffersToNativeWindow(mNativeWindow.get()); } @@ -1983,6 +1984,12 @@ status_t ACodec::configureCodec( && push != 0) { mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; } + + int32_t val; + if (msg->findInt32("push-blank-buffers-on-switch", &val) + && val != 0) { + mFlags |= kFlagPushBlankBuffersToNativeWindowOnSwitch; + } } int32_t rotationDegrees; -- cgit v1.1 From c3902bb77957a98082d03ec1cf8ff938495a674a Mon Sep 17 00:00:00 2001 From: Surajit Podder Date: Mon, 1 Feb 2016 13:51:18 +0530 Subject: video: Add metadata support for DataSource Add meta() API to query and update DataSource metadata. Change-Id: Ibc99fbb6b9bdd6ca6a9d0b25883ba5907946a81d --- media/libstagefright/DataSource.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'media') diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index b833f9e..34f0649 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include -- cgit v1.1 From 2fd815ffc3cac5655d0809bf762400e452734114 Mon Sep 17 00:00:00 2001 From: Shalaj Jain Date: Mon, 25 Jan 2016 13:20:10 -0800 Subject: stagefright: Clear RenderQueue on port settings changed Clear the RenderTracker RenderQueue before allocating new set of buffers during port settings change. The graphicBuffers inside the RenderQueue hold the actual buffer references which prevents them from being freed until this queue is cleared. Do not wait till executing state to clear the queue as then overall memory consumption goes up for the brief period. CRs-Fixed: 972394 Change-Id: If50ffc2d517f793a59c88d3fb213bf4c23b8c9f7 --- media/libstagefright/ACodec.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'media') diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 8cf38ef..b83d6c6 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -6781,6 +6781,11 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent( mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput); } + /* Clear the RenderQueue in which queued GraphicBuffers hold the + * actual buffer references in order to free them early. + */ + mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); + if (err == OK) { err = mCodec->allocateBuffersOnPort(kPortIndexOutput); ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " -- cgit v1.1 From 46da121c84a6f343e262b89a7ec4ac7941d58028 Mon Sep 17 00:00:00 2001 From: "Christopher R. Palmer" Date: Tue, 12 Jan 2016 21:40:02 -0500 Subject: nuplayer: Allow devices to force a flush when surface changes This fixes some playback problems on the Zenfone2 (running on 5.0 based blobs). The problems are easily reproduced by viewing a video in Chrome and then switching to full-screen mode. The change in surface causes the log to get flooded with messages like: dc_device_post: Buffer ID=14460 not imported by D until Android crashes. With this change, it ends up correctly mapping the surfaces after the flush fixing the problem. The code that is being #ifdef'ed out was added in M in commit commit a81c6229638a4db56752dd77a6610e0f0971e877 Author: Lajos Molnar Date: Fri Jul 10 19:17:45 2015 -0700 nuplayer: use codec->setSurface when possible to avoid seeking Bug: 22414719 Change-Id: I0442e12af960f86a0fc090b4a469c62ba638a1a0 and it appears that our blobs simply cannot handle this optimization and therefore we need a means by which to disable it. Change-Id: I105d647e724f5b63ef5cb0852481ecd2990c2d5e --- media/libmediaplayerservice/nuplayer/Android.mk | 4 ++++ media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'media') diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk index fbb1276..ff2a202 100644 --- a/media/libmediaplayerservice/nuplayer/Android.mk +++ b/media/libmediaplayerservice/nuplayer/Android.mk @@ -38,6 +38,10 @@ ifeq ($(TARGET_BOARD_PLATFORM),msm8974) LOCAL_CFLAGS += -DTARGET_8974 endif +ifeq ($(TARGET_NUPLAYER_CANNOT_SET_SURFACE_WITHOUT_A_FLUSH),true) +LOCAL_CFLAGS += -DCANNOT_SET_SURFACE_WITHOUT_A_FLUSH +endif + LOCAL_CLANG := true LOCAL_MODULE:= libstagefright_nuplayer diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index caac70b..1835101 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -660,7 +660,10 @@ void NuPlayer::onMessageReceived(const sp &msg) { // When mStarted is true, mSource must have been set. if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL // NOTE: mVideoDecoder's mSurface is always non-null - || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK)) { +#ifndef CANNOT_SET_SURFACE_WITHOUT_A_FLUSH + || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK) +#endif + ) { performSetSurface(surface); break; } -- cgit v1.1