summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-12-12 15:01:24 +0100
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-12-12 15:01:24 +0100
commite15fd68c5dc4089690b5d3086776c3851e504bb7 (patch)
tree2c75274dee02b07463c9164efdf6888e1a9c75dc
parent185e2110a53feb7720d91b6f8366ad27402f21cc (diff)
parent26c5fa31d17a638bf314de6e12e86bb8a86db44b (diff)
downloadframeworks_av-e15fd68c5dc4089690b5d3086776c3851e504bb7.zip
frameworks_av-e15fd68c5dc4089690b5d3086776c3851e504bb7.tar.gz
frameworks_av-e15fd68c5dc4089690b5d3086776c3851e504bb7.tar.bz2
Merge branch 'cm-13.0' of https://github.com/CyanogenMod/android_frameworks_av into replicant-6.0
-rw-r--r--camera/ICameraRecordingProxy.cpp6
-rw-r--r--include/camera/ICameraRecordingProxy.h6
-rw-r--r--include/media/AudioPolicy.h1
-rw-r--r--include/media/AudioSession.h71
-rw-r--r--include/media/AudioSystem.h14
-rw-r--r--include/media/IAudioPolicyService.h3
-rw-r--r--include/media/IAudioPolicyServiceClient.h5
-rw-r--r--include/media/IMediaDeathNotifier.h2
-rw-r--r--include/media/IOMX.h4
-rw-r--r--include/media/mediametadataretriever.h2
-rw-r--r--include/media/stagefright/CameraSource.h3
-rw-r--r--include/media/stagefright/DataSource.h61
-rw-r--r--include/media/stagefright/MPEG4Writer.h9
-rw-r--r--include/media/stagefright/MediaAdapter.h4
-rw-r--r--include/media/stagefright/MediaBuffer.h1
-rw-r--r--include/media/stagefright/MediaSource.h1
-rw-r--r--include/media/stagefright/MetaData.h1
-rw-r--r--include/media/stagefright/OMXCodec.h4
-rw-r--r--include/radio/Radio.h2
-rw-r--r--include/soundtrigger/SoundTrigger.h2
-rw-r--r--media/libavextensions/common/ExtensionsLoader.hpp2
-rw-r--r--media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp3
-rw-r--r--media/libavextensions/mediaplayerservice/AVNuUtils.cpp2
-rw-r--r--media/libavextensions/stagefright/AVExtensions.h3
-rw-r--r--media/libavextensions/stagefright/AVFactory.cpp6
-rw-r--r--media/libavextensions/stagefright/AVUtils.cpp2
-rw-r--r--media/libeffects/visualizer/EffectVisualizer.cpp9
-rw-r--r--media/libmedia/Android.mk1
-rw-r--r--media/libmedia/AudioRecord.cpp9
-rw-r--r--media/libmedia/AudioSystem.cpp33
-rw-r--r--media/libmedia/AudioTrack.cpp4
-rw-r--r--media/libmedia/IAudioPolicyService.cpp54
-rw-r--r--media/libmedia/IAudioPolicyServiceClient.cpp20
-rw-r--r--media/libmedia/IDrm.cpp4
-rw-r--r--media/libmedia/IMediaDeathNotifier.cpp2
-rw-r--r--media/libmedia/IOMX.cpp143
-rw-r--r--media/libmedia/MediaUtils.cpp74
-rw-r--r--media/libmedia/MediaUtils.h35
-rw-r--r--media/libmedia/mediametadataretriever.cpp4
-rw-r--r--media/libmedia/mediaplayer.cpp6
-rwxr-xr-xmedia/libmedia/mediarecorder.cpp2
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp13
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h1
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp1
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp4
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.cpp34
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp8
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp6
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp43
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h5
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp11
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp32
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.h4
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.cpp2
-rw-r--r--media/libstagefright/ACodec.cpp18
-rw-r--r--media/libstagefright/Android.mk4
-rw-r--r--media/libstagefright/AudioSource.cpp4
-rw-r--r--media/libstagefright/CameraSource.cpp37
-rw-r--r--media/libstagefright/DRMExtractor.cpp12
-rw-r--r--media/libstagefright/FFMPEGSoftCodec.cpp12
-rwxr-xr-xmedia/libstagefright/MPEG4Extractor.cpp55
-rw-r--r--media/libstagefright/MPEG4Writer.cpp22
-rw-r--r--media/libstagefright/MediaAdapter.cpp18
-rw-r--r--media/libstagefright/MediaCodecSource.cpp8
-rw-r--r--media/libstagefright/MediaMuxer.cpp3
-rw-r--r--media/libstagefright/OMXClient.cpp13
-rw-r--r--media/libstagefright/OMXCodec.cpp56
-rw-r--r--media/libstagefright/SampleIterator.cpp12
-rw-r--r--media/libstagefright/SampleTable.cpp187
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp2
-rw-r--r--media/libstagefright/Utils.cpp30
-rw-r--r--media/libstagefright/VideoFrameScheduler.cpp6
-rw-r--r--media/libstagefright/WAVExtractor.cpp12
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.cpp40
-rw-r--r--media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp28
-rw-r--r--media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp28
-rw-r--r--media/libstagefright/codecs/amrnb/common/Android.mk2
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/bytesused.h109
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/bytesused.cpp208
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp174
-rw-r--r--media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp62
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/amrdecode.h1
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h14
-rw-r--r--media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp28
-rw-r--r--media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp28
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/basic_op.h10
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/c2t64fx.c2
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/c4t64fx.c6
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/cor_h_x.c24
-rw-r--r--media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp16
-rw-r--r--media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp13
-rw-r--r--media/libstagefright/codecs/avcdec/SoftAVCDec.cpp28
-rw-r--r--media/libstagefright/codecs/avcdec/SoftAVCDec.h2
-rw-r--r--media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp30
-rw-r--r--media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp26
-rw-r--r--media/libstagefright/codecs/g711/dec/SoftG711.cpp21
-rw-r--r--media/libstagefright/codecs/gsm/dec/SoftGSM.cpp20
-rw-r--r--media/libstagefright/codecs/hevcdec/SoftHEVC.cpp50
-rw-r--r--media/libstagefright/codecs/hevcdec/SoftHEVC.h2
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp30
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp28
-rw-r--r--media/libstagefright/codecs/mp3dec/SoftMP3.cpp46
-rw-r--r--media/libstagefright/codecs/mp3dec/SoftMP3.h1
-rw-r--r--media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp33
-rw-r--r--media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h2
-rw-r--r--media/libstagefright/codecs/on2/dec/SoftVPX.cpp44
-rw-r--r--media/libstagefright/codecs/on2/dec/SoftVPX.h1
-rw-r--r--media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp149
-rw-r--r--media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp26
-rw-r--r--media/libstagefright/codecs/on2/h264dec/SoftAVC.h2
-rw-r--r--media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h2
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h6
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h6
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c9
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c9
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c13
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c7
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c2
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c8
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c24
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h2
-rw-r--r--media/libstagefright/codecs/opus/dec/SoftOpus.cpp23
-rw-r--r--media/libstagefright/codecs/raw/SoftRaw.cpp12
-rw-r--r--media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp29
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp6
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.cpp3
-rw-r--r--media/libstagefright/id3/ID3.cpp65
-rw-r--r--media/libstagefright/include/OMX.h4
-rw-r--r--media/libstagefright/include/OMXNodeInstance.h12
-rw-r--r--media/libstagefright/include/SampleTable.h9
-rw-r--r--media/libstagefright/include/SoftOMXComponent.h16
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp9
-rw-r--r--media/libstagefright/omx/OMX.cpp15
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp252
-rw-r--r--media/libstagefright/omx/SimpleSoftOMXComponent.cpp15
-rw-r--r--media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp30
-rw-r--r--media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp3
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.cpp14
-rw-r--r--media/libstagefright/rtsp/MyHandler.h2
-rw-r--r--media/libstagefright/wifi-display/Android.mk4
-rw-r--r--media/libstagefright/wifi-display/source/Converter.cpp2
-rw-r--r--media/mediaserver/Android.mk1
-rw-r--r--media/mediaserver/main_mediaserver.cpp6
-rw-r--r--media/mtp/MtpServer.cpp79
-rw-r--r--media/mtp/MtpServer.h6
-rw-r--r--radio/Radio.cpp6
-rw-r--r--services/audioflinger/Android.mk11
-rw-r--r--services/audioflinger/AudioMixer.cpp3
-rw-r--r--services/audioflinger/AudioResamplerQTI.cpp21
-rw-r--r--services/audioflinger/AudioResamplerQTI.h2
-rw-r--r--services/audioflinger/Effects.cpp29
-rw-r--r--services/audioflinger/FastCapture.cpp1
-rw-r--r--services/audioflinger/FastCaptureDumpState.cpp2
-rw-r--r--services/audioflinger/FastMixer.cpp18
-rw-r--r--services/audioflinger/ServiceUtilities.cpp8
-rw-r--r--services/audioflinger/ServiceUtilities.h1
-rw-r--r--services/audioflinger/Threads.cpp52
-rw-r--r--services/audioflinger/Threads.h4
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h4
-rw-r--r--services/audiopolicy/engineconfigurable/parameter-framework/Android.mk2
-rw-r--r--services/audiopolicy/service/AudioPolicyClientImpl.cpp4
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.cpp132
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.h19
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp71
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp9
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp95
-rw-r--r--services/audiopolicy/service/AudioPolicyService.h41
-rw-r--r--services/camera/libcameraservice/CameraFlashlight.cpp14
-rw-r--r--services/camera/libcameraservice/CameraService.cpp4
-rw-r--r--services/camera/libcameraservice/CameraService.h2
-rw-r--r--services/camera/libcameraservice/api1/CameraClient.cpp8
-rw-r--r--services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp8
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp8
-rw-r--r--services/soundtrigger/SoundTriggerHwService.cpp69
-rw-r--r--soundtrigger/SoundTrigger.cpp8
177 files changed, 2715 insertions, 1279 deletions
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
index 3dc0ffb..517b64f 100644
--- a/camera/ICameraRecordingProxy.cpp
+++ b/camera/ICameraRecordingProxy.cpp
@@ -31,6 +31,11 @@ enum {
RELEASE_RECORDING_FRAME,
};
+uint8_t ICameraRecordingProxy::baseObject = 0;
+
+size_t ICameraRecordingProxy::getCommonBaseAddress() {
+ return (size_t)&baseObject;
+}
class BpCameraRecordingProxy: public BpInterface<ICameraRecordingProxy>
{
@@ -106,4 +111,3 @@ status_t BnCameraRecordingProxy::onTransact(
// ----------------------------------------------------------------------------
}; // namespace android
-
diff --git a/include/camera/ICameraRecordingProxy.h b/include/camera/ICameraRecordingProxy.h
index 2aac284..4edf9cd 100644
--- a/include/camera/ICameraRecordingProxy.h
+++ b/include/camera/ICameraRecordingProxy.h
@@ -83,6 +83,12 @@ public:
virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener) = 0;
virtual void stopRecording() = 0;
virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+
+ // b/28466701
+ static size_t getCommonBaseAddress();
+ private:
+
+ static uint8_t baseObject;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
index 5a82bae..7e33df7 100644
--- a/include/media/AudioPolicy.h
+++ b/include/media/AudioPolicy.h
@@ -23,6 +23,7 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Vector.h>
+#include <media/AudioSession.h>
namespace android {
diff --git a/include/media/AudioSession.h b/include/media/AudioSession.h
new file mode 100644
index 0000000..d9658cc
--- /dev/null
+++ b/include/media/AudioSession.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIOSESSION_H
+#define ANDROID_AUDIOSESSION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <system/audio.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+// class to store streaminfo
+class AudioSessionInfo : public RefBase {
+public:
+ AudioSessionInfo(int session, audio_stream_type_t stream, audio_output_flags_t flags,
+ audio_channel_mask_t channelMask, uid_t uid) :
+ mSessionId(session), mStream(stream), mFlags(flags), mChannelMask(channelMask),
+ mUid(uid), mRefCount(0) {}
+
+ AudioSessionInfo() : mSessionId(0), mStream(AUDIO_STREAM_DEFAULT), mFlags(AUDIO_OUTPUT_FLAG_NONE), mChannelMask(AUDIO_CHANNEL_NONE), mUid(0) {}
+
+ /*virtual*/ ~AudioSessionInfo() {}
+
+ int mSessionId;
+ audio_stream_type_t mStream;
+ audio_output_flags_t mFlags;
+ audio_channel_mask_t mChannelMask;
+ uid_t mUid;
+
+ // AudioPolicyManager keeps mLock, no need for lock on reference count here
+ int mRefCount;
+
+ void readFromParcel(const Parcel &parcel) {
+ mSessionId = parcel.readInt32();
+ mStream = static_cast<audio_stream_type_t>(parcel.readInt32());
+ mFlags = static_cast<audio_output_flags_t>(parcel.readInt32());
+ mChannelMask = static_cast<audio_channel_mask_t>(parcel.readInt32());
+ mUid = static_cast<uid_t>(parcel.readInt32());
+ }
+
+ void writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32(mSessionId);
+ parcel->writeInt32(mStream);
+ parcel->writeInt32(mFlags);
+ parcel->writeInt32(mChannelMask);
+ parcel->writeInt32(mUid);
+ }
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOSESSION_H
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 35b06ba..3f4a610 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -31,8 +31,8 @@ namespace android {
typedef void (*audio_error_callback)(status_t err);
typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
-typedef void (*effect_session_callback)(int event,
- audio_stream_type_t stream, audio_unique_id_t sessionId, bool added);
+typedef void (*audio_session_callback)(int event,
+ sp<AudioSessionInfo>& session, bool added);
class IAudioFlinger;
class IAudioPolicyService;
@@ -94,7 +94,7 @@ public:
static void setErrorCallback(audio_error_callback cb);
static void setDynPolicyCallback(dynamic_policy_callback cb);
- static status_t setEffectSessionCallback(effect_session_callback cb);
+ static status_t setAudioSessionCallback(audio_session_callback cb);
// helper function to obtain AudioFlinger service handle
static const sp<IAudioFlinger> get_audio_flinger();
@@ -322,6 +322,8 @@ public:
audio_io_handle_t *handle);
static status_t stopAudioSource(audio_io_handle_t handle);
+ static status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions);
// ----------------------------------------------------------------------------
@@ -422,9 +424,7 @@ private:
virtual void onAudioPortListUpdate();
virtual void onAudioPatchListUpdate();
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
- virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId,
- bool added);
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
private:
Mutex mLock;
@@ -444,7 +444,7 @@ private:
static sp<IAudioFlinger> gAudioFlinger;
static audio_error_callback gAudioErrorCallback;
static dynamic_policy_callback gDynPolicyCallback;
- static effect_session_callback gEffectSessionCallback;
+ static audio_session_callback gAudioSessionCallback;
static size_t gInBuffSize;
// previous parameters for recording buffer size queries
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 3a7bd68..1df91ee 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -166,7 +166,8 @@ public:
audio_io_handle_t *handle) = 0;
virtual status_t stopAudioSource(audio_io_handle_t handle) = 0;
- virtual status_t setEffectSessionCallbacksEnabled(bool enabled) = 0;
+ virtual status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions) = 0;
};
diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h
index 3bdeb5a..ec38157 100644
--- a/include/media/IAudioPolicyServiceClient.h
+++ b/include/media/IAudioPolicyServiceClient.h
@@ -21,6 +21,7 @@
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <system/audio.h>
+#include <media/AudioSession.h>
namespace android {
@@ -38,9 +39,7 @@ public:
// Notifies a change in the mixing state of a specific mix in a dynamic audio policy
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
// Notifies when a default effect set is attached to a session/stream
- virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId,
- bool added) = 0;
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added) = 0;
};
diff --git a/include/media/IMediaDeathNotifier.h b/include/media/IMediaDeathNotifier.h
index bb3d0d8..aca6678 100644
--- a/include/media/IMediaDeathNotifier.h
+++ b/include/media/IMediaDeathNotifier.h
@@ -30,7 +30,7 @@ public:
virtual ~IMediaDeathNotifier() { removeObitRecipient(this); }
virtual void died() = 0;
- static const sp<IMediaPlayerService>& getMediaPlayerService();
+ static const sp<IMediaPlayerService> getMediaPlayerService();
private:
IMediaDeathNotifier &operator=(const IMediaDeathNotifier &);
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 27ad694..83a177a 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -107,7 +107,7 @@ public:
// Use |params| as an OMX buffer, but limit the size of the OMX buffer to |allottedSize|.
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) = 0;
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess = OMX_FALSE) = 0;
virtual status_t useGraphicBuffer(
node_id node, OMX_U32 port_index,
@@ -149,7 +149,7 @@ public:
// may be larger.
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) = 0;
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess = OMX_FALSE) = 0;
virtual status_t freeBuffer(
node_id node, OMX_U32 port_index, buffer_id buffer) = 0;
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index f655f35..8ed07ee 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -82,7 +82,7 @@ public:
const char* extractMetadata(int keyCode);
private:
- static const sp<IMediaPlayerService>& getService();
+ static const sp<IMediaPlayerService> getService();
class DeathNotifier: public IBinder::DeathRecipient
{
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 70149cc..3dcfe4e 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -243,6 +243,9 @@ protected:
status_t checkFrameRate(const CameraParameters& params,
int32_t frameRate);
+ static void adjustIncomingANWBuffer(IMemory* data);
+ static void adjustOutgoingANWBuffer(IMemory* data);
+
void stopCameraRecording();
status_t reset();
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index d627fec..c8ad05e 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -19,7 +19,7 @@
#define DATA_SOURCE_H_
#include <sys/types.h>
-
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
@@ -72,6 +72,20 @@ public:
bool getUInt32(off64_t offset, uint32_t *x);
bool getUInt64(off64_t offset, uint64_t *x);
+ // Reads in "count" entries of type T into vector *x.
+ // Returns true if "count" entries can be read.
+ // If fewer than "count" entries can be read, return false. In this case,
+ // the output vector *x will still have those entries that were read. Call
+ // x->size() to obtain the number of entries read.
+ // The optional parameter chunkSize specifies how many entries should be
+ // read from the data source at one time into a temporary buffer. Increasing
+ // chunkSize can improve the performance at the cost of extra memory usage.
+ // The default value for chunkSize is set to read at least 4k bytes at a
+ // time, depending on sizeof(T).
+ template <typename T>
+ bool getVector(off64_t offset, Vector<T>* x, size_t count,
+ size_t chunkSize = (4095 / sizeof(T)) + 1);
+
// May return ERROR_UNSUPPORTED.
virtual status_t getSize(off64_t *size);
@@ -128,6 +142,51 @@ private:
DataSource &operator=(const DataSource &);
};
+template <typename T>
+bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count,
+ size_t chunkSize)
+{
+ x->clear();
+ if (chunkSize == 0) {
+ return false;
+ }
+ if (count == 0) {
+ return true;
+ }
+
+ T tmp[chunkSize];
+ ssize_t numBytesRead;
+ size_t numBytesPerChunk = chunkSize * sizeof(T);
+ size_t i;
+
+ for (i = 0; i + chunkSize < count; i += chunkSize) {
+ // This loops is executed when more than chunkSize records need to be
+ // read.
+ numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk);
+ if (numBytesRead == -1) { // If readAt() returns -1, there is an error.
+ return false;
+ }
+ if (numBytesRead < numBytesPerChunk) {
+ // This case is triggered when the stream ends before the whole
+ // chunk is read.
+ x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+ return false;
+ }
+ x->appendArray(tmp, chunkSize);
+ offset += numBytesPerChunk;
+ }
+
+ // There are (count - i) more records to read.
+ // Right now, (count - i) <= chunkSize.
+ // We do the same thing as above, but with chunkSize replaced by count - i.
+ numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T));
+ if (numBytesRead == -1) {
+ return false;
+ }
+ x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+ return x->size() == count;
+}
+
} // namespace android
#endif // DATA_SOURCE_H_
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index aeaad8f..09a48f9 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -77,13 +77,17 @@ private:
int mFd;
status_t mInitCheck;
bool mIsRealTimeRecording;
+protected:
bool mUse4ByteNalLength;
+private:
bool mUse32BitOffset;
bool mIsFileSizeLimitExplicitlyRequested;
bool mPaused;
bool mStarted; // Writer thread + track threads started successfully
bool mWriterThreadStarted; // Only writer thread started successfully
+protected:
off64_t mOffset;
+private:
off_t mMdatOffset;
uint8_t *mMoovBoxBuffer;
off64_t mMoovBoxBufferOffset;
@@ -194,8 +198,11 @@ private:
// Acquire lock before calling these methods
off64_t addSample_l(MediaBuffer *buffer);
- off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
+protected:
+ static void StripStartcode(MediaBuffer *buffer);
+ virtual off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
+private:
bool exceedsFileSizeLimit();
bool use32BitFileOffset() const;
bool exceedsFileDurationLimit();
diff --git a/include/media/stagefright/MediaAdapter.h b/include/media/stagefright/MediaAdapter.h
index 369fce6..8622546 100644
--- a/include/media/stagefright/MediaAdapter.h
+++ b/include/media/stagefright/MediaAdapter.h
@@ -56,6 +56,8 @@ public:
// deep copy, such that after pushBuffer return, the buffer can be re-used.
status_t pushBuffer(MediaBuffer *buffer);
+ virtual void notifyError(status_t err);
+
private:
Mutex mAdapterLock;
// Make sure the read() wait for the incoming buffer.
@@ -68,6 +70,8 @@ private:
bool mStarted;
sp<MetaData> mOutputFormat;
+ status_t mStatus;
+
DISALLOW_EVIL_CONSTRUCTORS(MediaAdapter);
};
diff --git a/include/media/stagefright/MediaBuffer.h b/include/media/stagefright/MediaBuffer.h
index c8a50e8..5ab266f 100644
--- a/include/media/stagefright/MediaBuffer.h
+++ b/include/media/stagefright/MediaBuffer.h
@@ -93,6 +93,7 @@ protected:
private:
friend class MediaBufferGroup;
friend class OMXDecoder;
+ friend class MediaAdapter;
// For use by OMXDecoder, reference count must be 1, drop reference
// count to 0 without signalling the observer.
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index a653db9..7ab5f62 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -59,6 +59,7 @@ struct MediaSource : public virtual RefBase {
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
+ virtual void notifyError(status_t) {}
// Options that modify read() behaviour. The default is to
// a) not request a seek
// b) not be late, i.e. lateness_us = 0
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 2a3df22..66e7d63 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -68,6 +68,7 @@ enum {
kKeyIsSyncFrame = 'sync', // int32_t (bool)
kKeyIsCodecConfig = 'conf', // int32_t (bool)
kKeyTime = 'time', // int64_t (usecs)
+ kKeyTimeBoot = 'timb', // int64_t (usecs)
kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
kKeyTargetTime = 'tarT', // int64_t (usecs)
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index ea534e0..2f73de8 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -40,10 +40,6 @@ struct OMXCodec : public MediaSource,
kPreferSoftwareCodecs = 1,
kIgnoreCodecSpecificData = 2,
- // The client wants to access the output buffer's video
- // data for example for thumbnail extraction.
- kClientNeedsFramebuffer = 4,
-
// Request for software or hardware codecs. If request
// can not be fullfilled, Create() returns NULL.
kSoftwareCodecsOnly = 8,
diff --git a/include/radio/Radio.h b/include/radio/Radio.h
index 302bf16..a4dfdd1 100644
--- a/include/radio/Radio.h
+++ b/include/radio/Radio.h
@@ -75,7 +75,7 @@ public:
private:
Radio(radio_handle_t handle,
const sp<RadioCallback>&);
- static const sp<IRadioService>& getRadioService();
+ static const sp<IRadioService> getRadioService();
Mutex mLock;
sp<IRadio> mIRadio;
diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h
index bf5e1de..9a05cac 100644
--- a/include/soundtrigger/SoundTrigger.h
+++ b/include/soundtrigger/SoundTrigger.h
@@ -68,7 +68,7 @@ public:
private:
SoundTrigger(sound_trigger_module_handle_t module,
const sp<SoundTriggerCallback>&);
- static const sp<ISoundTriggerHwService>& getSoundTriggerHwService();
+ static const sp<ISoundTriggerHwService> getSoundTriggerHwService();
Mutex mLock;
sp<ISoundTrigger> mISoundTrigger;
diff --git a/media/libavextensions/common/ExtensionsLoader.hpp b/media/libavextensions/common/ExtensionsLoader.hpp
index 48bcf3b..15728ed 100644
--- a/media/libavextensions/common/ExtensionsLoader.hpp
+++ b/media/libavextensions/common/ExtensionsLoader.hpp
@@ -49,7 +49,7 @@ static const char * CUSTOMIZATION_LIB_NAME = "libavenhancements.so";
template <typename T>
T *ExtensionsLoader<T>::createInstance(const char *createFunctionName) {
- ALOGV("createInstance(%dbit) : %s", sizeof(intptr_t)*8, createFunctionName);
+ (void)createFunctionName;
// create extended object if extensions-lib is available and
// AV_ENHANCEMENTS is enabled
#if ENABLE_AV_ENHANCEMENTS
diff --git a/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp b/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp
index 0e42367..5306a39 100644
--- a/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp
+++ b/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,6 +28,7 @@
*/
#define LOG_TAG "AVMediaServiceUtils"
+//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
index 5f146c7..773a098 100644
--- a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
+++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
@@ -277,7 +277,7 @@ status_t AVNuUtils::convertToSinkFormatIfNeeded(
return BAD_VALUE;
}
- ALOGV("convert %zu bytes (frames %d) of format %x",
+ ALOGV("convert %zu bytes (frames %zu) of format %x",
buffer->size(), frames, srcFormat);
audio_format_t dstFormat;
diff --git a/media/libavextensions/stagefright/AVExtensions.h b/media/libavextensions/stagefright/AVExtensions.h
index b0e4bb5..c4c9aae 100644
--- a/media/libavextensions/stagefright/AVExtensions.h
+++ b/media/libavextensions/stagefright/AVExtensions.h
@@ -59,6 +59,7 @@ class ICameraRecordingProxy;
class String16;
class IGraphicBufferProducer;
struct Size;
+class MPEG4Writer;
/*
* Factory to create objects of base-classes in libstagefright
@@ -107,6 +108,8 @@ struct AVFactory {
const sp<IGraphicBufferProducer>& surface,
int64_t timeBetweenFrameCaptureUs,
bool storeMetaDataInVideoBuffers = true);
+
+ virtual MPEG4Writer *CreateMPEG4Writer(int fd);
// ----- NO TRESSPASSING BEYOND THIS LINE ------
DECLARE_LOADABLE_SINGLETON(AVFactory);
};
diff --git a/media/libavextensions/stagefright/AVFactory.cpp b/media/libavextensions/stagefright/AVFactory.cpp
index f6d5f53..7420d12 100644
--- a/media/libavextensions/stagefright/AVFactory.cpp
+++ b/media/libavextensions/stagefright/AVFactory.cpp
@@ -45,6 +45,7 @@
#include <media/stagefright/CameraSource.h>
#include <media/stagefright/CameraSourceTimeLapse.h>
#include <camera/CameraParameters.h>
+#include <media/stagefright/MPEG4Writer.h>
#include "common/ExtensionsLoader.hpp"
#include "stagefright/AVExtensions.h"
@@ -120,6 +121,11 @@ CameraSourceTimeLapse* AVFactory::CreateCameraSourceTimeLapseFromCamera(
clientName, clientUid, videoSize, videoFrameRate, surface,
timeBetweenFrameCaptureUs, storeMetaDataInVideoBuffers);
}
+
+MPEG4Writer* AVFactory::CreateMPEG4Writer(int fd) {
+ return new MPEG4Writer(fd);
+}
+
// ----- NO TRESSPASSING BEYOND THIS LINE ------
AVFactory::AVFactory() {
}
diff --git a/media/libavextensions/stagefright/AVUtils.cpp b/media/libavextensions/stagefright/AVUtils.cpp
index 413026b..a9cd4b2 100644
--- a/media/libavextensions/stagefright/AVUtils.cpp
+++ b/media/libavextensions/stagefright/AVUtils.cpp
@@ -812,7 +812,7 @@ status_t AVUtils::HEVCMuxer::parserProfileTierLevel(const uint8_t *data, size_t
}
static const uint8_t *findNextStartCode(
const uint8_t *data, size_t length) {
- ALOGV("findNextStartCode: %p %d", data, length);
+ ALOGV("findNextStartCode: %p %zu", data, length);
size_t bytesLeft = length;
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 0c310c5..91f9fc7 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -25,6 +25,7 @@
#include <time.h>
#include <math.h>
#include <audio_effects/effect_visualizer.h>
+#include <cutils/log.h>
extern "C" {
@@ -599,6 +600,14 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
} break;
case VISUALIZER_CMD_MEASURE: {
+ if (pReplyData == NULL || replySize == NULL ||
+ *replySize < (sizeof(int32_t) * MEASUREMENT_COUNT)) {
+ ALOGV("VISUALIZER_CMD_MEASURE() error *replySize %" PRIu32
+ " < (sizeof(int32_t) * MEASUREMENT_COUNT) %" PRIu32, *replySize,
+ sizeof(int32_t) * MEASUREMENT_COUNT);
+ android_errorWriteLog(0x534e4554, "30229821");
+ return -EINVAL;
+ }
uint16_t peakU16 = 0;
float sumRmsSquared = 0.0f;
uint8_t nbValidMeasurements = 0;
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 74e4eb1..efcd541 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -44,6 +44,7 @@ LOCAL_SRC_FILES:= \
IResourceManagerService.cpp \
IStreamSource.cpp \
MediaCodecInfo.cpp \
+ MediaUtils.cpp \
Metadata.cpp \
mediarecorder.cpp \
IMediaMetadataRetriever.cpp \
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 40f6c44..40cad59 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -67,7 +67,7 @@ status_t AudioRecord::getMinFrameCount(
// ---------------------------------------------------------------------------
AudioRecord::AudioRecord(const String16 &opPackageName)
- : mStatus(NO_INIT), mOpPackageName(opPackageName), mSessionId(AUDIO_SESSION_ALLOCATE),
+ : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName), mSessionId(AUDIO_SESSION_ALLOCATE),
mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
@@ -89,7 +89,8 @@ AudioRecord::AudioRecord(
int uid,
pid_t pid,
const audio_attributes_t* pAttributes)
- : mStatus(NO_INIT),
+ : mActive(false),
+ mStatus(NO_INIT),
mOpPackageName(opPackageName),
mSessionId(AUDIO_SESSION_ALLOCATE),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
@@ -273,7 +274,6 @@ status_t AudioRecord::set(
}
mStatus = NO_ERROR;
- mActive = false;
mUserData = user;
// TODO: add audio hardware input latency here
if (mTransfer == TRANSFER_CALLBACK ||
@@ -299,7 +299,7 @@ status_t AudioRecord::set(
status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
{
ALOGV("start, sync event %d trigger session %d", event, triggerSession);
- SEEMPLOG_RECORD(89,"");
+ SEEMPLOG_RECORD(71,"");
AutoMutex lock(mLock);
if (mActive) {
@@ -347,7 +347,6 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
void AudioRecord::stop()
{
- SEEMPLOG_RECORD(90,"");
AutoMutex lock(mLock);
if (!mActive) {
return;
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 10ec495..2e9fca9 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -37,7 +37,7 @@ sp<IAudioFlinger> AudioSystem::gAudioFlinger;
sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
-effect_session_callback AudioSystem::gEffectSessionCallback = NULL;
+audio_session_callback AudioSystem::gAudioSessionCallback = NULL;
// establish binder interface to AudioFlinger service
const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
@@ -652,19 +652,15 @@ status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
gDynPolicyCallback = cb;
}
-/*static*/ status_t AudioSystem::setEffectSessionCallback(effect_session_callback cb)
+/*static*/ status_t AudioSystem::setAudioSessionCallback(audio_session_callback cb)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
Mutex::Autolock _l(gLock);
- gEffectSessionCallback = cb;
+ gAudioSessionCallback = cb;
- status_t status = aps->setEffectSessionCallbacksEnabled(cb != NULL);
- if (status != OK) {
- gEffectSessionCallback = NULL;
- }
- return status;
+ return NO_ERROR;
}
// client singleton for AudioPolicyService binder interface
@@ -1238,18 +1234,29 @@ void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(
}
}
+// ---------------------------------------------------------------------------
+
+status_t AudioSystem::listAudioSessions(audio_stream_type_t stream,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->listAudioSessions(stream, sessions);
+}
+
void AudioSystem::AudioPolicyServiceClient::onOutputSessionEffectsUpdate(
- audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+ sp<AudioSessionInfo>& info, bool added)
{
- ALOGV("AudioPolicyServiceClient::onOutputSessionEffectsUpdate(%d, %d, %d)", stream, sessionId, added);
- effect_session_callback cb = NULL;
+ ALOGV("AudioPolicyServiceClient::onOutputSessionEffectsUpdate(%d, %d, %d)",
+ info->mStream, info->mSessionId, added);
+ audio_session_callback cb = NULL;
{
Mutex::Autolock _l(AudioSystem::gLock);
- cb = gEffectSessionCallback;
+ cb = gAudioSessionCallback;
}
if (cb != NULL) {
- cb(AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE, stream, sessionId, added);
+ cb(AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE, info, added);
}
}
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index d7256f8..ae016ef 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -165,6 +165,7 @@ status_t AudioTrack::getMinFrameCount(
AudioTrack::AudioTrack()
: mStatus(NO_INIT),
+ mState(STATE_STOPPED),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
@@ -196,6 +197,7 @@ AudioTrack::AudioTrack(
const audio_attributes_t* pAttributes,
bool doNotReconnect)
: mStatus(NO_INIT),
+ mState(STATE_STOPPED),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
@@ -227,6 +229,7 @@ AudioTrack::AudioTrack(
const audio_attributes_t* pAttributes,
bool doNotReconnect)
: mStatus(NO_INIT),
+ mState(STATE_STOPPED),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
@@ -478,7 +481,6 @@ status_t AudioTrack::set(
}
mStatus = NO_ERROR;
- mState = STATE_STOPPED;
mUserData = user;
mLoopCount = 0;
mLoopStart = 0;
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 6ff8149..abae614 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -74,7 +74,7 @@ enum {
START_AUDIO_SOURCE,
STOP_AUDIO_SOURCE,
SET_AUDIO_PORT_CALLBACK_ENABLED,
- SET_EFFECT_SESSION_CALLBACK_ENABLED,
+ LIST_AUDIO_SESSIONS,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -656,18 +656,6 @@ 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)
@@ -780,6 +768,30 @@ public:
status = (status_t)reply.readInt32();
return status;
}
+
+ virtual status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(streams);
+ status_t status = remote()->transact(LIST_AUDIO_SESSIONS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ status = reply.readInt32();
+ if (status == NO_ERROR) {
+ size_t size = (size_t)reply.readUint32();
+ for (size_t i = 0; i < size && reply.dataAvail() > 0; i++) {
+ sp<AudioSessionInfo> info = new AudioSessionInfo();
+ info->readFromParcel(reply);
+ sessions.push_back(info);
+ }
+ }
+ return status;
+ }
+
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1251,12 +1263,22 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
} break;
- case SET_EFFECT_SESSION_CALLBACK_ENABLED: {
+ case LIST_AUDIO_SESSIONS: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- status_t status = setEffectSessionCallbacksEnabled(data.readInt32() == 1);
+ audio_stream_type_t streams = (audio_stream_type_t)data.readInt32();
+
+ Vector< sp<AudioSessionInfo>> sessions;
+ status_t status = listAudioSessions(streams, sessions);
+
reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeUint32(static_cast<uint32_t>(sessions.size()));
+ for (size_t i = 0; i < sessions.size(); i++) {
+ sessions[i]->writeToParcel(reply);
+ }
+ }
return NO_ERROR;
- } break;
+ }
case ACQUIRE_SOUNDTRIGGER_SESSION: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp
index d6207ce..a325996 100644
--- a/media/libmedia/IAudioPolicyServiceClient.cpp
+++ b/media/libmedia/IAudioPolicyServiceClient.cpp
@@ -65,13 +65,15 @@ public:
remote()->transact(MIX_STATE_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
}
- void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId, bool added)
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
- data.writeInt32(stream);
- data.writeInt32(sessionId);
+ data.writeInt32(info->mStream);
+ data.writeInt32(info->mSessionId);
+ data.writeInt32(info->mFlags);
+ data.writeInt32(info->mChannelMask);
+ data.writeInt32(info->mUid);
data.writeInt32(added ? 1 : 0);
remote()->transact(OUTPUT_SESSION_EFFECTS_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -105,9 +107,15 @@ status_t BnAudioPolicyServiceClient::onTransact(
case OUTPUT_SESSION_EFFECTS_UPDATE: {
CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
audio_stream_type_t stream = static_cast<audio_stream_type_t>(data.readInt32());
- audio_unique_id_t sessionId = static_cast<audio_unique_id_t>(data.readInt32());
+ audio_session_t sessionId = static_cast<audio_session_t>(data.readInt32());
+ audio_output_flags_t flags = static_cast<audio_output_flags_t>(data.readInt32());
+ audio_channel_mask_t channelMask = static_cast<audio_channel_mask_t>(data.readInt32());
+ uid_t uid = static_cast<uid_t>(data.readInt32());
bool added = data.readInt32() > 0;
- onOutputSessionEffectsUpdate(stream, sessionId, added);
+
+ sp<AudioSessionInfo> info = new AudioSessionInfo(
+ sessionId, stream, flags, channelMask, uid);
+ onOutputSessionEffectsUpdate(info, added);
return NO_ERROR;
}
default:
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index b1ad0c5..6f6530b 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -658,7 +658,7 @@ status_t BnDrm::onTransact(
Vector<uint8_t> request;
String8 defaultUrl;
- DrmPlugin::KeyRequestType keyRequestType;
+ DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
status_t result = getKeyRequest(sessionId, initData, mimeType,
keyType, optionalParameters, request, defaultUrl,
@@ -912,7 +912,7 @@ status_t BnDrm::onTransact(
readVector(data, keyId);
readVector(data, message);
readVector(data, signature);
- bool match;
+ bool match = false;
uint32_t result = verify(sessionId, keyId, message, signature, match);
reply->writeInt32(match);
reply->writeInt32(result);
diff --git a/media/libmedia/IMediaDeathNotifier.cpp b/media/libmedia/IMediaDeathNotifier.cpp
index d4360ea..c43ef66 100644
--- a/media/libmedia/IMediaDeathNotifier.cpp
+++ b/media/libmedia/IMediaDeathNotifier.cpp
@@ -31,7 +31,7 @@ sp<IMediaDeathNotifier::DeathNotifier> IMediaDeathNotifier::sDeathNotifier;
SortedVector< wp<IMediaDeathNotifier> > IMediaDeathNotifier::sObitRecipients;
// establish binder interface to MediaPlayerService
-/*static*/const sp<IMediaPlayerService>&
+/*static*/const sp<IMediaPlayerService>
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 5356494..7e951c9 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -18,11 +18,14 @@
#define LOG_TAG "IOMX"
#include <utils/Log.h>
+#include <sys/mman.h>
+
#include <binder/IMemory.h>
#include <binder/Parcel.h>
#include <media/IOMX.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/AVMediaExtensions.h>
+#include <media/openmax/OMX_IndexExt.h>
namespace android {
@@ -246,7 +249,7 @@ public:
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) {
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL /* crossProcess */) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
@@ -447,7 +450,7 @@ public:
remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply);
status_t err = reply.readInt32();
- if (sidebandHandle) {
+ if (err == OK && sidebandHandle) {
*sidebandHandle = (native_handle_t *)reply.readNativeHandle();
}
return err;
@@ -480,7 +483,7 @@ public:
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) {
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL /* crossProcess */) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
@@ -694,34 +697,79 @@ status_t BnOMX::onTransact(
size_t size = data.readInt64();
- void *params = malloc(size);
- data.read(params, size);
-
- status_t err;
- switch (code) {
- case GET_PARAMETER:
- err = getParameter(node, index, params, size);
- break;
- case SET_PARAMETER:
- err = setParameter(node, index, params, size);
- break;
- case GET_CONFIG:
- err = getConfig(node, index, params, size);
- break;
- case SET_CONFIG:
- err = setConfig(node, index, params, size);
- break;
- case SET_INTERNAL_OPTION:
- {
- InternalOptionType type =
- (InternalOptionType)data.readInt32();
-
- err = setInternalOption(node, index, type, params, size);
- break;
+ status_t err = NOT_ENOUGH_DATA;
+ void *params = NULL;
+ size_t pageSize = 0;
+ size_t allocSize = 0;
+ bool isUsageBits = (index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits);
+ if ((isUsageBits && size < 4) ||
+ (!isUsageBits && code != SET_INTERNAL_OPTION && size < 8)) {
+ // we expect the structure to contain at least the size and
+ // version, 8 bytes total
+ ALOGE("b/27207275 (%zu) (%d/%d)", size, int(index), int(code));
+ android_errorWriteLog(0x534e4554, "27207275");
+ } else {
+ err = NO_MEMORY;
+ pageSize = (size_t) sysconf(_SC_PAGE_SIZE);
+ if (size > SIZE_MAX - (pageSize * 2)) {
+ ALOGE("requested param size too big");
+ } else {
+ allocSize = (size + pageSize * 2) & ~(pageSize - 1);
+ params = mmap(NULL, allocSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */);
+ }
+ if (params != MAP_FAILED) {
+ err = data.read(params, size);
+ if (err != OK) {
+ android_errorWriteLog(0x534e4554, "26914474");
+ } else {
+ err = NOT_ENOUGH_DATA;
+ OMX_U32 declaredSize = *(OMX_U32*)params;
+ if (code != SET_INTERNAL_OPTION &&
+ index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
+ declaredSize > size) {
+ // the buffer says it's bigger than it actually is
+ ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
+ android_errorWriteLog(0x534e4554, "27207275");
+ } else {
+ // mark the last page as inaccessible, to avoid exploitation
+ // of codecs that access past the end of the allocation because
+ // they didn't check the size
+ if (mprotect((char*)params + allocSize - pageSize, pageSize,
+ PROT_NONE) != 0) {
+ ALOGE("mprotect failed: %s", strerror(errno));
+ } else {
+ switch (code) {
+ case GET_PARAMETER:
+ err = getParameter(node, index, params, size);
+ break;
+ case SET_PARAMETER:
+ err = setParameter(node, index, params, size);
+ break;
+ case GET_CONFIG:
+ err = getConfig(node, index, params, size);
+ break;
+ case SET_CONFIG:
+ err = setConfig(node, index, params, size);
+ break;
+ case SET_INTERNAL_OPTION:
+ {
+ InternalOptionType type =
+ (InternalOptionType)data.readInt32();
+
+ err = setInternalOption(node, index, type, params, size);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+ }
+ }
+ }
+ } else {
+ ALOGE("couldn't map: %s", strerror(errno));
}
-
- default:
- TRESPASS();
}
reply->writeInt32(err);
@@ -730,7 +778,9 @@ status_t BnOMX::onTransact(
reply->write(params, size);
}
- free(params);
+ if (params) {
+ munmap(params, allocSize);
+ }
params = NULL;
return NO_ERROR;
@@ -790,7 +840,8 @@ status_t BnOMX::onTransact(
OMX_U32 allottedSize = data.readInt32();
buffer_id buffer;
- status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
+ status_t err = useBuffer(
+ node, port_index, params, &buffer, allottedSize, OMX_TRUE /* crossProcess */);
reply->writeInt32(err);
if (err == OK) {
@@ -846,9 +897,13 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
sp<IGraphicBufferProducer> bufferProducer;
- MetadataBufferType type;
+ MetadataBufferType type = kMetadataBufferTypeInvalid;
status_t err = createInputSurface(node, port_index, &bufferProducer, &type);
+ if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
+ android_errorWriteLog(0x534e4554, "26324358");
+ }
+
reply->writeInt32(type);
reply->writeInt32(err);
@@ -888,9 +943,13 @@ status_t BnOMX::onTransact(
sp<IGraphicBufferConsumer> bufferConsumer =
interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
- MetadataBufferType type;
+ MetadataBufferType type = kMetadataBufferTypeInvalid;
status_t err = setInputSurface(node, port_index, bufferConsumer, &type);
+ if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
+ android_errorWriteLog(0x534e4554, "26324358");
+ }
+
reply->writeInt32(type);
reply->writeInt32(err);
return NO_ERROR;
@@ -916,8 +975,12 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
OMX_BOOL enable = (OMX_BOOL)data.readInt32();
- MetadataBufferType type;
- status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
+ MetadataBufferType type = kMetadataBufferTypeInvalid;
+ status_t err =
+ // only control output metadata via Binder
+ port_index != 1 /* kOutputPortIndex */ ? BAD_VALUE :
+ storeMetaDataInBuffers(node, port_index, enable, &type);
+
reply->writeInt32(type);
reply->writeInt32(err);
@@ -950,11 +1013,13 @@ status_t BnOMX::onTransact(
OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
OMX_U32 audio_hw_sync = data.readInt32();
- native_handle_t *sideband_handle;
+ native_handle_t *sideband_handle = NULL;
status_t err = configureVideoTunnelMode(
node, port_index, tunneled, audio_hw_sync, &sideband_handle);
reply->writeInt32(err);
- reply->writeNativeHandle(sideband_handle);
+ if(err == OK){
+ reply->writeNativeHandle(sideband_handle);
+ }
return NO_ERROR;
}
@@ -1000,7 +1065,7 @@ status_t BnOMX::onTransact(
buffer_id buffer;
status_t err = allocateBufferWithBackup(
- node, port_index, params, &buffer, allottedSize);
+ node, port_index, params, &buffer, allottedSize, OMX_TRUE /* crossProcess */);
reply->writeInt32(err);
diff --git a/media/libmedia/MediaUtils.cpp b/media/libmedia/MediaUtils.cpp
new file mode 100644
index 0000000..a02ca65
--- /dev/null
+++ b/media/libmedia/MediaUtils.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "MediaUtils"
+#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <cutils/properties.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+#include "MediaUtils.h"
+
+namespace android {
+
+void limitProcessMemory(
+ const char *property,
+ size_t numberOfBytes,
+ size_t percentageOfTotalMem) {
+
+ long pageSize = sysconf(_SC_PAGESIZE);
+ long numPages = sysconf(_SC_PHYS_PAGES);
+ size_t maxMem = SIZE_MAX;
+
+ if (pageSize > 0 && numPages > 0) {
+ if (size_t(numPages) < SIZE_MAX / size_t(pageSize)) {
+ maxMem = size_t(numPages) * size_t(pageSize);
+ }
+ ALOGV("physMem: %zu", maxMem);
+ if (percentageOfTotalMem > 100) {
+ ALOGW("requested %zu%% of total memory, using 100%%", percentageOfTotalMem);
+ percentageOfTotalMem = 100;
+ }
+ maxMem = maxMem / 100 * percentageOfTotalMem;
+ if (numberOfBytes < maxMem) {
+ maxMem = numberOfBytes;
+ }
+ ALOGV("requested limit: %zu", maxMem);
+ } else {
+ ALOGW("couldn't determine total RAM");
+ }
+
+ int64_t propVal = property_get_int64(property, maxMem);
+ if (propVal > 0 && uint64_t(propVal) <= SIZE_MAX) {
+ maxMem = propVal;
+ }
+ ALOGV("actual limit: %zu", maxMem);
+
+ struct rlimit limit;
+ getrlimit(RLIMIT_AS, &limit);
+ ALOGV("original limits: %lld/%lld", (long long)limit.rlim_cur, (long long)limit.rlim_max);
+ limit.rlim_cur = maxMem;
+ setrlimit(RLIMIT_AS, &limit);
+ limit.rlim_cur = -1;
+ limit.rlim_max = -1;
+ getrlimit(RLIMIT_AS, &limit);
+ ALOGV("new limits: %lld/%lld", (long long)limit.rlim_cur, (long long)limit.rlim_max);
+
+}
+
+} // namespace android
diff --git a/media/libmedia/MediaUtils.h b/media/libmedia/MediaUtils.h
new file mode 100644
index 0000000..f80dd30
--- /dev/null
+++ b/media/libmedia/MediaUtils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MEDIA_UTILS_H
+#define _MEDIA_UTILS_H
+
+namespace android {
+
+/**
+ Limit the amount of memory a process can allocate using setrlimit(RLIMIT_AS).
+ The value to use will be read from the specified system property, or if the
+ property doesn't exist it will use the specified number of bytes or the
+ specified percentage of total memory, whichever is smaller.
+*/
+void limitProcessMemory(
+ const char *property,
+ size_t numberOfBytes,
+ size_t percentageOfTotalMem);
+
+} // namespace android
+
+#endif // _MEDIA_UTILS_H
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 9a76f58..08a9e6a 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -35,7 +35,7 @@ Mutex MediaMetadataRetriever::sServiceLock;
sp<IMediaPlayerService> MediaMetadataRetriever::sService;
sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
-const sp<IMediaPlayerService>& MediaMetadataRetriever::getService()
+const sp<IMediaPlayerService> MediaMetadataRetriever::getService()
{
Mutex::Autolock lock(sServiceLock);
if (sService == 0) {
@@ -62,7 +62,7 @@ const sp<IMediaPlayerService>& MediaMetadataRetriever::getService()
MediaMetadataRetriever::MediaMetadataRetriever()
{
ALOGV("constructor");
- const sp<IMediaPlayerService>& service(getService());
+ const sp<IMediaPlayerService> service(getService());
if (service == 0) {
ALOGE("failed to obtain MediaMetadataRetrieverService");
return;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 3c6bef3..1057fc0 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -152,7 +152,7 @@ status_t MediaPlayer::setDataSource(
ALOGV("setDataSource(%s)", url);
status_t err = BAD_VALUE;
if (url != NULL) {
- const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
@@ -169,7 +169,7 @@ status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
status_t err = UNKNOWN_ERROR;
- const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
@@ -185,7 +185,7 @@ status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
{
ALOGV("setDataSource");
status_t err = UNKNOWN_ERROR;
- const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 8b7b171..144654c 100755
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -641,7 +641,7 @@ MediaRecorder::MediaRecorder(const String16& opPackageName) : mSurfaceMediaSourc
{
ALOGV("constructor");
- const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != NULL) {
mMediaRecorder = service->createMediaRecorder(opPackageName);
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 1e911c2..61afe99 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -237,7 +237,8 @@ void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attribu
// copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
- utf16_to_utf8(tags.string(), tagSize, attributes->tags);
+ utf16_to_utf8(tags.string(), tagSize, attributes->tags,
+ sizeof(attributes->tags) / sizeof(attributes->tags[0]));
}
} else {
ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
@@ -558,6 +559,12 @@ void MediaPlayerService::removeClient(wp<Client> client)
mClients.remove(client);
}
+bool MediaPlayerService::hasClient(wp<Client> client)
+{
+ Mutex::Autolock lock(mLock);
+ return mClients.indexOf(client) != NAME_NOT_FOUND;
+}
+
MediaPlayerService::Client::Client(
const sp<MediaPlayerService>& service, pid_t pid,
int32_t connId, const sp<IMediaPlayerClient>& client,
@@ -1054,6 +1061,10 @@ status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& playe
ALOGV("setNextPlayer");
Mutex::Autolock l(mLock);
sp<Client> c = static_cast<Client*>(player.get());
+ if (c != NULL && !mService->hasClient(c)) {
+ return BAD_VALUE;
+ }
+
mNextClient = c;
if (c != NULL) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index ff8f550..2bd7ec5 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -227,6 +227,7 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args);
void removeClient(wp<Client> client);
+ bool hasClient(wp<Client> client);
// For battery usage tracking purpose
struct BatteryUsageInfo {
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 7bd99cc..f725b90 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -228,6 +228,7 @@ sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option)
ALOGV("rotation: %d", frameCopy->mRotationAngle);
frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
memcpy(frameCopy->mData, frame->mData, frame->mSize);
+ frameCopy->mData = 0;
delete frame; // Fix memory leakage
return mThumbnail;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index d182a68..442dba1 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1743,7 +1743,7 @@ status_t StagefrightRecorder::setupMPEG4orWEBMRecording() {
if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
writer = new WebmWriter(mOutputFd);
} else {
- writer = mp4writer = new MPEG4Writer(mOutputFd);
+ writer = mp4writer = AVFactory::get()->CreateMPEG4Writer(mOutputFd);
}
if (mVideoSource < VIDEO_SOURCE_LIST_END) {
@@ -1814,6 +1814,8 @@ status_t StagefrightRecorder::setupMPEG4orWEBMRecording() {
void StagefrightRecorder::setupMPEG4orWEBMMetaData(sp<MetaData> *meta) {
int64_t startTimeUs = systemTime() / 1000;
(*meta)->setInt64(kKeyTime, startTimeUs);
+ int64_t startTimeBootUs = systemTime(SYSTEM_TIME_BOOTTIME) / 1000;
+ (*meta)->setInt64(kKeyTimeBoot, startTimeBootUs);
(*meta)->setInt32(kKeyFileType, mOutputFormat);
(*meta)->setInt32(kKeyBitRate, mTotalBitRate);
if (mMovieTimeScale > 0) {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index beda8bd..949c12f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -232,6 +232,9 @@ status_t NuPlayer::GenericSource::initFromDataSource() {
for (size_t i = 0; i < numtracks; ++i) {
sp<MediaSource> track = extractor->getTrack(i);
+ if (track == NULL) {
+ continue;
+ }
sp<MetaData> meta = extractor->getTrackMetaData(i);
@@ -274,24 +277,27 @@ status_t NuPlayer::GenericSource::initFromDataSource() {
}
}
- if (track != NULL) {
- mSources.push(track);
- int64_t durationUs;
- if (meta->findInt64(kKeyDuration, &durationUs)) {
- if (durationUs > mDurationUs) {
- mDurationUs = durationUs;
- }
+ mSources.push(track);
+ int64_t durationUs;
+ if (meta->findInt64(kKeyDuration, &durationUs)) {
+ if (durationUs > mDurationUs) {
+ mDurationUs = durationUs;
}
+ }
- int32_t bitrate;
- if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
- totalBitrate += bitrate;
- } else {
- totalBitrate = -1;
- }
+ int32_t bitrate;
+ if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
+ totalBitrate += bitrate;
+ } else {
+ totalBitrate = -1;
}
}
+ if (mSources.size() == 0) {
+ ALOGE("b/23705695");
+ return UNKNOWN_ERROR;
+ }
+
mBitrate = totalBitrate;
return OK;
@@ -339,7 +345,7 @@ int64_t NuPlayer::GenericSource::getLastReadPosition() {
status_t NuPlayer::GenericSource::setBuffers(
bool audio, Vector<MediaBuffer *> &buffers) {
- if ((mIsSecure || mUseSetBuffers) && !audio) {
+ if (mIsSecure && !audio && mVideoTrack.mSource != NULL) {
return mVideoTrack.mSource->setBuffers(buffers);
}
return INVALID_OPERATION;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 9f8556e..5deb61e 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -42,7 +42,7 @@ class WVMExtractor;
struct NuPlayer::GenericSource : public NuPlayer::Source {
GenericSource(const sp<AMessage> &notify, bool uidValid, uid_t uid);
- virtual status_t setDataSource(
+ status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 1835101..ef2e6ec 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -681,10 +681,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
// If the video decoder is not set (perhaps audio only in this case)
// do not perform a seek as it is not needed.
int64_t currentPositionUs = 0;
- if (getCurrentPosition(&currentPositionUs) == OK) {
- mDeferredActions.push_back(
- new SeekAction(currentPositionUs));
- }
+ getCurrentPosition(&currentPositionUs);
+ mDeferredActions.push_back(
+ new SeekAction(currentPositionUs));
}
// If there is a new surface texture, instantiate decoders
@@ -1157,6 +1156,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
mRenderer->flush(
false /* audio */, false /* notifyComplete */);
}
+ mRenderer->signalAudioTearDownComplete();
int64_t positionUs;
if (!msg->findInt64("positionUs", &positionUs)) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 1c51c4b..725a1b2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -247,7 +247,7 @@ protected:
void finishFlushIfPossible();
void onStart(int64_t startPositionUs = -1);
- void onResume();
+ virtual void onResume();
void onPause();
bool audioDecoderStillNeeded();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
index ac3c6b6..2c07f28 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
@@ -235,6 +235,12 @@ bool NuPlayer::CCDecoder::parseSEINalUnit(
payload_size += last_byte;
} while (last_byte == 0xFF);
+ if (payload_size > SIZE_MAX / 8
+ || !br.atLeastNumBitsLeft(payload_size * 8)) {
+ ALOGV("Malformed SEI payload");
+ break;
+ }
+
// sei_payload()
if (payload_type == 4) {
bool isCC = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 2336eb7..8afdefe 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -127,7 +127,7 @@ NuPlayer::Renderer::Renderer(
mAudioRenderingStartGeneration(0),
mRenderingDataDelivered(false),
mAudioOffloadPauseTimeoutGeneration(0),
- mAudioTornDown(false),
+ mAudioTearingDown(false),
mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
mTotalBuffersQueued(0),
@@ -626,6 +626,12 @@ void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatAudioTearDownComplete:
+ {
+ onAudioTearDownComplete();
+ break;
+ }
+
case kWhatAudioOffloadPauseTimeout:
{
int32_t generation;
@@ -780,6 +786,7 @@ size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
mAudioFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs);
// we don't know how much data we are queueing for offloaded tracks.
mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
+ mAnchorTimeMediaUs = nowMediaUs;
}
// for non-offloaded audio, we need to compute the frames written because
@@ -836,7 +843,7 @@ void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
bool NuPlayer::Renderer::onDrainAudioQueue() {
// do not drain audio during teardown as queued buffers may be invalid.
- if (mAudioTornDown) {
+ if (mAudioTearingDown) {
return false;
}
// TODO: This call to getPosition checks if AudioTrack has been created
@@ -850,18 +857,6 @@ bool NuPlayer::Renderer::onDrainAudioQueue() {
// immediately after start. Investigate error message
// "vorbis_dsp_synthesis returned -135", along with RTSP.
uint32_t numFramesPlayed;
- if(!mAudioSink->ready() && !mAudioQueue.empty()) {
- while (!mAudioQueue.empty()) {
- QueueEntry *entry = &*mAudioQueue.begin();
- if (entry->mBuffer == NULL) {
- notifyEOS(true /* audio */, entry->mFinalResult);
- }
- mAudioQueue.erase(mAudioQueue.begin());
- entry = NULL;
- }
- return false;
- }
-
if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
// When getPosition fails, renderer will not reschedule the draining
// unless new samples are queued.
@@ -1591,7 +1586,7 @@ void NuPlayer::Renderer::onResume() {
notifyAudioTearDown();
}
//Update anchor time after resuming playback.
- if (offloadingAudio()) {
+ if (offloadingAudio() && status == NO_ERROR) {
int64_t nowUs = ALooper::GetNowUs();
int64_t nowMediaUs =
mAudioFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs);
@@ -1717,10 +1712,10 @@ int64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) {
}
void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
- if (mAudioTornDown) {
+ if (mAudioTearingDown) {
return;
}
- mAudioTornDown = true;
+ mAudioTearingDown = true;
int64_t currentPositionUs;
sp<AMessage> notify = mNotify->dup();
@@ -1760,6 +1755,11 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
bool isStreaming) {
ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
offloadOnly, offloadingAudio());
+
+ if (mAudioTearingDown) {
+ ALOGW("openAudioSink: not opening now!, would happen after teardown");
+ return OK;
+ }
bool audioSinkChanged = false;
int32_t numChannels;
@@ -1957,7 +1957,6 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
if (audioSinkChanged) {
onAudioSinkChanged();
}
- mAudioTornDown = false;
return OK;
}
@@ -1967,5 +1966,13 @@ void NuPlayer::Renderer::onCloseAudioSink() {
mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
}
+void NuPlayer::Renderer::signalAudioTearDownComplete() {
+ (new AMessage(kWhatAudioTearDownComplete, this))->post();
+}
+
+void NuPlayer::Renderer::onAudioTearDownComplete() {
+ mAudioTearingDown = false;
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index e872227..a84e673 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -83,6 +83,7 @@ struct NuPlayer::Renderer : public AHandler {
bool *isOffloaded,
bool isStreaming);
void closeAudioSink();
+ void signalAudioTearDownComplete();
enum {
kWhatEOS = 'eos ',
@@ -92,6 +93,7 @@ struct NuPlayer::Renderer : public AHandler {
kWhatMediaRenderingStart = 'mdrd',
kWhatAudioTearDown = 'adTD',
kWhatAudioOffloadPauseTimeout = 'aOPT',
+ kWhatAudioTearDownComplete = 'aTDC',
};
enum AudioTearDownReason {
@@ -184,7 +186,7 @@ protected:
int64_t mLastPositionUpdateUs;
int32_t mAudioOffloadPauseTimeoutGeneration;
- bool mAudioTornDown;
+ bool mAudioTearingDown;
audio_offload_info_t mCurrentOffloadInfo;
struct PcmInfo {
@@ -257,6 +259,7 @@ protected:
uint32_t flags,
bool isStreaming);
void onCloseAudioSink();
+ void onAudioTearDownComplete();
void notifyEOS(bool audio, status_t finalResult, int64_t delayUs = 0);
void notifyFlushComplete(bool audio);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
index f53afbd..ee70306 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
@@ -144,8 +144,17 @@ ssize_t NuPlayer::NuPlayerStreamListener::read(
copy = size;
}
+ if (entry->mIndex >= mBuffers.size()) {
+ return ERROR_MALFORMED;
+ }
+
+ sp<IMemory> mem = mBuffers.editItemAt(entry->mIndex);
+ if (mem == NULL || mem->size() < copy || mem->size() - copy < entry->mOffset) {
+ return ERROR_MALFORMED;
+ }
+
memcpy(data,
- (const uint8_t *)mBuffers.editItemAt(entry->mIndex)->pointer()
+ (const uint8_t *)mem->pointer()
+ entry->mOffset,
copy);
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 35567a5..4962520 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -24,6 +24,7 @@
#include "MyHandler.h"
#include "SDPLoader.h"
+#include <cutils/properties.h>
#include <media/IMediaHTTPService.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
@@ -32,6 +33,7 @@
namespace android {
const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
+const uint32_t kMaxNumKeepDamagedAccessUnits = 30;
NuPlayer::RTSPSource::RTSPSource(
const sp<AMessage> &notify,
@@ -54,7 +56,10 @@ NuPlayer::RTSPSource::RTSPSource(
mBuffering(false),
mSeekGeneration(0),
mEOSTimeoutAudio(0),
- mEOSTimeoutVideo(0) {
+ mEOSTimeoutVideo(0),
+ mVideoTrackIndex(-1),
+ mKeepDamagedAccessUnits(false),
+ mNumKeepDamagedAccessUnits(0) {
if (headers) {
mExtraHeaders = *headers;
@@ -433,11 +438,22 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
sp<ABuffer> accessUnit;
CHECK(msg->findBuffer("accessUnit", &accessUnit));
+ bool isVideo = trackIndex == (size_t)mVideoTrackIndex;
int32_t damaged;
if (accessUnit->meta()->findInt32("damaged", &damaged)
&& damaged) {
- ALOGI("dropping damaged access unit.");
- break;
+ if (isVideo && mKeepDamagedAccessUnits
+ && mNumKeepDamagedAccessUnits < kMaxNumKeepDamagedAccessUnits) {
+ ALOGI("keep a damaged access unit.");
+ ++mNumKeepDamagedAccessUnits;
+ } else {
+ ALOGI("dropping damaged access unit.");
+ break;
+ }
+ } else {
+ if (isVideo) {
+ mNumKeepDamagedAccessUnits = 0;
+ }
}
if (mTSParser != NULL) {
@@ -613,6 +629,16 @@ void NuPlayer::RTSPSource::onConnected() {
bool isAudio = !strncasecmp(mime, "audio/", 6);
bool isVideo = !strncasecmp(mime, "video/", 6);
+ if (isVideo) {
+ mVideoTrackIndex = i;
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("rtsp.video.keep-damaged-au", value, NULL)
+ && !strcasecmp(mime, value)) {
+ ALOGV("enable to keep damaged au for %s", mime);
+ mKeepDamagedAccessUnits = true;
+ }
+ }
+
TrackInfo info;
info.mTimeScale = timeScale;
info.mRTPTime = 0;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 6438a1e..c431174 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -118,6 +118,10 @@ private:
sp<AReplyToken> mSeekReplyID;
+ int32_t mVideoTrackIndex;
+ bool mKeepDamagedAccessUnits;
+ uint32_t mNumKeepDamagedAccessUnits;
+
sp<AnotherPacketSource> getSource(bool audio);
void onConnected();
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 136eda5..b9c915e 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "StreamingSource"
#include <utils/Log.h>
+#include <inttypes.h>
+
#include "StreamingSource.h"
#include "ATSParser.h"
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b83d6c6..581bfba 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1746,7 +1746,10 @@ status_t ACodec::configureCodec(
ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
mComponentName.c_str(), err);
- return err;
+ if (mOMX->livesLocally(mNode, getpid())) {
+ return err;
+ }
+ ALOGI("ignoring failure to use internal MediaCodec key.");
}
// For this specific case we could be using camera source even if storeMetaDataInBuffers
// returns Gralloc source. Pretend that we are; this will force us to use nBufferSize.
@@ -2535,6 +2538,7 @@ status_t ACodec::setupAACCodec(
: OMX_AUDIO_AACStreamFormatMP4FF;
OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
+ InitOMXParams(&presentation);
presentation.nMaxOutputChannels = maxOutputChannelCount;
presentation.nDrcCut = drc.drcCut;
presentation.nDrcBoost = drc.drcBoost;
@@ -3567,7 +3571,7 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
// XXX
// Allow higher profiles to be set since the encoder seems to support
-#if 0
+#ifdef USE_AVC_BASELINE_PROFILE
if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
ALOGW("Use baseline profile instead of %d for AVC recording",
h264type.eProfile);
@@ -4208,6 +4212,16 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
rect.nWidth = videoDef->nFrameWidth;
rect.nHeight = videoDef->nFrameHeight;
}
+#ifdef MTK_HARDWARE
+ if (!strncmp(mComponentName.c_str(), "OMX.MTK.", 8) && mOMX->getConfig(
+ mNode, (OMX_INDEXTYPE) 0x7f00001c /* OMX_IndexVendorMtkOmxVdecGetCropInfo */,
+ &rect, sizeof(rect)) != OK) {
+ rect.nLeft = 0;
+ rect.nTop = 0;
+ rect.nWidth = videoDef->nFrameWidth;
+ rect.nHeight = videoDef->nFrameHeight;
+ }
+#endif
if (rect.nLeft < 0 ||
rect.nTop < 0 ||
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 29fb418..792c139 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -173,6 +173,10 @@ ifeq ($(TARGET_BOARD_PLATFORM),omap4)
LOCAL_CFLAGS += -DBOARD_CANT_REALLOCATE_OMX_BUFFERS
endif
+ifeq ($(TARGET_USE_AVC_BASELINE_PROFILE), true)
+LOCAL_CFLAGS += -DUSE_AVC_BASELINE_PROFILE
+endif
+
ifeq ($(call is-vendor-board-platform,QCOM),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true)
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 78fc3b8..77a7d1c 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -55,8 +55,12 @@ AudioSource::AudioSource(
: mStarted(false),
mSampleRate(sampleRate),
mOutSampleRate(outSampleRate > 0 ? outSampleRate : sampleRate),
+ mTrackMaxAmplitude(false),
+ mStartTimeUs(0),
+ mMaxAmplitude(0),
mPrevSampleTimeUs(0),
mFirstSampleTimeUs(-1ll),
+ mInitialReadTimeUs(0),
mNumFramesReceived(0),
mNumClientOwnedBuffers(0),
mRecPaused(false) {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index e2ad924..f6b4741 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -27,8 +27,10 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
+#include <media/hardware/HardwareAPI.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
+#include <camera/ICameraRecordingProxy.h>
#include <gui/Surface.h>
#include <utils/String8.h>
#include <cutils/properties.h>
@@ -701,7 +703,13 @@ status_t CameraSource::start(MetaData *meta) {
if (meta) {
int64_t startTimeUs;
- if (meta->findInt64(kKeyTime, &startTimeUs)) {
+
+ auto key = kKeyTime;
+ if (!property_get_bool("media.camera.ts.monotonic", true)) {
+ key = kKeyTimeBoot;
+ }
+
+ if (meta->findInt64(key, &startTimeUs)) {
mStartTimeUs = startTimeUs;
}
@@ -843,6 +851,8 @@ void CameraSource::releaseQueuedFrames() {
List<sp<IMemory> >::iterator it;
while (!mFramesReceived.empty()) {
it = mFramesReceived.begin();
+ // b/28466701
+ adjustOutgoingANWBuffer(it->get());
releaseRecordingFrame(*it);
mFramesReceived.erase(it);
++mNumFramesDropped;
@@ -863,6 +873,9 @@ void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
it != mFramesBeingEncoded.end(); ++it) {
if ((*it)->pointer() == buffer->data()) {
+ // b/28466701
+ adjustOutgoingANWBuffer(it->get());
+
releaseOneRecordingFrame((*it));
mFramesBeingEncoded.erase(it);
++mNumFramesEncoded;
@@ -981,6 +994,10 @@ void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
++mNumFramesReceived;
CHECK(data != NULL && data->size() > 0);
+
+ // b/28466701
+ adjustIncomingANWBuffer(data.get());
+
mFramesReceived.push_back(data);
int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
mFrameTimes.push_back(timeUs);
@@ -994,6 +1011,24 @@ bool CameraSource::isMetaDataStoredInVideoBuffers() const {
return mIsMetaDataStoredInVideoBuffers;
}
+void CameraSource::adjustIncomingANWBuffer(IMemory* data) {
+ VideoNativeMetadata *payload =
+ reinterpret_cast<VideoNativeMetadata*>(data->pointer());
+ if (payload->eType == kMetadataBufferTypeANWBuffer) {
+ payload->pBuffer = (ANativeWindowBuffer*)(((uint8_t*)payload->pBuffer) +
+ ICameraRecordingProxy::getCommonBaseAddress());
+ }
+}
+
+void CameraSource::adjustOutgoingANWBuffer(IMemory* data) {
+ VideoNativeMetadata *payload =
+ reinterpret_cast<VideoNativeMetadata*>(data->pointer());
+ if (payload->eType == kMetadataBufferTypeANWBuffer) {
+ payload->pBuffer = (ANativeWindowBuffer*)(((uint8_t*)payload->pBuffer) -
+ ICameraRecordingProxy::getCommonBaseAddress());
+ }
+}
+
CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
mSource = source;
}
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 9cb6e86..e2bc89c 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -200,7 +200,17 @@ status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
continue;
}
- CHECK(dstOffset + 4 <= (*buffer)->size());
+ if (dstOffset > SIZE_MAX - 4 ||
+ dstOffset + 4 > SIZE_MAX - nalLength ||
+ dstOffset + 4 + nalLength > (*buffer)->size()) {
+ (*buffer)->release();
+ (*buffer) = NULL;
+ if (decryptedDrmBuffer.data) {
+ delete [] decryptedDrmBuffer.data;
+ decryptedDrmBuffer.data = NULL;
+ }
+ return ERROR_MALFORMED;
+ }
dstData[dstOffset++] = 0;
dstData[dstOffset++] = 0;
diff --git a/media/libstagefright/FFMPEGSoftCodec.cpp b/media/libstagefright/FFMPEGSoftCodec.cpp
index 26afd89..0d5802b 100644
--- a/media/libstagefright/FFMPEGSoftCodec.cpp
+++ b/media/libstagefright/FFMPEGSoftCodec.cpp
@@ -35,6 +35,8 @@
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/Utils.h>
+#include <cutils/properties.h>
+
#include <OMX_Component.h>
#include <OMX_AudioExt.h>
#include <OMX_IndexExt.h>
@@ -319,12 +321,14 @@ status_t FFMPEGSoftCodec::setVideoFormat(
// from the CAF L release. It was unfortunately moved to a proprietary
// blob and an architecture which is hellish for OEMs who wish to
// customize the platform.
- if (err == OK && (!strncmp(componentName, "OMX.qcom.", 9))) {
+ if (err == OK && (!strncmp(componentName, "OMX.qcom.", 9)
+ || !strncmp(componentName, "OMX.ittiam.", 11))) {
status_t xerr = OK;
int32_t mode = 0;
OMX_QCOM_PARAM_PORTDEFINITIONTYPE portFmt;
+ InitOMXParams(&portFmt);
portFmt.nPortIndex = kPortIndexInput;
if (msg->findInt32("use-arbitrary-mode", &mode) && mode) {
@@ -392,9 +396,13 @@ status_t FFMPEGSoftCodec::setVideoFormat(
}
// Enable Sync-frame decode mode for thumbnails
+ char board[PROPERTY_VALUE_MAX];
+ property_get("ro.board.platform", board, NULL);
int32_t thumbnailMode = 0;
if (msg->findInt32("thumbnail-mode", &thumbnailMode) &&
- thumbnailMode > 0) {
+ thumbnailMode > 0 &&
+ !(!strcmp(board, "msm8996") || !strcmp(board, "msm8937") ||
+ !strcmp(board, "msm8953") || !strcmp(board, "msm8976"))) {
ALOGV("Enabling thumbnail mode.");
QOMX_ENABLETYPE enableType;
OMX_INDEXTYPE indexType;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index c7c238e..80ef7b7 100755
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -50,6 +50,12 @@
namespace android {
+enum {
+ // maximum size of an atom. Some atoms can be bigger according to the spec,
+ // but we only allow up to this size.
+ kMaxAtomSize = 64 * 1024 * 1024,
+};
+
class MPEG4Source : public MediaSource {
public:
// Caller retains ownership of both "dataSource" and "sampleTable".
@@ -544,7 +550,10 @@ status_t MPEG4Extractor::readMetaData() {
}
if (psshsize > 0 && psshsize <= UINT32_MAX) {
char *buf = (char*)malloc(psshsize);
- CHECK(buf != NULL);
+ if (!buf) {
+ ALOGE("b/28471206");
+ return NO_MEMORY;
+ }
char *ptr = buf;
for (size_t i = 0; i < mPssh.size(); i++) {
memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
@@ -842,6 +851,13 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
PathAdder autoAdder(&mPath, chunk_type);
off64_t chunk_data_size = *offset + chunk_size - data_offset;
+ if (chunk_type != FOURCC('m', 'd', 'a', 't') && chunk_data_size > kMaxAtomSize) {
+ char errMsg[100];
+ sprintf(errMsg, "%s atom has size %" PRId64, chunk, chunk_data_size);
+ ALOGE("%s (b/28615448)", errMsg);
+ android_errorWriteWithInfoLog(0x534e4554, "28615448", -1, errMsg, strlen(errMsg));
+ return ERROR_MALFORMED;
+ }
if (chunk_type != FOURCC('c', 'p', 'r', 't')
&& chunk_type != FOURCC('c', 'o', 'v', 'r')
@@ -939,6 +955,11 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
}
if (isTrack) {
+ int32_t trackId;
+ // There must be exact one track header per track.
+ if (!mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
+ mLastTrack->skipTrack = true;
+ }
if (mLastTrack->skipTrack) {
Track *cur = mFirstTrack;
@@ -1032,7 +1053,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
int64_t delay = (media_time * samplerate + 500000) / 1000000;
mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
- int64_t paddingus = duration - (segment_duration + media_time);
+ int64_t paddingus = duration - (int64_t)(segment_duration + media_time);
if (paddingus < 0) {
// track duration from media header (which is what kKeyDuration is) might
// be slightly shorter than the segment duration, which would make the
@@ -1730,6 +1751,11 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
sp<ABuffer> buffer = new ABuffer(chunk_data_size);
+ if (buffer->data() == NULL) {
+ ALOGE("b/28471206");
+ return NO_MEMORY;
+ }
+
if (mDataSource->readAt(
data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
return ERROR_IO;
@@ -1747,6 +1773,11 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
{
sp<ABuffer> buffer = new ABuffer(chunk_data_size);
+ if (buffer->data() == NULL) {
+ ALOGE("b/28471206");
+ return NO_MEMORY;
+ }
+
if (mDataSource->readAt(
data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
return ERROR_IO;
@@ -1980,6 +2011,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
return ERROR_IO;
}
+ if (mLastTrack == NULL)
+ return ERROR_MALFORMED;
+
uint32_t type = ntohl(buffer);
// For the 3GPP file format, the handler-type within the 'hdlr' box
// shall be 'text'. We also want to support 'sbtl' handler type
@@ -2079,6 +2113,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
return ERROR_MALFORMED;
}
sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
+ if (buffer->data() == NULL) {
+ ALOGE("b/28471206");
+ return NO_MEMORY;
+ }
if (mDataSource->readAt(
data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
return ERROR_IO;
@@ -2879,6 +2917,9 @@ sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
break;
}
}
+ } else {
+ ALOGE("b/21657957");
+ return NULL;
}
ALOGV("getTrack called, pssh: %zu", mPssh.size());
@@ -4258,7 +4299,15 @@ status_t MPEG4Source::read(
continue;
}
- CHECK(dstOffset + 4 <= mBuffer->size());
+ if (dstOffset > SIZE_MAX - 4 ||
+ dstOffset + 4 > SIZE_MAX - nalLength ||
+ dstOffset + 4 + nalLength > mBuffer->size()) {
+ ALOGE("b/27208621 : %zu %zu", dstOffset, mBuffer->size());
+ android_errorWriteLog(0x534e4554, "27208621");
+ mBuffer->release();
+ mBuffer = NULL;
+ return ERROR_MALFORMED;
+ }
dstData[dstOffset++] = 0;
dstData[dstOffset++] = 0;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 2f1b6ac..16da3eb 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1023,7 +1023,11 @@ uint32_t MPEG4Writer::getMpeg4Time() {
// MP4 file uses time counting seconds since midnight, Jan. 1, 1904
// while time function returns Unix epoch values which starts
// at 1970-01-01. Lets add the number of seconds between them
- uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60);
+ static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
+ if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
+ return 0;
+ }
+ uint32_t mpeg4Time = uint32_t(now) + delta;
return mpeg4Time;
}
@@ -1144,7 +1148,7 @@ off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
return old_offset;
}
-static void StripStartcode(MediaBuffer *buffer) {
+void MPEG4Writer::StripStartcode(MediaBuffer *buffer) {
if (buffer->range_length() < 4) {
return;
}
@@ -1833,9 +1837,16 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
}
int64_t startTimeUs;
+
if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
startTimeUs = 0;
}
+
+ int64_t startTimeBootUs;
+ if (params == NULL || !params->findInt64(kKeyTimeBoot, &startTimeBootUs)) {
+ startTimeBootUs = 0;
+ }
+
mStartTimeRealUs = startTimeUs;
int32_t rotationDegrees;
@@ -1846,6 +1857,7 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
initTrackingProgressStatus(params);
sp<MetaData> meta = new MetaData;
+
if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
/*
* This extra delay of accepting incoming audio/video signals
@@ -1861,10 +1873,12 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
startTimeOffsetUs = kInitialDelayTimeUs;
}
startTimeUs += startTimeOffsetUs;
+ startTimeBootUs += startTimeOffsetUs;
ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
}
meta->setInt64(kKeyTime, startTimeUs);
+ meta->setInt64(kKeyTimeBoot, startTimeBootUs);
status_t err = mSource->start(meta.get());
if (err != OK) {
@@ -2448,7 +2462,9 @@ status_t MPEG4Writer::Track::threadEntry() {
ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track",
timestampUs, lastTimestampUs, trackName);
copy->release();
- return UNKNOWN_ERROR;
+ err = UNKNOWN_ERROR;
+ mSource->notifyError(err);
+ return err;
}
// if the duration is different for this sample, see if it is close enough to the previous
diff --git a/media/libstagefright/MediaAdapter.cpp b/media/libstagefright/MediaAdapter.cpp
index d680e0c..ec4550f 100644
--- a/media/libstagefright/MediaAdapter.cpp
+++ b/media/libstagefright/MediaAdapter.cpp
@@ -27,7 +27,8 @@ namespace android {
MediaAdapter::MediaAdapter(const sp<MetaData> &meta)
: mCurrentMediaBuffer(NULL),
mStarted(false),
- mOutputFormat(meta) {
+ mOutputFormat(meta),
+ mStatus(OK) {
}
MediaAdapter::~MediaAdapter() {
@@ -51,6 +52,9 @@ status_t MediaAdapter::stop() {
// If stop() happens immediately after a pushBuffer(), we should
// clean up the mCurrentMediaBuffer
if (mCurrentMediaBuffer != NULL) {
+ mCurrentMediaBuffer->setObserver(this);
+ mCurrentMediaBuffer->claim();
+ mCurrentMediaBuffer->setObserver(0);
mCurrentMediaBuffer->release();
mCurrentMediaBuffer = NULL;
}
@@ -113,13 +117,23 @@ status_t MediaAdapter::pushBuffer(MediaBuffer *buffer) {
ALOGE("pushBuffer called before start");
return INVALID_OPERATION;
}
+ if (mStatus != OK) {
+ ALOGE("pushBuffer called when MediaAdapter in error status");
+ return mStatus;
+ }
mCurrentMediaBuffer = buffer;
mBufferReadCond.signal();
ALOGV("wait for the buffer returned @ pushBuffer! %p", buffer);
mBufferReturnedCond.wait(mAdapterLock);
- return OK;
+ return mStatus;
+}
+
+void MediaAdapter::notifyError(status_t err) {
+ Mutex::Autolock autoLock(mAdapterLock);
+ mStatus = err;
+ mBufferReturnedCond.signal();
}
} // namespace android
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index adbde54..14a3c0d 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -38,6 +38,7 @@
#include <media/stagefright/Utils.h>
#include <OMX_Core.h>
#include <stagefright/AVExtensions.h>
+#include <cutils/properties.h>
namespace android {
@@ -663,8 +664,13 @@ status_t MediaCodecSource::onStart(MetaData *params) {
status_t err = OK;
if (mFlags & FLAG_USE_SURFACE_INPUT) {
+ auto key = kKeyTime;
+ if (!property_get_bool("media.camera.ts.monotonic", true)) {
+ key = kKeyTimeBoot;
+ }
+
int64_t startTimeUs;
- if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
+ if (!params || !params->findInt64(key, &startTimeUs)) {
startTimeUs = -1ll;
}
resume(startTimeUs);
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index b13877d..798a855 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -35,6 +35,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/Utils.h>
+#include <stagefright/AVExtensions.h>
namespace android {
@@ -42,7 +43,7 @@ MediaMuxer::MediaMuxer(int fd, OutputFormat format)
: mFormat(format),
mState(UNINITIALIZED) {
if (format == OUTPUT_FORMAT_MPEG_4) {
- mWriter = new MPEG4Writer(fd);
+ mWriter = AVFactory::get()->CreateMPEG4Writer(fd);
} else if (format == OUTPUT_FORMAT_WEBM) {
mWriter = new WebmWriter(fd);
}
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index eff07f9..4f3e636 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -90,7 +90,7 @@ struct MuxOMX : public IOMX {
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize);
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess);
virtual status_t useGraphicBuffer(
node_id node, OMX_U32 port_index,
@@ -120,7 +120,7 @@ struct MuxOMX : public IOMX {
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize);
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess);
virtual status_t freeBuffer(
node_id node, OMX_U32 port_index, buffer_id buffer);
@@ -323,8 +323,9 @@ status_t MuxOMX::getGraphicBufferUsage(
status_t MuxOMX::useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) {
- return getOMX(node)->useBuffer(node, port_index, params, buffer, allottedSize);
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL /* crossProcess */) {
+ return getOMX(node)->useBuffer(
+ node, port_index, params, buffer, allottedSize, OMX_FALSE /* crossProcess */);
}
status_t MuxOMX::useGraphicBuffer(
@@ -376,9 +377,9 @@ status_t MuxOMX::allocateBuffer(
status_t MuxOMX::allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) {
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL /* crossProcess */) {
return getOMX(node)->allocateBufferWithBackup(
- node, port_index, params, buffer, allottedSize);
+ node, port_index, params, buffer, allottedSize, OMX_FALSE /* crossProcess */);
}
status_t MuxOMX::freeBuffer(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index abe19a0..de00ff2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -355,21 +355,6 @@ sp<MediaSource> OMXCodec::Create(
ALOGV("Attempting to allocate OMX node '%s'", componentName);
- if (!createEncoder
- && (quirks & kOutputBuffersAreUnreadable)
- && (flags & kClientNeedsFramebuffer)) {
- if (strncmp(componentName, "OMX.SEC.", 8)) {
- // For OMX.SEC.* decoders we can enable a special mode that
- // gives the client access to the framebuffer contents.
-
- ALOGW("Component '%s' does not give the client access to "
- "the framebuffer contents. Skipping.",
- componentName);
-
- continue;
- }
- }
-
status_t err = omx->allocateNode(componentName, observer, &node);
if (err == OK) {
ALOGV("Successfully allocated OMX node '%s'", componentName);
@@ -399,7 +384,7 @@ status_t OMXCodec::parseHEVCCodecSpecificData(
const uint8_t *ptr = (const uint8_t *)data;
// verify minimum size and configurationVersion == 1.
- if (size < 7 || ptr[0] != 1) {
+ if (size < 23 || ptr[0] != 1) {
return ERROR_MALFORMED;
}
@@ -414,6 +399,9 @@ status_t OMXCodec::parseHEVCCodecSpecificData(
size -= 1;
size_t j = 0, i = 0;
for (i = 0; i < numofArrays; i++) {
+ if (size < 3) {
+ return ERROR_MALFORMED;
+ }
ptr += 1;
size -= 1;
@@ -678,35 +666,6 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
initOutputFormat(meta);
- if ((mFlags & kClientNeedsFramebuffer)
- && !strncmp(mComponentName, "OMX.SEC.", 8)) {
- // This appears to no longer be needed???
-
- OMX_INDEXTYPE index;
-
- status_t err =
- mOMX->getExtensionIndex(
- mNode,
- "OMX.SEC.index.ThumbnailMode",
- &index);
-
- if (err != OK) {
- return err;
- }
-
- OMX_BOOL enable = OMX_TRUE;
- err = mOMX->setConfig(mNode, index, &enable, sizeof(enable));
-
- if (err != OK) {
- CODEC_LOGE("setConfig('OMX.SEC.index.ThumbnailMode') "
- "returned error 0x%08x", err);
-
- return err;
- }
-
- mQuirks &= ~kOutputBuffersAreUnreadable;
- }
-
if (mNativeWindow != NULL
&& !mIsEncoder
&& !strncasecmp(mMIME, "video/", 6)
@@ -1678,7 +1637,9 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
- CHECK(mem.get() != NULL);
+ if (mem == NULL || mem->pointer() == NULL) {
+ return NO_MEMORY;
+ }
BufferInfo info;
info.mData = NULL;
@@ -2399,9 +2360,6 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
#ifdef USE_S3D_SUPPORT
case (OMX_EVENTTYPE)OMX_EventS3DInformation:
{
- if (mFlags & kClientNeedsFramebuffer)
- break;
-
sp<IServiceManager> sm = defaultServiceManager();
sp<android::IExynosHWCService> hwc = interface_cast<android::IExynosHWCService>(
sm->getService(String16("Exynos.HWCService")));
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index 6042a9a..f5558ce 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -95,13 +95,16 @@ status_t SampleIterator::seekTo(uint32_t sampleIndex) {
CHECK(sampleIndex < mStopChunkSampleIndex);
+ if (mSamplesPerChunk == 0) {
+ ALOGE("b/22802344");
+ return ERROR_MALFORMED;
+ }
+
uint32_t chunk =
(sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk
+ mFirstChunk;
if (!mInitialized || chunk != mCurrentChunkIndex) {
- mCurrentChunkIndex = chunk;
-
status_t err;
if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
ALOGE("getChunkOffset return error");
@@ -112,18 +115,21 @@ status_t SampleIterator::seekTo(uint32_t sampleIndex) {
uint32_t firstChunkSampleIndex =
mFirstChunkSampleIndex
- + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk);
+ + mSamplesPerChunk * (chunk - mFirstChunk);
for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
size_t sampleSize;
if ((err = getSampleSizeDirect(
firstChunkSampleIndex + i, &sampleSize)) != OK) {
ALOGE("getSampleSizeDirect return error");
+ mCurrentChunkSampleSizes.clear();
return err;
}
mCurrentChunkSampleSizes.push(sampleSize);
}
+
+ mCurrentChunkIndex = chunk;
}
uint32_t chunkRelativeSampleIndex =
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index ee5def5..8a38c24 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -18,6 +18,8 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <limits>
+
#include "include/SampleTable.h"
#include "include/SampleIterator.h"
@@ -27,11 +29,6 @@
#include <media/stagefright/DataSource.h>
#include <media/stagefright/Utils.h>
-/* TODO: remove after being merged into other branches */
-#ifndef UINT32_MAX
-#define UINT32_MAX (4294967295U)
-#endif
-
namespace android {
// static
@@ -45,6 +42,8 @@ const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
////////////////////////////////////////////////////////////////////////////////
+const off64_t kMaxOffset = std::numeric_limits<off64_t>::max();
+
struct SampleTable::CompositionDeltaLookup {
CompositionDeltaLookup();
@@ -121,6 +120,7 @@ SampleTable::SampleTable(const sp<DataSource> &source)
mSampleSizeFieldSize(0),
mDefaultSampleSize(0),
mNumSampleSizes(0),
+ mHasTimeToSample(false),
mTimeToSampleCount(0),
mTimeToSample(NULL),
mSampleTimeEntries(NULL),
@@ -131,7 +131,8 @@ SampleTable::SampleTable(const sp<DataSource> &source)
mNumSyncSamples(0),
mSyncSamples(NULL),
mLastSyncSampleIndex(0),
- mSampleToChunkEntries(NULL) {
+ mSampleToChunkEntries(NULL),
+ mTotalSize(0) {
mSampleIterator = new SampleIterator(this);
}
@@ -142,6 +143,9 @@ SampleTable::~SampleTable() {
delete[] mSyncSamples;
mSyncSamples = NULL;
+ delete[] mTimeToSample;
+ mTimeToSample = NULL;
+
delete mCompositionDeltaLookup;
mCompositionDeltaLookup = NULL;
@@ -151,9 +155,6 @@ SampleTable::~SampleTable() {
delete[] mSampleTimeEntries;
mSampleTimeEntries = NULL;
- delete[] mTimeToSample;
- mTimeToSample = NULL;
-
delete mSampleIterator;
mSampleIterator = NULL;
}
@@ -162,7 +163,7 @@ bool SampleTable::isValid() const {
return mChunkOffsetOffset >= 0
&& mSampleToChunkOffset >= 0
&& mSampleSizeOffset >= 0
- && mTimeToSample != NULL;
+ && mHasTimeToSample;
}
status_t SampleTable::setChunkOffsetParams(
@@ -209,6 +210,11 @@ status_t SampleTable::setChunkOffsetParams(
status_t SampleTable::setSampleToChunkParams(
off64_t data_offset, size_t data_size) {
if (mSampleToChunkOffset >= 0) {
+ // already set
+ return ERROR_MALFORMED;
+ }
+
+ if (data_offset < 0) {
return ERROR_MALFORMED;
}
@@ -231,32 +237,67 @@ status_t SampleTable::setSampleToChunkParams(
mNumSampleToChunkOffsets = U32_AT(&header[4]);
- if ((data_size - 8) / 12 < mNumSampleToChunkOffsets) {
+ if ((data_size - 8) / sizeof(SampleToChunkEntry) < mNumSampleToChunkOffsets) {
return ERROR_MALFORMED;
}
- if (SIZE_MAX / sizeof(SampleToChunkEntry) <= (size_t)mNumSampleToChunkOffsets)
+ if ((uint64_t)kMaxTotalSize / sizeof(SampleToChunkEntry) <=
+ (uint64_t)mNumSampleToChunkOffsets) {
+ ALOGE("Sample-to-chunk table size too large.");
return ERROR_OUT_OF_RANGE;
+ }
+
+ mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
+ sizeof(SampleToChunkEntry);
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Sample-to-chunk table size would make sample table too large.\n"
+ " Requested sample-to-chunk table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)mNumSampleToChunkOffsets *
+ sizeof(SampleToChunkEntry),
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
+ return ERROR_OUT_OF_RANGE;
+ }
mSampleToChunkEntries =
new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
- if (!mSampleToChunkEntries)
+ if (!mSampleToChunkEntries) {
+ ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
+ (unsigned long long)mNumSampleToChunkOffsets);
return ERROR_OUT_OF_RANGE;
+ }
+
+ if (mNumSampleToChunkOffsets == 0) {
+ return OK;
+ }
+
+ if ((off64_t)(kMaxOffset - 8 -
+ ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
+ < mSampleToChunkOffset) {
+ return ERROR_MALFORMED;
+ }
for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
- uint8_t buffer[12];
+ uint8_t buffer[sizeof(SampleToChunkEntry)];
- if ((off64_t)(INT64_MAX - 8 - (i * 12)) < mSampleToChunkOffset) {
+ if ((SIZE_MAX - 8 - (i * 12)) < (size_t)mSampleToChunkOffset) {
return ERROR_MALFORMED;
}
if (mDataSource->readAt(
- mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
+ mSampleToChunkOffset + 8 + i * sizeof(SampleToChunkEntry),
+ buffer,
+ sizeof(buffer))
!= (ssize_t)sizeof(buffer)) {
return ERROR_IO;
}
-
- CHECK(U32_AT(buffer) >= 1); // chunk index is 1 based in the spec.
+ // chunk index is 1 based in the spec.
+ if (U32_AT(buffer) < 1) {
+ ALOGE("b/23534160");
+ return ERROR_OUT_OF_RANGE;
+ }
// We want the chunk index to be 0-based.
mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
@@ -332,7 +373,7 @@ status_t SampleTable::setSampleSizeParams(
status_t SampleTable::setTimeToSampleParams(
off64_t data_offset, size_t data_size) {
- if (mTimeToSample != NULL || data_size < 8) {
+ if (mHasTimeToSample || data_size < 8) {
return ERROR_MALFORMED;
}
@@ -348,24 +389,51 @@ status_t SampleTable::setTimeToSampleParams(
}
mTimeToSampleCount = U32_AT(&header[4]);
+ if (mTimeToSampleCount > UINT32_MAX / (2 * sizeof(uint32_t))) {
+ // Choose this bound because
+ // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
+ // time-to-sample entry in the time-to-sample table.
+ // 2) mTimeToSampleCount is the number of entries of the time-to-sample
+ // table.
+ // 3) We hope that the table size does not exceed UINT32_MAX.
+ ALOGE("Time-to-sample table size too large.");
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ // Note: At this point, we know that mTimeToSampleCount * 2 will not
+ // overflow because of the above condition.
+
uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
- if (allocSize > UINT32_MAX) {
+ mTotalSize += allocSize;
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Time-to-sample table size would make sample table too large.\n"
+ " Requested time-to-sample table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)allocSize,
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
return ERROR_OUT_OF_RANGE;
}
+
mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
- if (!mTimeToSample)
+ if (!mTimeToSample) {
+ ALOGE("Cannot allocate time-to-sample table with %llu entries.",
+ (unsigned long long)mTimeToSampleCount);
return ERROR_OUT_OF_RANGE;
+ }
- size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
- if (mDataSource->readAt(
- data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
+ if (mDataSource->readAt(data_offset + 8, mTimeToSample,
+ (size_t)allocSize) < (ssize_t)allocSize) {
+ ALOGE("Incomplete data read for time-to-sample table.");
return ERROR_IO;
}
- for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
+ for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
mTimeToSample[i] = ntohl(mTimeToSample[i]);
}
+ mHasTimeToSample = true;
return OK;
}
@@ -397,17 +465,32 @@ status_t SampleTable::setCompositionTimeToSampleParams(
mNumCompositionTimeDeltaEntries = numEntries;
uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t);
- if (allocSize > UINT32_MAX) {
+ if (allocSize > kMaxTotalSize) {
+ ALOGE("Composition-time-to-sample table size too large.");
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ mTotalSize += allocSize;
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Composition-time-to-sample table would make sample table too large.\n"
+ " Requested composition-time-to-sample table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)allocSize,
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
return ERROR_OUT_OF_RANGE;
}
mCompositionTimeDeltaEntries = new (std::nothrow) uint32_t[2 * numEntries];
- if (!mCompositionTimeDeltaEntries)
+ if (!mCompositionTimeDeltaEntries) {
+ ALOGE("Cannot allocate composition-time-to-sample table with %llu "
+ "entries.", (unsigned long long)numEntries);
return ERROR_OUT_OF_RANGE;
+ }
- if (mDataSource->readAt(
- data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
- < (ssize_t)numEntries * 8) {
+ if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
+ (size_t)allocSize) < (ssize_t)allocSize) {
delete[] mCompositionTimeDeltaEntries;
mCompositionTimeDeltaEntries = NULL;
@@ -448,18 +531,33 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size)
ALOGV("Table of sync samples is empty or has only a single entry!");
}
- uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t);
- if (allocSize > SIZE_MAX) {
+ uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
+ if (allocSize > kMaxTotalSize) {
+ ALOGE("Sync sample table size too large.");
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ mTotalSize += allocSize;
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Sync sample table size would make sample table too large.\n"
+ " Requested sync sample table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)allocSize,
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
return ERROR_OUT_OF_RANGE;
}
mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples];
- if (!mSyncSamples)
+ if (!mSyncSamples) {
+ ALOGE("Cannot allocate sync sample table with %llu entries.",
+ (unsigned long long)mNumSyncSamples);
return ERROR_OUT_OF_RANGE;
+ }
- size_t size = mNumSyncSamples * sizeof(uint32_t);
- if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
- != (ssize_t)size) {
+ if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples,
+ (size_t)allocSize) != (ssize_t)allocSize) {
return ERROR_IO;
}
@@ -524,9 +622,24 @@ void SampleTable::buildSampleEntriesTable() {
return;
}
+ mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Sample entry table size would make sample table too large.\n"
+ " Requested sample entry table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
+ return;
+ }
+
mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
- if (!mSampleTimeEntries)
+ if (!mSampleTimeEntries) {
+ ALOGE("Cannot allocate sample entry table with %llu entries.",
+ (unsigned long long)mNumSampleSizes);
return;
+ }
uint32_t sampleIndex = 0;
uint32_t sampleTime = 0;
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 8d3392e..d5ef1a6 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -46,7 +46,7 @@ static bool FileHasAcceptableExtension(const char *extension) {
".mov", ".ra", ".rm", ".rmvb", ".ac3", ".ape", ".dts",
".mp1", ".mp2", ".f4v", "hlv", "nrg", "m2v", ".swf",
".avi", ".mpg", ".mpeg", ".awb", ".vc1", ".vob", ".divx",
- ".mpga", ".mov", ".qcp", ".ec3"
+ ".mpga", ".mov", ".qcp", ".ec3", ".opus"
};
static const size_t kNumValidExtensions =
sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 592510b..489ccc3 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -694,22 +694,30 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
// reassemble the csd data into its original form
sp<ABuffer> csd0;
if (msg->findBuffer("csd-0", &csd0)) {
+ int csd0size = csd0->size();
if (mime == MEDIA_MIMETYPE_VIDEO_AVC) {
sp<ABuffer> csd1;
if (msg->findBuffer("csd-1", &csd1)) {
- char avcc[1024]; // that oughta be enough, right?
- size_t outsize = reassembleAVCC(csd0, csd1, avcc);
- meta->setData(kKeyAVCC, kKeyAVCC, avcc, outsize);
+ Vector<char> avcc;
+ int avccSize = csd0size + csd1->size() + 1024;
+ if (avcc.resize(avccSize) < 0) {
+ ALOGE("error allocating avcc (size %d); abort setting avcc.", avccSize);
+ } else {
+ size_t outsize = reassembleAVCC(csd0, csd1, avcc.editArray());
+ meta->setData(kKeyAVCC, kKeyAVCC, avcc.array(), outsize);
+ }
}
} else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
- int csd0size = csd0->size();
- char esds[csd0size + 31];
- // The written ESDS is actually for an audio stream, but it's enough
- // for transporting the CSD to muxers.
- reassembleESDS(csd0, esds);
- meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds));
- } else {
- AVUtils::get()->HEVCMuxerUtils().reassembleHEVCCSD(mime, csd0, meta);
+ Vector<char> esds;
+ int esdsSize = csd0size + 31;
+ if (esds.resize(esdsSize) < 0) {
+ ALOGE("error allocating esds (size %d); abort setting esds.", esdsSize);
+ } else {
+ // The written ESDS is actually for an audio stream, but it's enough
+ // for transporting the CSD to muxers.
+ reassembleESDS(csd0, esds.editArray());
+ meta->setData(kKeyESDS, kKeyESDS, esds.array(), esds.size());
+ }
}
}
diff --git a/media/libstagefright/VideoFrameScheduler.cpp b/media/libstagefright/VideoFrameScheduler.cpp
index 02b8783..c17faf3 100644
--- a/media/libstagefright/VideoFrameScheduler.cpp
+++ b/media/libstagefright/VideoFrameScheduler.cpp
@@ -459,14 +459,16 @@ nsecs_t VideoFrameScheduler::schedule(nsecs_t renderTime) {
mTimeCorrection -= mVsyncPeriod / 2;
renderTime -= mVsyncPeriod / 2;
nextVsyncTime -= mVsyncPeriod;
- --vsyncsForLastFrame;
+ if (vsyncsForLastFrame > 0)
+ --vsyncsForLastFrame;
} else if (mTimeCorrection < -correctionLimit &&
(vsyncsPerFrameAreNearlyConstant || vsyncsForLastFrame == minVsyncsPerFrame)) {
// add a VSYNC
mTimeCorrection += mVsyncPeriod / 2;
renderTime += mVsyncPeriod / 2;
nextVsyncTime += mVsyncPeriod;
- ++vsyncsForLastFrame;
+ if (vsyncsForLastFrame < ULONG_MAX)
+ ++vsyncsForLastFrame;
}
ATRACE_INT("FRAME_VSYNCS", vsyncsForLastFrame);
}
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index cc1d7ce..62bb416 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -315,9 +315,17 @@ status_t WAVExtractor::init() {
1000000LL * (mDataSize / 65 * 320) / 8000;
} else {
size_t bytesPerSample = mBitsPerSample >> 3;
+
+ if (!bytesPerSample || !mNumChannels)
+ return ERROR_MALFORMED;
+
+ size_t num_samples = mDataSize / (mNumChannels * bytesPerSample);
+
+ if (!mSampleRate)
+ return ERROR_MALFORMED;
+
durationUs =
- 1000000LL * (mDataSize / (mNumChannels * bytesPerSample))
- / mSampleRate;
+ 1000000LL * num_samples / mSampleRate;
}
mTrackMeta->setInt64(kKeyDuration, durationUs);
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index c945305..0d3151d 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -211,6 +211,10 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
(OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+ if (!isValidOMXParam(aacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (aacParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -246,6 +250,10 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -286,6 +294,10 @@ OMX_ERRORTYPE SoftAAC2::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.aac",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -300,6 +312,10 @@ OMX_ERRORTYPE SoftAAC2::internalSetParameter(
const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
(const OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+ if (!isValidOMXParam(aacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (aacParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -320,6 +336,11 @@ OMX_ERRORTYPE SoftAAC2::internalSetParameter(
{
const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *aacPresParams =
(const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *)params;
+
+ if (!isValidOMXParam(aacPresParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
// for the following parameters of the OMX_AUDIO_PARAM_AACPROFILETYPE structure,
// a value of -1 implies the parameter is not set by the application:
// nMaxOutputChannels uses default platform properties, see configureDownmix()
@@ -386,6 +407,10 @@ OMX_ERRORTYPE SoftAAC2::internalSetParameter(
const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -623,12 +648,15 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) {
signalError = true;
} else {
adtsHeaderSize = (protectionAbsent ? 7 : 9);
-
- inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize;
- inBufferLength[0] = aac_frame_length - adtsHeaderSize;
-
- inHeader->nOffset += adtsHeaderSize;
- inHeader->nFilledLen -= adtsHeaderSize;
+ if (aac_frame_length < adtsHeaderSize) {
+ signalError = true;
+ } else {
+ inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize;
+ inBufferLength[0] = aac_frame_length - adtsHeaderSize;
+
+ inHeader->nOffset += adtsHeaderSize;
+ inHeader->nFilledLen -= adtsHeaderSize;
+ }
}
}
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
index c6724c2..ab0a228 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
@@ -154,6 +154,10 @@ OMX_ERRORTYPE SoftAACEncoder::internalGetParameter(
OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -174,6 +178,10 @@ OMX_ERRORTYPE SoftAACEncoder::internalGetParameter(
OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
(OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+ if (!isValidOMXParam(aacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (aacParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -198,6 +206,10 @@ OMX_ERRORTYPE SoftAACEncoder::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -229,6 +241,10 @@ OMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_encoder.aac",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -243,6 +259,10 @@ OMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -266,6 +286,10 @@ OMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
(OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+ if (!isValidOMXParam(aacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (aacParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -286,6 +310,10 @@ OMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 35aa883..e8dabed 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -123,6 +123,10 @@ OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -143,6 +147,10 @@ OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
(OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+ if (!isValidOMXParam(aacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (aacParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -202,6 +210,10 @@ OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -233,6 +245,10 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_encoder.aac",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -247,6 +263,10 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -270,6 +290,10 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
(OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+ if (!isValidOMXParam(aacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (aacParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -310,6 +334,10 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/codecs/amrnb/common/Android.mk b/media/libstagefright/codecs/amrnb/common/Android.mk
index 5e632a6..80b67bb 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.mk
+++ b/media/libstagefright/codecs/amrnb/common/Android.mk
@@ -7,7 +7,6 @@ LOCAL_SRC_FILES := \
src/bitno_tab.cpp \
src/bitreorder_tab.cpp \
src/bits2prm.cpp \
- src/bytesused.cpp \
src/c2_9pf_tab.cpp \
src/copy.cpp \
src/div_32.cpp \
@@ -38,7 +37,6 @@ LOCAL_SRC_FILES := \
src/mult_r.cpp \
src/norm_l.cpp \
src/norm_s.cpp \
- src/overflow_tbl.cpp \
src/ph_disp_tab.cpp \
src/pow2.cpp \
src/pow2_tbl.cpp \
diff --git a/media/libstagefright/codecs/amrnb/common/include/bytesused.h b/media/libstagefright/codecs/amrnb/common/include/bytesused.h
deleted file mode 100644
index 934efbe..0000000
--- a/media/libstagefright/codecs/amrnb/common/include/bytesused.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
- 3GPP TS 26.073
- ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
- Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Pathname: .audio/gsm-amr/c/include/BytesUsed.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Added #ifdef __cplusplus after Include section.
-
- Who: Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file declares a table BytesUsed.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef BYTESUSED_H
-#define BYTESUSED_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
- /*----------------------------------------------------------------------------
- ; MACROS
- ; Define module specific macros here
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; DEFINES
- ; Include all pre-processor statements here.
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; EXTERNAL VARIABLES REFERENCES
- ; Declare variables used in this module but defined elsewhere
- ----------------------------------------------------------------------------*/
- extern const short BytesUsed[];
-
- /*----------------------------------------------------------------------------
- ; SIMPLE TYPEDEF'S
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; ENUMERATED TYPEDEF'S
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; STRUCTURES TYPEDEF'S
- ----------------------------------------------------------------------------*/
-
-
- /*----------------------------------------------------------------------------
- ; GLOBAL FUNCTION DEFINITIONS
- ; Function Prototype declaration
- ----------------------------------------------------------------------------*/
-
-
- /*----------------------------------------------------------------------------
- ; END
- ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
diff --git a/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp b/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp
deleted file mode 100644
index b61bac4..0000000
--- a/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
- 3GPP TS 26.073
- ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
- Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Pathname: ./audio/gsm-amr/c/src/BytesUsed.c
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Corrected entries for all SID frames and updated function
- description. Updated copyright year.
-
- Description: Added #ifdef __cplusplus and removed "extern" from table
- definition. Removed corresponding header file from Include
- section.
-
- Description: Put "extern" back.
-
- Who: Date:
- Description:
-
-------------------------------------------------------------------------------
- INPUT AND OUTPUT DEFINITIONS
-
- Inputs:
- None
-
- Local Stores/Buffers/Pointers Needed:
- None
-
- Global Stores/Buffers/Pointers Needed:
- None
-
- Outputs:
- None
-
- Pointers and Buffers Modified:
- None
-
- Local Stores Modified:
- None
-
- Global Stores Modified:
- None
-
-------------------------------------------------------------------------------
- FUNCTION DESCRIPTION
-
- This function creates a table called BytesUsed that holds the value that
- describes the number of bytes required to hold one frame worth of data in
- the WMF (non-IF2) frame format. Each table entry is the sum of the frame
- type byte and the number of bytes used up by the core speech data for each
- 3GPP frame type.
-
-------------------------------------------------------------------------------
- REQUIREMENTS
-
- None
-
-------------------------------------------------------------------------------
- REFERENCES
-
- [1] "AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0
- Release 4, June 2001, page 13.
-
-------------------------------------------------------------------------------
- PSEUDO-CODE
-
-
-------------------------------------------------------------------------------
- RESOURCES USED
- When the code is written for a specific target processor the
- the resources used should be documented below.
-
- STACK USAGE: [stack count for this module] + [variable to represent
- stack usage for each subroutine called]
-
- where: [stack usage variable] = stack usage for [subroutine
- name] (see [filename].ext)
-
- DATA MEMORY USED: x words
-
- PROGRAM MEMORY USED: x words
-
- CLOCK CYCLES: [cycle count equation for this module] + [variable
- used to represent cycle count for each subroutine
- called]
-
- where: [cycle count variable] = cycle count for [subroutine
- name] (see [filename].ext)
-
-------------------------------------------------------------------------------
-*/
-
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include "typedef.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
- /*----------------------------------------------------------------------------
- ; MACROS
- ; Define module specific macros here
- ----------------------------------------------------------------------------*/
-
-
- /*----------------------------------------------------------------------------
- ; DEFINES
- ; Include all pre-processor statements here. Include conditional
- ; compile variables also.
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; LOCAL FUNCTION DEFINITIONS
- ; Function Prototype declaration
- ----------------------------------------------------------------------------*/
-
-
- /*----------------------------------------------------------------------------
- ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
- ; Variable declaration - defined here and used outside this module
- ----------------------------------------------------------------------------*/
- const short BytesUsed[16] =
- {
- 13, /* 4.75 */
- 14, /* 5.15 */
- 16, /* 5.90 */
- 18, /* 6.70 */
- 20, /* 7.40 */
- 21, /* 7.95 */
- 27, /* 10.2 */
- 32, /* 12.2 */
- 6, /* GsmAmr comfort noise */
- 7, /* Gsm-Efr comfort noise */
- 6, /* IS-641 comfort noise */
- 6, /* Pdc-Efr comfort noise */
- 0, /* future use */
- 0, /* future use */
- 0, /* future use */
- 1 /* No transmission */
- };
- /*----------------------------------------------------------------------------
- ; EXTERNAL FUNCTION REFERENCES
- ; Declare functions defined elsewhere and referenced in this module
- ----------------------------------------------------------------------------*/
-
-
- /*----------------------------------------------------------------------------
- ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
- ; Declare variables used in this module but defined elsewhere
- ----------------------------------------------------------------------------*/
-
-
- /*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-/*----------------------------------------------------------------------------
-; FUNCTION CODE
-----------------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------------
-; Define all local variables
-----------------------------------------------------------------------------*/
-
-
-/*----------------------------------------------------------------------------
-; Function body here
-----------------------------------------------------------------------------*/
-
-
-/*----------------------------------------------------------------------------
-; Return nothing or data or data pointer
-----------------------------------------------------------------------------*/
-
diff --git a/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp
deleted file mode 100644
index c4a016d..0000000
--- a/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
- 3GPP TS 26.073
- ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
- Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/src/overflow_tbl.c
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Added #ifdef __cplusplus and removed "extern" from table
- definition.
-
- Description: Put "extern" back.
-
- Who: Date:
- Description:
-
-------------------------------------------------------------------------------
- MODULE DESCRIPTION
-
- This file contains the declaration for overflow_tbl[] used by the l_shl()
- and l_shr() functions.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include "typedef.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
- /*----------------------------------------------------------------------------
- ; MACROS
- ; [Define module specific macros here]
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; DEFINES
- ; [Include all pre-processor statements here. Include conditional
- ; compile variables also.]
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; LOCAL FUNCTION DEFINITIONS
- ; [List function prototypes here]
- ----------------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------------
- ; LOCAL VARIABLE DEFINITIONS
- ; [Variable declaration - defined here and used outside this module]
- ----------------------------------------------------------------------------*/
- const Word32 overflow_tbl [32] = {0x7fffffffL, 0x3fffffffL,
- 0x1fffffffL, 0x0fffffffL,
- 0x07ffffffL, 0x03ffffffL,
- 0x01ffffffL, 0x00ffffffL,
- 0x007fffffL, 0x003fffffL,
- 0x001fffffL, 0x000fffffL,
- 0x0007ffffL, 0x0003ffffL,
- 0x0001ffffL, 0x0000ffffL,
- 0x00007fffL, 0x00003fffL,
- 0x00001fffL, 0x00000fffL,
- 0x000007ffL, 0x000003ffL,
- 0x000001ffL, 0x000000ffL,
- 0x0000007fL, 0x0000003fL,
- 0x0000001fL, 0x0000000fL,
- 0x00000007L, 0x00000003L,
- 0x00000001L, 0x00000000L
- };
-
- /*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-/*
-------------------------------------------------------------------------------
- FUNCTION NAME:
-------------------------------------------------------------------------------
- INPUT AND OUTPUT DEFINITIONS
-
- Inputs:
- None
-
- Outputs:
- None
-
- Returns:
- None
-
- Global Variables Used:
- None
-
- Local Variables Needed:
- None
-
-------------------------------------------------------------------------------
- FUNCTION DESCRIPTION
-
- None
-
-------------------------------------------------------------------------------
- REQUIREMENTS
-
- None
-
-------------------------------------------------------------------------------
- REFERENCES
-
- [1] l_shl() function in basic_op2.c, UMTS GSM AMR speech codec, R99 -
- Version 3.2.0, March 2, 2001
-
-------------------------------------------------------------------------------
- PSEUDO-CODE
-
-
-------------------------------------------------------------------------------
- RESOURCES USED [optional]
-
- When the code is written for a specific target processor the
- the resources used should be documented below.
-
- HEAP MEMORY USED: x bytes
-
- STACK MEMORY USED: x bytes
-
- CLOCK CYCLES: (cycle count equation for this function) + (variable
- used to represent cycle count for each subroutine
- called)
- where: (cycle count variable) = cycle count for [subroutine
- name]
-
-------------------------------------------------------------------------------
- CAUTION [optional]
- [State any special notes, constraints or cautions for users of this function]
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; FUNCTION CODE
-----------------------------------------------------------------------------*/
-
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index f8316fd..edf648d 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -148,6 +148,10 @@ OMX_ERRORTYPE SoftAMR::internalGetParameter(
OMX_AUDIO_PARAM_AMRTYPE *amrParams =
(OMX_AUDIO_PARAM_AMRTYPE *)params;
+ if (!isValidOMXParam(amrParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (amrParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -174,6 +178,10 @@ OMX_ERRORTYPE SoftAMR::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -207,6 +215,10 @@ OMX_ERRORTYPE SoftAMR::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (mMode == MODE_NARROW) {
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.amrnb",
@@ -229,6 +241,10 @@ OMX_ERRORTYPE SoftAMR::internalSetParameter(
const OMX_AUDIO_PARAM_AMRTYPE *aacParams =
(const OMX_AUDIO_PARAM_AMRTYPE *)params;
+ if (!isValidOMXParam(aacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (aacParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -241,6 +257,10 @@ OMX_ERRORTYPE SoftAMR::internalSetParameter(
const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -303,6 +323,13 @@ void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
return;
}
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ notifyEmptyBufferDone(inHeader);
+ continue;
+ }
+
if (inHeader->nOffset == 0) {
mAnchorTimeUs = inHeader->nTimeStamp;
mNumSamplesOutput = 0;
@@ -312,6 +339,26 @@ void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
int32_t numBytesRead;
if (mMode == MODE_NARROW) {
+ if (outHeader->nAllocLen < kNumSamplesPerFrameNB * sizeof(int16_t)) {
+ ALOGE("b/27662364: NB expected output buffer %zu bytes vs %u",
+ kNumSamplesPerFrameNB * sizeof(int16_t), outHeader->nAllocLen);
+ android_errorWriteLog(0x534e4554, "27662364");
+ notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ int16 mode = ((inputPtr[0] >> 3) & 0x0f);
+ // for WMF since MIME_IETF is used when calling AMRDecode.
+ size_t frameSize = WmfDecBytesPerFrame[mode] + 1;
+
+ if (inHeader->nFilledLen < frameSize) {
+ ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen);
+ notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
numBytesRead =
AMRDecode(mState,
(Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
@@ -339,6 +386,15 @@ void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
return;
}
} else {
+ if (outHeader->nAllocLen < kNumSamplesPerFrameWB * sizeof(int16_t)) {
+ ALOGE("b/27662364: WB expected output buffer %zu bytes vs %u",
+ kNumSamplesPerFrameWB * sizeof(int16_t), outHeader->nAllocLen);
+ android_errorWriteLog(0x534e4554, "27662364");
+ notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
int16 mode = ((inputPtr[0] >> 3) & 0x0f);
if (mode >= 10 && mode <= 13) {
@@ -353,10 +409,8 @@ void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
size_t frameSize = getFrameSize(mode);
if (inHeader->nFilledLen < frameSize) {
- ALOGE("Filled length vs frameSize %u vs %lu. Corrupt clip?",
- inHeader->nFilledLen, frameSize);
-
- notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen);
+ notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
mSignalledError = true;
return;
}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h
index 0988e17..f224fb6 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h
+++ b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h
@@ -104,7 +104,6 @@ terms listed above has been obtained from the copyright holder.
; INCLUDES
----------------------------------------------------------------------------*/
#include "typedef.h"
-#include "mode.h"
#include "frame_type_3gpp.h"
/*--------------------------------------------------------------------------*/
diff --git a/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h b/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h
index 8f54ee8..dc64d67 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h
+++ b/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h
@@ -87,6 +87,7 @@ terms listed above has been obtained from the copyright holder.
#include "gsm_amr_typedefs.h"
#include "frame_type_3gpp.h"
+#include "amrdecode.h"
/*--------------------------------------------------------------------------*/
#ifdef __cplusplus
@@ -136,19 +137,6 @@ extern "C"
Word8 *id);
/*
- * AMRDecode steps into the part of the library that decodes the raw data
- * speech bits for the decoding process. It returns the address offset of
- * the next frame to be decoded.
- */
- Word16 AMRDecode(
- void *state_data,
- enum Frame_Type_3GPP frame_type,
- UWord8 *speech_bits_ptr,
- Word16 *raw_pcm_buffer,
- Word16 input_format
- );
-
- /*
* This function resets the state memory used by the GSM AMR decoder. This
* function returns zero. It will return negative one if there is an error.
*/
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index 9489457..aaa6731 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -120,6 +120,10 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalGetParameter(
OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -140,6 +144,10 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalGetParameter(
OMX_AUDIO_PARAM_AMRTYPE *amrParams =
(OMX_AUDIO_PARAM_AMRTYPE *)params;
+ if (!isValidOMXParam(amrParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (amrParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -158,6 +166,10 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -188,6 +200,10 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_encoder.amrnb",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -202,6 +218,10 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter(
const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -225,6 +245,10 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter(
OMX_AUDIO_PARAM_AMRTYPE *amrParams =
(OMX_AUDIO_PARAM_AMRTYPE *)params;
+ if (!isValidOMXParam(amrParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (amrParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -252,6 +276,10 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index 91a512d..9d50c4e 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -155,6 +155,10 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalGetParameter(
OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -175,6 +179,10 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalGetParameter(
OMX_AUDIO_PARAM_AMRTYPE *amrParams =
(OMX_AUDIO_PARAM_AMRTYPE *)params;
+ if (!isValidOMXParam(amrParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (amrParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -196,6 +204,10 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -226,6 +238,10 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_encoder.amrwb",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -240,6 +256,10 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter(
const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
(const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -263,6 +283,10 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter(
OMX_AUDIO_PARAM_AMRTYPE *amrParams =
(OMX_AUDIO_PARAM_AMRTYPE *)params;
+ if (!isValidOMXParam(amrParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (amrParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -299,6 +323,10 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
index e63a55a..d36f455 100644
--- a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -222,14 +222,18 @@ static_vo Word16 shl (Word16 var1, Word16 var2)
}
else
{
- result = (Word32) var1 *((Word32) 1 << var2);
- if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+ if (var2 > 15 && var1 != 0)
{
var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);
}
else
{
- var_out = extract_l (result);
+ result = (Word32) var1 *((Word32) 1 << var2);
+ if ((result != (Word32) ((Word16) result))) {
+ var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);
+ } else {
+ var_out = extract_l (result);
+ }
}
}
return (var_out);
diff --git a/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
index c7c9279..dbb94c6 100644
--- a/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
+++ b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
@@ -93,7 +93,7 @@ void ACELP_2t64_fx(
#endif
Isqrt_n(&s, &exp);
- k_dn = vo_round(L_shl(s, (exp + 8))); /* k_dn = 256..4096 */
+ k_dn = voround(L_shl(s, (exp + 8))); /* k_dn = 256..4096 */
k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */
/* mix normalized cn[] and dn[] */
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
index b9a9e26..49a89a1 100644
--- a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -257,7 +257,7 @@ void ACELP_4t64_fx(
#endif
Isqrt_n(&s, &exp);
- k_dn = (L_shl(s, (exp + 5 + 3)) + 0x8000) >> 16; /* k_dn = 256..4096 */
+ k_dn = voround(L_shl(s, (exp + 5 + 3))); /* k_dn = 256..4096 */
k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */
/* mix normalized cn[] and dn[] */
@@ -1005,7 +1005,7 @@ void search_ixiy(
for (x = track_x; x < L_SUBFR; x += STEP)
{
ps1 = *ps + dn[x];
- alp1 = alp0 + ((*p0++)<<13);
+ alp1 = L_add(alp0, ((*p0++)<<13));
if (dn2[x] < thres_ix)
{
@@ -1018,7 +1018,7 @@ void search_ixiy(
alp2 = alp2 + ((*p2++)<<14);
alp_16 = extract_h(alp2);
sq = vo_mult(ps2, ps2);
- s = vo_L_mult(alpk, sq) - ((sqk * alp_16)<<1);
+ s = L_sub(vo_L_mult(alpk, sq), L_mult(sqk, alp_16));
if (s > 0)
{
diff --git a/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
index b2aa759..e834396 100644
--- a/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
+++ b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
@@ -55,10 +55,10 @@ void cor_h_x(
p1 = &x[i];
p2 = &h[0];
for (j = i; j < L_SUBFR; j++)
- L_tmp += vo_L_mult(*p1++, *p2++);
+ L_tmp = L_add(L_tmp, vo_L_mult(*p1++, *p2++));
y32[i] = L_tmp;
- L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp: (L_tmp == INT_MIN ? INT_MAX : -L_tmp);
if(L_tmp > L_max)
{
L_max = L_tmp;
@@ -68,10 +68,10 @@ void cor_h_x(
p1 = &x[i+1];
p2 = &h[0];
for (j = i+1; j < L_SUBFR; j++)
- L_tmp += vo_L_mult(*p1++, *p2++);
+ L_tmp = L_add(L_tmp, vo_L_mult(*p1++, *p2++));
y32[i+1] = L_tmp;
- L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp: (L_tmp == INT_MIN ? INT_MAX : -L_tmp);
if(L_tmp > L_max1)
{
L_max1 = L_tmp;
@@ -81,10 +81,10 @@ void cor_h_x(
p1 = &x[i+2];
p2 = &h[0];
for (j = i+2; j < L_SUBFR; j++)
- L_tmp += vo_L_mult(*p1++, *p2++);
+ L_tmp = L_add(L_tmp, vo_L_mult(*p1++, *p2++));
y32[i+2] = L_tmp;
- L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp: (L_tmp == INT_MIN ? INT_MAX : -L_tmp);
if(L_tmp > L_max2)
{
L_max2 = L_tmp;
@@ -94,17 +94,23 @@ void cor_h_x(
p1 = &x[i+3];
p2 = &h[0];
for (j = i+3; j < L_SUBFR; j++)
- L_tmp += vo_L_mult(*p1++, *p2++);
+ L_tmp = L_add(L_tmp, vo_L_mult(*p1++, *p2++));
y32[i+3] = L_tmp;
- L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp: (L_tmp == INT_MIN ? INT_MAX : -L_tmp);
if(L_tmp > L_max3)
{
L_max3 = L_tmp;
}
}
/* tot += 3*max / 8 */
- L_max = ((L_max + L_max1 + L_max2 + L_max3) >> 2);
+ if (L_max > INT_MAX - L_max1 ||
+ L_max + L_max1 > INT_MAX - L_max2 ||
+ L_max + L_max1 + L_max2 > INT_MAX - L_max3) {
+ L_max = INT_MAX >> 2;
+ } else {
+ L_max = ((L_max + L_max1 + L_max2 + L_max3) >> 2);
+ }
L_tot = vo_L_add(L_tot, L_max); /* +max/4 */
L_tot = vo_L_add(L_tot, (L_max >> 1)); /* +max/8 */
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index fa6ec40..cce6d15 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -370,6 +370,10 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
(OMX_VIDEO_PARAM_BITRATETYPE *) params;
+ if (!isValidOMXParam(bitRate)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (bitRate->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -384,6 +388,10 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
OMX_VIDEO_PARAM_AVCTYPE *avcParams =
(OMX_VIDEO_PARAM_AVCTYPE *)params;
+ if (!isValidOMXParam(avcParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (avcParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -427,6 +435,10 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
(OMX_VIDEO_PARAM_BITRATETYPE *) params;
+ if (!isValidOMXParam(bitRate)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (bitRate->nPortIndex != 1 ||
bitRate->eControlRate != OMX_Video_ControlRateVariable) {
return OMX_ErrorUndefined;
@@ -441,6 +453,10 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
OMX_VIDEO_PARAM_AVCTYPE *avcType =
(OMX_VIDEO_PARAM_AVCTYPE *)params;
+ if (!isValidOMXParam(avcType)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (avcType->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
index 0b8d9e2..d0bbee2 100644
--- a/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
+++ b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
@@ -23,19 +23,6 @@
#define PREF_16_VEC 129 /* 1MV bias versus 4MVs*/
-const static int distance_tab[9][9] = /* [hp_guess][k] */
-{
- {0, 1, 1, 1, 1, 1, 1, 1, 1},
- {1, 0, 1, 2, 3, 4, 3, 2, 1},
- {1, 0, 0, 0, 1, 2, 3, 2, 1},
- {1, 2, 1, 0, 1, 2, 3, 4, 3},
- {1, 2, 1, 0, 0, 0, 1, 2, 3},
- {1, 4, 3, 2, 1, 0, 1, 2, 3},
- {1, 2, 3, 2, 1, 0, 0, 0, 1},
- {1, 2, 3, 4, 3, 2, 1, 0, 1},
- {1, 0, 1, 2, 3, 2, 1, 0, 0}
-};
-
#define CLIP_RESULT(x) if((uint)x > 0xFF){ \
x = 0xFF & (~(x>>31));}
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index afbe230..2130ccf 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -381,7 +381,7 @@ void SoftAVC::onReset() {
resetPlugin();
}
-void SoftAVC::setDecodeArgs(
+bool SoftAVC::setDecodeArgs(
ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
@@ -389,7 +389,6 @@ void SoftAVC::setDecodeArgs(
size_t timeStampIx) {
size_t sizeY = outputBufferWidth() * outputBufferHeight();
size_t sizeUV;
- uint8_t *pBuf;
ps_dec_ip->u4_size = sizeof(ivd_video_decode_ip_t);
ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
@@ -409,22 +408,28 @@ void SoftAVC::setDecodeArgs(
ps_dec_ip->u4_num_Bytes = 0;
}
+ sizeUV = sizeY / 4;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
+
+ uint8_t *pBuf;
if (outHeader) {
+ if (outHeader->nAllocLen < sizeY + (sizeUV * 2)) {
+ android_errorWriteLog(0x534e4554, "27569635");
+ return false;
+ }
pBuf = outHeader->pBuffer;
} else {
+ // mFlushOutBuffer always has the right size.
pBuf = mFlushOutBuffer;
}
- sizeUV = sizeY / 4;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
-
ps_dec_ip->s_out_buffer.pu1_bufs[0] = pBuf;
ps_dec_ip->s_out_buffer.pu1_bufs[1] = pBuf + sizeY;
ps_dec_ip->s_out_buffer.pu1_bufs[2] = pBuf + sizeY + sizeUV;
ps_dec_ip->s_out_buffer.u4_num_bufs = 3;
- return;
+ return true;
}
void SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
/* Once the output buffers are flushed, ignore any buffers that are held in decoder */
@@ -573,7 +578,12 @@ void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
WORD32 timeDelay, timeTaken;
size_t sizeY, sizeUV;
- setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
+ if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
+ ALOGE("Decoder arg setup failed");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
// If input dump is enabled, then write to file
DUMP_TO_FILE(mInFile, s_dec_ip.pv_stream_buffer, s_dec_ip.u4_num_Bytes);
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.h b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
index 9dcabb4..c710c76 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.h
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
@@ -109,7 +109,7 @@ private:
status_t resetPlugin();
- void setDecodeArgs(
+ bool setDecodeArgs(
ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 387d17d..e4e8fd7 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -926,6 +926,10 @@ OMX_ERRORTYPE SoftAVC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params)
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
(OMX_VIDEO_PARAM_BITRATETYPE *)params;
+ if (!isValidOMXParam(bitRate)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (bitRate->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -939,6 +943,10 @@ OMX_ERRORTYPE SoftAVC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params)
{
OMX_VIDEO_PARAM_AVCTYPE *avcParams = (OMX_VIDEO_PARAM_AVCTYPE *)params;
+ if (!isValidOMXParam(avcParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (avcParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -976,14 +984,24 @@ OMX_ERRORTYPE SoftAVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR p
switch (indexFull) {
case OMX_IndexParamVideoBitrate:
{
- return internalSetBitrateParams(
- (const OMX_VIDEO_PARAM_BITRATETYPE *)params);
+ OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
+ (OMX_VIDEO_PARAM_BITRATETYPE *)params;
+
+ if (!isValidOMXParam(bitRate)) {
+ return OMX_ErrorBadParameter;
+ }
+
+ return internalSetBitrateParams(bitRate);
}
case OMX_IndexParamVideoAvc:
{
OMX_VIDEO_PARAM_AVCTYPE *avcType = (OMX_VIDEO_PARAM_AVCTYPE *)params;
+ if (!isValidOMXParam(avcType)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (avcType->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -1035,6 +1053,10 @@ OMX_ERRORTYPE SoftAVC::setConfig(
OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
(OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params;
+ if (!isValidOMXParam(params)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorBadPortIndex;
}
@@ -1048,6 +1070,10 @@ OMX_ERRORTYPE SoftAVC::setConfig(
OMX_VIDEO_CONFIG_BITRATETYPE *params =
(OMX_VIDEO_CONFIG_BITRATETYPE *)_params;
+ if (!isValidOMXParam(params)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorBadPortIndex;
}
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 9edffd2..caceda9 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -159,6 +159,10 @@ OMX_ERRORTYPE SoftFlacEncoder::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -180,6 +184,11 @@ OMX_ERRORTYPE SoftFlacEncoder::internalGetParameter(
case OMX_IndexParamAudioFlac:
{
OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params;
+
+ if (!isValidOMXParam(flacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
flacParams->nCompressionLevel = mCompressionLevel;
flacParams->nChannels = mNumChannels;
flacParams->nSampleRate = mSampleRate;
@@ -199,6 +208,10 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamAudioPcm)");
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
ALOGE("SoftFlacEncoder::internalSetParameter() Error #1");
return OMX_ErrorUndefined;
@@ -221,6 +234,10 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_encoder.flac",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -236,6 +253,11 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
{
// used only for setting the compression level
OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params;
+
+ if (!isValidOMXParam(flacParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
mCompressionLevel = flacParams->nCompressionLevel; // range clamping done inside encoder
return OMX_ErrorNone;
}
@@ -245,6 +267,10 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
OMX_PARAM_PORTDEFINITIONTYPE *defParams =
(OMX_PARAM_PORTDEFINITIONTYPE *)params;
+ if (!isValidOMXParam(defParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (defParams->nPortIndex == 0) {
if (defParams->nBufferSize > kMaxInputBufferSize) {
ALOGE("Input buffer size must be at most %d bytes",
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 015515e..c8277de 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -110,6 +110,10 @@ OMX_ERRORTYPE SoftG711::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -148,6 +152,10 @@ OMX_ERRORTYPE SoftG711::internalSetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -170,6 +178,10 @@ OMX_ERRORTYPE SoftG711::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (mIsMLaw) {
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.g711mlaw",
@@ -228,6 +240,15 @@ void SoftG711::onQueueFilled(OMX_U32 /* portIndex */) {
mSignalledError = true;
}
+ if (inHeader->nFilledLen * sizeof(int16_t) > outHeader->nAllocLen) {
+ ALOGE("output buffer too small (%d).", outHeader->nAllocLen);
+ android_errorWriteLog(0x534e4554, "27793163");
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
const uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset;
if (mIsMLaw) {
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index bd01a1a..04d5a33 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -110,6 +110,10 @@ OMX_ERRORTYPE SoftGSM::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -141,6 +145,10 @@ OMX_ERRORTYPE SoftGSM::internalSetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -161,6 +169,10 @@ OMX_ERRORTYPE SoftGSM::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.gsm",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -216,6 +228,14 @@ void SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) {
mSignalledError = true;
}
+ if (outHeader->nAllocLen < (inHeader->nFilledLen / kMSGSMFrameSize) * 320) {
+ ALOGE("output buffer is not large enough (%d).", outHeader->nAllocLen);
+ android_errorWriteLog(0x534e4554, "27793367");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset;
int n = mSignalledError ? 0 : DecodeGSM(mGsm,
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index e601125..1dac868 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -343,14 +343,13 @@ void SoftHEVC::onReset() {
resetPlugin();
}
-void SoftHEVC::setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip,
+bool SoftHEVC::setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
OMX_BUFFERHEADERTYPE *outHeader,
size_t timeStampIx) {
size_t sizeY = outputBufferWidth() * outputBufferHeight();
size_t sizeUV;
- uint8_t *pBuf;
ps_dec_ip->u4_size = sizeof(ivd_video_decode_ip_t);
ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
@@ -370,22 +369,28 @@ void SoftHEVC::setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip,
ps_dec_ip->u4_num_Bytes = 0;
}
+ sizeUV = sizeY / 4;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
+
+ uint8_t *pBuf;
if (outHeader) {
+ if (outHeader->nAllocLen < sizeY + (sizeUV * 2)) {
+ android_errorWriteLog(0x534e4554, "27569635");
+ return false;
+ }
pBuf = outHeader->pBuffer;
} else {
+ // mFlushOutBuffer always has the right size.
pBuf = mFlushOutBuffer;
}
- sizeUV = sizeY / 4;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
-
ps_dec_ip->s_out_buffer.pu1_bufs[0] = pBuf;
ps_dec_ip->s_out_buffer.pu1_bufs[1] = pBuf + sizeY;
ps_dec_ip->s_out_buffer.pu1_bufs[2] = pBuf + sizeY + sizeUV;
ps_dec_ip->s_out_buffer.u4_num_bufs = 3;
- return;
+ return true;
}
void SoftHEVC::onPortFlushCompleted(OMX_U32 portIndex) {
/* Once the output buffers are flushed, ignore any buffers that are held in decoder */
@@ -439,6 +444,9 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) {
if (NULL == mCodecCtx) {
if (OK != initDecoder()) {
+ ALOGE("Failed to initialize decoder");
+ notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+ mSignalledError = true;
return;
}
}
@@ -520,7 +528,12 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) {
WORD32 timeDelay, timeTaken;
size_t sizeY, sizeUV;
- setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
+ if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
+ ALOGE("Decoder arg setup failed");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
GETTIME(&mTimeStart, NULL);
/* Compute time elapsed between end of previous decode()
@@ -530,6 +543,25 @@ 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);
+ bool unsupportedResolution =
+ (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
+
+ /* Check for unsupported dimensions */
+ if (unsupportedResolution) {
+ ALOGE("Unsupported resolution : %dx%d", mWidth, mHeight);
+ notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & 0xFF));
+ if (allocationFailed) {
+ ALOGE("Allocation failure in decoder");
+ notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
GETTIME(&mTimeEnd, NULL);
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.h b/media/libstagefright/codecs/hevcdec/SoftHEVC.h
index 21bb99e..943edfd 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.h
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.h
@@ -106,7 +106,7 @@ private:
status_t resetDecoder();
status_t resetPlugin();
- void setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip,
+ bool setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
OMX_BUFFERHEADERTYPE *outHeader,
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 0c1a149..1dd631a 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -210,8 +210,17 @@ void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) {
PortInfo *port = editPortInfo(1);
OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader;
+ OMX_U32 yFrameSize = sizeof(uint8) * mHandle->size;
+ if ((outHeader->nAllocLen < yFrameSize) ||
+ (outHeader->nAllocLen - yFrameSize < yFrameSize / 2)) {
+ ALOGE("Too small output buffer for reference frame: %lu bytes",
+ (unsigned long)outHeader->nAllocLen);
+ android_errorWriteLog(0x534e4554, "30033990");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
PVSetReferenceYUV(mHandle, outHeader->pBuffer);
-
mFramesConfigured = true;
}
@@ -229,6 +238,23 @@ void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) {
int32_t bufferSize = inHeader->nFilledLen;
int32_t tmp = bufferSize;
+ OMX_U32 frameSize;
+ OMX_U64 yFrameSize = (OMX_U64)mWidth * (OMX_U64)mHeight;
+ if (yFrameSize > ((OMX_U64)UINT32_MAX / 3) * 2) {
+ ALOGE("Frame size too large");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+ frameSize = (OMX_U32)(yFrameSize + (yFrameSize / 2));
+
+ if (outHeader->nAllocLen < frameSize) {
+ android_errorWriteLog(0x534e4554, "27833616");
+ ALOGE("Insufficient output buffer size");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
// The PV decoder is lying to us, sometimes it'll claim to only have
// consumed a subset of the buffer when it clearly consumed all of it.
// ignore whatever it says...
@@ -272,7 +298,7 @@ void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) {
++mInputBufferCount;
outHeader->nOffset = 0;
- outHeader->nFilledLen = (mWidth * mHeight * 3) / 2;
+ outHeader->nFilledLen = frameSize;
List<BufferInfo *>::iterator it = outQueue.begin();
while ((*it)->mHeader != outHeader) {
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index f2a4e65..2eb51c9 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -116,6 +116,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() {
ALOGE("Failed to get default encoding parameters");
return OMX_ErrorUndefined;
}
+ if (mFramerate == 0) {
+ ALOGE("Framerate should not be 0");
+ return OMX_ErrorUndefined;
+ }
mEncParams->encMode = mEncodeMode;
mEncParams->encWidth[0] = mWidth;
mEncParams->encHeight[0] = mHeight;
@@ -232,6 +236,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
(OMX_VIDEO_PARAM_BITRATETYPE *) params;
+ if (!isValidOMXParam(bitRate)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (bitRate->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -246,6 +254,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
OMX_VIDEO_PARAM_H263TYPE *h263type =
(OMX_VIDEO_PARAM_H263TYPE *)params;
+ if (!isValidOMXParam(h263type)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (h263type->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -267,6 +279,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
OMX_VIDEO_PARAM_MPEG4TYPE *mpeg4type =
(OMX_VIDEO_PARAM_MPEG4TYPE *)params;
+ if (!isValidOMXParam(mpeg4type)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (mpeg4type->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -301,6 +317,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
(OMX_VIDEO_PARAM_BITRATETYPE *) params;
+ if (!isValidOMXParam(bitRate)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (bitRate->nPortIndex != 1 ||
bitRate->eControlRate != OMX_Video_ControlRateVariable) {
return OMX_ErrorUndefined;
@@ -315,6 +335,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
OMX_VIDEO_PARAM_H263TYPE *h263type =
(OMX_VIDEO_PARAM_H263TYPE *)params;
+ if (!isValidOMXParam(h263type)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (h263type->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -337,6 +361,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
OMX_VIDEO_PARAM_MPEG4TYPE *mpeg4type =
(OMX_VIDEO_PARAM_MPEG4TYPE *)params;
+ if (!isValidOMXParam(mpeg4type)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (mpeg4type->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 4c4da60..005956d 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -122,6 +122,17 @@ void SoftMP3::initDecoder() {
mIsFirst = true;
}
+void *SoftMP3::memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len) {
+ if (len > outHeader->nAllocLen) {
+ ALOGE("memset buffer too small: got %u, expected %zu", outHeader->nAllocLen, len);
+ android_errorWriteLog(0x534e4554, "29422022");
+ notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL);
+ mSignalledError = true;
+ return NULL;
+ }
+ return memset(outHeader->pBuffer, c, len);
+}
+
OMX_ERRORTYPE SoftMP3::internalGetParameter(
OMX_INDEXTYPE index, OMX_PTR params) {
switch (index) {
@@ -130,6 +141,10 @@ OMX_ERRORTYPE SoftMP3::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -153,6 +168,10 @@ OMX_ERRORTYPE SoftMP3::internalGetParameter(
OMX_AUDIO_PARAM_MP3TYPE *mp3Params =
(OMX_AUDIO_PARAM_MP3TYPE *)params;
+ if (!isValidOMXParam(mp3Params)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (mp3Params->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
@@ -178,6 +197,10 @@ OMX_ERRORTYPE SoftMP3::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.mp3",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -192,6 +215,10 @@ OMX_ERRORTYPE SoftMP3::internalSetParameter(
const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -262,6 +289,14 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
mConfig->inputBufferUsedLength = 0;
mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
+ if ((int32)outHeader->nAllocLen < mConfig->outputFrameSize) {
+ ALOGE("input buffer too small: got %u, expected %u",
+ outHeader->nAllocLen, mConfig->outputFrameSize);
+ android_errorWriteLog(0x534e4554, "27793371");
+ notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL);
+ mSignalledError = true;
+ return;
+ }
mConfig->pOutputBuffer =
reinterpret_cast<int16_t *>(outHeader->pBuffer);
@@ -294,7 +329,10 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
outHeader->nOffset = 0;
outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
- memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
+ if (!memsetSafe(outHeader, 0, outHeader->nFilledLen)) {
+ return;
+ }
+
}
outHeader->nFlags = OMX_BUFFERFLAG_EOS;
mSignalledOutputEos = true;
@@ -306,9 +344,9 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
// if mIsFirst is true as we may not have a valid
// mConfig->samplingRate and mConfig->num_channels?
ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence");
- memset(outHeader->pBuffer,
- 0,
- mConfig->outputFrameSize * sizeof(int16_t));
+ if (!memsetSafe(outHeader, 0, mConfig->outputFrameSize * sizeof(int16_t))) {
+ return;
+ }
if (inHeader) {
mConfig->inputBufferUsedLength = inHeader->nFilledLen;
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h
index c769795..5b6af88 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.h
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h
@@ -75,6 +75,7 @@ private:
void initPorts();
void initDecoder();
+ void *memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len);
DISALLOW_EVIL_CONSTRUCTORS(SoftMP3);
};
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 4307c4e..e134d38 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -466,7 +466,7 @@ OMX_ERRORTYPE SoftMPEG2::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR
return ret;
}
-void SoftMPEG2::setDecodeArgs(
+bool SoftMPEG2::setDecodeArgs(
ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
@@ -474,7 +474,6 @@ void SoftMPEG2::setDecodeArgs(
size_t timeStampIx) {
size_t sizeY = outputBufferWidth() * outputBufferHeight();
size_t sizeUV;
- uint8_t *pBuf;
ps_dec_ip->u4_size = sizeof(ivd_video_decode_ip_t);
ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
@@ -494,22 +493,28 @@ void SoftMPEG2::setDecodeArgs(
ps_dec_ip->u4_num_Bytes = 0;
}
+ sizeUV = sizeY / 4;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
+ ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
+
+ uint8_t *pBuf;
if (outHeader) {
+ if (outHeader->nAllocLen < sizeY + (sizeUV * 2)) {
+ android_errorWriteLog(0x534e4554, "27569635");
+ return false;
+ }
pBuf = outHeader->pBuffer;
} else {
+ // mFlushOutBuffer always has the right size.
pBuf = mFlushOutBuffer;
}
- sizeUV = sizeY / 4;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
-
ps_dec_ip->s_out_buffer.pu1_bufs[0] = pBuf;
ps_dec_ip->s_out_buffer.pu1_bufs[1] = pBuf + sizeY;
ps_dec_ip->s_out_buffer.pu1_bufs[2] = pBuf + sizeY + sizeUV;
ps_dec_ip->s_out_buffer.u4_num_bufs = 3;
- return;
+ return true;
}
void SoftMPEG2::onPortFlushCompleted(OMX_U32 portIndex) {
/* Once the output buffers are flushed, ignore any buffers that are held in decoder */
@@ -622,7 +627,11 @@ void SoftMPEG2::onQueueFilled(OMX_U32 portIndex) {
WORD32 timeDelay, timeTaken;
size_t sizeY, sizeUV;
- setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
+ if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
+ ALOGE("Decoder arg setup failed");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
// If input dump is enabled, then write to file
DUMP_TO_FILE(mInFile, s_dec_ip.pv_stream_buffer, s_dec_ip.u4_num_Bytes);
@@ -665,9 +674,9 @@ void SoftMPEG2::onQueueFilled(OMX_U32 portIndex) {
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);
+ if (setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
+ ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
+ }
return;
}
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
index a625e08..f48b70b 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
@@ -117,7 +117,7 @@ private:
status_t resetPlugin();
status_t reInitDecoder();
- void setDecodeArgs(
+ bool setDecodeArgs(
ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index e161fb8..444a7fc 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -102,7 +102,6 @@ status_t SoftVPX::destroyDecoder() {
}
bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset) {
- List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
BufferInfo *outInfo = NULL;
OMX_BUFFERHEADERTYPE *outHeader = NULL;
@@ -149,15 +148,18 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por
outHeader->nFlags = 0;
outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
outHeader->nTimeStamp = *(OMX_TICKS *)mImg->user_priv;
-
- uint8_t *dst = outHeader->pBuffer;
- const uint8_t *srcY = (const uint8_t *)mImg->planes[VPX_PLANE_Y];
- const uint8_t *srcU = (const uint8_t *)mImg->planes[VPX_PLANE_U];
- const uint8_t *srcV = (const uint8_t *)mImg->planes[VPX_PLANE_V];
- size_t srcYStride = mImg->stride[VPX_PLANE_Y];
- size_t srcUStride = mImg->stride[VPX_PLANE_U];
- size_t srcVStride = mImg->stride[VPX_PLANE_V];
- copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
+ if (outputBufferSafe(outHeader)) {
+ uint8_t *dst = outHeader->pBuffer;
+ const uint8_t *srcY = (const uint8_t *)mImg->planes[VPX_PLANE_Y];
+ const uint8_t *srcU = (const uint8_t *)mImg->planes[VPX_PLANE_U];
+ const uint8_t *srcV = (const uint8_t *)mImg->planes[VPX_PLANE_V];
+ size_t srcYStride = mImg->stride[VPX_PLANE_Y];
+ size_t srcUStride = mImg->stride[VPX_PLANE_U];
+ size_t srcVStride = mImg->stride[VPX_PLANE_V];
+ copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
+ } else {
+ outHeader->nFilledLen = 0;
+ }
mImg = NULL;
outInfo->mOwnedByUs = false;
@@ -185,6 +187,25 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por
return true;
}
+bool SoftVPX::outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader) {
+ uint32_t width = outputBufferWidth();
+ uint32_t height = outputBufferHeight();
+ uint64_t nFilledLen = width;
+ nFilledLen *= height;
+ if (nFilledLen > UINT32_MAX / 3) {
+ ALOGE("b/29421675, nFilledLen overflow %llu w %u h %u",
+ (unsigned long long)nFilledLen, width, height);
+ android_errorWriteLog(0x534e4554, "29421675");
+ return false;
+ } else if (outHeader->nAllocLen < outHeader->nFilledLen) {
+ ALOGE("b/27597103, buffer too small");
+ android_errorWriteLog(0x534e4554, "27597103");
+ return false;
+ }
+
+ return true;
+}
+
void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
return;
@@ -193,7 +214,6 @@ void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
bool EOSseen = false;
- vpx_codec_err_t err;
bool portWillReset = false;
while ((mEOSStatus == INPUT_EOS_SEEN || !inQueue.empty())
@@ -217,8 +237,6 @@ void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
mTimeStamps[mTimeStampIdx] = inHeader->nTimeStamp;
- BufferInfo *outInfo = *outQueue.begin();
- OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
mEOSStatus = INPUT_EOS_SEEN;
EOSseen = true;
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.h b/media/libstagefright/codecs/on2/dec/SoftVPX.h
index 8ccbae2..84cf79c 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.h
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.h
@@ -66,6 +66,7 @@ private:
status_t initDecoder();
status_t destroyDecoder();
bool outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset);
+ bool outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader);
DISALLOW_EVIL_CONSTRUCTORS(SoftVPX);
};
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index 410f9d0..5c950c7 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -368,20 +368,24 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
OMX_VIDEO_PARAM_BITRATETYPE *bitrate =
(OMX_VIDEO_PARAM_BITRATETYPE *)param;
- if (bitrate->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
+ if (!isValidOMXParam(bitrate)) {
+ return OMX_ErrorBadParameter;
+ }
- bitrate->nTargetBitrate = mBitrate;
+ if (bitrate->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
- if (mBitrateControlMode == VPX_VBR) {
- bitrate->eControlRate = OMX_Video_ControlRateVariable;
- } else if (mBitrateControlMode == VPX_CBR) {
- bitrate->eControlRate = OMX_Video_ControlRateConstant;
- } else {
- return OMX_ErrorUnsupportedSetting;
- }
- return OMX_ErrorNone;
+ bitrate->nTargetBitrate = mBitrate;
+
+ if (mBitrateControlMode == VPX_VBR) {
+ bitrate->eControlRate = OMX_Video_ControlRateVariable;
+ } else if (mBitrateControlMode == VPX_CBR) {
+ bitrate->eControlRate = OMX_Video_ControlRateConstant;
+ } else {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ return OMX_ErrorNone;
}
// VP8 specific parameters that use extension headers
@@ -389,33 +393,41 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
OMX_VIDEO_PARAM_VP8TYPE *vp8Params =
(OMX_VIDEO_PARAM_VP8TYPE *)param;
- if (vp8Params->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
+ if (!isValidOMXParam(vp8Params)) {
+ return OMX_ErrorBadParameter;
+ }
+
+ if (vp8Params->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
- vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain;
- vp8Params->eLevel = mLevel;
- vp8Params->nDCTPartitions = mDCTPartitions;
- vp8Params->bErrorResilientMode = mErrorResilience;
- return OMX_ErrorNone;
+ vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain;
+ vp8Params->eLevel = mLevel;
+ vp8Params->nDCTPartitions = mDCTPartitions;
+ vp8Params->bErrorResilientMode = mErrorResilience;
+ return OMX_ErrorNone;
}
case OMX_IndexParamVideoAndroidVp8Encoder: {
OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams =
(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param;
- if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
+ if (!isValidOMXParam(vp8AndroidParams)) {
+ return OMX_ErrorBadParameter;
+ }
- vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval;
- vp8AndroidParams->eTemporalPattern = mTemporalPatternType;
- vp8AndroidParams->nTemporalLayerCount = mTemporalLayers;
- vp8AndroidParams->nMinQuantizer = mMinQuantizer;
- vp8AndroidParams->nMaxQuantizer = mMaxQuantizer;
- memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio,
- mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio));
- return OMX_ErrorNone;
+ if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval;
+ vp8AndroidParams->eTemporalPattern = mTemporalPatternType;
+ vp8AndroidParams->nTemporalLayerCount = mTemporalLayers;
+ vp8AndroidParams->nMinQuantizer = mMinQuantizer;
+ vp8AndroidParams->nMaxQuantizer = mMaxQuantizer;
+ memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio,
+ mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio));
+ return OMX_ErrorNone;
}
default:
@@ -430,17 +442,38 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
const int32_t indexFull = index;
switch (indexFull) {
- case OMX_IndexParamVideoBitrate:
- return internalSetBitrateParams(
- (const OMX_VIDEO_PARAM_BITRATETYPE *)param);
+ case OMX_IndexParamVideoBitrate: {
+ const OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
+ (const OMX_VIDEO_PARAM_BITRATETYPE*) param;
+
+ if (!isValidOMXParam(bitRate)) {
+ return OMX_ErrorBadParameter;
+ }
- case OMX_IndexParamVideoVp8:
- return internalSetVp8Params(
- (const OMX_VIDEO_PARAM_VP8TYPE *)param);
+ return internalSetBitrateParams(bitRate);
+ }
- case OMX_IndexParamVideoAndroidVp8Encoder:
- return internalSetAndroidVp8Params(
- (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
+ case OMX_IndexParamVideoVp8: {
+ const OMX_VIDEO_PARAM_VP8TYPE *vp8Params =
+ (const OMX_VIDEO_PARAM_VP8TYPE*) param;
+
+ if (!isValidOMXParam(vp8Params)) {
+ return OMX_ErrorBadParameter;
+ }
+
+ return internalSetVp8Params(vp8Params);
+ }
+
+ case OMX_IndexParamVideoAndroidVp8Encoder: {
+ const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams =
+ (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE*) param;
+
+ if (!isValidOMXParam(vp8AndroidParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
+ return internalSetAndroidVp8Params(vp8AndroidParams);
+ }
default:
return SoftVideoEncoderOMXComponent::internalSetParameter(index, param);
@@ -455,6 +488,10 @@ OMX_ERRORTYPE SoftVPXEncoder::setConfig(
OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
(OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params;
+ if (!isValidOMXParam(params)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorBadPortIndex;
}
@@ -468,6 +505,10 @@ OMX_ERRORTYPE SoftVPXEncoder::setConfig(
OMX_VIDEO_CONFIG_BITRATETYPE *params =
(OMX_VIDEO_CONFIG_BITRATETYPE *)_params;
+ if (!isValidOMXParam(params)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorBadPortIndex;
}
@@ -688,9 +729,10 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
const uint8_t *source =
inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
+ size_t frameSize = mWidth * mHeight * 3 / 2;
if (mInputDataIsMeta) {
source = extractGraphicBuffer(
- mConversionBuffer, mWidth * mHeight * 3 / 2,
+ mConversionBuffer, frameSize,
source, inputBufferHeader->nFilledLen,
mWidth, mHeight);
if (source == NULL) {
@@ -698,11 +740,21 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
return;
}
- } else if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
- ConvertYUV420SemiPlanarToYUV420Planar(
- source, mConversionBuffer, mWidth, mHeight);
+ } else {
+ if (inputBufferHeader->nFilledLen < frameSize) {
+ android_errorWriteLog(0x534e4554, "27569635");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ } else if (inputBufferHeader->nFilledLen > frameSize) {
+ ALOGW("Input buffer contains too many pixels");
+ }
- source = mConversionBuffer;
+ if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
+ ConvertYUV420SemiPlanarToYUV420Planar(
+ source, mConversionBuffer, mWidth, mHeight);
+
+ source = mConversionBuffer;
+ }
}
vpx_image_t raw_frame;
vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
@@ -764,9 +816,14 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts;
outputBufferHeader->nFlags = 0;
if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY)
- outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+ outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
outputBufferHeader->nOffset = 0;
outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz;
+ if (outputBufferHeader->nFilledLen > outputBufferHeader->nAllocLen) {
+ android_errorWriteLog(0x534e4554, "27569635");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
memcpy(outputBufferHeader->pBuffer,
encoded_packet->data.frame.buf,
encoded_packet->data.frame.sz);
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 6b8b395..2f61d12 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -202,7 +202,12 @@ void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) {
}
if (mFirstPicture && !outQueue.empty()) {
- drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
+ if (!drainOneOutputBuffer(mFirstPictureId, mFirstPicture)) {
+ ALOGE("Drain failed");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
delete[] mFirstPicture;
mFirstPicture = NULL;
mFirstPictureId = -1;
@@ -242,15 +247,20 @@ void SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
memcpy(mFirstPicture, data, pictureSize);
}
-void SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
+bool SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
BufferInfo *outInfo = *outQueue.begin();
- outQueue.erase(outQueue.begin());
OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+ OMX_U32 frameSize = mWidth * mHeight * 3 / 2;
+ if (outHeader->nAllocLen - outHeader->nOffset < frameSize) {
+ android_errorWriteLog(0x534e4554, "27833616");
+ return false;
+ }
+ outQueue.erase(outQueue.begin());
OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
outHeader->nTimeStamp = header->nTimeStamp;
outHeader->nFlags = header->nFlags;
- outHeader->nFilledLen = mWidth * mHeight * 3 / 2;
+ outHeader->nFilledLen = frameSize;
uint8_t *dst = outHeader->pBuffer + outHeader->nOffset;
const uint8_t *srcY = data;
@@ -265,6 +275,7 @@ void SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
delete header;
outInfo->mOwnedByUs = false;
notifyFillBufferDone(outHeader);
+ return true;
}
void SoftAVC::drainAllOutputBuffers(bool eos) {
@@ -277,7 +288,12 @@ void SoftAVC::drainAllOutputBuffers(bool eos) {
mHandle, &decodedPicture, eos /* flush */)) {
int32_t picId = decodedPicture.picId;
uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
- drainOneOutputBuffer(picId, data);
+ if (!drainOneOutputBuffer(picId, data)) {
+ ALOGE("Drain failed");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
}
}
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index 069107d..b8c1807 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -71,7 +71,7 @@ private:
status_t initDecoder();
void drainAllOutputBuffers(bool eos);
- void drainOneOutputBuffer(int32_t picId, uint8_t *data);
+ bool drainOneOutputBuffer(int32_t picId, uint8_t *data);
void saveFirstOutputBuffer(int32_t pidId, uint8_t *data);
CropSettingsMode handleCropParams(const H264SwDecInfo& decInfo);
diff --git a/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h b/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h
index fe112bc..9814e73 100644
--- a/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h
+++ b/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h
@@ -161,7 +161,7 @@ extern "C"
void H264SwDecTrace(char *);
/* function prototype for memory allocation */
- void* H264SwDecMalloc(u32 size);
+ void* H264SwDecMalloc(u32 size, u32 num);
/* function prototype for memory free */
void H264SwDecFree(void *ptr);
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
index 91e38b8..1992885 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
@@ -86,7 +86,7 @@ typedef OMX_S16 ARM_BLOCK8x8[64];
/* Alignment operation */
-#define armAlignToBytes(Ptr,N) (Ptr + ( ((N-(int)Ptr)&(N-1)) / sizeof(*Ptr) ))
+#define armAlignToBytes(Ptr,N) (Ptr + ( ((N-(intptr_t)Ptr)&(N-1)) / sizeof(*Ptr) ))
#define armAlignTo2Bytes(Ptr) armAlignToBytes(Ptr,2)
#define armAlignTo4Bytes(Ptr) armAlignToBytes(Ptr,4)
#define armAlignTo8Bytes(Ptr) armAlignToBytes(Ptr,8)
@@ -98,8 +98,8 @@ typedef OMX_S16 ARM_BLOCK8x8[64];
#define armRetDataErrIf(condition, code) if(condition) { return (code); }
#ifndef ALIGNMENT_DOESNT_MATTER
-#define armIsByteAligned(Ptr,N) ((((int)(Ptr)) % N)==0)
-#define armNotByteAligned(Ptr,N) ((((int)(Ptr)) % N)!=0)
+#define armIsByteAligned(Ptr,N) ((((intptr_t)(Ptr)) % N)==0)
+#define armNotByteAligned(Ptr,N) ((((intptr_t)(Ptr)) % N)!=0)
#else
#define armIsByteAligned(Ptr,N) (1)
#define armNotByteAligned(Ptr,N) (0)
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
index fbb97e2..7304863 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
@@ -86,7 +86,7 @@ typedef OMX_S16 ARM_BLOCK8x8[64];
/* Alignment operation */
-#define armAlignToBytes(Ptr,N) (Ptr + ( ((N-(int)Ptr)&(N-1)) / sizeof(*Ptr) ))
+#define armAlignToBytes(Ptr,N) (Ptr + ( ((N-(intptr_t)Ptr)&(N-1)) / sizeof(*Ptr) ))
#define armAlignTo2Bytes(Ptr) armAlignToBytes(Ptr,2)
#define armAlignTo4Bytes(Ptr) armAlignToBytes(Ptr,4)
#define armAlignTo8Bytes(Ptr) armAlignToBytes(Ptr,8)
@@ -98,8 +98,8 @@ typedef OMX_S16 ARM_BLOCK8x8[64];
#define armRetDataErrIf(condition, code) if(condition) { return (code); }
#ifndef ALIGNMENT_DOESNT_MATTER
-#define armIsByteAligned(Ptr,N) ((((int)(Ptr)) % N)==0)
-#define armNotByteAligned(Ptr,N) ((((int)(Ptr)) % N)!=0)
+#define armIsByteAligned(Ptr,N) ((((intptr_t)(Ptr)) % N)==0)
+#define armNotByteAligned(Ptr,N) ((((intptr_t)(Ptr)) % N)!=0)
#else
#define armIsByteAligned(Ptr,N) (1)
#define armNotByteAligned(Ptr,N) (0)
diff --git a/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c
index dcf2ef6..55c0065 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c
@@ -700,18 +700,21 @@ void H264SwDecTrace(char *string)
library function malloc for allocation of memory.
------------------------------------------------------------------------------*/
-void* H264SwDecMalloc(u32 size)
+void* H264SwDecMalloc(u32 size, u32 num)
{
+ if (size > UINT32_MAX / num) {
+ return NULL;
+ }
#if defined(CHECK_MEMORY_USAGE)
/* Note that if the decoder has to free and reallocate some of the buffers
* the total value will be invalid */
static u32 numBytes = 0;
- numBytes += size;
+ numBytes += size * num;
DEBUG(("Allocated %d bytes, total %d\n", size, numBytes));
#endif
- return malloc(size);
+ return malloc(size * num);
}
/*------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c
index aadc75f..e756a1f 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c
@@ -85,7 +85,7 @@ int main(int argc, char **argv)
rewind(finput);
/* allocate memory for stream buffer, exit if unsuccessful */
- byteStrm = byteStrmStart = (u8 *)H264SwDecMalloc(sizeof(u8)*strmLen);
+ byteStrm = byteStrmStart = (u8 *)H264SwDecMalloc(sizeof(u8), strmLen);
if (byteStrm == NULL)
{
printf("UNABLE TO ALLOCATE MEMORY\n");
@@ -298,9 +298,12 @@ void H264SwDecTrace(char *string)
library function malloc for allocation of memory.
------------------------------------------------------------------------------*/
-void* H264SwDecMalloc(u32 size)
+void* H264SwDecMalloc(u32 size, u32 num)
{
- return malloc(size);
+ if (size > UINT32_MAX / num) {
+ return NULL;
+ }
+ return malloc(size * num);
}
/*------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
index a073dcb..f820dfd 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
@@ -35,6 +35,8 @@
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
+#include <log/log.h>
+
#include <stdlib.h>
#include <string.h>
#include "basetype.h"
@@ -79,8 +81,13 @@ void H264SwDecTrace(char *string) {
UNUSED(string);
}
-void* H264SwDecMalloc(u32 size) {
- return malloc(size);
+void* H264SwDecMalloc(u32 size, u32 num) {
+ if (size > UINT32_MAX / num) {
+ ALOGE("can't allocate %u * %u bytes", size, num);
+ android_errorWriteLog(0x534e4554, "27855419");
+ return NULL;
+ }
+ return malloc(size * num);
}
void H264SwDecFree(void *ptr) {
@@ -144,7 +151,7 @@ H264SwDecRet H264SwDecInit(H264SwDecInst *decInst, u32 noOutputReordering)
return(H264SWDEC_PARAM_ERR);
}
- pDecCont = (decContainer_t *)H264SwDecMalloc(sizeof(decContainer_t));
+ pDecCont = (decContainer_t *)H264SwDecMalloc(sizeof(decContainer_t), 1);
if (pDecCont == NULL)
{
diff --git a/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
index 42170d3..9a386bb 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
@@ -413,9 +413,12 @@ void H264SwDecTrace(char *string)
Function name: H264SwDecmalloc
------------------------------------------------------------------------------*/
-void* H264SwDecMalloc(u32 size)
+void* H264SwDecMalloc(u32 size, u32 num)
{
- return malloc(size);
+ if (size > UINT32_MAX / num) {
+ return NULL;
+ }
+ return malloc(size * num);
}
/*------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c
index a816871..0ac480f 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c
@@ -101,7 +101,7 @@ u32 h264bsdInit(storage_t *pStorage, u32 noOutputReordering)
* specific NEON optimized "memset" for clearing the structure */
size = (sizeof(macroblockLayer_t) + 63) & ~0x3F;
- pStorage->mbLayer = (macroblockLayer_t*)H264SwDecMalloc(size);
+ pStorage->mbLayer = (macroblockLayer_t*)H264SwDecMalloc(size, 1);
if (!pStorage->mbLayer)
return HANTRO_NOK;
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c
index 9517d0a..799bd16 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c
@@ -60,6 +60,7 @@
#include "h264bsd_util.h"
#include "basetype.h"
+#include <log/log.h>
/*------------------------------------------------------------------------------
2. External compiler flags
--------------------------------------------------------------------------------
@@ -998,6 +999,13 @@ u32 h264bsdInitDpb(
ASSERT(maxFrameNum);
ASSERT(dpbSize);
+ // see comment in loop below about size calculation
+ if (picSizeInMbs > (UINT32_MAX - 32 - 15) / 384) {
+ ALOGE("b/28533562");
+ android_errorWriteLog(0x534e4554, "28533562");
+ return(MEMORY_ALLOCATION_ERROR);
+ }
+
dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
dpb->maxRefFrames = MAX(maxRefFrames, 1);
if (noReordering)
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c
index 3234754..ff7a42a 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c
@@ -58,6 +58,10 @@
3. Module defines
------------------------------------------------------------------------------*/
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
/*------------------------------------------------------------------------------
4. Local function prototypes
------------------------------------------------------------------------------*/
@@ -326,9 +330,23 @@ u32 h264bsdActivateParamSets(storage_t *pStorage, u32 ppsId, u32 isIdr)
pStorage->activePps = pStorage->pps[ppsId];
pStorage->activeSpsId = pStorage->activePps->seqParameterSetId;
pStorage->activeSps = pStorage->sps[pStorage->activeSpsId];
- pStorage->picSizeInMbs =
- pStorage->activeSps->picWidthInMbs *
- pStorage->activeSps->picHeightInMbs;
+
+ /* report error before multiplication to prevent integer overflow */
+ if (pStorage->activeSps->picWidthInMbs == 0)
+ {
+ pStorage->picSizeInMbs = 0;
+ }
+ else if (pStorage->activeSps->picHeightInMbs >
+ UINT32_MAX / pStorage->activeSps->picWidthInMbs)
+ {
+ return(MEMORY_ALLOCATION_ERROR);
+ }
+ else
+ {
+ pStorage->picSizeInMbs =
+ pStorage->activeSps->picWidthInMbs *
+ pStorage->activeSps->picHeightInMbs;
+ }
pStorage->currImage->width = pStorage->activeSps->picWidthInMbs;
pStorage->currImage->height = pStorage->activeSps->picHeightInMbs;
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h
index 216ad04..9f0eb7d 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h
@@ -141,7 +141,7 @@
/* macro to allocate memory */
#define ALLOCATE(ptr, count, type) \
{ \
- (ptr) = H264SwDecMalloc((count) * sizeof(type)); \
+ (ptr) = H264SwDecMalloc(sizeof(type), (count)); \
}
/* macro to free allocated memory */
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index cb10bce..2e44ed7 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -134,6 +134,10 @@ OMX_ERRORTYPE SoftOpus::internalGetParameter(
OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
(OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
+ if (!isValidOMXParam(opusParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (opusParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -156,6 +160,10 @@ OMX_ERRORTYPE SoftOpus::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -191,6 +199,10 @@ OMX_ERRORTYPE SoftOpus::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.opus",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -205,6 +217,10 @@ OMX_ERRORTYPE SoftOpus::internalSetParameter(
const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
(const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
+ if (!isValidOMXParam(opusParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (opusParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -442,12 +458,17 @@ void SoftOpus::onQueueFilled(OMX_U32 portIndex) {
const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
const uint32_t size = inHeader->nFilledLen;
+ size_t frameSize = kMaxOpusOutputPacketSizeSamples;
+ if (frameSize > outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels) {
+ frameSize = outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels;
+ android_errorWriteLog(0x534e4554, "27833616");
+ }
int numFrames = opus_multistream_decode(mDecoder,
data,
size,
(int16_t *)outHeader->pBuffer,
- kMaxOpusOutputPacketSizeSamples,
+ frameSize,
0);
if (numFrames < 0) {
ALOGE("opus_multistream_decode returned %d", numFrames);
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index 0d80098..f90c1b3 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -104,6 +104,10 @@ OMX_ERRORTYPE SoftRaw::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -135,6 +139,10 @@ OMX_ERRORTYPE SoftRaw::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.raw",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -149,6 +157,10 @@ OMX_ERRORTYPE SoftRaw::internalSetParameter(
const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 08200c1..7209796 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -131,6 +131,10 @@ OMX_ERRORTYPE SoftVorbis::internalGetParameter(
OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
(OMX_AUDIO_PARAM_VORBISTYPE *)params;
+ if (!isValidOMXParam(vorbisParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (vorbisParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -162,6 +166,10 @@ OMX_ERRORTYPE SoftVorbis::internalGetParameter(
OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
(OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+ if (!isValidOMXParam(pcmParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
@@ -198,6 +206,10 @@ OMX_ERRORTYPE SoftVorbis::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
"audio_decoder.vorbis",
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -212,6 +224,10 @@ OMX_ERRORTYPE SoftVorbis::internalSetParameter(
const OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
(const OMX_AUDIO_PARAM_VORBISTYPE *)params;
+ if (!isValidOMXParam(vorbisParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (vorbisParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
@@ -269,6 +285,12 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
const uint8_t *data = header->pBuffer + header->nOffset;
size_t size = header->nFilledLen;
+ if (size < 7) {
+ ALOGE("Too small input buffer: %zu bytes", size);
+ android_errorWriteLog(0x534e4554, "27833616");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
ogg_buffer buf;
ogg_reference ref;
@@ -374,9 +396,14 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
ALOGW("vorbis_dsp_synthesis returned %d", err);
#endif
} else {
+ size_t numSamplesPerBuffer = kMaxNumSamplesPerBuffer;
+ if (numSamplesPerBuffer > outHeader->nAllocLen / sizeof(int16_t)) {
+ numSamplesPerBuffer = outHeader->nAllocLen / sizeof(int16_t);
+ android_errorWriteLog(0x534e4554, "27833616");
+ }
numFrames = vorbis_dsp_pcmout(
mState, (int16_t *)outHeader->pBuffer,
- (kMaxNumSamplesPerBuffer / mVi->channels));
+ (numSamplesPerBuffer / mVi->channels));
if (numFrames < 0) {
ALOGE("vorbis_dsp_pcmout returned %d", numFrames);
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index d0c8ced..2a861d7 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -266,8 +266,14 @@ std::list<FrameRenderTracker::Info> SoftwareRenderer::render(
uint8_t *dst_y = (uint8_t *)dst;
size_t dst_y_size = buf->stride * buf->height;
+
+#ifdef EXYNOS4_ENHANCEMENTS
+ size_t dst_c_stride = buf->stride / 2;
+ size_t dst_c_size = ALIGN(dst_c_stride, 16) * buf->height / 2;
+#else
size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
size_t dst_c_size = dst_c_stride * buf->height / 2;
+#endif
uint8_t *dst_v = dst_y + dst_y_size;
uint8_t *dst_u = dst_v + dst_c_size;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 52be368..b030e90 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1911,6 +1911,9 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
while (!it.done()) {
size_t length;
const uint8_t *data = it.getData(&length);
+ if (!data) {
+ return ERROR_MALFORMED;
+ }
static const char *kMatchName =
"com.apple.streaming.transportStreamTimestamp";
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 76d65f0..d1fd0d9 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -77,7 +77,10 @@ ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)
mFirstFrameOffset(0),
mVersion(ID3_UNKNOWN),
mRawSize(0) {
- sp<MemorySource> source = new MemorySource(data, size);
+ sp<MemorySource> source = new (std::nothrow) MemorySource(data, size);
+
+ if (source == NULL)
+ return;
mIsValid = parseV2(source, 0);
@@ -543,6 +546,10 @@ void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
n -= skipped;
}
+ if (n <= 0) {
+ return;
+ }
+
if (encoding == 0x00) {
// supposedly ISO 8859-1
id->setTo((const char*)frameData + 1, n);
@@ -556,11 +563,16 @@ void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
const char16_t *framedata = (const char16_t *) (frameData + 1);
char16_t *framedatacopy = NULL;
#if BYTE_ORDER == LITTLE_ENDIAN
- framedatacopy = new char16_t[len];
- for (int i = 0; i < len; i++) {
- framedatacopy[i] = bswap_16(framedata[i]);
+ if (len > 0) {
+ framedatacopy = new (std::nothrow) char16_t[len];
+ if (framedatacopy == NULL) {
+ return;
+ }
+ for (int i = 0; i < len; i++) {
+ framedatacopy[i] = bswap_16(framedata[i]);
+ }
+ framedata = framedatacopy;
}
- framedata = framedatacopy;
#endif
id->setTo(framedata, len);
if (framedatacopy != NULL) {
@@ -573,15 +585,26 @@ void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
const char16_t *framedata = (const char16_t *) (frameData + 1);
char16_t *framedatacopy = NULL;
if (*framedata == 0xfffe) {
- // endianness marker doesn't match host endianness, convert
- framedatacopy = new char16_t[len];
+ // endianness marker != host endianness, convert & skip
+ if (len <= 1) {
+ return; // nothing after the marker
+ }
+ framedatacopy = new (std::nothrow) char16_t[len];
+ if (framedatacopy == NULL) {
+ return;
+ }
for (int i = 0; i < len; i++) {
framedatacopy[i] = bswap_16(framedata[i]);
}
framedata = framedatacopy;
- }
- // If the string starts with an endianness marker, skip it
- if (*framedata == 0xfeff) {
+ // and skip over the marker
+ framedata++;
+ len--;
+ } else if (*framedata == 0xfeff) {
+ // endianness marker == host endianness, skip it
+ if (len <= 1) {
+ return; // nothing after the marker
+ }
framedata++;
len--;
}
@@ -596,12 +619,16 @@ void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
}
if (eightBit) {
// collapse to 8 bit, then let the media scanner client figure out the real encoding
- char *frame8 = new char[len];
- for (int i = 0; i < len; i++) {
- frame8[i] = framedata[i];
+ char *frame8 = new (std::nothrow) char[len];
+ if (frame8 != NULL) {
+ for (int i = 0; i < len; i++) {
+ frame8[i] = framedata[i];
+ }
+ id->setTo(frame8, len);
+ delete [] frame8;
+ } else {
+ id->setTo(framedata, len);
}
- id->setTo(frame8, len);
- delete [] frame8;
} else {
id->setTo(framedata, len);
}
@@ -619,6 +646,11 @@ const uint8_t *ID3::Iterator::getData(size_t *length) const {
return NULL;
}
+ // Prevent integer underflow
+ if (mFrameSize < getHeaderLength()) {
+ return NULL;
+ }
+
*length = mFrameSize - getHeaderLength();
return mFrameData;
@@ -833,6 +865,9 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const {
while (!it.done()) {
size_t size;
const uint8_t *data = it.getData(&size);
+ if (!data) {
+ return NULL;
+ }
if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
uint8_t encoding = data[0];
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index e7c4f6d..b20b2ea 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -81,7 +81,7 @@ public:
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize);
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess);
virtual status_t useGraphicBuffer(
node_id node, OMX_U32 port_index,
@@ -113,7 +113,7 @@ public:
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize);
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess);
virtual status_t freeBuffer(
node_id node, OMX_U32 port_index, buffer_id buffer);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index a19d2b3..5ba0e8f 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -21,6 +21,7 @@
#include "OMX.h"
#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
#include <utils/threads.h>
namespace android {
@@ -71,7 +72,7 @@ struct OMXNodeInstance {
status_t useBuffer(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer, OMX_U32 allottedSize);
+ OMX::buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess);
status_t useGraphicBuffer(
OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
@@ -101,7 +102,7 @@ struct OMXNodeInstance {
status_t allocateBufferWithBackup(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer, OMX_U32 allottedSize);
+ OMX::buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess);
status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer);
@@ -145,6 +146,9 @@ private:
OMX::node_id mNodeID;
OMX_HANDLETYPE mHandle;
sp<IOMXObserver> mObserver;
+ bool mSailed; // configuration is set (no more meta-mode changes)
+ bool mQueriedProhibitedExtensions;
+ SortedVector<OMX_INDEXTYPE> mProhibitedExtensions;
bool mIsSecure;
atomic_bool mDying;
@@ -187,10 +191,12 @@ private:
// For buffer id management
OMX::buffer_id makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader);
- OMX_BUFFERHEADERTYPE *findBufferHeader(OMX::buffer_id buffer);
+ OMX_BUFFERHEADERTYPE *findBufferHeader(OMX::buffer_id buffer, OMX_U32 portIndex);
OMX::buffer_id findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader);
void invalidateBufferID(OMX::buffer_id buffer);
+ bool isProhibitedIndex_l(OMX_INDEXTYPE index);
+
status_t useGraphicBuffer2_l(
OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
OMX::buffer_id *buffer);
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 460492b..552eef7 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -95,6 +95,9 @@ private:
static const uint32_t kSampleSizeType32;
static const uint32_t kSampleSizeTypeCompact;
+ // Limit the total size of all internal tables to 200MiB.
+ static const size_t kMaxTotalSize = 200 * (1 << 20);
+
sp<DataSource> mDataSource;
Mutex mLock;
@@ -110,8 +113,9 @@ private:
uint32_t mDefaultSampleSize;
uint32_t mNumSampleSizes;
+ bool mHasTimeToSample;
uint32_t mTimeToSampleCount;
- uint32_t *mTimeToSample;
+ uint32_t* mTimeToSample;
struct SampleTimeEntry {
uint32_t mSampleIndex;
@@ -137,6 +141,9 @@ private:
};
SampleToChunkEntry *mSampleToChunkEntries;
+ // Approximate size of all tables combined.
+ uint64_t mTotalSize;
+
friend struct SampleIterator;
// normally we don't round
diff --git a/media/libstagefright/include/SoftOMXComponent.h b/media/libstagefright/include/SoftOMXComponent.h
index a808611..3ab6f88 100644
--- a/media/libstagefright/include/SoftOMXComponent.h
+++ b/media/libstagefright/include/SoftOMXComponent.h
@@ -168,6 +168,22 @@ private:
DISALLOW_EVIL_CONSTRUCTORS(SoftOMXComponent);
};
+template<typename T>
+bool isValidOMXParam(T *a) {
+ static_assert(offsetof(typeof(*a), nSize) == 0, "nSize not at offset 0");
+ static_assert(std::is_same< decltype(a->nSize), OMX_U32>::value, "nSize has wrong type");
+ static_assert(offsetof(typeof(*a), nVersion) == 4, "nVersion not at offset 4");
+ static_assert(std::is_same< decltype(a->nVersion), OMX_VERSIONTYPE>::value,
+ "nVersion has wrong type");
+
+ if (a->nSize < sizeof(*a)) {
+ ALOGE("b/27207275: need %zu, got %u", sizeof(*a), a->nSize);
+ android_errorWriteLog(0x534e4554, "27207275");
+ return false;
+ }
+ return true;
+}
+
} // namespace android
#endif // SOFT_OMX_COMPONENT_H_
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index e3c3e80..3ad3118 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -509,7 +509,7 @@ int64_t ATSParser::Program::recoverPTS(uint64_t PTS_33bit) {
mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
} else {
mLastRecoveredPTS = static_cast<int64_t>(
- ((mLastRecoveredPTS - PTS_33bit + 0x100000000ll)
+ ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000ll)
& 0xfffffffe00000000ull) | PTS_33bit);
// We start from 0, but recovered PTS could be slightly below 0.
// Clamp it to 0 as rest of the pipeline doesn't take negative pts.
@@ -1713,6 +1713,13 @@ bool ATSParser::PSISection::isCRCOkay() const {
unsigned sectionLength = U16_AT(data + 1) & 0xfff;
ALOGV("sectionLength %u, skip %u", sectionLength, mSkipBytes);
+
+ if(sectionLength < mSkipBytes) {
+ ALOGE("b/28333006");
+ android_errorWriteLog(0x534e4554, "28333006");
+ return false;
+ }
+
// Skip the preceding field present when payload start indicator is on.
sectionLength -= mSkipBytes;
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index efb1a1c..153a979 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -179,7 +179,12 @@ void OMX::binderDied(const wp<IBinder> &the_late_who) {
Mutex::Autolock autoLock(mLock);
ssize_t index = mLiveNodes.indexOfKey(the_late_who);
- CHECK(index >= 0);
+
+ if (index < 0) {
+ ALOGE("b/27597103, nonexistent observer on binderDied");
+ android_errorWriteLog(0x534e4554, "27597103");
+ return;
+ }
instance = mLiveNodes.editValueAt(index);
mLiveNodes.removeItemsAt(index);
@@ -363,9 +368,9 @@ status_t OMX::configureVideoTunnelMode(
status_t OMX::useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) {
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess) {
return findInstance(node)->useBuffer(
- port_index, params, buffer, allottedSize);
+ port_index, params, buffer, allottedSize, crossProcess);
}
status_t OMX::useGraphicBuffer(
@@ -416,9 +421,9 @@ status_t OMX::allocateBuffer(
status_t OMX::allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer, OMX_U32 allottedSize) {
+ buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess) {
return findInstance(node)->allocateBufferWithBackup(
- port_index, params, buffer, allottedSize);
+ port_index, params, buffer, allottedSize, crossProcess);
}
status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 8c949cb..c09064f 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -101,23 +101,34 @@ static void InitOMXParams(T *params) {
namespace android {
struct BufferMeta {
- BufferMeta(const sp<IMemory> &mem, bool is_backup = false)
+ BufferMeta(
+ const sp<IMemory> &mem, OMX_U32 portIndex, bool copyToOmx,
+ bool copyFromOmx, OMX_U8 *backup)
: mMem(mem),
- mIsBackup(is_backup) {
+ mCopyFromOmx(copyFromOmx),
+ mCopyToOmx(copyToOmx),
+ mPortIndex(portIndex),
+ mBackup(backup) {
}
- BufferMeta(size_t size)
+ BufferMeta(size_t size, OMX_U32 portIndex)
: mSize(size),
- mIsBackup(false) {
+ mCopyFromOmx(false),
+ mCopyToOmx(false),
+ mPortIndex(portIndex),
+ mBackup(NULL) {
}
- BufferMeta(const sp<GraphicBuffer> &graphicBuffer)
+ BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex)
: mGraphicBuffer(graphicBuffer),
- mIsBackup(false) {
+ mCopyFromOmx(false),
+ mCopyToOmx(false),
+ mPortIndex(portIndex),
+ mBackup(NULL) {
}
void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
- if (!mIsBackup) {
+ if (!mCopyFromOmx) {
return;
}
@@ -129,7 +140,7 @@ struct BufferMeta {
}
void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
- if (!mIsBackup) {
+ if (!mCopyToOmx) {
return;
}
@@ -159,15 +170,30 @@ struct BufferMeta {
return buf;
}
+ bool copyToOmx() const {
+ return mCopyToOmx;
+ }
+
void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
mGraphicBuffer = graphicBuffer;
}
+ OMX_U32 getPortIndex() {
+ return mPortIndex;
+ }
+
+ ~BufferMeta() {
+ delete[] mBackup;
+ }
+
private:
sp<GraphicBuffer> mGraphicBuffer;
sp<IMemory> mMem;
size_t mSize;
- bool mIsBackup;
+ bool mCopyFromOmx;
+ bool mCopyToOmx;
+ OMX_U32 mPortIndex;
+ OMX_U8 *mBackup;
BufferMeta(const BufferMeta &);
BufferMeta &operator=(const BufferMeta &);
@@ -193,6 +219,8 @@ OMXNodeInstance::OMXNodeInstance(
mNodeID(0),
mHandle(NULL),
mObserver(observer),
+ mSailed(false),
+ mQueriedProhibitedExtensions(false),
mBufferIDCount(0)
{
mName = ADebug::GetDebugName(name);
@@ -366,7 +394,11 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) {
status_t OMXNodeInstance::sendCommand(
OMX_COMMANDTYPE cmd, OMX_S32 param) {
- const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
+ if (cmd == OMX_CommandStateSet) {
+ // There are no configurations past first StateSet command.
+ mSailed = true;
+ }
+ const sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
if (bufferSource != NULL && cmd == OMX_CommandStateSet) {
if (param == OMX_StateIdle) {
// Initiating transition from Executing -> Idle
@@ -399,10 +431,57 @@ status_t OMXNodeInstance::sendCommand(
return StatusFromOMXError(err);
}
+bool OMXNodeInstance::isProhibitedIndex_l(OMX_INDEXTYPE index) {
+ // these extensions can only be used from OMXNodeInstance, not by clients directly.
+ static const char *restricted_extensions[] = {
+ "OMX.google.android.index.storeMetaDataInBuffers",
+ "OMX.google.android.index.storeANWBufferInMetadata",
+ "OMX.google.android.index.prepareForAdaptivePlayback",
+ "OMX.google.android.index.configureVideoTunnelMode",
+ "OMX.google.android.index.useAndroidNativeBuffer2",
+ "OMX.google.android.index.useAndroidNativeBuffer",
+ "OMX.google.android.index.enableAndroidNativeBuffers",
+ "OMX.google.android.index.allocateNativeHandle",
+ "OMX.google.android.index.getAndroidNativeBufferUsage",
+ };
+
+ if ((index > OMX_IndexComponentStartUnused && index <= OMX_IndexParamStandardComponentRole)
+ || (index > OMX_IndexPortStartUnused && index <= OMX_IndexParamCompBufferSupplier)
+ || (index > OMX_IndexAudioStartUnused && index <= OMX_IndexConfigAudioChannelVolume)
+ || (index > OMX_IndexVideoStartUnused && index <= OMX_IndexConfigVideoNalSize)
+ || (index > OMX_IndexCommonStartUnused
+ && index <= OMX_IndexConfigCommonTransitionEffect)
+ || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused
+ && index <= (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3)
+ || (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused
+ && index <= (OMX_INDEXTYPE)OMX_IndexParamSliceSegments)
+ || (index > (OMX_INDEXTYPE)OMX_IndexExtOtherStartUnused
+ && index <= (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits)) {
+ return false;
+ }
+
+ if (!mQueriedProhibitedExtensions) {
+ for (size_t i = 0; i < NELEM(restricted_extensions); ++i) {
+ OMX_INDEXTYPE ext;
+ if (OMX_GetExtensionIndex(mHandle, (OMX_STRING)restricted_extensions[i], &ext) == OMX_ErrorNone) {
+ mProhibitedExtensions.add(ext);
+ }
+ }
+ mQueriedProhibitedExtensions = true;
+ }
+
+ return mProhibitedExtensions.indexOf(index) >= 0;
+}
+
status_t OMXNodeInstance::getParameter(
OMX_INDEXTYPE index, void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
+ if (isProhibitedIndex_l(index)) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return BAD_INDEX;
+ }
+
OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
// some errors are expected for getParameter
@@ -418,6 +497,11 @@ status_t OMXNodeInstance::setParameter(
OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
+ if (isProhibitedIndex_l(index)) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return BAD_INDEX;
+ }
+
OMX_ERRORTYPE err = OMX_SetParameter(
mHandle, index, const_cast<void *>(params));
CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index);
@@ -428,6 +512,11 @@ status_t OMXNodeInstance::getConfig(
OMX_INDEXTYPE index, void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
+ if (isProhibitedIndex_l(index)) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return BAD_INDEX;
+ }
+
OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
// some errors are expected for getConfig
@@ -443,6 +532,11 @@ status_t OMXNodeInstance::setConfig(
OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
+ if (isProhibitedIndex_l(index)) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return BAD_INDEX;
+ }
+
OMX_ERRORTYPE err = OMX_SetConfig(
mHandle, index, const_cast<void *>(params));
CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index);
@@ -522,7 +616,12 @@ status_t OMXNodeInstance::storeMetaDataInBuffers(
status_t OMXNodeInstance::storeMetaDataInBuffers_l(
OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
+ if (mSailed) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return INVALID_OPERATION;
+ }
if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
+ android_errorWriteLog(0x534e4554, "26324358");
return BAD_VALUE;
}
@@ -588,6 +687,10 @@ status_t OMXNodeInstance::prepareForAdaptivePlayback(
OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
OMX_U32 maxFrameHeight) {
Mutex::Autolock autolock(mLock);
+ if (mSailed) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return INVALID_OPERATION;
+ }
CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u",
portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
@@ -618,6 +721,10 @@ status_t OMXNodeInstance::configureVideoTunnelMode(
OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
native_handle_t **sidebandHandle) {
Mutex::Autolock autolock(mLock);
+ if (mSailed) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return INVALID_OPERATION;
+ }
CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u",
portString(portIndex), portIndex, tunneled, audioHwSync);
@@ -658,23 +765,48 @@ status_t OMXNodeInstance::configureVideoTunnelMode(
status_t OMXNodeInstance::useBuffer(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer, OMX_U32 allottedSize) {
+ OMX::buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess) {
Mutex::Autolock autoLock(mLock);
- if (allottedSize > params->size()) {
+ if (allottedSize > params->size() || portIndex >= NELEM(mNumPortBuffers)) {
return BAD_VALUE;
}
- BufferMeta *buffer_meta = new BufferMeta(params);
+ // metadata buffers are not connected cross process
+ BufferMeta *buffer_meta;
+ bool isMeta = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
+ bool useBackup = crossProcess && isMeta; // use a backup buffer instead of the actual buffer
+ OMX_U8 *data = static_cast<OMX_U8 *>(params->pointer());
+ // allocate backup buffer
+ if (useBackup) {
+ data = new (std::nothrow) OMX_U8[allottedSize];
+ if (data == NULL) {
+ return NO_MEMORY;
+ }
+ memset(data, 0, allottedSize);
+
+ // if we are not connecting the buffers, the sizes must match
+ if (allottedSize != params->size()) {
+ CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data));
+ delete[] data;
+ return BAD_VALUE;
+ }
+
+ buffer_meta = new BufferMeta(
+ params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, data);
+ } else {
+ buffer_meta = new BufferMeta(
+ params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, NULL);
+ }
OMX_BUFFERHEADERTYPE *header;
OMX_ERRORTYPE err = OMX_UseBuffer(
mHandle, &header, portIndex, buffer_meta,
- allottedSize, static_cast<OMX_U8 *>(params->pointer()));
+ allottedSize, data);
if (err != OMX_ErrorNone) {
CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
- portIndex, (size_t)allottedSize, params->pointer()));
+ portIndex, (size_t)allottedSize, data));
delete buffer_meta;
buffer_meta = NULL;
@@ -716,7 +848,7 @@ status_t OMXNodeInstance::useGraphicBuffer2_l(
return UNKNOWN_ERROR;
}
- BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
+ BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
OMX_BUFFERHEADERTYPE *header = NULL;
OMX_U8* bufferHandle = const_cast<OMX_U8*>(
@@ -774,7 +906,7 @@ status_t OMXNodeInstance::useGraphicBuffer(
return StatusFromOMXError(err);
}
- BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
+ BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
OMX_BUFFERHEADERTYPE *header;
@@ -815,6 +947,9 @@ status_t OMXNodeInstance::useGraphicBuffer(
status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
+ if (header == NULL) {
+ return BAD_VALUE;
+ }
if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
return BAD_VALUE;
}
@@ -848,7 +983,7 @@ status_t OMXNodeInstance::updateGraphicBufferInMeta(
OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
- OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, buffer, header);
}
@@ -856,7 +991,16 @@ status_t OMXNodeInstance::createGraphicBufferSource(
OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer, MetadataBufferType *type) {
status_t err;
- const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource();
+ // only allow graphic source on input port, when there are no allocated buffers yet
+ if (portIndex != kPortIndexInput) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return BAD_VALUE;
+ } else if (mNumPortBuffers[portIndex] > 0) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return INVALID_OPERATION;
+ }
+
+ const sp<GraphicBufferSource> surfaceCheck = getGraphicBufferSource();
if (surfaceCheck != NULL) {
if (portIndex < NELEM(mMetadataType) && type != NULL) {
*type = mMetadataType[portIndex];
@@ -977,7 +1121,7 @@ status_t OMXNodeInstance::allocateBuffer(
void **buffer_data) {
Mutex::Autolock autoLock(mLock);
- BufferMeta *buffer_meta = new BufferMeta(size);
+ BufferMeta *buffer_meta = new BufferMeta(size, portIndex);
OMX_BUFFERHEADERTYPE *header;
@@ -1012,13 +1156,21 @@ status_t OMXNodeInstance::allocateBuffer(
status_t OMXNodeInstance::allocateBufferWithBackup(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer, OMX_U32 allottedSize) {
+ OMX::buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess) {
Mutex::Autolock autoLock(mLock);
- if (allottedSize > params->size()) {
+ if (allottedSize > params->size() || portIndex >= NELEM(mNumPortBuffers)) {
return BAD_VALUE;
}
- BufferMeta *buffer_meta = new BufferMeta(params, true);
+ // metadata buffers are not connected cross process
+ bool isMeta = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
+ bool copy = !(crossProcess && isMeta);
+
+ BufferMeta *buffer_meta = new BufferMeta(
+ params, portIndex,
+ (portIndex == kPortIndexInput) && copy /* copyToOmx */,
+ (portIndex == kPortIndexOutput) && copy /* copyFromOmx */,
+ NULL /* data */);
OMX_BUFFERHEADERTYPE *header;
@@ -1059,7 +1211,10 @@ status_t OMXNodeInstance::freeBuffer(
removeActiveBuffer(portIndex, buffer);
- OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
+ if (header == NULL) {
+ return BAD_VALUE;
+ }
BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
@@ -1075,7 +1230,10 @@ status_t OMXNodeInstance::freeBuffer(
status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer, int fenceFd) {
Mutex::Autolock autoLock(mLock);
- OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput);
+ if (header == NULL) {
+ return BAD_VALUE;
+ }
header->nFilledLen = 0;
header->nOffset = 0;
header->nFlags = 0;
@@ -1108,7 +1266,16 @@ status_t OMXNodeInstance::emptyBuffer(
OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
Mutex::Autolock autoLock(mLock);
- OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
+ // no emptybuffer if using input surface
+ if (getGraphicBufferSource() != NULL) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return INVALID_OPERATION;
+ }
+
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
+ if (header == NULL) {
+ return BAD_VALUE;
+ }
BufferMeta *buffer_meta =
static_cast<BufferMeta *>(header->pAppPrivate);
sp<ABuffer> backup = buffer_meta->getBuffer(header, true /* backup */, false /* limit */);
@@ -1116,7 +1283,8 @@ status_t OMXNodeInstance::emptyBuffer(
// convert incoming ANW meta buffers if component is configured for gralloc metadata mode
// ignore rangeOffset in this case
- if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource
+ if (buffer_meta->copyToOmx()
+ && mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource
&& backup->capacity() >= sizeof(VideoNativeMetadata)
&& codec->capacity() >= sizeof(VideoGrallocMetadata)
&& ((VideoNativeMetadata *)backup->base())->eType
@@ -1388,7 +1556,10 @@ bool OMXNodeInstance::handleMessage(omx_message &msg) {
if (msg.type == omx_message::FILL_BUFFER_DONE) {
OMX_BUFFERHEADERTYPE *buffer =
- findBufferHeader(msg.u.extended_buffer_data.buffer);
+ findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput);
+ if (buffer == NULL) {
+ return false;
+ }
{
Mutex::Autolock _l(mDebugLock);
@@ -1419,7 +1590,10 @@ bool OMXNodeInstance::handleMessage(omx_message &msg) {
}
} else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
OMX_BUFFERHEADERTYPE *buffer =
- findBufferHeader(msg.u.buffer_data.buffer);
+ findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput);
+ if (buffer == NULL) {
+ return false;
+ }
{
Mutex::Autolock _l(mDebugLock);
@@ -1520,6 +1694,13 @@ void OMXNodeInstance::onEvent(
&& arg2 == OMX_StateExecuting) {
bufferSource->omxExecuting();
}
+
+ // allow configuration if we return to the loaded state
+ if (event == OMX_EventCmdComplete
+ && arg1 == OMX_CommandStateSet
+ && arg2 == OMX_StateLoaded) {
+ mSailed = false;
+ }
}
// static
@@ -1620,7 +1801,8 @@ OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader)
return buffer;
}
-OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
+OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(
+ OMX::buffer_id buffer, OMX_U32 portIndex) {
if (buffer == 0) {
return NULL;
}
@@ -1630,7 +1812,15 @@ OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
CLOGW("findBufferHeader: buffer %u not found", buffer);
return NULL;
}
- return mBufferIDToBufferHeader.valueAt(index);
+ OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index);
+ BufferMeta *buffer_meta =
+ static_cast<BufferMeta *>(header->pAppPrivate);
+ if (buffer_meta->getPortIndex() != portIndex) {
+ CLOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer);
+ android_errorWriteLog(0x534e4554, "28816827");
+ return NULL;
+ }
+ return header;
}
OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index 1fd0641..2ae807e 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -125,6 +125,10 @@ OMX_ERRORTYPE SimpleSoftOMXComponent::internalGetParameter(
OMX_PARAM_PORTDEFINITIONTYPE *defParams =
(OMX_PARAM_PORTDEFINITIONTYPE *)params;
+ if (!isValidOMXParam(defParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (defParams->nPortIndex >= mPorts.size()
|| defParams->nSize
!= sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
@@ -152,6 +156,10 @@ OMX_ERRORTYPE SimpleSoftOMXComponent::internalSetParameter(
OMX_PARAM_PORTDEFINITIONTYPE *defParams =
(OMX_PARAM_PORTDEFINITIONTYPE *)params;
+ if (!isValidOMXParam(defParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (defParams->nPortIndex >= mPorts.size()) {
return OMX_ErrorBadPortIndex;
}
@@ -497,6 +505,13 @@ void SimpleSoftOMXComponent::onPortEnable(OMX_U32 portIndex, bool enable) {
CHECK_EQ((int)port->mTransition, (int)PortInfo::NONE);
CHECK(port->mDef.bEnabled == !enable);
+ if (port->mDef.eDir != OMX_DirOutput) {
+ ALOGE("Port enable/disable allowed only on output ports.");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ android_errorWriteLog(0x534e4554, "29421804");
+ return;
+ }
+
if (!enable) {
port->mDef.bEnabled = OMX_FALSE;
port->mTransition = PortInfo::DISABLING;
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 4ce165b..19dde83 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -264,6 +264,10 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter(
OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > kMaxPortIndex) {
return OMX_ErrorBadPortIndex;
}
@@ -292,6 +296,10 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter(
OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
(OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
+ if (!isValidOMXParam(profileLevel)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (profileLevel->nPortIndex != kInputPortIndex) {
ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex);
return OMX_ErrorUnsupportedIndex;
@@ -322,6 +330,10 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
+ if (!isValidOMXParam(roleParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (strncmp((const char *)roleParams->cRole,
mComponentRole,
OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -336,6 +348,10 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+ if (!isValidOMXParam(formatParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (formatParams->nPortIndex > kMaxPortIndex) {
return OMX_ErrorBadPortIndex;
}
@@ -363,6 +379,11 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
{
const PrepareForAdaptivePlaybackParams* adaptivePlaybackParams =
(const PrepareForAdaptivePlaybackParams *)params;
+
+ if (!isValidOMXParam(adaptivePlaybackParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
mIsAdaptive = adaptivePlaybackParams->bEnable;
if (mIsAdaptive) {
mAdaptiveMaxWidth = adaptivePlaybackParams->nMaxFrameWidth;
@@ -381,6 +402,11 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
{
OMX_PARAM_PORTDEFINITIONTYPE *newParams =
(OMX_PARAM_PORTDEFINITIONTYPE *)params;
+
+ if (!isValidOMXParam(newParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &newParams->format.video;
OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(newParams->nPortIndex)->mDef;
@@ -421,6 +447,10 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig(
{
OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
+ if (!isValidOMXParam(rectParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (rectParams->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUndefined;
}
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 8ea7a6e..dc3ed39 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -606,6 +606,9 @@ const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer(
break;
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
+#ifdef MTK_HARDWARE
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+#endif
ConvertRGB32ToPlanar(
dst, dstStride, dstVStride,
(const uint8_t *)bits, width, height, srcStride,
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 92ad1ec..497fae6 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ASessionDescription"
#include <utils/Log.h>
+#include <cutils/log.h>
#include "ASessionDescription.h"
@@ -211,12 +212,12 @@ void ASessionDescription::getFormatType(
*PT = x;
- char key[20];
- sprintf(key, "a=rtpmap:%lu", x);
+ char key[32];
+ snprintf(key, sizeof(key), "a=rtpmap:%lu", x);
CHECK(findAttribute(index, key, desc));
- sprintf(key, "a=fmtp:%lu", x);
+ snprintf(key, sizeof(key), "a=fmtp:%lu", x);
if (!findAttribute(index, key, params)) {
params->clear();
}
@@ -228,8 +229,11 @@ bool ASessionDescription::getDimensions(
*width = 0;
*height = 0;
- char key[20];
- sprintf(key, "a=framesize:%lu", PT);
+ char key[33];
+ snprintf(key, sizeof(key), "a=framesize:%lu", PT);
+ if (PT > 9999999) {
+ android_errorWriteLog(0x534e4554, "25747670");
+ }
AString value;
if (!findAttribute(index, key, &value)) {
return false;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 7290ee2..70063b1 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -18,7 +18,9 @@
#define MY_HANDLER_H_
+#ifndef LOG_NDEBUG
//#define LOG_NDEBUG 0
+#endif
#ifndef LOG_TAG
#define LOG_TAG "MyHandler"
diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk
index fb28624..6f17747 100644
--- a/media/libstagefright/wifi-display/Android.mk
+++ b/media/libstagefright/wifi-display/Android.mk
@@ -33,6 +33,10 @@ LOCAL_SHARED_LIBRARIES:= \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_CLANG := true
+ifeq ($(BOARD_NO_INTRA_MACROBLOCK_MODE_SUPPORT),true)
+LOCAL_CFLAGS += -DBOARD_NO_INTRA_MACROBLOCK_MODE_SUPPORT
+endif
+
LOCAL_MODULE:= libstagefright_wfd
LOCAL_MODULE_TAGS:= optional
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 471152e..9a2d08a 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -173,8 +173,10 @@ status_t Converter::initEncoder() {
mOutputFormat->setInt32("frame-rate", 30);
mOutputFormat->setInt32("i-frame-interval", 15); // Iframes every 15 secs
+#ifndef BOARD_NO_INTRA_MACROBLOCK_MODE_SUPPORT
// Configure encoder to use intra macroblock refresh mode
mOutputFormat->setInt32("intra-refresh-mode", OMX_VIDEO_IntraRefreshCyclic);
+#endif
int width, height, mbs;
if (!mOutputFormat->findInt32("width", &width)
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index 33766b5..ac25582 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -37,6 +37,7 @@ LOCAL_STATIC_LIBRARIES := \
LOCAL_C_INCLUDES := \
frameworks/av/media/libmediaplayerservice \
+ frameworks/av/media/libmedia \
frameworks/av/services/medialog \
frameworks/av/services/audioflinger \
frameworks/av/services/audiopolicy \
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index c16e646..f785c0d 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -36,6 +36,7 @@
#include "MediaPlayerService.h"
#include "ResourceManagerService.h"
#include "service/AudioPolicyService.h"
+#include "MediaUtils.h"
#include "SoundTriggerHwService.h"
#include "RadioService.h"
@@ -47,6 +48,11 @@ using namespace android;
int main(int argc __unused, char** argv)
{
+ limitProcessMemory(
+ "ro.media.maxmem", /* property that defines limit */
+ SIZE_MAX, /* upper limit in bytes */
+ 65 /* upper limit as percentage of physical RAM */);
+
signal(SIGPIPE, SIG_IGN);
char value[PROPERTY_VALUE_MAX];
bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 6a334e6..d5f8ff4 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -137,20 +137,9 @@ void MtpServer::removeStorage(MtpStorage* storage) {
}
MtpStorage* MtpServer::getStorage(MtpStorageID id) {
- if (id == 0)
- return mStorages[0];
- for (size_t i = 0; i < mStorages.size(); i++) {
- MtpStorage* storage = mStorages[i];
- if (storage->getStorageID() == id)
- return storage;
- }
- return NULL;
-}
+ Mutex::Autolock autoLock(mMutex);
-bool MtpServer::hasStorage(MtpStorageID id) {
- if (id == 0 || id == 0xFFFFFFFF)
- return mStorages.size() > 0;
- return (getStorage(id) != NULL);
+ return getStorageLocked(id);
}
void MtpServer::run() {
@@ -215,10 +204,11 @@ void MtpServer::run() {
mResponse.setTransactionID(transaction);
ALOGV("sending response %04X", mResponse.getResponseCode());
ret = mResponse.write(fd);
+ const int savedErrno = errno;
mResponse.dump();
if (ret < 0) {
ALOGE("request write returned %d, errno: %d", ret, errno);
- if (errno == ECANCELED) {
+ if (savedErrno == ECANCELED) {
// return to top of loop and wait for next command
continue;
}
@@ -259,6 +249,23 @@ void MtpServer::sendObjectUpdated(MtpObjectHandle handle) {
sendEvent(MTP_EVENT_OBJECT_PROP_CHANGED, handle);
}
+MtpStorage* MtpServer::getStorageLocked(MtpStorageID id) {
+ if (id == 0)
+ return mStorages.empty() ? NULL : mStorages[0];
+ for (size_t i = 0; i < mStorages.size(); i++) {
+ MtpStorage* storage = mStorages[i];
+ if (storage->getStorageID() == id)
+ return storage;
+ }
+ return NULL;
+}
+
+bool MtpServer::hasStorage(MtpStorageID id) {
+ if (id == 0 || id == 0xFFFFFFFF)
+ return mStorages.size() > 0;
+ return (getStorageLocked(id) != NULL);
+}
+
void MtpServer::sendStoreAdded(MtpStorageID id) {
ALOGV("sendStoreAdded %08X\n", id);
sendEvent(MTP_EVENT_STORE_ADDED, id);
@@ -542,7 +549,7 @@ MtpResponseCode MtpServer::doGetStorageInfo() {
return MTP_RESPONSE_INVALID_PARAMETER;
MtpStorageID id = mRequest.getParameter(1);
- MtpStorage* storage = getStorage(id);
+ MtpStorage* storage = getStorageLocked(id);
if (!storage)
return MTP_RESPONSE_INVALID_STORAGE_ID;
@@ -793,15 +800,19 @@ MtpResponseCode MtpServer::doGetObject() {
// then transfer the file
int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
- ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
- close(mfr.fd);
if (ret < 0) {
- if (errno == ECANCELED)
- return MTP_RESPONSE_TRANSACTION_CANCELLED;
- else
- return MTP_RESPONSE_GENERAL_ERROR;
+ if (errno == ECANCELED) {
+ result = MTP_RESPONSE_TRANSACTION_CANCELLED;
+ } else {
+ result = MTP_RESPONSE_GENERAL_ERROR;
+ }
+ } else {
+ result = MTP_RESPONSE_OK;
}
- return MTP_RESPONSE_OK;
+
+ ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
+ close(mfr.fd);
+ return result;
}
MtpResponseCode MtpServer::doGetThumb() {
@@ -870,14 +881,15 @@ MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) {
// transfer the file
int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
- close(mfr.fd);
+ result = MTP_RESPONSE_OK;
if (ret < 0) {
if (errno == ECANCELED)
- return MTP_RESPONSE_TRANSACTION_CANCELLED;
+ result = MTP_RESPONSE_TRANSACTION_CANCELLED;
else
- return MTP_RESPONSE_GENERAL_ERROR;
+ result = MTP_RESPONSE_GENERAL_ERROR;
}
- return MTP_RESPONSE_OK;
+ close(mfr.fd);
+ return result;
}
MtpResponseCode MtpServer::doSendObjectInfo() {
@@ -888,7 +900,7 @@ MtpResponseCode MtpServer::doSendObjectInfo() {
if (mRequest.getParameterCount() < 2)
return MTP_RESPONSE_INVALID_PARAMETER;
MtpStorageID storageID = mRequest.getParameter(1);
- MtpStorage* storage = getStorage(storageID);
+ MtpStorage* storage = getStorageLocked(storageID);
MtpObjectHandle parent = mRequest.getParameter(2);
if (!storage)
return MTP_RESPONSE_INVALID_STORAGE_ID;
@@ -991,6 +1003,7 @@ MtpResponseCode MtpServer::doSendObject() {
MtpResponseCode result = MTP_RESPONSE_OK;
mode_t mask;
int ret, initialData;
+ bool isCanceled = false;
if (mSendObjectHandle == kInvalidObjectHandle) {
ALOGE("Expected SendObjectInfo before SendObject");
@@ -1038,6 +1051,10 @@ MtpResponseCode MtpServer::doSendObject() {
ALOGV("receiving %s\n", (const char *)mSendObjectFilePath);
// transfer the file
ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
+ if ((ret < 0) && (errno == ECANCELED)) {
+ isCanceled = true;
+ }
+
ALOGV("MTP_RECEIVE_FILE returned %d\n", ret);
}
}
@@ -1045,7 +1062,7 @@ MtpResponseCode MtpServer::doSendObject() {
if (ret < 0) {
unlink(mSendObjectFilePath);
- if (errno == ECANCELED)
+ if (isCanceled)
result = MTP_RESPONSE_TRANSACTION_CANCELLED;
else
result = MTP_RESPONSE_GENERAL_ERROR;
@@ -1214,6 +1231,7 @@ MtpResponseCode MtpServer::doSendPartialObject() {
length -= initialData;
}
+ bool isCanceled = false;
if (ret < 0) {
ALOGE("failed to write initial data");
} else {
@@ -1225,12 +1243,15 @@ MtpResponseCode MtpServer::doSendPartialObject() {
// transfer the file
ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
+ if ((ret < 0) && (errno == ECANCELED)) {
+ isCanceled = true;
+ }
ALOGV("MTP_RECEIVE_FILE returned %d", ret);
}
}
if (ret < 0) {
mResponse.setParameter(1, 0);
- if (errno == ECANCELED)
+ if (isCanceled)
return MTP_RESPONSE_TRANSACTION_CANCELLED;
else
return MTP_RESPONSE_GENERAL_ERROR;
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 8bd0472..a79e199 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -95,8 +95,6 @@ public:
virtual ~MtpServer();
MtpStorage* getStorage(MtpStorageID id);
- inline bool hasStorage() { return mStorages.size() > 0; }
- bool hasStorage(MtpStorageID id);
void addStorage(MtpStorage* storage);
void removeStorage(MtpStorage* storage);
@@ -108,6 +106,10 @@ public:
void sendObjectUpdated(MtpObjectHandle handle);
private:
+ MtpStorage* getStorageLocked(MtpStorageID id);
+ inline bool hasStorage() { return mStorages.size() > 0; }
+ bool hasStorage(MtpStorageID id);
+
void sendStoreAdded(MtpStorageID id);
void sendStoreRemoved(MtpStorageID id);
void sendEvent(MtpEventCode code, uint32_t param1);
diff --git a/radio/Radio.cpp b/radio/Radio.cpp
index e3554c2..3c04fb0 100644
--- a/radio/Radio.cpp
+++ b/radio/Radio.cpp
@@ -55,7 +55,7 @@ namespace {
sp<DeathNotifier> gDeathNotifier;
}; // namespace anonymous
-const sp<IRadioService>& Radio::getRadioService()
+const sp<IRadioService> Radio::getRadioService()
{
Mutex::Autolock _l(gLock);
if (gRadioService.get() == 0) {
@@ -84,7 +84,7 @@ status_t Radio::listModules(struct radio_properties *properties,
uint32_t *numModules)
{
ALOGV("listModules()");
- const sp<IRadioService>& service = getRadioService();
+ const sp<IRadioService> service = getRadioService();
if (service == 0) {
return NO_INIT;
}
@@ -98,7 +98,7 @@ sp<Radio> Radio::attach(radio_handle_t handle,
{
ALOGV("attach()");
sp<Radio> radio;
- const sp<IRadioService>& service = getRadioService();
+ const sp<IRadioService> service = getRadioService();
if (service == 0) {
return radio;
}
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 0dd2af6..8ea26d3 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -160,12 +160,19 @@ LOCAL_SHARED_LIBRARIES := \
libaudioutils
#QTI Resampler
-ifeq ($(call is-vendor-board-platform,QCOM), true)
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)),true)
+ifdef TARGET_2ND_ARCH
LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) += AudioResamplerQTI.cpp.arm
LOCAL_C_INCLUDES_$(TARGET_2ND_ARCH) += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
LOCAL_SHARED_LIBRARIES_$(TARGET_2ND_ARCH) += libqct_resampler
LOCAL_CFLAGS_$(TARGET_2ND_ARCH) += -DQTI_RESAMPLER
+else
+LOCAL_SRC_FILES += AudioResamplerQTI.cpp.arm
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
+LOCAL_SHARED_LIBRARIES += libqct_resampler
+LOCAL_CFLAGS += -DQTI_RESAMPLER
+endif
endif
endif
#QTI Resampler
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 806eaf1..bb9d4e5 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -781,7 +781,8 @@ bool AudioMixer::track_t::setResampler(uint32_t trackSampleRate, uint32_t devSam
#ifdef QTI_RESAMPLER
if ((trackSampleRate <= QTI_RESAMPLER_MAX_SAMPLERATE) &&
(trackSampleRate > devSampleRate * 2) &&
- ((devSampleRate == 48000)||(devSampleRate == 44100))) {
+ ((devSampleRate == 48000)||(devSampleRate == 44100)) &&
+ (resamplerChannelCount <= 2)) {
quality = AudioResampler::QTI_QUALITY;
}
#endif
diff --git a/services/audioflinger/AudioResamplerQTI.cpp b/services/audioflinger/AudioResamplerQTI.cpp
index 44b741e..0d57e09 100644
--- a/services/audioflinger/AudioResamplerQTI.cpp
+++ b/services/audioflinger/AudioResamplerQTI.cpp
@@ -51,8 +51,9 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
{
int16_t vl = mVolume[0];
int16_t vr = mVolume[1];
- int16_t *pBuf;
+ int32_t *pBuf;
+ int64_t tempL, tempR;
size_t inFrameRequest;
size_t inFrameCount = getNumInSample(outFrameCount);
size_t index = 0;
@@ -74,7 +75,7 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
if(mResamplerOutBuf) {
delete [] mResamplerOutBuf;
}
- mTmpBuf = new int16_t[inFrameRequest + 16];
+ mTmpBuf = new int32_t[inFrameRequest + 16];
mResamplerOutBuf = new int32_t[out_count];
}
@@ -95,7 +96,7 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
goto resample_exit;
}
- mTmpBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ mTmpBuf[index++] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
if (frameIndex >= mBuffer.frameCount) {
provider->releaseBuffer(&mBuffer);
@@ -121,8 +122,8 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
goto resample_exit;
}
- mTmpBuf[index] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
- pBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ mTmpBuf[index] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
+ pBuf[index++] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
if (frameIndex >= mBuffer.frameCount * 2) {
provider->releaseBuffer(&mBuffer);
}
@@ -133,8 +134,12 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
resample_exit:
for (int i = 0; i < out_count; i += 2) {
- fout[i] += float_from_q4_27(mResamplerOutBuf[i] * vl);
- fout[i+1] += float_from_q4_27(mResamplerOutBuf[i+1] * vr);
+ // Multiplying q4.27 data with u4.12 gain could result in 39 fractional bit data(27+12)
+ // To get back the 27 fractional bit format output data, do right shift by 12
+ tempL = (int64_t)mResamplerOutBuf[i] * vl;
+ tempR = (int64_t)mResamplerOutBuf[i+1] * vr;
+ fout[i] += float_from_q4_27((int32_t)(tempL>>12));
+ fout[i+1] += float_from_q4_27((int32_t)(tempR>>12));
}
mFrameIndex = frameIndex;
@@ -151,7 +156,7 @@ void AudioResamplerQTI::setSampleRate(int32_t inSampleRate)
void AudioResamplerQTI::init()
{
- QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate);
+ QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate, 1/*32bit in*/);
}
size_t AudioResamplerQTI::getNumInSample(size_t outFrameCount)
diff --git a/services/audioflinger/AudioResamplerQTI.h b/services/audioflinger/AudioResamplerQTI.h
index 0b30a9f..1cf93fc 100644
--- a/services/audioflinger/AudioResamplerQTI.h
+++ b/services/audioflinger/AudioResamplerQTI.h
@@ -35,7 +35,7 @@ public:
size_t getNumInSample(size_t outFrameCount);
int16_t *mState;
- int16_t *mTmpBuf;
+ int32_t *mTmpBuf;
int32_t *mResamplerOutBuf;
size_t mFrameIndex;
size_t stateSize;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 879b6c9..5505d2e 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -543,6 +543,13 @@ status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
return NO_ERROR;
}
+// round up delta valid if value and divisor are positive.
+template <typename T>
+static T roundUpDelta(const T &value, const T &divisor) {
+ T remainder = value % divisor;
+ return remainder == 0 ? 0 : divisor - remainder;
+}
+
status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
uint32_t cmdSize,
void *pCmdData,
@@ -558,6 +565,28 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
if (mStatus != NO_ERROR) {
return mStatus;
}
+ if (cmdCode == EFFECT_CMD_GET_PARAM &&
+ (*replySize < sizeof(effect_param_t) ||
+ ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t))) {
+ android_errorWriteLog(0x534e4554, "29251553");
+ return -EINVAL;
+ }
+ if ((cmdCode == EFFECT_CMD_SET_PARAM
+ || cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) && // DEFERRED not generally used
+ (sizeof(effect_param_t) > cmdSize
+ || ((effect_param_t *)pCmdData)->psize > cmdSize
+ - sizeof(effect_param_t)
+ || ((effect_param_t *)pCmdData)->vsize > cmdSize
+ - sizeof(effect_param_t)
+ - ((effect_param_t *)pCmdData)->psize
+ || roundUpDelta(((effect_param_t *)pCmdData)->psize, (uint32_t)sizeof(int)) >
+ cmdSize
+ - sizeof(effect_param_t)
+ - ((effect_param_t *)pCmdData)->psize
+ - ((effect_param_t *)pCmdData)->vsize)) {
+ android_errorWriteLog(0x534e4554, "30204301");
+ return -EINVAL;
+ }
status_t status = (*mEffectInterface)->command(mEffectInterface,
cmdCode,
cmdSize,
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index 2493fb7..7c8a25f 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -25,6 +25,7 @@
#include <media/AudioBufferProvider.h>
#include <utils/Log.h>
#include <utils/Trace.h>
+#include "AudioFlinger.h"
#include "FastCapture.h"
namespace android {
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/FastCaptureDumpState.cpp
index 53eeba5..de4a6db 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/FastCaptureDumpState.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "FastCaptureDumpState"
-//define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include "Configuration.h"
#include <utils/Log.h>
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 45c68b5..2bc8066 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -334,6 +334,11 @@ void FastMixer::onWork()
if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
ALOG_ASSERT(mMixerBuffer != NULL);
+
+ // AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
+ // so we keep a side copy of enabledTracks
+ bool anyEnabledTracks = false;
+
// for each track, update volume and check for underrun
unsigned currentTrackMask = current->mTrackMask;
while (currentTrackMask != 0) {
@@ -392,11 +397,13 @@ void FastMixer::onWork()
underruns.mBitFields.mPartial++;
underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL;
mMixer->enable(name);
+ anyEnabledTracks = true;
}
} else {
underruns.mBitFields.mFull++;
underruns.mBitFields.mMostRecent = UNDERRUN_FULL;
mMixer->enable(name);
+ anyEnabledTracks = true;
}
ftDump->mUnderruns = underruns;
ftDump->mFramesReady = framesReady;
@@ -407,9 +414,14 @@ void FastMixer::onWork()
pts = AudioBufferProvider::kInvalidPTS;
}
- // process() is CPU-bound
- mMixer->process(pts);
- mMixerBufferState = MIXED;
+ if (anyEnabledTracks) {
+ // process() is CPU-bound
+ mMixer->process(pts);
+ mMixerBufferState = MIXED;
+ } else if (mMixerBufferState != ZEROED) {
+ mMixerBufferState = UNDEFINED;
+ }
+
} else if (mMixerBufferState == MIXED) {
mMixerBufferState = UNDEFINED;
}
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 2e68dad..031ff05 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -106,6 +106,14 @@ bool captureAudioOutputAllowed() {
return ok;
}
+bool accessFmRadioAllowed() {
+ static const String16 sAccessFmRadio("android.permission.ACCESS_FM_RADIO");
+ // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
+ bool ok = PermissionCache::checkCallingPermission(sAccessFmRadio);
+ if (!ok) ALOGE("Request requires android.permission.ACCESS_FM_RADIO");
+ return ok;
+}
+
bool captureHotwordAllowed() {
static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index fba6dce..dffb114 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -21,6 +21,7 @@ namespace android {
extern pid_t getpid_cached;
bool recordingAllowed(const String16& opPackageName);
+bool accessFmRadioAllowed();
bool captureAudioOutputAllowed();
bool captureHotwordAllowed();
bool settingsAllowed();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c3ee6c2..e5e8bdb 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2574,11 +2574,10 @@ void AudioFlinger::PlaybackThread::cacheParameters_l()
}
}
-void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void AudioFlinger::PlaybackThread::invalidateTracks_l(audio_stream_type_t streamType)
{
ALOGV("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
this, streamType, mTracks.size());
- Mutex::Autolock _l(mLock);
size_t size = mTracks.size();
for (size_t i = 0; i < size; i++) {
@@ -2589,6 +2588,12 @@ void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamTy
}
}
+void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+{
+ Mutex::Autolock _l(mLock);
+ invalidateTracks_l(streamType);
+}
+
status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
{
int session = chain->sessionId();
@@ -4470,8 +4475,12 @@ void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& ar
dprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames());
// Make a non-atomic copy of fast mixer dump state so it won't change underneath us
- const FastMixerDumpState copy(mFastMixerDumpState);
- copy.dump(fd);
+ // while we are dumping it. It may be inconsistent, but it won't mutate!
+ // This is a large object so we place it on the heap.
+ // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
+ const FastMixerDumpState *copy = new FastMixerDumpState(mFastMixerDumpState);
+ copy->dump(fd);
+ delete copy;
#ifdef STATE_QUEUE_DUMP
// Similar for state queue
@@ -4863,6 +4872,10 @@ bool AudioFlinger::DirectOutputThread::shouldStandby_l()
bool trackPaused = false;
bool trackStopped = false;
+ if ((mType == DIRECT) && audio_is_linear_pcm(mFormat) && !usesHwAvSync()) {
+ return !mStandby;
+ }
+
// do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack
// after a timeout and we will enter standby then.
if (mTracks.size() > 0) {
@@ -4983,6 +4996,8 @@ void AudioFlinger::DirectOutputThread::cacheParameters_l()
mStandbyDelayNs = 0;
} else if ((mType == OFFLOAD) && !audio_is_linear_pcm(mFormat)) {
mStandbyDelayNs = kOffloadStandbyDelayNs;
+ } else if (mType == DIRECT && mIsDirectPcm) {
+ mStandbyDelayNs = kOffloadStandbyDelayNs;
} else {
mStandbyDelayNs = microseconds(mActiveSleepTimeUs*2);
}
@@ -5154,15 +5169,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
if (track->isInvalid()) {
ALOGW("An invalidated track shouldn't be in active list");
tracksToRemove->add(track);
- continue;
- }
-
- if (track->mState == TrackBase::IDLE) {
+ } else if (track->mState == TrackBase::IDLE) {
ALOGW("An idle track shouldn't be in active list");
- continue;
- }
-
- if (track->isPausing()) {
+ } else if (track->isPausing()) {
track->setPaused();
if (last) {
if (mHwSupportsPause && !mHwPaused) {
@@ -5185,7 +5194,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
if (last) {
mFlushPending = true;
}
- } else if (track->isResumePending()){
+ } else if (track->isResumePending()) {
track->resumeAck();
if (last) {
if (mPausedBytesRemaining) {
@@ -5361,6 +5370,13 @@ void AudioFlinger::OffloadThread::flushHw_l()
}
}
+void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
+{
+ Mutex::Autolock _l(mLock);
+ mFlushPending = true;
+ PlaybackThread::invalidateTracks_l(streamType);
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
@@ -6454,9 +6470,13 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a
dprintf(fd, " Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
dprintf(fd, " Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
- // Make a non-atomic copy of fast capture dump state so it won't change underneath us
- const FastCaptureDumpState copy(mFastCaptureDumpState);
- copy.dump(fd);
+ // Make a non-atomic copy of fast capture dump state so it won't change underneath us
+ // while we are dumping it. It may be inconsistent, but it won't mutate!
+ // This is a large object so we place it on the heap.
+ // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
+ const FastCaptureDumpState *copy = new FastCaptureDumpState(mFastCaptureDumpState);
+ copy->dump(fd);
+ delete copy;
}
void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args __unused)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 48ff77d..8fab1e4 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -617,7 +617,8 @@ public:
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
// called with AudioFlinger lock held
- void invalidateTracks(audio_stream_type_t streamType);
+ void invalidateTracks_l(audio_stream_type_t streamType);
+ virtual void invalidateTracks(audio_stream_type_t streamType);
virtual size_t frameCount() const { return mNormalFrameCount; }
@@ -1000,6 +1001,7 @@ protected:
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
+ virtual void invalidateTracks(audio_stream_type_t streamType);
private:
size_t mPausedWriteLength; // length in bytes of write interrupted by pause
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index a5edc14..93e6266 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -332,8 +332,8 @@ public:
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
- virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId, bool added) = 0;
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& streamInfo, bool added) = 0;
+
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/Android.mk
index c402fd5..be86231 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.mk
@@ -4,4 +4,4 @@ LOCAL_PATH := $(call my-dir)
# Recursive call sub-folder Android.mk
#######################################################################
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(LOCAL_PATH)/plugin/Android.mk
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index d71daa4..82720f4 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -220,9 +220,9 @@ void AudioPolicyService::AudioPolicyClient::onDynamicPolicyMixStateUpdate(
}
void AudioPolicyService::AudioPolicyClient::onOutputSessionEffectsUpdate(
- audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+ sp<AudioSessionInfo>& info, bool added)
{
- mAudioPolicyService->onOutputSessionEffectsUpdate(stream, sessionId, added);
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, added);
}
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId()
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index f2d7f6f..d6fabfe 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -228,6 +228,8 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
{
status_t status = NO_ERROR;
+ ALOGV("addOutputSessionEffects %d", audioSession);
+
Mutex::Autolock _l(mLock);
// create audio processors according to stream
// FIXME: should we have specific post processing settings for internal streams?
@@ -235,6 +237,22 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
stream = AUDIO_STREAM_MUSIC;
}
+
+ // send the streaminfo notification only once
+ ssize_t sidx = mOutputAudioSessionInfo.indexOfKey(audioSession);
+ if (sidx >= 0) {
+ // AudioSessionInfo is existing and we just need to increase ref count
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(sidx);
+ info->mRefCount++;
+
+ if (info->mRefCount == 1) {
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, true);
+ }
+ ALOGV("addOutputSessionEffects(): session info %d refCount=%d", audioSession, info->mRefCount);
+ } else {
+ ALOGV("addOutputSessionEffects(): no output stream info found for stream");
+ }
+
ssize_t index = mOutputStreams.indexOfKey(stream);
if (index < 0) {
ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
@@ -246,8 +264,6 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
if (idx < 0) {
procDesc = new EffectVector(audioSession);
mOutputSessions.add(audioSession, procDesc);
-
- mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, true);
} else {
// EffectVector is existing and we just need to increase ref count
procDesc = mOutputSessions.valueAt(idx);
@@ -279,65 +295,123 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
return status;
}
-status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
- audio_stream_type_t stream,
- int audioSession)
+status_t AudioPolicyEffects::releaseOutputAudioSessionInfo(audio_io_handle_t /* output */,
+ audio_stream_type_t stream,
+ int session)
{
- status_t status = NO_ERROR;
- (void) output; // argument not used for now
- (void) stream; // argument not used for now
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
Mutex::Autolock _l(mLock);
- ssize_t index = mOutputSessions.indexOfKey(audioSession);
- if (index < 0) {
- ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
- return NO_ERROR;
+
+ ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session);
+ if (idx >= 0) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(idx);
+ if (info->mRefCount == 0) {
+ mOutputAudioSessionInfo.removeItemsAt(idx);
+ }
+ ALOGV("releaseOutputAudioSessionInfo() sessionId=%d refcount=%d",
+ session, info->mRefCount);
+ } else {
+ ALOGV("releaseOutputAudioSessionInfo() no session info found");
}
+ return NO_ERROR;
+}
- EffectVector *procDesc = mOutputSessions.valueAt(index);
+status_t AudioPolicyEffects::updateOutputAudioSessionInfo(audio_io_handle_t /* output */,
+ audio_stream_type_t stream,
+ int session,
+ audio_output_flags_t flags,
+ audio_channel_mask_t channelMask, uid_t uid)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
- // just in case it already has a death wish
- if (procDesc->mRefCount == 0) {
+ Mutex::Autolock _l(mLock);
+
+ // TODO: Handle other stream types based on client registration
+ if (stream != AUDIO_STREAM_MUSIC) {
return NO_ERROR;
}
- procDesc->mRefCount--;
- ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
- audioSession, procDesc->mRefCount);
+ // update AudioSessionInfo. This is used in the stream open/close path
+ // to notify userspace applications about session creation and
+ // teardown, allowing the app to make decisions about effects for
+ // a particular stream. This is independent of the current
+ // output_session_processing feature which forcibly attaches a
+ // static list of effects to a stream.
+ ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session);
+ sp<AudioSessionInfo> info;
+ if (idx < 0) {
+ info = new AudioSessionInfo(session, stream, flags, channelMask, uid);
+ mOutputAudioSessionInfo.add(session, info);
+ } else {
+ // the streaminfo may actually change
+ info = mOutputAudioSessionInfo.valueAt(idx);
+ info->mFlags = flags;
+ info->mChannelMask = channelMask;
+ }
- if (procDesc->mRefCount == 0) {
- mAudioPolicyService->releaseOutputSessionEffectsDelayed(
- output, stream, audioSession, 10000);
+ ALOGV("updateOutputAudioSessionInfo() sessionId=%d, flags=0x%x, channelMask=0x%x uid=%d refCount=%d",
+ info->mSessionId, info->mFlags, info->mChannelMask, info->mUid, info->mRefCount);
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyEffects::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ ALOGV("listAudioSessions() streams %d", streams);
+
+ for (unsigned int i = 0; i < mOutputAudioSessionInfo.size(); i++) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(i);
+ if (streams == -1 || info->mStream == streams) {
+ sessions.push_back(info);
+ }
}
- return status;
+ return NO_ERROR;
}
-status_t AudioPolicyEffects::doReleaseOutputSessionEffects(audio_io_handle_t output,
+status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
audio_stream_type_t stream,
int audioSession)
{
status_t status = NO_ERROR;
(void) output; // argument not used for now
+ (void) stream; // argument not used for now
Mutex::Autolock _l(mLock);
- ssize_t index = mOutputSessions.indexOfKey(audioSession);
+ ssize_t index = mOutputAudioSessionInfo.indexOfKey(audioSession);
+ if (index >= 0) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(index);
+ info->mRefCount--;
+ if (info->mRefCount == 0) {
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, false);
+ }
+ ALOGV("releaseOutputSessionEffects(): session=%d refCount=%d", info->mSessionId, info->mRefCount);
+ } else {
+ ALOGV("releaseOutputSessionEffects: no stream info was attached to this stream");
+ }
+
+ index = mOutputSessions.indexOfKey(audioSession);
if (index < 0) {
- ALOGV("doReleaseOutputSessionEffects: no output processing was attached to this stream");
+ ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
return NO_ERROR;
}
EffectVector *procDesc = mOutputSessions.valueAt(index);
- ALOGV("doReleaseOutputSessionEffects(): session: %d, refCount: %d",
+ procDesc->mRefCount--;
+ ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
audioSession, procDesc->mRefCount);
-
if (procDesc->mRefCount == 0) {
procDesc->setProcessorEnabled(false);
procDesc->mEffects.clear();
delete procDesc;
mOutputSessions.removeItemsAt(index);
- mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, false);
- ALOGV("doReleaseOutputSessionEffects(): output processing released from session: %d",
+ ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
audioSession);
}
return status;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 7988515..a95d49f 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -46,7 +46,7 @@ public:
// The constructor will parse audio_effects.conf
// First it will look whether vendor specific file exists,
// otherwise it will parse the system default file.
- AudioPolicyEffects(AudioPolicyService *audioPolicyService);
+ AudioPolicyEffects(AudioPolicyService *audioPolicyService);
virtual ~AudioPolicyEffects();
// NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
@@ -86,11 +86,18 @@ public:
audio_stream_type_t stream,
int audioSession);
- // For deferred release
- status_t doReleaseOutputSessionEffects(audio_io_handle_t output,
- audio_stream_type_t stream,
- int audioSession);
+ status_t updateOutputAudioSessionInfo(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession,
+ audio_output_flags_t flags,
+ audio_channel_mask_t channelMask, uid_t uid);
+
+ status_t releaseOutputAudioSessionInfo(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession);
+ status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions);
private:
@@ -200,6 +207,8 @@ private:
KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
// Automatic output effects are unique for audiosession ID
KeyedVector< int32_t, EffectVector* > mOutputSessions;
+ // Stream info for session events
+ KeyedVector< int32_t, sp<AudioSessionInfo> > mOutputAudioSessionInfo;
AudioPolicyService *mAudioPolicyService;
};
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index c0d3866..b23c35e 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -161,19 +161,32 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- ALOGV("getOutput()");
- Mutex::Autolock _l(mLock);
+ ALOGV("getOutputForAttr()");
+ status_t status = NO_ERROR;
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
- // if the caller is us, trust the specified uid
- if (IPCThreadState::self()->getCallingPid() != getpid_cached || uid == (uid_t)-1) {
- uid_t newclientUid = IPCThreadState::self()->getCallingUid();
- if (uid != (uid_t)-1 && uid != newclientUid) {
- ALOGW("%s uid %d tried to pass itself off as %d", __FUNCTION__, newclientUid, uid);
+ // if the caller is us, trust the specified uid
+ if (IPCThreadState::self()->getCallingPid() != getpid_cached || uid == (uid_t)-1) {
+ uid_t newclientUid = IPCThreadState::self()->getCallingUid();
+ if (uid != (uid_t)-1 && uid != newclientUid) {
+ ALOGW("%s uid %d tried to pass itself off as %d", __FUNCTION__, newclientUid, uid);
+ }
+ uid = newclientUid;
}
- uid = newclientUid;
+ status = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, samplingRate,
+ format, channelMask, flags, selectedDeviceId, offloadInfo);
+
+ audioPolicyEffects = mAudioPolicyEffects;
}
- return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, samplingRate,
- format, channelMask, flags, selectedDeviceId, offloadInfo);
+
+ if (status == NO_ERROR && audioPolicyEffects != 0) {
+ audioPolicyEffects->updateOutputAudioSessionInfo(*output,
+ *stream, session, flags, channelMask, uid);
+ }
+
+ return status;
}
status_t AudioPolicyService::startOutput(audio_io_handle_t output,
@@ -269,8 +282,16 @@ void AudioPolicyService::doReleaseOutput(audio_io_handle_t output,
audio_session_t session)
{
ALOGV("doReleaseOutput from tid %d", gettid());
- Mutex::Autolock _l(mLock);
- mAudioPolicyManager->releaseOutput(output, stream, session);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
+ mAudioPolicyManager->releaseOutput(output, stream, session);
+ }
+ if (audioPolicyEffects != 0) {
+ audioPolicyEffects->releaseOutputAudioSessionInfo(output,
+ stream, session);
+ }
}
status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
@@ -295,6 +316,11 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) {
return BAD_VALUE;
}
+
+ if ((attr->source == AUDIO_SOURCE_FM_TUNER) && !accessFmRadioAllowed()) {
+ return BAD_VALUE;
+ }
+
sp<AudioPolicyEffects>audioPolicyEffects;
status_t status;
AudioPolicyInterface::input_type_t inputType;
@@ -717,4 +743,25 @@ status_t AudioPolicyService::stopAudioSource(audio_io_handle_t handle)
return mAudioPolicyManager->stopAudioSource(handle);
}
+status_t AudioPolicyService::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+
+ if (audioPolicyEffects != 0) {
+ return audioPolicyEffects->listAudioSessions(streams, sessions);
+ }
+
+ // no errors here if effects are not available
+ return NO_ERROR;
+}
+
+
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
index 318c6d2..da7f45d 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
@@ -275,6 +275,10 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
return BAD_VALUE;
}
+ if ((inputSource == AUDIO_SOURCE_FM_TUNER) && !accessFmRadioAllowed()) {
+ return BAD_VALUE;
+ }
+
#ifdef HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB
if (inputSource == AUDIO_SOURCE_HOTWORD)
inputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
@@ -642,4 +646,9 @@ status_t AudioPolicyService::stopAudioSource(audio_io_handle_t handle)
return INVALID_OPERATION;
}
+status_t AudioPolicyService::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ return INVALID_OPERATION;
+}
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 58cfe37..79370f4 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -177,23 +177,6 @@ void AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled)
mNotificationClients.valueFor(uid)->setAudioPortCallbacksEnabled(enabled);
}
-status_t AudioPolicyService::setEffectSessionCallbacksEnabled(bool enabled)
-{
- Mutex::Autolock _l(mNotificationClientsLock);
-
- uid_t uid = IPCThreadState::self()->getCallingUid();
- if (mNotificationClients.indexOfKey(uid) < 0) {
- return NO_INIT;
- }
- if (!modifyAudioRoutingAllowed()) {
- ALOGE("setEffectSessionCallbacksEnabled requires MODIFY_AUDIO_ROUTING");
- return PERMISSION_DENIED;
- }
- mNotificationClients.valueFor(uid)->setEffectSessionCallbacksEnabled(enabled);
- return OK;
-}
-
-
// removeNotificationClient() is called when the client process dies.
void AudioPolicyService::removeNotificationClient(uid_t uid)
{
@@ -271,22 +254,18 @@ status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_co
return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}
-void AudioPolicyService::onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId,
- bool added)
+void AudioPolicyService::onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
{
ALOGV("AudioPolicyService::onOutputSessionEffectsUpdate(%d, %d, %d)",
- stream, sessionId, added);
- mOutputCommandThread->effectSessionUpdateCommand(stream, sessionId, added);
+ info->mStream, info->mSessionId, added);
+ mOutputCommandThread->effectSessionUpdateCommand(info, added);
}
-void AudioPolicyService::doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId,
- bool added)
+void AudioPolicyService::doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
{
Mutex::Autolock _l(mNotificationClientsLock);
for (size_t i = 0; i < mNotificationClients.size(); i++) {
- mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(stream, sessionId, added);
+ mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(info, added);
}
}
@@ -294,8 +273,7 @@ AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyS
const sp<IAudioPolicyServiceClient>& client,
uid_t uid)
: mService(service), mUid(uid), mAudioPolicyServiceClient(client),
- mAudioPortCallbacksEnabled(false),
- mEffectSessionCallbacksEnabled(false)
+ mAudioPortCallbacksEnabled(false)
{
}
@@ -327,10 +305,10 @@ void AudioPolicyService::NotificationClient::onAudioPatchListUpdate()
}
void AudioPolicyService::NotificationClient::onOutputSessionEffectsUpdate(
- audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+ sp<AudioSessionInfo>& info, bool added)
{
- if (mAudioPolicyServiceClient != 0 && mEffectSessionCallbacksEnabled) {
- mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(stream, sessionId, added);
+ if (mAudioPolicyServiceClient != 0) {
+ mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(info, added);
}
}
@@ -347,23 +325,12 @@ void AudioPolicyService::NotificationClient::setAudioPortCallbacksEnabled(bool e
mAudioPortCallbacksEnabled = enabled;
}
-void AudioPolicyService::NotificationClient::setEffectSessionCallbacksEnabled(bool enabled)
-{
- mEffectSessionCallbacksEnabled = enabled;
-}
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
IPCThreadState::self()->getCallingPid());
}
-void AudioPolicyService::releaseOutputSessionEffectsDelayed(
- audio_io_handle_t output, audio_stream_type_t stream,
- audio_unique_id_t sessionId, int delayMs)
-{
- mAudioCommandThread->releaseOutputSessionEffectsCommand(output, stream, sessionId, delayMs);
-}
-
static bool tryLock(Mutex& mutex)
{
bool locked = false;
@@ -639,30 +606,16 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
EffectSessionUpdateData *data =
(EffectSessionUpdateData *)command->mParam.get();
ALOGV("AudioCommandThread() processing effect session update %d %d %d",
- data->mStream, data->mSessionId, data->mAdded);
+ data->mAudioSessionInfo->mStream, data->mAudioSessionInfo->mSessionId,
+ data->mAdded);
svc = mService.promote();
if (svc == 0) {
break;
}
mLock.unlock();
- svc->doOnOutputSessionEffectsUpdate(data->mStream, data->mSessionId, data->mAdded);
+ svc->doOnOutputSessionEffectsUpdate(data->mAudioSessionInfo, data->mAdded);
mLock.lock();
} break;
- case RELEASE_OUTPUT_SESSION_EFFECTS: {
- ReleaseOutputSessionEffectsData *data =
- (ReleaseOutputSessionEffectsData *)command->mParam.get();
- ALOGV("AudioCommandThread() processing release output session effects %d %d %d",
- data->mOutput, data->mStream, data->mSessionId);
- svc = mService.promote();
- if (svc == 0) {
- break;
- }
- mLock.unlock();
- svc->mAudioPolicyEffects->doReleaseOutputSessionEffects(
- data->mOutput, data->mStream, data->mSessionId);
- mLock.lock();
- } break;
-
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -937,37 +890,19 @@ void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand(
}
void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand(
- audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+ sp<AudioSessionInfo>& streamInfo, bool added)
{
sp<AudioCommand> command = new AudioCommand();
command->mCommand = EFFECT_SESSION_UPDATE;
EffectSessionUpdateData *data = new EffectSessionUpdateData();
- data->mStream = stream;
- data->mSessionId = sessionId;
+ data->mAudioSessionInfo = streamInfo;
data->mAdded = added;
command->mParam = data;
ALOGV("AudioCommandThread() sending effect session update (id=%d) for stream %d (added=%d)",
- stream, sessionId, added);
+ streamInfo->mStream, streamInfo->mSessionId, added);
sendCommand(command);
}
-void AudioPolicyService::AudioCommandThread::releaseOutputSessionEffectsCommand(
- audio_io_handle_t output, audio_stream_type_t stream,
- audio_unique_id_t sessionId, int delayMs)
-{
- sp<AudioCommand> command = new AudioCommand();
- command->mCommand = RELEASE_OUTPUT_SESSION_EFFECTS;
- ReleaseOutputSessionEffectsData *data = new ReleaseOutputSessionEffectsData();
- data->mOutput = output;
- data->mStream = stream;
- data->mSessionId = sessionId;
- command->mParam = data;
- ALOGV("AudioCommandThread() sending release output session effects (id=%d) for stream %d",
- sessionId, stream);
- sendCommand(command, delayMs);
-}
-
-
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 9b17a26..b7f55ae 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -202,7 +202,8 @@ public:
audio_io_handle_t *handle);
virtual status_t stopAudioSource(audio_io_handle_t handle);
- virtual status_t setEffectSessionCallbacksEnabled(bool enabled);
+ virtual status_t listAudioSessions(audio_stream_type_t stream,
+ Vector< sp<AudioSessionInfo>>& sessions);
status_t doStartOutput(audio_io_handle_t output,
audio_stream_type_t stream,
@@ -231,14 +232,8 @@ public:
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
- void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId, bool added);
- void doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId, bool added);
- void releaseOutputSessionEffectsDelayed(audio_io_handle_t output,
- audio_stream_type_t stream,
- audio_unique_id_t sessionId,
- int delayMs);
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+ void doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
private:
AudioPolicyService() ANDROID_API;
@@ -273,7 +268,6 @@ private:
SET_AUDIOPORT_CONFIG,
DYN_POLICY_MIX_STATE_UPDATE,
EFFECT_SESSION_UPDATE,
- RELEASE_OUTPUT_SESSION_EFFECTS,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -316,12 +310,7 @@ private:
int delayMs);
void dynamicPolicyMixStateUpdateCommand(String8 regId, int32_t state);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
- void effectSessionUpdateCommand(audio_stream_type_t stream,
- audio_unique_id_t sessionId, bool added);
- void releaseOutputSessionEffectsCommand(audio_io_handle_t output,
- audio_stream_type_t stream,
- audio_unique_id_t sessionId,
- int delayMs = 0);
+ void effectSessionUpdateCommand(sp<AudioSessionInfo>& info, bool added);
private:
class AudioCommandData;
@@ -420,18 +409,10 @@ private:
class EffectSessionUpdateData : public AudioCommandData {
public:
- audio_stream_type_t mStream;
- audio_unique_id_t mSessionId;
+ sp<AudioSessionInfo> mAudioSessionInfo;
bool mAdded;
};
- class ReleaseOutputSessionEffectsData : public AudioCommandData {
- public:
- audio_io_handle_t mOutput;
- audio_stream_type_t mStream;
- audio_unique_id_t mSessionId;
- };
-
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -541,8 +522,8 @@ private:
virtual audio_unique_id_t newAudioUniqueId();
- virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId, bool added);
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+
private:
AudioPolicyService *mAudioPolicyService;
@@ -560,9 +541,8 @@ private:
void onAudioPatchListUpdate();
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void setAudioPortCallbacksEnabled(bool enabled);
- void setEffectSessionCallbacksEnabled(bool enabled);
- void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
- audio_unique_id_t sessionId, bool added);
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info,
+ bool added);
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
@@ -574,7 +554,6 @@ private:
const uid_t mUid;
const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
bool mAudioPortCallbacksEnabled;
- bool mEffectSessionCallbacksEnabled;
};
// Internal dump utilities.
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index 406c1c4..62ce610 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -828,6 +828,18 @@ status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
return device->setPreviewWindow(mSurface);
}
+static void notifyCallback(int32_t, int32_t, int32_t, void*) {
+ /* Empty */
+}
+
+static void dataCallback(int32_t, const sp<IMemory>&, camera_frame_metadata_t*, void*) {
+ /* Empty */
+}
+
+static void dataCallbackTimestamp(nsecs_t, int32_t, const sp<IMemory>&, void*) {
+ /* Empty */
+}
+
status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
const String8& cameraId) {
sp<CameraHardwareInterface> device =
@@ -841,7 +853,7 @@ status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
}
// need to set __get_memory in set_callbacks().
- device->setCallbacks(NULL, NULL, NULL, NULL);
+ device->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, this);
mParameters = device->getParameters();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a560b93..3c9fd16 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -81,7 +81,7 @@ static void camera_device_status_change(
sp<CameraService> cs = const_cast<CameraService*>(
static_cast<const CameraService*>(callbacks));
- cs->onDeviceStatusChanged(static_cast<camera_device_status_t>(camera_id),
+ cs->onDeviceStatusChanged(camera_id,
static_cast<camera_device_status_t>(new_status));
}
@@ -277,7 +277,7 @@ CameraService::~CameraService() {
gCameraService = nullptr;
}
-void CameraService::onDeviceStatusChanged(camera_device_status_t cameraId,
+void CameraService::onDeviceStatusChanged(int cameraId,
camera_device_status_t newStatus) {
ALOGI("%s: Status changed for cameraId=%d, newStatus=%d", __FUNCTION__,
cameraId, newStatus);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ee4c3f9..53233bd 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -102,7 +102,7 @@ public:
/////////////////////////////////////////////////////////////////////
// HAL Callbacks
- virtual void onDeviceStatusChanged(camera_device_status_t cameraId,
+ virtual void onDeviceStatusChanged(int cameraId,
camera_device_status_t newStatus);
virtual void onTorchStatusChanged(const String8& cameraId,
ICameraServiceListener::TorchStatus
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 55555fd..af46d63 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -243,11 +243,6 @@ void CameraClient::disconnect() {
return;
}
- if (mClientPid <= 0) {
- LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
- return;
- }
-
// Make sure disconnect() is done once and once only, whether it is called
// from the user directly, or called by the destructor.
if (mHardware == 0) return;
@@ -700,6 +695,9 @@ void CameraClient::disableMsgType(int32_t msgType) {
#define CHECK_MESSAGE_INTERVAL 10 // 10ms
bool CameraClient::lockIfMessageWanted(int32_t msgType) {
+#ifdef MTK_HARDWARE
+ return true;
+#endif
int sleepCount = 0;
while (mMsgEnabled & msgType) {
if (mLock.tryLock() == NO_ERROR) {
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 66d7b00..9e6c0db 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -30,6 +30,7 @@
#include <utils/Trace.h>
#include <gui/BufferItem.h>
#include <gui/Surface.h>
+#include <camera/ICameraRecordingProxy.h>
#include <media/hardware/HardwareAPI.h>
#include "common/CameraDeviceBase.h"
@@ -826,6 +827,9 @@ status_t StreamingProcessor::processRecordingFrame() {
(uint8_t*)heap->getBase() + offset);
payload->eType = kMetadataBufferTypeANWBuffer;
payload->pBuffer = imgBuffer.mGraphicBuffer->getNativeBuffer();
+ // b/28466701
+ payload->pBuffer = (ANativeWindowBuffer*)((uint8_t*)payload->pBuffer -
+ ICameraRecordingProxy::getCommonBaseAddress());
payload->nFenceFd = -1;
ALOGVV("%s: Camera %d: Sending out ANWBuffer %p",
@@ -874,6 +878,10 @@ void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
return;
}
+ // b/28466701
+ payload->pBuffer = (ANativeWindowBuffer*)(((uint8_t*)payload->pBuffer) +
+ ICameraRecordingProxy::getCommonBaseAddress());
+
// Release the buffer back to the recording queue
size_t itemIndex;
for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 50d9d75..8b43154 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -43,6 +43,7 @@
#include <utils/Trace.h>
#include <utils/Timers.h>
+#include "CameraService.h"
#include "utils/CameraTraces.h"
#include "mediautils/SchedulingPolicyService.h"
#include "device3/Camera3Device.h"
@@ -1115,6 +1116,13 @@ status_t Camera3Device::createDefaultRequest(int templateId,
CameraMetadata *request) {
ATRACE_CALL();
ALOGV("%s: for template %d", __FUNCTION__, templateId);
+
+ if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
+ android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
+ IPCThreadState::self()->getCallingUid(), NULL, 0);
+ return BAD_VALUE;
+ }
+
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 9de6fe2..a1cc6ff 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -270,6 +270,37 @@ void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognitio
if (module == NULL) {
return;
}
+ if (event-> type == SOUND_MODEL_TYPE_KEYPHRASE && event->data_size != 0
+ && event->data_offset != sizeof(struct sound_trigger_phrase_recognition_event)) {
+ // set some defaults for the phrase if the recognition event won't be parsed properly
+ // TODO: read defaults from the config
+
+ struct sound_trigger_phrase_recognition_event newEvent;
+ memset(&newEvent, 0, sizeof(struct sound_trigger_phrase_recognition_event));
+
+ sp<Model> model = module->getModel(event->model);
+
+ newEvent.num_phrases = 1;
+ newEvent.phrase_extras[0].id = 100;
+ newEvent.phrase_extras[0].recognition_modes = RECOGNITION_MODE_VOICE_TRIGGER;
+ newEvent.phrase_extras[0].confidence_level = 100;
+ newEvent.phrase_extras[0].num_levels = 1;
+ newEvent.phrase_extras[0].levels[0].level = 100;
+ newEvent.phrase_extras[0].levels[0].user_id = 100;
+ newEvent.common.status = event->status;
+ newEvent.common.type = event->type;
+ newEvent.common.model = event->model;
+ newEvent.common.capture_available = event->capture_available;
+ newEvent.common.capture_session = event->capture_session;
+ newEvent.common.capture_delay_ms = event->capture_delay_ms;
+ newEvent.common.capture_preamble_ms = event->capture_preamble_ms;
+ newEvent.common.trigger_in_data = event->trigger_in_data;
+ newEvent.common.audio_config = event->audio_config;
+ newEvent.common.data_size = event->data_size;
+ newEvent.common.data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
+
+ event = &newEvent.common;
+ }
sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
if (eventMemory == 0) {
return;
@@ -534,6 +565,22 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM
struct sound_trigger_sound_model *sound_model =
(struct sound_trigger_sound_model *)modelMemory->pointer();
+ size_t structSize;
+ if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+ structSize = sizeof(struct sound_trigger_phrase_sound_model);
+ } else {
+ structSize = sizeof(struct sound_trigger_sound_model);
+ }
+
+ if (sound_model->data_offset < structSize ||
+ sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
+ modelMemory->size() < sound_model->data_offset ||
+ sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
+ android_errorWriteLog(0x534e4554, "30148546");
+ ALOGE("loadSoundModel() data_size is too big");
+ return BAD_VALUE;
+ }
+
AutoMutex lock(mLock);
if (mModels.size() >= mDescriptor.properties.max_sound_models) {
@@ -603,11 +650,23 @@ status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t ha
return PERMISSION_DENIED;
}
- if (dataMemory != 0 && dataMemory->pointer() == NULL) {
- ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
+ if (dataMemory == 0 || dataMemory->pointer() == NULL) {
+ ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
return BAD_VALUE;
}
+
+ struct sound_trigger_recognition_config *config =
+ (struct sound_trigger_recognition_config *)dataMemory->pointer();
+
+ if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
+ config->data_size > (UINT_MAX - config->data_offset) ||
+ dataMemory->size() < config->data_offset ||
+ config->data_size > (dataMemory->size() - config->data_offset)) {
+ ALOGE("startRecognition() data_size is too big");
+ return BAD_VALUE;
+ }
+
AutoMutex lock(mLock);
if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
return INVALID_OPERATION;
@@ -616,17 +675,11 @@ status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t ha
if (model == 0) {
return BAD_VALUE;
}
- if ((dataMemory == 0) ||
- (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) {
- return BAD_VALUE;
- }
if (model->mState == Model::STATE_ACTIVE) {
return INVALID_OPERATION;
}
- struct sound_trigger_recognition_config *config =
- (struct sound_trigger_recognition_config *)dataMemory->pointer();
//TODO: get capture handle and device from audio policy service
config->capture_handle = model->mCaptureIOHandle;
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
index 2138cb7..e959b83 100644
--- a/soundtrigger/SoundTrigger.cpp
+++ b/soundtrigger/SoundTrigger.cpp
@@ -55,7 +55,7 @@ namespace {
sp<DeathNotifier> gDeathNotifier;
}; // namespace anonymous
-const sp<ISoundTriggerHwService>& SoundTrigger::getSoundTriggerHwService()
+const sp<ISoundTriggerHwService> SoundTrigger::getSoundTriggerHwService()
{
Mutex::Autolock _l(gLock);
if (gSoundTriggerHwService.get() == 0) {
@@ -84,7 +84,7 @@ status_t SoundTrigger::listModules(struct sound_trigger_module_descriptor *modul
uint32_t *numModules)
{
ALOGV("listModules()");
- const sp<ISoundTriggerHwService>& service = getSoundTriggerHwService();
+ const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
if (service == 0) {
return NO_INIT;
}
@@ -96,7 +96,7 @@ sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module
{
ALOGV("attach()");
sp<SoundTrigger> soundTrigger;
- const sp<ISoundTriggerHwService>& service = getSoundTriggerHwService();
+ const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
if (service == 0) {
return soundTrigger;
}
@@ -116,7 +116,7 @@ sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module
status_t SoundTrigger::setCaptureState(bool active)
{
ALOGV("setCaptureState(%d)", active);
- const sp<ISoundTriggerHwService>& service = getSoundTriggerHwService();
+ const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
if (service == 0) {
return NO_INIT;
}