Merge "aaudio: test some state transitions"
diff --git a/camera/include/camera/camera2/CaptureRequest.h b/camera/include/camera/camera2/CaptureRequest.h
index 0180183..e39dfcf 100644
--- a/camera/include/camera/camera2/CaptureRequest.h
+++ b/camera/include/camera/camera2/CaptureRequest.h
@@ -43,6 +43,7 @@
CameraMetadata mMetadata;
Vector<sp<Surface> > mSurfaceList;
bool mIsReprocess;
+ void* mContext; // arbitrary user context from NDK apps, null for java apps
/**
* Keep impl up-to-date with CaptureRequest.java in frameworks/base
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
index 5b4c180..ac1856b 100644
--- a/camera/ndk/NdkCaptureRequest.cpp
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -142,3 +142,40 @@
delete request;
return;
}
+
+EXPORT
+camera_status_t ACaptureRequest_setUserContext(
+ ACaptureRequest* request, void* context) {
+ if (request == nullptr) {
+ ALOGE("%s: invalid argument! request is NULL", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return request->setContext(context);
+}
+
+EXPORT
+camera_status_t ACaptureRequest_getUserContext(
+ const ACaptureRequest* request, /*out*/void** context) {
+ if (request == nullptr || context == nullptr) {
+ ALOGE("%s: invalid argument! request %p, context %p",
+ __FUNCTION__, request, context);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return request->getContext(context);
+}
+
+EXPORT
+ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) {
+ ATRACE_CALL();
+ if (src == nullptr) {
+ ALOGE("%s: src is null!", __FUNCTION__);
+ return nullptr;
+ }
+
+ ACaptureRequest* pRequest = new ACaptureRequest();
+ pRequest->settings = new ACameraMetadata(*(src->settings));
+ pRequest->targets = new ACameraOutputTargets();
+ *(pRequest->targets) = *(src->targets);
+ pRequest->context = src->context;
+ return pRequest;
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 9ce0ac8..45fa28e 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -372,6 +372,7 @@
sp<CaptureRequest> req(new CaptureRequest());
req->mMetadata = request->settings->getInternalData();
req->mIsReprocess = false; // NDK does not support reprocessing yet
+ req->mContext = request->context;
for (auto outputTarget : request->targets->mOutputs) {
ANativeWindow* anw = outputTarget.mWindow;
@@ -398,6 +399,7 @@
ACameraOutputTarget outputTarget(anw);
pRequest->targets->mOutputs.insert(outputTarget);
}
+ pRequest->context = req->mContext;
return pRequest;
}
diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h
index e5b453e..06b2cc3 100644
--- a/camera/ndk/impl/ACaptureRequest.h
+++ b/camera/ndk/impl/ACaptureRequest.h
@@ -45,8 +45,19 @@
};
struct ACaptureRequest {
+ camera_status_t setContext(void* ctx) {
+ context = ctx;
+ return ACAMERA_OK;
+ }
+
+ camera_status_t getContext(void** ctx) const {
+ *ctx = context;
+ return ACAMERA_OK;
+ }
+
ACameraMetadata* settings;
ACameraOutputTargets* targets;
+ void* context;
};
#endif // _ACAPTURE_REQUEST_H
diff --git a/camera/ndk/include/camera/NdkCaptureRequest.h b/camera/ndk/include/camera/NdkCaptureRequest.h
index c62ba2c..4961ce3 100644
--- a/camera/ndk/include/camera/NdkCaptureRequest.h
+++ b/camera/ndk/include/camera/NdkCaptureRequest.h
@@ -305,6 +305,58 @@
#endif /* __ANDROID_API__ >= 24 */
+#if __ANDROID_API__ >= 28
+
+/**
+ * Associate an arbitrary user context pointer to the {@link ACaptureRequest}
+ *
+ * This method is useful for user to identify the capture request in capture session callbacks.
+ * The context is NULL for newly created request.
+ * {@link ACameraOutputTarget_free} will not free the context. Also calling this method twice
+ * will not cause the previous context be freed.
+ * Also note that calling this method after the request has been sent to capture session will not
+ * change the context pointer in the capture callbacks.
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param context the user context pointer to be associated with this capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL.</li></ul>
+ */
+camera_status_t ACaptureRequest_setUserContext(
+ ACaptureRequest* request, void* context);
+
+/**
+ * Get the user context pointer of the {@link ACaptureRequest}
+ *
+ * This method is useful for user to identify the capture request in capture session callbacks.
+ * The context is NULL for newly created request.
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param context the user context pointer of this capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL.</li></ul>
+ */
+camera_status_t ACaptureRequest_getUserContext(
+ const ACaptureRequest* request, /*out*/void** context);
+
+/**
+ * Create a copy of input {@link ACaptureRequest}.
+ *
+ * <p>The returned ACaptureRequest must be freed by the application by {@link ACaptureRequest_free}
+ * after application is done using it.</p>
+ *
+ * @param src the input {@link ACaptureRequest} to be copied.
+ *
+ * @return a valid ACaptureRequest pointer or NULL if the input request cannot be copied.
+ */
+ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src);
+
+#endif /* __ANDROID_API__ >= 28 */
+
__END_DECLS
#endif /* _NDK_CAPTURE_REQUEST_H */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 0a8a6e9..58d239b 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -26,9 +26,11 @@
ACameraOutputTarget_create;
ACameraOutputTarget_free;
ACaptureRequest_addTarget;
+ ACaptureRequest_copy;
ACaptureRequest_free;
ACaptureRequest_getAllTags;
ACaptureRequest_getConstEntry;
+ ACaptureRequest_getUserContext;
ACaptureRequest_removeTarget;
ACaptureRequest_setEntry_double;
ACaptureRequest_setEntry_float;
@@ -36,6 +38,7 @@
ACaptureRequest_setEntry_i64;
ACaptureRequest_setEntry_rational;
ACaptureRequest_setEntry_u8;
+ ACaptureRequest_setUserContext;
ACaptureSessionOutputContainer_add;
ACaptureSessionOutputContainer_create;
ACaptureSessionOutputContainer_free;
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 2731f0f..f26ed25 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -678,6 +678,15 @@
off64_t pos = 0;
off64_t post_id3_pos;
uint32_t header;
+ uint8_t mpeg_header[5];
+ if (source->readAt(0, mpeg_header, sizeof(mpeg_header)) < (ssize_t)sizeof(mpeg_header)) {
+ return NULL;
+ }
+
+ if (!memcmp("\x00\x00\x01\xba", mpeg_header, 4) && (mpeg_header[4] >> 4) == 2) {
+ ALOGV("MPEG1PS container is not supported!");
+ return NULL;
+ }
if (!Resync(source, 0, &pos, &post_id3_pos, &header)) {
return NULL;
}
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 26a320c..2432cac 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -89,7 +89,8 @@
audio_input_flags_t flags,
uid_t uid,
pid_t pid,
- const audio_attributes_t* pAttributes)
+ const audio_attributes_t* pAttributes,
+ audio_port_handle_t selectedDeviceId)
: mActive(false),
mStatus(NO_INIT),
mOpPackageName(opPackageName),
@@ -97,12 +98,11 @@
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mProxy(NULL),
- mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
mPortId(AUDIO_PORT_HANDLE_NONE)
{
mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
- uid, pid, pAttributes);
+ uid, pid, pAttributes, selectedDeviceId);
}
AudioRecord::~AudioRecord()
@@ -148,7 +148,8 @@
audio_input_flags_t flags,
uid_t uid,
pid_t pid,
- const audio_attributes_t* pAttributes)
+ const audio_attributes_t* pAttributes,
+ audio_port_handle_t selectedDeviceId)
{
ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
@@ -156,6 +157,8 @@
inputSource, sampleRate, format, channelMask, frameCount, notificationFrames,
sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid);
+ mSelectedDeviceId = selectedDeviceId;
+
switch (transferType) {
case TRANSFER_DEFAULT:
if (cbf == NULL || threadCanCallJava) {
@@ -489,6 +492,7 @@
mAudioRecord->stop();
}
android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
+ mProxy->interrupt();
}
}
return NO_ERROR;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 36961d6..30f97ac 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2651,23 +2651,28 @@
status_t AudioTrack::dump(int fd, const Vector<String16>& args __unused) const
{
-
- const size_t SIZE = 256;
- char buffer[SIZE];
String8 result;
result.append(" AudioTrack::dump\n");
- snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType,
- mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
- result.append(buffer);
- snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%zu)\n", mFormat,
- mChannelCount, mFrameCount);
- result.append(buffer);
- snprintf(buffer, 255, " sample rate(%u), speed(%f), status(%d)\n",
- mSampleRate, mPlaybackRate.mSpeed, mStatus);
- result.append(buffer);
- snprintf(buffer, 255, " state(%d), latency (%d)\n", mState, mLatency);
- result.append(buffer);
+ result.appendFormat(" status(%d), state(%d), session Id(%d), flags(%x)\n",
+ mStatus, mState, mSessionId, mFlags);
+ result.appendFormat(" stream type(%d), left - right volume(%f, %f)\n",
+ (mStreamType == AUDIO_STREAM_DEFAULT) ?
+ audio_attributes_to_stream_type(&mAttributes) : mStreamType,
+ mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
+ result.appendFormat(" format(%x), channel mask(%x), channel count(%u)\n",
+ mFormat, mChannelMask, mChannelCount);
+ result.appendFormat(" sample rate(%u), original sample rate(%u), speed(%f)\n",
+ mSampleRate, mOriginalSampleRate, mPlaybackRate.mSpeed);
+ result.appendFormat(" frame count(%zu), req. frame count(%zu)\n",
+ mFrameCount, mReqFrameCount);
+ result.appendFormat(" notif. frame count(%u), req. notif. frame count(%u),"
+ " req. notif. per buff(%u)\n",
+ mNotificationFramesAct, mNotificationFramesReq, mNotificationsPerBufferReq);
+ result.appendFormat(" latency (%d), selected device Id(%d), routed device Id(%d)\n",
+ mLatency, mSelectedDeviceId, mRoutedDeviceId);
+ result.appendFormat(" output(%d) AF latency (%u) AF frame count(%zu) AF SampleRate(%u)\n",
+ mOutput, mAfLatency, mAfFrameCount, mAfSampleRate);
::write(fd, result.string(), result.size());
return NO_ERROR;
}
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index c6ad1b5..51596a2 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -185,7 +185,8 @@
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
uid_t uid = AUDIO_UID_INVALID,
pid_t pid = -1,
- const audio_attributes_t* pAttributes = NULL);
+ const audio_attributes_t* pAttributes = NULL,
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
/* Terminates the AudioRecord and unregisters it from AudioFlinger.
* Also destroys all resources associated with the AudioRecord.
@@ -223,7 +224,8 @@
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
uid_t uid = AUDIO_UID_INVALID,
pid_t pid = -1,
- const audio_attributes_t* pAttributes = NULL);
+ const audio_attributes_t* pAttributes = NULL,
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
/* Result of constructing the AudioRecord. This must be checked for successful initialization
* before using any AudioRecord API (except for set()), because using
diff --git a/media/libaudiohal/EffectBufferHalHidl.h b/media/libaudiohal/EffectBufferHalHidl.h
index 66a81c2..d7a43ae 100644
--- a/media/libaudiohal/EffectBufferHalHidl.h
+++ b/media/libaudiohal/EffectBufferHalHidl.h
@@ -35,6 +35,8 @@
virtual audio_buffer_t* audioBuffer();
virtual void* externalData() const;
+ virtual size_t getSize() const override { return mBufferSize; }
+
virtual void setExternalData(void* external);
virtual void setFrameCount(size_t frameCount);
virtual bool checkFrameCountChange();
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 61fb6bab..f4d1958 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -121,16 +121,24 @@
}
status_t EffectHalHidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
- if (mInBuffer == 0 || buffer->audioBuffer() != mInBuffer->audioBuffer()) {
- mBuffersChanged = true;
+ if (!mBuffersChanged) {
+ if (buffer.get() == nullptr || mInBuffer.get() == nullptr) {
+ mBuffersChanged = buffer.get() != mInBuffer.get();
+ } else {
+ mBuffersChanged = buffer->audioBuffer() != mInBuffer->audioBuffer();
+ }
}
mInBuffer = buffer;
return OK;
}
status_t EffectHalHidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
- if (mOutBuffer == 0 || buffer->audioBuffer() != mOutBuffer->audioBuffer()) {
- mBuffersChanged = true;
+ if (!mBuffersChanged) {
+ if (buffer.get() == nullptr || mOutBuffer.get() == nullptr) {
+ mBuffersChanged = buffer.get() != mOutBuffer.get();
+ } else {
+ mBuffersChanged = buffer->audioBuffer() != mOutBuffer->audioBuffer();
+ }
}
mOutBuffer = buffer;
return OK;
diff --git a/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
index e862f6e..1cae662 100644
--- a/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
@@ -37,6 +37,8 @@
return externalData() != nullptr ? externalData() : audioBuffer()->raw;
}
+ virtual size_t getSize() const = 0;
+
virtual void setExternalData(void* external) = 0;
virtual void setFrameCount(size_t frameCount) = 0;
virtual bool checkFrameCountChange() = 0; // returns whether frame count has been updated
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 3e72c89..43b97a5 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -1947,11 +1947,10 @@
case AUDIO_FORMAT_PCM_16_BIT:
switch (mixerOutFormat) {
case AUDIO_FORMAT_PCM_FLOAT:
- memcpy_to_float_from_q4_27((float*)out, (int32_t*)in, sampleCount);
+ memcpy_to_float_from_q4_27((float*)out, (const int32_t*)in, sampleCount);
break;
case AUDIO_FORMAT_PCM_16_BIT:
- // two int16_t are produced per iteration
- ditherAndClamp((int32_t*)out, (int32_t*)in, sampleCount >> 1);
+ memcpy_to_i16_from_q4_27((int16_t*)out, (const int32_t*)in, sampleCount);
break;
default:
LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
diff --git a/media/libaudioprocessing/tests/test-mixer.cpp b/media/libaudioprocessing/tests/test-mixer.cpp
index 75dbf91..b67810d 100644
--- a/media/libaudioprocessing/tests/test-mixer.cpp
+++ b/media/libaudioprocessing/tests/test-mixer.cpp
@@ -316,8 +316,7 @@
outputSampleRate, outputChannels, outputFrames, useMixerFloat);
if (auxFilename) {
// Aux buffer is always in q4_27 format for now.
- // memcpy_to_i16_from_q4_27(), but with stereo frame count (not sample count)
- ditherAndClamp((int32_t*)auxAddr, (int32_t*)auxAddr, outputFrames >> 1);
+ memcpy_to_i16_from_q4_27((int16_t*)auxAddr, (const int32_t*)auxAddr, outputFrames);
writeFile(auxFilename, auxAddr, outputSampleRate, 1, outputFrames, false);
}
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index cb15b60..ea16072 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -44,9 +44,6 @@
#define LVM_MAXINT_8 127 /* Maximum positive integer size */
#define LVM_MAXINT_16 32767
-#ifdef BUILD_FLOAT
-#define LVM_MAXFLOAT 1.0f
-#endif
#define LVM_MAXINT_32 2147483647
#define LVM_MAXENUM 2147483647
@@ -99,8 +96,32 @@
typedef uint32_t LVM_UINT32; /* Unsigned 32-bit word */
#ifdef BUILD_FLOAT
-typedef float LVM_FLOAT; /* single precission floating point*/
-#endif
+
+#define LVM_MAXFLOAT 1.f
+
+typedef float LVM_FLOAT; /* single precision floating point */
+
+// If NATIVE_FLOAT_BUFFER is defined, we expose effects as floating point format;
+// otherwise we expose as integer 16 bit and translate to float for the effect libraries.
+// Hence, NATIVE_FLOAT_BUFFER should only be enabled under BUILD_FLOAT compilation.
+
+#define NATIVE_FLOAT_BUFFER
+
+#endif // BUILD_FLOAT
+
+// Select whether we expose int16_t or float buffers.
+#ifdef NATIVE_FLOAT_BUFFER
+
+#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
+typedef float effect_buffer_t;
+
+#else // NATIVE_FLOAT_BUFFER
+
+#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_16_BIT
+typedef int16_t effect_buffer_t;
+
+#endif // NATIVE_FLOAT_BUFFER
+
/****************************************************************************************/
/* */
/* Standard Enumerated types */
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index 91e2246..341dbc2 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -1,5 +1,8 @@
LOCAL_PATH:= $(call my-dir)
+# The wrapper -DBUILD_FLOAT needs to match
+# the lvm library -DBUILD_FLOAT.
+
# music bundle wrapper
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -20,15 +23,17 @@
LOCAL_STATIC_LIBRARIES += libmusicbundle
LOCAL_SHARED_LIBRARIES := \
- liblog \
+ libaudioutils \
libcutils \
- libdl
+ libdl \
+ liblog \
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/Bundle \
$(LOCAL_PATH)/../lib/Common/lib/ \
$(LOCAL_PATH)/../lib/Bundle/lib/ \
- $(call include-path-for, audio-effects)
+ $(call include-path-for, audio-effects) \
+ $(call include-path-for, audio-utils) \
LOCAL_HEADER_LIBRARIES += libhardware_headers
include $(BUILD_SHARED_LIBRARY)
@@ -53,15 +58,17 @@
LOCAL_STATIC_LIBRARIES += libreverb
LOCAL_SHARED_LIBRARIES := \
- liblog \
+ libaudioutils \
libcutils \
- libdl
+ libdl \
+ liblog \
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/Reverb \
$(LOCAL_PATH)/../lib/Common/lib/ \
$(LOCAL_PATH)/../lib/Reverb/lib/ \
- $(call include-path-for, audio-effects)
+ $(call include-path-for, audio-effects) \
+ $(call include-path-for, audio-utils) \
LOCAL_HEADER_LIBRARIES += libhardware_headers
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index aae80b6..146e9e8 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
+#include <audio_utils/primitives.h>
#include <log/log.h>
#include "EffectBundle.h"
@@ -63,16 +64,6 @@
}\
}
-
-static inline int16_t clamp16(int32_t sample)
-{
- // check overflow for both positive and negative values:
- // all bits above short range must me equal to sign bit
- if ((sample>>15) ^ (sample>>31))
- sample = 0x7FFF ^ (sample>>31);
- return sample;
-}
-
// Namespaces
namespace android {
namespace {
@@ -299,7 +290,7 @@
pContext->pBundledContext->SamplesToExitCountVirt = 0;
pContext->pBundledContext->SamplesToExitCountBb = 0;
pContext->pBundledContext->SamplesToExitCountEq = 0;
-#ifdef BUILD_FLOAT
+#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
pContext->pBundledContext->pInputBuffer = NULL;
pContext->pBundledContext->pOutputBuffer = NULL;
#endif
@@ -470,13 +461,9 @@
if (pContext->pBundledContext->workBuffer != NULL) {
free(pContext->pBundledContext->workBuffer);
}
-#ifdef BUILD_FLOAT
- if (pContext->pBundledContext->pInputBuffer != NULL) {
- free(pContext->pBundledContext->pInputBuffer);
- }
- if (pContext->pBundledContext->pOutputBuffer != NULL) {
- free(pContext->pBundledContext->pOutputBuffer);
- }
+#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
+ free(pContext->pBundledContext->pInputBuffer);
+ free(pContext->pBundledContext->pOutputBuffer);
#endif
delete pContext->pBundledContext;
pContext->pBundledContext = LVM_NULL;
@@ -549,7 +536,7 @@
pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pContext->config.inputCfg.format = EFFECT_BUFFER_FORMAT;
pContext->config.inputCfg.samplingRate = 44100;
pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
@@ -557,7 +544,7 @@
pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pContext->config.outputCfg.format = EFFECT_BUFFER_FORMAT;
pContext->config.outputCfg.samplingRate = 44100;
pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
@@ -734,47 +721,6 @@
return 0;
} /* end LvmBundle_init */
-#ifdef BUILD_FLOAT
-/**********************************************************************************
- FUNCTION INT16LTOFLOAT
-***********************************************************************************/
-// Todo: need to write function descriptor
-static void Int16ToFloat(const LVM_INT16 *src, LVM_FLOAT *dst, size_t n) {
- size_t ii;
- src += n-1;
- dst += n-1;
- for (ii = n; ii != 0; ii--) {
- *dst = ((LVM_FLOAT)((LVM_INT16)*src)) / 32768.0f;
- src--;
- dst--;
- }
- return;
-}
-/**********************************************************************************
- FUNCTION FLOATTOINT16_SAT
-***********************************************************************************/
-// Todo : Need to write function descriptor
-static void FloatToInt16_SAT(const LVM_FLOAT *src, LVM_INT16 *dst, size_t n) {
- size_t ii;
- LVM_INT32 temp;
-
- src += n-1;
- dst += n-1;
- for (ii = n; ii != 0; ii--) {
- temp = (LVM_INT32)((*src) * 32768.0f);
- if (temp >= 32767) {
- *dst = 32767;
- } else if (temp <= -32768) {
- *dst = -32768;
- } else {
- *dst = (LVM_INT16)temp;
- }
- src--;
- dst--;
- }
- return;
-}
-#endif
//----------------------------------------------------------------------------
// LvmBundle_process()
//----------------------------------------------------------------------------
@@ -782,8 +728,8 @@
// Apply LVM Bundle effects
//
// Inputs:
-// pIn: pointer to stereo 16 bit input data
-// pOut: pointer to stereo 16 bit output data
+// pIn: pointer to stereo float or 16 bit input data
+// pOut: pointer to stereo float or 16 bit output data
// frameCount: Frames to process
// pContext: effect engine context
// strength strength to be applied
@@ -793,44 +739,37 @@
//
//----------------------------------------------------------------------------
#ifdef BUILD_FLOAT
-int LvmBundle_process(LVM_INT16 *pIn,
- LVM_INT16 *pOut,
+int LvmBundle_process(effect_buffer_t *pIn,
+ effect_buffer_t *pOut,
int frameCount,
EffectContext *pContext){
-
- //LVM_ControlParams_t ActiveParams; /* Current control Parameters */
LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
- LVM_INT16 *pOutTmp;
- LVM_FLOAT *pInputBuff;
- LVM_FLOAT *pOutputBuff;
-
- if (pContext->pBundledContext->pInputBuffer == NULL ||
+ effect_buffer_t *pOutTmp;
+#ifndef NATIVE_FLOAT_BUFFER
+ if (pContext->pBundledContext->pInputBuffer == nullptr ||
pContext->pBundledContext->frameCount < frameCount) {
- if (pContext->pBundledContext->pInputBuffer != NULL) {
- free(pContext->pBundledContext->pInputBuffer);
- }
- pContext->pBundledContext->pInputBuffer = (LVM_FLOAT *)malloc(frameCount * \
- sizeof(LVM_FLOAT) * FCC_2);
+ free(pContext->pBundledContext->pInputBuffer);
+ pContext->pBundledContext->pInputBuffer =
+ (LVM_FLOAT *)calloc(frameCount, sizeof(LVM_FLOAT) * FCC_2);
}
- if (pContext->pBundledContext->pOutputBuffer == NULL ||
+ if (pContext->pBundledContext->pOutputBuffer == nullptr ||
pContext->pBundledContext->frameCount < frameCount) {
- if (pContext->pBundledContext->pOutputBuffer != NULL) {
- free(pContext->pBundledContext->pOutputBuffer);
- }
- pContext->pBundledContext->pOutputBuffer = (LVM_FLOAT *)malloc(frameCount * \
- sizeof(LVM_FLOAT) * FCC_2);
+ free(pContext->pBundledContext->pOutputBuffer);
+ pContext->pBundledContext->pOutputBuffer =
+ (LVM_FLOAT *)calloc(frameCount, sizeof(LVM_FLOAT) * FCC_2);
}
- if ((pContext->pBundledContext->pInputBuffer == NULL) ||
- (pContext->pBundledContext->pOutputBuffer == NULL)) {
- ALOGV("LVM_ERROR : LvmBundle_process memory allocation for float buffer's failed");
+ if (pContext->pBundledContext->pInputBuffer == nullptr ||
+ pContext->pBundledContext->pOutputBuffer == nullptr) {
+ ALOGE("LVM_ERROR : LvmBundle_process memory allocation for float buffer's failed");
return -EINVAL;
}
- pInputBuff = pContext->pBundledContext->pInputBuffer;
- pOutputBuff = pContext->pBundledContext->pOutputBuffer;
+ LVM_FLOAT * const pInputBuff = pContext->pBundledContext->pInputBuffer;
+ LVM_FLOAT * const pOutputBuff = pContext->pBundledContext->pOutputBuffer;
+#endif
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
pOutTmp = pOut;
@@ -840,7 +779,7 @@
free(pContext->pBundledContext->workBuffer);
}
pContext->pBundledContext->workBuffer =
- (LVM_INT16 *)calloc(frameCount, sizeof(LVM_INT16) * FCC_2);
+ (effect_buffer_t *)calloc(frameCount, sizeof(effect_buffer_t) * FCC_2);
if (pContext->pBundledContext->workBuffer == NULL) {
return -ENOMEM;
}
@@ -852,43 +791,61 @@
return -EINVAL;
}
- #ifdef LVM_PCM
- fwrite(pIn, frameCount*sizeof(LVM_INT16) * FCC_2, 1, pContext->pBundledContext->PcmInPtr);
+#ifdef LVM_PCM
+ fwrite(pIn,
+ frameCount*sizeof(effect_buffer_t) * FCC_2, 1, pContext->pBundledContext->PcmInPtr);
fflush(pContext->pBundledContext->PcmInPtr);
- #endif
+#endif
+#ifndef NATIVE_FLOAT_BUFFER
/* Converting input data from fixed point to float point */
- Int16ToFloat(pIn, pInputBuff, frameCount * 2);
+ memcpy_to_float_from_i16(pInputBuff, pIn, frameCount * FCC_2);
/* Process the samples */
LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
pInputBuff, /* Input buffer */
pOutputBuff, /* Output buffer */
(LVM_UINT16)frameCount, /* Number of samples to read */
- 0); /* Audo Time */
+ 0); /* Audio Time */
+ /* Converting output data from float point to fixed point */
+ memcpy_to_i16_from_float(pOutTmp, pOutputBuff, frameCount * FCC_2);
+
+#else
+ /* Process the samples */
+ LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
+ pIn, /* Input buffer */
+ pOutTmp, /* Output buffer */
+ (LVM_UINT16)frameCount, /* Number of samples to read */
+ 0); /* Audio Time */
+#endif
LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
if(LvmStatus != LVM_SUCCESS) return -EINVAL;
- /* Converting output data from float point to fixed point */
- FloatToInt16_SAT(pOutputBuff, pOutTmp, (LVM_UINT16)frameCount * 2);
- #ifdef LVM_PCM
- fwrite(pOutTmp, frameCount*sizeof(LVM_INT16) * FCC_2, 1, pContext->pBundledContext->PcmOutPtr);
+#ifdef LVM_PCM
+ fwrite(pOutTmp,
+ frameCount*sizeof(effect_buffer_t) * FCC_2, 1, pContext->pBundledContext->PcmOutPtr);
fflush(pContext->pBundledContext->PcmOutPtr);
- #endif
+#endif
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
- for (int i = 0; i < frameCount * 2; i++){
+ for (int i = 0; i < frameCount * FCC_2; i++) {
+#ifndef NATIVE_FLOAT_BUFFER
pOut[i] = clamp16((LVM_INT32)pOut[i] + (LVM_INT32)pOutTmp[i]);
+#else
+ pOut[i] = pOut[i] + pOutTmp[i];
+#endif
}
}
return 0;
} /* end LvmBundle_process */
-#else
+
+#else // BUILD_FLOAT
+
int LvmBundle_process(LVM_INT16 *pIn,
LVM_INT16 *pOut,
int frameCount,
- EffectContext *pContext){
+ EffectContext *pContext) {
LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
LVM_INT16 *pOutTmp;
@@ -901,7 +858,7 @@
free(pContext->pBundledContext->workBuffer);
}
pContext->pBundledContext->workBuffer =
- (LVM_INT16 *)calloc(frameCount, sizeof(LVM_INT16) * 2);
+ (effect_buffer_t *)calloc(frameCount, sizeof(effect_buffer_t) * FCC_2);
if (pContext->pBundledContext->workBuffer == NULL) {
return -ENOMEM;
}
@@ -913,10 +870,11 @@
return -EINVAL;
}
- #ifdef LVM_PCM
- fwrite(pIn, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmInPtr);
+#ifdef LVM_PCM
+ fwrite(pIn, frameCount * sizeof(*pIn) * FCC_2,
+ 1 /* nmemb */, pContext->pBundledContext->PcmInPtr);
fflush(pContext->pBundledContext->PcmInPtr);
- #endif
+#endif
//ALOGV("Calling LVM_Process");
@@ -925,15 +883,16 @@
pIn, /* Input buffer */
pOutTmp, /* Output buffer */
(LVM_UINT16)frameCount, /* Number of samples to read */
- 0); /* Audo Time */
+ 0); /* Audio Time */
LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
if(LvmStatus != LVM_SUCCESS) return -EINVAL;
- #ifdef LVM_PCM
- fwrite(pOutTmp, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmOutPtr);
+#ifdef LVM_PCM
+ fwrite(pOutTmp, frameCount * sizeof(*pOutTmp) * FCC_2,
+ 1 /* nmemb */, pContext->pBundledContext->PcmOutPtr);
fflush(pContext->pBundledContext->PcmOutPtr);
- #endif
+#endif
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
for (int i=0; i<frameCount*2; i++){
@@ -942,7 +901,8 @@
}
return 0;
} /* end LvmBundle_process */
-#endif
+
+#endif // BUILD_FLOAT
//----------------------------------------------------------------------------
// EqualizerUpdateActiveParams()
@@ -1276,8 +1236,7 @@
CHECK_ARG(pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO);
CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
|| pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
- CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
-
+ CHECK_ARG(pConfig->inputCfg.format == EFFECT_BUFFER_FORMAT);
pContext->config = *pConfig;
switch (pConfig->inputCfg.samplingRate) {
@@ -3349,10 +3308,17 @@
pContext->pBundledContext->NumberEffectsCalled = 0;
/* Process all the available frames, block processing is
handled internalLY by the LVM bundle */
- processStatus = android::LvmBundle_process( (LVM_INT16 *)inBuffer->raw,
- (LVM_INT16 *)outBuffer->raw,
- outBuffer->frameCount,
- pContext);
+#ifdef NATIVE_FLOAT_BUFFER
+ processStatus = android::LvmBundle_process(inBuffer->f32,
+ outBuffer->f32,
+ outBuffer->frameCount,
+ pContext);
+#else
+ processStatus = android::LvmBundle_process(inBuffer->s16,
+ outBuffer->s16,
+ outBuffer->frameCount,
+ pContext);
+#endif
if (processStatus != 0){
ALOGV("\tLVM_ERROR : LvmBundle_process returned error %d", processStatus);
if (status == 0) {
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 291383a..6bf045d 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -95,7 +95,7 @@
int SamplesToExitCountEq;
int SamplesToExitCountBb;
int SamplesToExitCountVirt;
- LVM_INT16 *workBuffer;
+ effect_buffer_t *workBuffer;
int frameCount;
int32_t bandGaindB[FIVEBAND_NUMBANDS];
int volume;
@@ -103,10 +103,10 @@
FILE *PcmInPtr;
FILE *PcmOutPtr;
#endif
- #ifdef BUILD_FLOAT
+#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
LVM_FLOAT *pInputBuffer;
LVM_FLOAT *pOutputBuffer;
- #endif
+#endif
};
/* SessionContext : One session */
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 3d8e982..0630285 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
+#include <audio_utils/primitives.h>
#include <log/log.h>
#include "EffectReverb.h"
@@ -135,6 +136,12 @@
&gInsertPresetReverbDescriptor
};
+#ifdef BUILD_FLOAT
+typedef float process_buffer_t; // process in float
+#else
+typedef int32_t process_buffer_t; // process in Q4_27
+#endif // BUILD_FLOAT
+
struct ReverbContext{
const struct effect_interface_s *itfe;
effect_config_t config;
@@ -152,8 +159,8 @@
FILE *PcmOutPtr;
#endif
LVM_Fs_en SampleRate;
- LVM_INT32 *InFrames32;
- LVM_INT32 *OutFrames32;
+ process_buffer_t *InFrames;
+ process_buffer_t *OutFrames;
size_t bufferSizeIn;
size_t bufferSizeOut;
bool auxiliary;
@@ -262,7 +269,7 @@
*pHandle = (effect_handle_t)pContext;
- #ifdef LVM_PCM
+#ifdef LVM_PCM
pContext->PcmInPtr = NULL;
pContext->PcmOutPtr = NULL;
@@ -273,19 +280,15 @@
(pContext->PcmOutPtr == NULL)){
return -EINVAL;
}
- #endif
+#endif
+ int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
// Allocate memory for reverb process (*2 is for STEREO)
-#ifdef BUILD_FLOAT
- pContext->bufferSizeIn = LVREV_MAX_FRAME_SIZE * sizeof(float) * 2;
- pContext->bufferSizeOut = pContext->bufferSizeIn;
-#else
- pContext->bufferSizeIn = LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2;
- pContext->bufferSizeOut = pContext->bufferSizeIn;
-#endif
- pContext->InFrames32 = (LVM_INT32 *)malloc(pContext->bufferSizeIn);
- pContext->OutFrames32 = (LVM_INT32 *)malloc(pContext->bufferSizeOut);
+ pContext->bufferSizeIn = LVREV_MAX_FRAME_SIZE * sizeof(process_buffer_t) * channels;
+ pContext->bufferSizeOut = LVREV_MAX_FRAME_SIZE * sizeof(process_buffer_t) * FCC_2;
+ pContext->InFrames = (process_buffer_t *)calloc(pContext->bufferSizeIn, 1 /* size */);
+ pContext->OutFrames = (process_buffer_t *)calloc(pContext->bufferSizeOut, 1 /* size */);
ALOGV("\tEffectCreate %p, size %zu", pContext, sizeof(ReverbContext));
ALOGV("\tEffectCreate end\n");
@@ -305,8 +308,8 @@
fclose(pContext->PcmInPtr);
fclose(pContext->PcmOutPtr);
#endif
- free(pContext->InFrames32);
- free(pContext->OutFrames32);
+ free(pContext->InFrames);
+ free(pContext->OutFrames);
pContext->bufferSizeIn = 0;
pContext->bufferSizeOut = 0;
Reverb_free(pContext);
@@ -344,114 +347,6 @@
} \
}
-#if 0
-//----------------------------------------------------------------------------
-// MonoTo2I_32()
-//----------------------------------------------------------------------------
-// Purpose:
-// Convert MONO to STEREO
-//
-//----------------------------------------------------------------------------
-
-void MonoTo2I_32( const LVM_INT32 *src,
- LVM_INT32 *dst,
- LVM_INT16 n)
-{
- LVM_INT16 ii;
- src += (n-1);
- dst += ((n*2)-1);
-
- for (ii = n; ii != 0; ii--)
- {
- *dst = *src;
- dst--;
-
- *dst = *src;
- dst--;
- src--;
- }
-
- return;
-}
-
-//----------------------------------------------------------------------------
-// From2iToMono_32()
-//----------------------------------------------------------------------------
-// Purpose:
-// Convert STEREO to MONO
-//
-//----------------------------------------------------------------------------
-
-void From2iToMono_32( const LVM_INT32 *src,
- LVM_INT32 *dst,
- LVM_INT16 n)
-{
- LVM_INT16 ii;
- LVM_INT32 Temp;
-
- for (ii = n; ii != 0; ii--)
- {
- Temp = (*src>>1);
- src++;
-
- Temp +=(*src>>1);
- src++;
-
- *dst = Temp;
- dst++;
- }
-
- return;
-}
-#endif
-
-#ifdef BUILD_FLOAT
-/**********************************************************************************
- FUNCTION INT16LTOFLOAT
-***********************************************************************************/
-// Todo: need to write function descriptor
-static void Int16ToFloat(const LVM_INT16 *src, LVM_FLOAT *dst, size_t n) {
- size_t ii;
- src += n-1;
- dst += n-1;
- for (ii = n; ii != 0; ii--) {
- *dst = ((LVM_FLOAT)((LVM_INT16)*src)) / 32768.0f;
- src--;
- dst--;
- }
- return;
-}
-/**********************************************************************************
- FUNCTION FLOATTOINT16_SAT
-***********************************************************************************/
-// Todo : Need to write function descriptor
-static void FloatToInt16_SAT(const LVM_FLOAT *src, LVM_INT16 *dst, size_t n) {
- size_t ii;
- LVM_INT32 temp;
-
- for (ii = 0; ii < n; ii++) {
- temp = (LVM_INT32)((*src) * 32768.0f);
- if (temp >= 32767) {
- *dst = 32767;
- } else if (temp <= -32768) {
- *dst = -32768;
- } else {
- *dst = (LVM_INT16)temp;
- }
- src++;
- dst++;
- }
- return;
-}
-#endif
-
-static inline int16_t clamp16(int32_t sample)
-{
- if ((sample>>15) ^ (sample>>31))
- sample = 0x7FFF ^ (sample>>31);
- return sample;
-}
-
//----------------------------------------------------------------------------
// process()
//----------------------------------------------------------------------------
@@ -459,8 +354,8 @@
// Apply the Reverb
//
// Inputs:
-// pIn: pointer to stereo/mono 16 bit input data
-// pOut: pointer to stereo 16 bit output data
+// pIn: pointer to stereo/mono float or 16 bit input data
+// pOut: pointer to stereo float or 16 bit output data
// frameCount: Frames to process
// pContext: effect engine context
// strength strength to be applied
@@ -469,116 +364,107 @@
// pOut: pointer to updated stereo 16 bit output data
//
//----------------------------------------------------------------------------
-
-int process( LVM_INT16 *pIn,
- LVM_INT16 *pOut,
+int process( effect_buffer_t *pIn,
+ effect_buffer_t *pOut,
int frameCount,
ReverbContext *pContext){
- LVM_INT16 samplesPerFrame = 1;
+ int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
- LVM_INT16 *OutFrames16;
-#ifdef BUILD_FLOAT
- LVM_FLOAT *pInputBuff;
- LVM_FLOAT *pOutputBuff;
-#endif
-#ifdef BUILD_FLOAT
- if (pContext->InFrames32 == NULL ||
- pContext->bufferSizeIn < frameCount * sizeof(float) * 2) {
- if (pContext->InFrames32 != NULL) {
- free(pContext->InFrames32);
- }
- pContext->bufferSizeIn = frameCount * sizeof(float) * 2;
- pContext->InFrames32 = (LVM_INT32 *)malloc(pContext->bufferSizeIn);
- }
- if (pContext->OutFrames32 == NULL ||
- pContext->bufferSizeOut < frameCount * sizeof(float) * 2) {
- if (pContext->OutFrames32 != NULL) {
- free(pContext->OutFrames32);
- }
- pContext->bufferSizeOut = frameCount * sizeof(float) * 2;
- pContext->OutFrames32 = (LVM_INT32 *)malloc(pContext->bufferSizeOut);
- }
- pInputBuff = (float *)pContext->InFrames32;
- pOutputBuff = (float *)pContext->OutFrames32;
-#endif
// Check that the input is either mono or stereo
- if (pContext->config.inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO) {
- samplesPerFrame = 2;
- } else if (pContext->config.inputCfg.channels != AUDIO_CHANNEL_OUT_MONO) {
- ALOGV("\tLVREV_ERROR : process invalid PCM format");
+ if (!(channels == 1 || channels == FCC_2) ) {
+ ALOGE("\tLVREV_ERROR : process invalid PCM format");
return -EINVAL;
}
- OutFrames16 = (LVM_INT16 *)pContext->OutFrames32;
+#ifdef BUILD_FLOAT
+ size_t inSize = frameCount * sizeof(process_buffer_t) * channels;
+ size_t outSize = frameCount * sizeof(process_buffer_t) * FCC_2;
+ if (pContext->InFrames == NULL ||
+ pContext->bufferSizeIn < inSize) {
+ free(pContext->InFrames);
+ pContext->bufferSizeIn = inSize;
+ pContext->InFrames = (process_buffer_t *)calloc(1, pContext->bufferSizeIn);
+ }
+ if (pContext->OutFrames == NULL ||
+ pContext->bufferSizeOut < outSize) {
+ free(pContext->OutFrames);
+ pContext->bufferSizeOut = outSize;
+ pContext->OutFrames = (process_buffer_t *)calloc(1, pContext->bufferSizeOut);
+ }
+
+#ifndef NATIVE_FLOAT_BUFFER
+ effect_buffer_t * const OutFrames16 = (effect_buffer_t *)pContext->OutFrames;
+#endif
+#endif
// Check for NULL pointers
- if((pContext->InFrames32 == NULL)||(pContext->OutFrames32 == NULL)){
- ALOGV("\tLVREV_ERROR : process failed to allocate memory for temporary buffers ");
+ if ((pContext->InFrames == NULL) || (pContext->OutFrames == NULL)) {
+ ALOGE("\tLVREV_ERROR : process failed to allocate memory for temporary buffers ");
return -EINVAL;
}
- #ifdef LVM_PCM
- fwrite(pIn, frameCount*sizeof(LVM_INT16)*samplesPerFrame, 1, pContext->PcmInPtr);
+#ifdef LVM_PCM
+ fwrite(pIn, frameCount * sizeof(*pIn) * channels, 1 /* nmemb */, pContext->PcmInPtr);
fflush(pContext->PcmInPtr);
- #endif
+#endif
if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
Reverb_LoadPreset(pContext);
}
- // Convert to Input 32 bits
if (pContext->auxiliary) {
#ifdef BUILD_FLOAT
- Int16ToFloat(pIn, pInputBuff, frameCount * samplesPerFrame);
+#ifdef NATIVE_FLOAT_BUFFER
+ static_assert(std::is_same<decltype(*pIn), decltype(*pContext->InFrames)>::value,
+ "pIn and InFrames must be same type");
+ memcpy(pContext->InFrames, pIn, frameCount * channels * sizeof(*pIn));
#else
- for(int i=0; i<frameCount*samplesPerFrame; i++){
- pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
+ memcpy_to_float_from_i16(
+ pContext->InFrames, pIn, frameCount * channels);
+#endif
+#else //no BUILD_FLOAT
+ for (int i = 0; i < frameCount * channels; i++) {
+ pContext->InFrames[i] = (process_buffer_t)pIn[i]<<8;
}
#endif
} else {
// insert reverb input is always stereo
for (int i = 0; i < frameCount; i++) {
-#ifndef BUILD_FLOAT
- pContext->InFrames32[2*i] = (pIn[2*i] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
- pContext->InFrames32[2*i+1] = (pIn[2*i+1] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
+#ifdef BUILD_FLOAT
+#ifdef NATIVE_FLOAT_BUFFER
+ pContext->InFrames[2 * i] = (process_buffer_t)pIn[2 * i] * REVERB_SEND_LEVEL;
+ pContext->InFrames[2 * i + 1] = (process_buffer_t)pIn[2 * i + 1] * REVERB_SEND_LEVEL;
#else
- pInputBuff[2 * i] = (LVM_FLOAT)pIn[2 * i] * REVERB_SEND_LEVEL / 32768.0f;
- pInputBuff[2 * i + 1] = (LVM_FLOAT)pIn[2 * i + 1] * REVERB_SEND_LEVEL / 32768.0f;
+ pContext->InFrames[2 * i] =
+ (process_buffer_t)pIn[2 * i] * REVERB_SEND_LEVEL / 32768.0f;
+ pContext->InFrames[2 * i + 1] =
+ (process_buffer_t)pIn[2 * i + 1] * REVERB_SEND_LEVEL / 32768.0f;
+#endif
+#else
+ pContext->InFrames[2*i] = (pIn[2*i] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
+ pContext->InFrames[2*i+1] = (pIn[2*i+1] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
#endif
}
}
if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
-#ifdef BUILD_FLOAT
- memset(pOutputBuff, 0, frameCount * sizeof(LVM_FLOAT) * 2); //always stereo here
-#else
- memset(pContext->OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2); //always stereo here
-#endif
+ memset(pContext->OutFrames, 0,
+ frameCount * sizeof(*pContext->OutFrames) * FCC_2); //always stereo here
} else {
if(pContext->bEnabled == LVM_FALSE && pContext->SamplesToExitCount > 0) {
-#ifdef BUILD_FLOAT
- memset(pInputBuff, 0, frameCount * sizeof(LVM_FLOAT) * samplesPerFrame);
-#else
- memset(pContext->InFrames32,0,frameCount * sizeof(LVM_INT32) * samplesPerFrame);
-#endif
- ALOGV("\tZeroing %d samples per frame at the end of call", samplesPerFrame);
+ memset(pContext->InFrames, 0,
+ frameCount * sizeof(*pContext->OutFrames) * channels);
+ ALOGV("\tZeroing %d samples per frame at the end of call", channels);
}
/* Process the samples, producing a stereo output */
-#ifdef BUILD_FLOAT
LvmStatus = LVREV_Process(pContext->hInstance, /* Instance handle */
- pInputBuff, /* Input buffer */
- pOutputBuff, /* Output buffer */
+ pContext->InFrames, /* Input buffer */
+ pContext->OutFrames, /* Output buffer */
frameCount); /* Number of samples to read */
-#else
- LvmStatus = LVREV_Process(pContext->hInstance, /* Instance handle */
- pContext->InFrames32, /* Input buffer */
- pContext->OutFrames32, /* Output buffer */
- frameCount); /* Number of samples to read */
-#endif
- }
+ }
LVM_ERROR_CHECK(LvmStatus, "LVREV_Process", "process")
if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
@@ -586,55 +472,87 @@
// Convert to 16 bits
if (pContext->auxiliary) {
#ifdef BUILD_FLOAT
- FloatToInt16_SAT(pOutputBuff, OutFrames16, (size_t)frameCount * 2);
-#else
- for (int i=0; i < frameCount*2; i++) { //always stereo here
- OutFrames16[i] = clamp16(pContext->OutFrames32[i]>>8);
- }
+ // nothing to do here
+#ifndef NATIVE_FLOAT_BUFFER
+ // pContext->OutFrames and OutFrames16 point to the same buffer
+ // make sure the float to int conversion happens in the right order.
+ memcpy_to_i16_from_float(OutFrames16, pContext->OutFrames,
+ (size_t)frameCount * FCC_2);
#endif
- } else {
-#ifdef BUILD_FLOAT
- for (int i = 0; i < frameCount * 2; i++) {//always stereo here
- //pOutputBuff and OutFrames16 point to the same buffer, so better to
- //accumulate in pInputBuff, which is available
- pInputBuff[i] = pOutputBuff[i] + (LVM_FLOAT)pIn[i] / 32768.0f;
- }
-
- FloatToInt16_SAT(pInputBuff, OutFrames16, (size_t)frameCount * 2);
#else
- for (int i=0; i < frameCount*2; i++) { //always stereo here
- OutFrames16[i] = clamp16((pContext->OutFrames32[i]>>8) + (LVM_INT32)pIn[i]);
- }
+ memcpy_to_i16_from_q4_27(OutFrames16, pContext->OutFrames, (size_t)frameCount * FCC_2);
+#endif
+ } else {
+#ifdef BUILD_FLOAT
+#ifdef NATIVE_FLOAT_BUFFER
+ for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
+ // Mix with dry input
+ pContext->OutFrames[i] += pIn[i];
+ }
+#else
+ for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
+ // pOutputBuff and OutFrames16 point to the same buffer
+ // make sure the float to int conversion happens in the right order.
+ pContext->OutFrames[i] += (process_buffer_t)pIn[i] / 32768.0f;
+ }
+ memcpy_to_i16_from_float(OutFrames16, pContext->OutFrames,
+ (size_t)frameCount * FCC_2);
+#endif
+#else
+ for (int i=0; i < frameCount * FCC_2; i++) { // always stereo here
+ OutFrames16[i] = clamp16((pContext->OutFrames[i]>>8) + (process_buffer_t)pIn[i]);
+ }
#endif
// apply volume with ramp if needed
if ((pContext->leftVolume != pContext->prevLeftVolume ||
pContext->rightVolume != pContext->prevRightVolume) &&
pContext->volumeMode == REVERB_VOLUME_RAMP) {
+#if defined (BUILD_FLOAT) && defined (NATIVE_FLOAT_BUFFER)
+ // FIXME: still using int16 volumes.
+ // For reference: REVERB_UNIT_VOLUME (0x1000) // 1.0 in 4.12 format
+ float vl = (float)pContext->prevLeftVolume / 4096;
+ float incl = (((float)pContext->leftVolume / 4096) - vl) / frameCount;
+ float vr = (float)pContext->prevRightVolume / 4096;
+ float incr = (((float)pContext->rightVolume / 4096) - vr) / frameCount;
+
+ for (int i = 0; i < frameCount; i++) {
+ pContext->OutFrames[FCC_2 * i] *= vl;
+ pContext->OutFrames[FCC_2 * i + 1] *= vr;
+
+ vl += incl;
+ vr += incr;
+ }
+#else
LVM_INT32 vl = (LVM_INT32)pContext->prevLeftVolume << 16;
LVM_INT32 incl = (((LVM_INT32)pContext->leftVolume << 16) - vl) / frameCount;
LVM_INT32 vr = (LVM_INT32)pContext->prevRightVolume << 16;
LVM_INT32 incr = (((LVM_INT32)pContext->rightVolume << 16) - vr) / frameCount;
for (int i = 0; i < frameCount; i++) {
- OutFrames16[2*i] =
+ OutFrames16[FCC_2 * i] =
clamp16((LVM_INT32)((vl >> 16) * OutFrames16[2*i]) >> 12);
- OutFrames16[2*i+1] =
+ OutFrames16[FCC_2 * i + 1] =
clamp16((LVM_INT32)((vr >> 16) * OutFrames16[2*i+1]) >> 12);
vl += incl;
vr += incr;
}
-
+#endif
pContext->prevLeftVolume = pContext->leftVolume;
pContext->prevRightVolume = pContext->rightVolume;
} else if (pContext->volumeMode != REVERB_VOLUME_OFF) {
if (pContext->leftVolume != REVERB_UNIT_VOLUME ||
pContext->rightVolume != REVERB_UNIT_VOLUME) {
for (int i = 0; i < frameCount; i++) {
- OutFrames16[2*i] =
+#if defined(BUILD_FLOAT) && defined(NATIVE_FLOAT_BUFFER)
+ pContext->OutFrames[FCC_2 * i] *= ((float)pContext->leftVolume / 4096);
+ pContext->OutFrames[FCC_2 * i + 1] *= ((float)pContext->rightVolume / 4096);
+#else
+ OutFrames16[FCC_2 * i] =
clamp16((LVM_INT32)(pContext->leftVolume * OutFrames16[2*i]) >> 12);
- OutFrames16[2*i+1] =
+ OutFrames16[FCC_2 * i + 1] =
clamp16((LVM_INT32)(pContext->rightVolume * OutFrames16[2*i+1]) >> 12);
+#endif
}
}
pContext->prevLeftVolume = pContext->leftVolume;
@@ -643,20 +561,25 @@
}
}
- #ifdef LVM_PCM
- fwrite(OutFrames16, frameCount*sizeof(LVM_INT16)*2, 1, pContext->PcmOutPtr);
+#ifdef LVM_PCM
+ fwrite(pContext->OutFrames, frameCount * sizeof(*pContext->OutFrames) * FCC_2,
+ 1 /* nmemb */, pContext->PcmOutPtr);
fflush(pContext->PcmOutPtr);
- #endif
+#endif
// Accumulate if required
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
//ALOGV("\tBuffer access is ACCUMULATE");
- for (int i=0; i<frameCount*2; i++){ //always stereo here
+ for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
+#ifndef NATIVE_FLOAT_BUFFER
pOut[i] = clamp16((int32_t)pOut[i] + (int32_t)OutFrames16[i]);
+#else
+ pOut[i] += pContext->OutFrames[i];
+#endif
}
}else{
//ALOGV("\tBuffer access is WRITE");
- memcpy(pOut, OutFrames16, frameCount*sizeof(LVM_INT16)*2);
+ memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
}
return 0;
@@ -733,8 +656,7 @@
CHECK_ARG(pConfig->outputCfg.channels == AUDIO_CHANNEL_OUT_STEREO);
CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
|| pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
- CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
-
+ CHECK_ARG(pConfig->inputCfg.format == EFFECT_BUFFER_FORMAT);
//ALOGV("\tReverb_setConfig calling memcpy");
pContext->config = *pConfig;
@@ -847,8 +769,7 @@
} else {
pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
}
-
- pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pContext->config.inputCfg.format = EFFECT_BUFFER_FORMAT;
pContext->config.inputCfg.samplingRate = 44100;
pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
@@ -856,7 +777,7 @@
pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pContext->config.outputCfg.format = EFFECT_BUFFER_FORMAT;
pContext->config.outputCfg.samplingRate = 44100;
pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
@@ -2031,10 +1952,17 @@
}
//ALOGV("\tReverb_process() Calling process with %d frames", outBuffer->frameCount);
/* Process all the available frames, block processing is handled internalLY by the LVM bundle */
- status = process( (LVM_INT16 *)inBuffer->raw,
- (LVM_INT16 *)outBuffer->raw,
- outBuffer->frameCount,
- pContext);
+#if defined (BUILD_FLOAT) && defined (NATIVE_FLOAT_BUFFER)
+ status = process( inBuffer->f32,
+ outBuffer->f32,
+ outBuffer->frameCount,
+ pContext);
+#else
+ status = process( inBuffer->s16,
+ outBuffer->s16,
+ outBuffer->frameCount,
+ pContext);
+#endif
if (pContext->bEnabled == LVM_FALSE) {
if (pContext->SamplesToExitCount > 0) {
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 5282352..72f5f58 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -61,6 +61,9 @@
PAUSE,
RESUME,
GET_METRICS,
+ SET_INPUT_DEVICE,
+ GET_ROUTED_DEVICE_ID,
+ ENABLE_AUDIO_DEVICE_CALLBACK,
};
@@ -337,6 +340,57 @@
remote()->transact(RELEASE, data, &reply);
return reply.readInt32();
}
+
+ status_t setInputDevice(audio_port_handle_t deviceId)
+ {
+ ALOGV("setInputDevice");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(deviceId);
+
+ status_t status = remote()->transact(SET_INPUT_DEVICE, data, &reply);
+ if (status != OK) {
+ ALOGE("setInputDevice binder call failed: %d", status);
+ return status;
+ }
+ return reply.readInt32();;
+ }
+
+ audio_port_handle_t getRoutedDeviceId(audio_port_handle_t *deviceId)
+ {
+ ALOGV("getRoutedDeviceId");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+
+ status_t status = remote()->transact(GET_ROUTED_DEVICE_ID, data, &reply);
+ if (status != OK) {
+ ALOGE("getRoutedDeviceid binder call failed: %d", status);
+ *deviceId = AUDIO_PORT_HANDLE_NONE;
+ return status;
+ }
+
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ *deviceId = AUDIO_PORT_HANDLE_NONE;
+ } else {
+ *deviceId = reply.readInt32();
+ }
+ return status;
+ }
+
+ status_t enableAudioDeviceCallback(bool enabled)
+ {
+ ALOGV("enableAudioDeviceCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeBool(enabled);
+ status_t status = remote()->transact(ENABLE_AUDIO_DEVICE_CALLBACK, data, &reply);
+ if (status != OK) {
+ ALOGE("enableAudioDeviceCallback binder call failed: %d, %d", enabled, status);
+ return status;
+ }
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder");
@@ -543,6 +597,41 @@
}
return NO_ERROR;
} break;
+ case SET_INPUT_DEVICE: {
+ ALOGV("SET_INPUT_DEVICE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ audio_port_handle_t deviceId;
+ status_t status = data.readInt32(&deviceId);
+ if (status == NO_ERROR) {
+ reply->writeInt32(setInputDevice(deviceId));
+ } else {
+ reply->writeInt32(BAD_VALUE);
+ }
+ return NO_ERROR;
+ } break;
+ case GET_ROUTED_DEVICE_ID: {
+ ALOGV("GET_ROUTED_DEVICE_ID");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ audio_port_handle_t deviceId;
+ status_t status = getRoutedDeviceId(&deviceId);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(deviceId);
+ }
+ return NO_ERROR;
+ } break;
+ case ENABLE_AUDIO_DEVICE_CALLBACK: {
+ ALOGV("ENABLE_AUDIO_DEVICE_CALLBACK");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ bool enabled;
+ status_t status = data.readBool(&enabled);
+ if (status == NO_ERROR) {
+ reply->writeInt32(enableAudioDeviceCallback(enabled));
+ } else {
+ reply->writeInt32(BAD_VALUE);
+ }
+ return NO_ERROR;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 9d0341a..3cef329 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -19,6 +19,7 @@
#define ANDROID_IMEDIARECORDER_H
#include <binder/IInterface.h>
+#include <system/audio.h>
namespace android {
@@ -64,6 +65,10 @@
virtual status_t release() = 0;
virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
+
+ virtual status_t setInputDevice(audio_port_handle_t deviceId) = 0;
+ virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
+ virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 40dd9f9..748153c 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -18,6 +18,7 @@
#define MEDIA_RECORDER_BASE_H_
+#include <media/AudioSystem.h>
#include <media/mediarecorder.h>
#include <system/audio.h>
@@ -62,6 +63,10 @@
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
+ virtual status_t setInputDevice(audio_port_handle_t deviceId) = 0;
+ virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId) = 0;
+ virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) = 0;
+ virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
protected:
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index b9717ea..5f2a6fe 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -141,6 +141,8 @@
MEDIA_RECORDER_TRACK_EVENT_ERROR = 100,
MEDIA_RECORDER_TRACK_EVENT_INFO = 101,
MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000,
+
+ MEDIA_RECORDER_AUDIO_ROUTING_CHANGED = 10000,
};
/*
@@ -253,6 +255,9 @@
status_t setInputSurface(const sp<PersistentSurface>& surface);
sp<IGraphicBufferProducer> querySurfaceMediaSourceFromMediaServer();
status_t getMetrics(Parcel *reply);
+ status_t setInputDevice(audio_port_handle_t deviceId);
+ status_t getRoutedDeviceId(audio_port_handle_t *deviceId);
+ status_t enableAudioDeviceCallback(bool enabled);
private:
void doCleanUp();
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 4405930..aab845b 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -792,4 +792,41 @@
notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
}
+status_t MediaRecorder::setInputDevice(audio_port_handle_t deviceId)
+{
+ ALOGV("setInputDevice");
+
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ return mMediaRecorder->setInputDevice(deviceId);
+}
+
+status_t MediaRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId)
+{
+ ALOGV("getRoutedDeviceId");
+
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ status_t status = mMediaRecorder->getRoutedDeviceId(deviceId);
+ if (status != NO_ERROR) {
+ *deviceId = AUDIO_PORT_HANDLE_NONE;
+ }
+ return status;
+}
+
+status_t MediaRecorder::enableAudioDeviceCallback(bool enabled)
+{
+ ALOGV("enableAudioDeviceCallback");
+
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ return mMediaRecorder->enableAudioDeviceCallback(enabled);
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index a423fee..dcd393b 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -411,6 +411,25 @@
}
}
+MediaRecorderClient::AudioDeviceUpdatedNotifier::AudioDeviceUpdatedNotifier(
+ const sp<IMediaRecorderClient>& listener) {
+ mListener = listener;
+}
+
+MediaRecorderClient::AudioDeviceUpdatedNotifier::~AudioDeviceUpdatedNotifier() {
+}
+
+void MediaRecorderClient::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
+ audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId) {
+ sp<IMediaRecorderClient> listener = mListener.promote();
+ if (listener != NULL) {
+ listener->notify(MEDIA_RECORDER_AUDIO_ROUTING_CHANGED, audioIo, deviceId);
+ } else {
+ ALOGW("listener for process %d death is gone", MEDIA_RECORDER_AUDIO_ROUTING_CHANGED);
+ }
+}
+
void MediaRecorderClient::clearDeathNotifiers_l() {
if (mCameraDeathListener != nullptr) {
mCameraDeathListener->unlinkToDeath();
@@ -459,6 +478,9 @@
MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
omx->linkToDeath(mCodecDeathListener, 0);
+ mAudioDeviceUpdatedNotifier = new AudioDeviceUpdatedNotifier(listener);
+ mRecorder->setAudioDeviceCallback(mAudioDeviceUpdatedNotifier);
+
return OK;
}
@@ -479,4 +501,30 @@
return OK;
}
+status_t MediaRecorderClient::setInputDevice(audio_port_handle_t deviceId) {
+ ALOGV("setInputDevice(%d)", deviceId);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder != NULL) {
+ return mRecorder->setInputDevice(deviceId);
+ }
+ return NO_INIT;
+}
+
+status_t MediaRecorderClient::getRoutedDeviceId(audio_port_handle_t* deviceId) {
+ ALOGV("getRoutedDeviceId");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder != NULL) {
+ return mRecorder->getRoutedDeviceId(deviceId);
+ }
+ return NO_INIT;
+}
+
+status_t MediaRecorderClient::enableAudioDeviceCallback(bool enabled) {
+ ALOGV("enableDeviceCallback: %d", enabled);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder != NULL) {
+ return mRecorder->enableAudioDeviceCallback(enabled);
+ }
+ return NO_INIT;
+}
}; // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 711db2c..538b461 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -18,6 +18,7 @@
#ifndef ANDROID_MEDIARECORDERCLIENT_H
#define ANDROID_MEDIARECORDERCLIENT_H
+#include <media/AudioSystem.h>
#include <media/IMediaRecorder.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
@@ -58,6 +59,18 @@
wp<IMediaRecorderClient> mListener;
};
+ class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback
+ {
+ public:
+ AudioDeviceUpdatedNotifier(const sp<IMediaRecorderClient>& listener);
+ virtual ~AudioDeviceUpdatedNotifier();
+ virtual void onAudioDeviceUpdate(
+ audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId);
+ private:
+ wp<IMediaRecorderClient> mListener;
+ };
+
void clearDeathNotifiers_l();
public:
@@ -91,6 +104,9 @@
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource();
+ virtual status_t setInputDevice(audio_port_handle_t deviceId);
+ virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
+ virtual status_t enableAudioDeviceCallback(bool enabled);
private:
friend class MediaPlayerService; // for accessing private constructor
@@ -103,6 +119,7 @@
sp<ServiceDeathNotifier> mCameraDeathListener;
sp<ServiceDeathNotifier> mCodecDeathListener;
+ sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedNotifier;
pid_t mPid;
Mutex mLock;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 89354d6..77eaefe 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -103,7 +103,9 @@
mOutputFd(-1),
mAudioSource(AUDIO_SOURCE_CNT),
mVideoSource(VIDEO_SOURCE_LIST_END),
- mStarted(false) {
+ mStarted(false),
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mDeviceCallbackEnabled(false) {
ALOGV("Constructor");
@@ -204,7 +206,7 @@
return OK;
}
-// The client side of mediaserver asks it to creat a SurfaceMediaSource
+// The client side of mediaserver asks it to create a SurfaceMediaSource
// and return a interface reference. The client side will use that
// while encoding GL Frames
sp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const {
@@ -1069,7 +1071,8 @@
mAudioChannels,
mSampleRate,
mClientUid,
- mClientPid);
+ mClientPid,
+ mSelectedDeviceId);
status_t err = audioSource->initCheck();
@@ -1120,6 +1123,10 @@
sp<MediaCodecSource> audioEncoder =
MediaCodecSource::Create(mLooper, format, audioSource);
+ sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
+ if (mDeviceCallbackEnabled && callback != 0) {
+ audioSource->addAudioDeviceCallback(callback);
+ }
mAudioSourceNode = audioSource;
if (audioEncoder == NULL) {
@@ -2116,6 +2123,46 @@
return OK;
}
+status_t StagefrightRecorder::setInputDevice(audio_port_handle_t deviceId) {
+ ALOGV("setInputDevice");
+
+ if (mSelectedDeviceId != deviceId) {
+ mSelectedDeviceId = deviceId;
+ if (mAudioSourceNode != 0) {
+ return mAudioSourceNode->setInputDevice(deviceId);
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t StagefrightRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId) {
+ ALOGV("getRoutedDeviceId");
+
+ if (mAudioSourceNode != 0) {
+ status_t status = mAudioSourceNode->getRoutedDeviceId(deviceId);
+ return status;
+ }
+ return NO_INIT;
+}
+
+void StagefrightRecorder::setAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback) {
+ mAudioDeviceCallback = callback;
+}
+
+status_t StagefrightRecorder::enableAudioDeviceCallback(bool enabled) {
+ mDeviceCallbackEnabled = enabled;
+ sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
+ if (mAudioSourceNode != 0 && callback != 0) {
+ if (enabled) {
+ return mAudioSourceNode->addAudioDeviceCallback(callback);
+ } else {
+ return mAudioSourceNode->removeAudioDeviceCallback(callback);
+ }
+ }
+ return NO_ERROR;
+}
+
status_t StagefrightRecorder::dump(
int fd, const Vector<String16>& args) const {
ALOGV("dump");
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 5111c8e..ec7e8ed 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -72,6 +72,10 @@
virtual status_t dump(int fd, const Vector<String16> &args) const;
// Querying a SurfaceMediaSourcer
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const;
+ virtual status_t setInputDevice(audio_port_handle_t deviceId);
+ virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
+ virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
+ virtual status_t enableAudioDeviceCallback(bool enabled);
private:
mutable Mutex mLock;
@@ -144,6 +148,10 @@
sp<IGraphicBufferProducer> mGraphicBufferProducer;
sp<ALooper> mLooper;
+ audio_port_handle_t mSelectedDeviceId;
+ bool mDeviceCallbackEnabled;
+ wp<AudioSystem::AudioDeviceCallback> mAudioDeviceCallback;
+
static const int kMaxHighSpeedFps = 1000;
status_t prepareInternal();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 6c4b823..d1e5d45 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1311,6 +1311,7 @@
mResetting = true;
stopPlaybackTimer("kWhatReset");
+ stopRebufferingTimer(true);
mDeferredActions.push_back(
new FlushDecoderAction(
@@ -1604,6 +1605,37 @@
}
}
+void NuPlayer::startRebufferingTimer() {
+ Mutex::Autolock autoLock(mPlayingTimeLock);
+ if (mLastStartedRebufferingTimeNs == 0) {
+ mLastStartedRebufferingTimeNs = systemTime();
+ ALOGV("startRebufferingTimer() time %20" PRId64 "", mLastStartedRebufferingTimeNs);
+ }
+}
+
+void NuPlayer::stopRebufferingTimer(bool exitingPlayback) {
+ Mutex::Autolock autoLock(mPlayingTimeLock);
+
+ ALOGV("stopRebufferTimer() time %20" PRId64 " (exiting %d)", mLastStartedRebufferingTimeNs, exitingPlayback);
+
+ if (mLastStartedRebufferingTimeNs != 0) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ int64_t now = systemTime();
+ int64_t rebuffered = now - mLastStartedRebufferingTimeNs;
+ ALOGV("stopRebufferingTimer() log %20" PRId64 "", rebuffered);
+
+ if (rebuffered > 0) {
+ driver->notifyMoreRebufferingTimeUs((rebuffered+500)/1000);
+ if (exitingPlayback) {
+ driver->notifyRebufferingWhenExit(true);
+ }
+ }
+ }
+ mLastStartedRebufferingTimeNs = 0;
+ }
+}
+
void NuPlayer::onPause() {
stopPlaybackTimer("onPause");
@@ -2250,6 +2282,7 @@
CHECK(mVideoDecoder == NULL);
stopPlaybackTimer("performReset");
+ stopRebufferingTimer(true);
cancelPollDuration();
@@ -2503,6 +2536,7 @@
if (mStarted) {
ALOGI("buffer low, pausing...");
+ startRebufferingTimer();
mPausedForBuffering = true;
onPause();
}
@@ -2516,6 +2550,7 @@
if (mStarted) {
ALOGI("buffer ready, resuming...");
+ stopRebufferingTimer(false);
mPausedForBuffering = false;
// do not resume yet if client didn't unpause
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 492b8d4..fda69e8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -183,6 +183,10 @@
void stopPlaybackTimer(const char *where);
void startPlaybackTimer(const char *where);
+ int64_t mLastStartedRebufferingTimeNs;
+ void startRebufferingTimer();
+ void stopRebufferingTimer(bool exitingPlayback);
+
int64_t mPreviousSeekTimeUs;
List<sp<Action> > mDeferredActions;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index bd54df0..ebf57c6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -56,6 +56,10 @@
static const char *kPlayerError = "android.media.mediaplayer.err";
static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
+//
+static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
+static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
+static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
NuPlayerDriver::NuPlayerDriver(pid_t pid)
@@ -67,6 +71,9 @@
mPositionUs(-1),
mSeekInProgress(false),
mPlayingTimeUs(0),
+ mRebufferingTimeUs(0),
+ mRebufferingEvents(0),
+ mRebufferingAtExit(false),
mLooper(new ALooper),
mMediaClock(new MediaClock),
mPlayer(new NuPlayer(pid, mMediaClock)),
@@ -582,6 +589,12 @@
mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
+ if (mRebufferingEvents != 0) {
+ mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
+ mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
+ mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
+ }
+
mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
}
@@ -661,6 +674,9 @@
mPositionUs = -1;
mLooping = false;
mPlayingTimeUs = 0;
+ mRebufferingTimeUs = 0;
+ mRebufferingEvents = 0;
+ mRebufferingAtExit = false;
return OK;
}
@@ -811,6 +827,17 @@
mPlayingTimeUs += playingUs;
}
+void NuPlayerDriver::notifyMoreRebufferingTimeUs(int64_t rebufferingUs) {
+ Mutex::Autolock autoLock(mLock);
+ mRebufferingTimeUs += rebufferingUs;
+ mRebufferingEvents++;
+}
+
+void NuPlayerDriver::notifyRebufferingWhenExit(bool status) {
+ Mutex::Autolock autoLock(mLock);
+ mRebufferingAtExit = status;
+}
+
void NuPlayerDriver::notifySeekComplete() {
ALOGV("notifySeekComplete(%p)", this);
Mutex::Autolock autoLock(mLock);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 6ca6344..13b46c3 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -84,6 +84,8 @@
void notifySetSurfaceComplete();
void notifyDuration(int64_t durationUs);
void notifyMorePlayingTimeUs(int64_t timeUs);
+ void notifyMoreRebufferingTimeUs(int64_t timeUs);
+ void notifyRebufferingWhenExit(bool status);
void notifySeekComplete();
void notifySeekComplete_l();
void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
@@ -126,6 +128,9 @@
int64_t mPositionUs;
bool mSeekInProgress;
int64_t mPlayingTimeUs;
+ int64_t mRebufferingTimeUs;
+ int32_t mRebufferingEvents;
+ bool mRebufferingAtExit;
// <<<
sp<ALooper> mLooper;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index f2b1f10..b8da980 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -52,7 +52,7 @@
AudioSource::AudioSource(
audio_source_t inputSource, const String16 &opPackageName,
uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate,
- uid_t uid, pid_t pid)
+ uid_t uid, pid_t pid, audio_port_handle_t selectedDeviceId)
: mStarted(false),
mSampleRate(sampleRate),
mOutSampleRate(outSampleRate > 0 ? outSampleRate : sampleRate),
@@ -101,7 +101,9 @@
AudioRecord::TRANSFER_DEFAULT,
AUDIO_INPUT_FLAG_NONE,
uid,
- pid);
+ pid,
+ NULL /*pAttributes*/,
+ selectedDeviceId);
mInitCheck = mRecord->initCheck();
if (mInitCheck != OK) {
mRecord.clear();
@@ -465,4 +467,35 @@
return value;
}
+status_t AudioSource::setInputDevice(audio_port_handle_t deviceId) {
+ if (mRecord != 0) {
+ return mRecord->setInputDevice(deviceId);
+ }
+ return NO_INIT;
+}
+
+status_t AudioSource::getRoutedDeviceId(audio_port_handle_t* deviceId) {
+ if (mRecord != 0) {
+ *deviceId = mRecord->getRoutedDeviceId();
+ return NO_ERROR;
+ }
+ return NO_INIT;
+}
+
+status_t AudioSource::addAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback) {
+ if (mRecord != 0) {
+ return mRecord->addAudioDeviceCallback(callback);
+ }
+ return NO_INIT;
+}
+
+status_t AudioSource::removeAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback) {
+ if (mRecord != 0) {
+ return mRecord->removeAudioDeviceCallback(callback);
+ }
+ return NO_INIT;
+}
+
} // namespace android
diff --git a/media/libstagefright/codec2/include/C2.h b/media/libstagefright/codec2/include/C2.h
index bd563ff..01d1341 100644
--- a/media/libstagefright/codec2/include/C2.h
+++ b/media/libstagefright/codec2/include/C2.h
@@ -66,7 +66,7 @@
* mitigate binary breaks by adhering to the following conventions:
*
* - at most one vtable with placeholder virtual methods
- * - all optional/placeholder virtual methods returning a C2Status, with C2_OMITTED not requiring
+ * - all optional/placeholder virtual methods returning a c2_status_t, with C2_OMITTED not requiring
* any update to input/output arguments.
* - limiting symbol export of inline methods
* - use of pimpl (or shared-pimpl)
@@ -106,9 +106,9 @@
typedef const char *C2StringLiteral;
/**
- * C2Status: status codes used.
+ * c2_status_t: status codes used.
*/
-enum C2Status : int32_t {
+enum c2_status_t : int32_t {
/*
* Use android status constants if available. Otherwise, define the android status constants as
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 22e4360..d978e42 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -91,7 +91,7 @@
* \retval C2_REFUSED no permission to wait for the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented waiting for the fence (unexpected)
*/
- C2Status wait(nsecs_t timeoutNs);
+ c2_status_t wait(nsecs_t timeoutNs);
/**
* Used to check if this fence is valid (if there is a chance for it to be signaled.)
@@ -158,7 +158,7 @@
* \retval C2_REFUSED no permission to signal the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
*/
- C2Status fire();
+ c2_status_t fire();
/**
* Trigger this event from the merging of the supplied fences. This means that it will be
@@ -172,7 +172,7 @@
* \retval C2_REFUSED no permission to merge the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented merging the fence(s) (unexpected)
*/
- C2Status merge(std::vector<C2Fence> fences);
+ c2_status_t merge(std::vector<C2Fence> fences);
/**
* Abandons the event and any associated fence(s).
@@ -186,7 +186,7 @@
* \retval C2_REFUSED no permission to abandon the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
*/
- C2Status abandon();
+ c2_status_t abandon();
private:
class Impl;
@@ -200,12 +200,12 @@
* Interface for objects that encapsulate an updatable status value.
*/
struct _C2InnateStatus {
- inline C2Status status() const { return mStatus; }
+ inline c2_status_t status() const { return mStatus; }
protected:
- _C2InnateStatus(C2Status status) : mStatus(status) { }
+ _C2InnateStatus(c2_status_t status) : mStatus(status) { }
- C2Status mStatus; // this status is updatable by the object
+ c2_status_t mStatus; // this status is updatable by the object
};
/// @}
@@ -230,10 +230,10 @@
}
protected:
- C2Acquirable(C2Status error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
+ C2Acquirable(c2_status_t error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
private:
- C2Status mInitialError;
+ c2_status_t mInitialError;
T mT; // TODO: move instead of copy
};
@@ -449,11 +449,11 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Status error() const;
+ c2_status_t error() const;
protected:
C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
- explicit C2ReadView(C2Status error);
+ explicit C2ReadView(c2_status_t error);
private:
class Impl;
@@ -482,11 +482,11 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Status error() const;
+ c2_status_t error() const;
protected:
C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
- explicit C2WriteView(C2Status error);
+ explicit C2WriteView(c2_status_t error);
private:
class Impl;
@@ -631,7 +631,7 @@
* \retval C2_TIMED_OUT the reservation timed out \todo when?
* \retval C2_CORRUPTED some unknown error prevented reserving space. (unexpected)
*/
- C2Status reserve(size_t size, C2Fence *fence /* nullable */);
+ c2_status_t reserve(size_t size, C2Fence *fence /* nullable */);
/**
* Abandons a portion of this segment. This will move to the beginning of this segment.
@@ -644,7 +644,7 @@
* \retval C2_TIMED_OUT the operation timed out (unexpected)
* \retval C2_CORRUPTED some unknown error prevented abandoning the data (unexpected)
*/
- C2Status abandon(size_t size);
+ c2_status_t abandon(size_t size);
/**
* Share a portion as block(s) with consumers (these are moved to the used section).
@@ -661,7 +661,7 @@
* \retval C2_TIMED_OUT the operation timed out (unexpected)
* \retval C2_CORRUPTED some unknown error prevented sharing the data (unexpected)
*/
- C2Status share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
+ c2_status_t share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
/**
* Returns the beginning offset of this segment from the start of this circular block.
@@ -695,7 +695,7 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Status error() const;
+ c2_status_t error() const;
};
/**
@@ -716,7 +716,7 @@
* \param size number of bytes to commit to the next segment
* \param fence fence used for the commit (the fence must signal before the data is committed)
*/
- C2Status commit(size_t size, C2Fence fence);
+ c2_status_t commit(size_t size, C2Fence fence);
/**
* Maps this block into memory and returns a write view for it.
@@ -1016,14 +1016,14 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Status error() const;
+ c2_status_t error() const;
protected:
C2GraphicView(
const _C2PlanarCapacityAspect *parent,
uint8_t *const *data,
const C2PlaneLayout& layout);
- explicit C2GraphicView(C2Status error);
+ explicit C2GraphicView(c2_status_t error);
private:
class Impl;
@@ -1224,7 +1224,7 @@
* \retval C2_NO_MEMORY not enough memory to register for this callback
* \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
*/
- C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+ c2_status_t registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
/**
* Unregisters a previously registered pre-destroy notification.
@@ -1236,7 +1236,7 @@
* \retval C2_NOT_FOUND the notification was not found
* \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
*/
- C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+ c2_status_t unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
///@}
@@ -1262,7 +1262,7 @@
* \retval C2_NO_MEMORY not enough memory to attach the metadata (this return value is not
* used if the same kind of metadata is already attached to the buffer).
*/
- C2Status setInfo(const std::shared_ptr<C2Info> &info);
+ c2_status_t setInfo(const std::shared_ptr<C2Info> &info);
/**
* Checks if there is a certain type of metadata attached to this buffer.
@@ -1385,7 +1385,7 @@
* the usage flags are invalid (caller error)
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
*/
- virtual C2Status map(
+ virtual c2_status_t map(
size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
void **addr /* nonnull */) = 0;
@@ -1409,7 +1409,7 @@
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
* \retval C2_REFUSED no permission to unmap the portion (unexpected - system)
*/
- virtual C2Status unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
+ virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
/**
* Returns true if this is a valid allocation.
@@ -1472,7 +1472,7 @@
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
*/
- virtual C2Status map(
+ virtual c2_status_t map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
// TODO: return <addr, size> buffers with plane sizes
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
@@ -1492,7 +1492,7 @@
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
* \retval C2_REFUSED no permission to unmap the section (unexpected - system)
*/
- virtual C2Status unmap(C2Fence *fenceFd /* nullable */) = 0;
+ virtual c2_status_t unmap(C2Fence *fenceFd /* nullable */) = 0;
/**
* Returns true if this is a valid allocation.
@@ -1544,8 +1544,10 @@
/**
* Information about an allocator.
+ *
+ * Allocators don't have a query API so all queriable information is stored here.
*/
- struct Info {
+ struct Traits {
C2String name; ///< allocator name
id_t id; ///< allocator ID
type_t supportedTypes; ///< supported allocation types
@@ -1574,13 +1576,15 @@
virtual id_t getId() const = 0;
/**
- * Returns the allocator information.
+ * Returns the allocator traits.
*
* This method MUST be "non-blocking" and return within 1ms.
*
+ * Allocators don't have a full-fledged query API, only this method.
+ *
* \return allocator information
*/
- virtual std::shared_ptr<const Info> getInfo() const = 0;
+ virtual std::shared_ptr<const Traits> getTraits() const = 0;
/**
* Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
@@ -1604,7 +1608,7 @@
* \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Status newLinearAllocation(
+ virtual c2_status_t newLinearAllocation(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
@@ -1627,7 +1631,7 @@
* \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Status priorLinearAllocation(
+ virtual c2_status_t priorLinearAllocation(
const C2Handle *handle __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
@@ -1660,7 +1664,7 @@
* \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Status newGraphicAllocation(
+ virtual c2_status_t newGraphicAllocation(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
@@ -1684,7 +1688,7 @@
* \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
*/
- virtual C2Status priorGraphicAllocation(
+ virtual c2_status_t priorGraphicAllocation(
const C2Handle *handle __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
@@ -1764,7 +1768,7 @@
* \retval C2_OMITTED this pool does not support linear blocks
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
*/
- virtual C2Status fetchLinearBlock(
+ virtual c2_status_t fetchLinearBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
*block = nullptr;
@@ -1792,7 +1796,7 @@
* \retval C2_OMITTED this pool does not support circular blocks
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
*/
- virtual C2Status fetchCircularBlock(
+ virtual c2_status_t fetchCircularBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
*block = nullptr;
@@ -1823,7 +1827,7 @@
* \retval C2_OMITTED this pool does not support 2D blocks
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
*/
- virtual C2Status fetchGraphicBlock(
+ virtual c2_status_t fetchGraphicBlock(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index c88de62..2dbf7ea 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -36,25 +36,6 @@
class C2Component;
-class C2ComponentListener {
-public:
- virtual void onWorkDone(std::weak_ptr<C2Component> component,
- std::vector<std::unique_ptr<C2Work>> workItems) = 0;
-
- virtual void onTripped(std::weak_ptr<C2Component> component,
- std::vector<std::shared_ptr<C2SettingResult>> settingResult) = 0;
-
- virtual void onError(std::weak_ptr<C2Component> component,
- uint32_t errorCode) = 0;
-
- // virtual void onTunnelReleased(<from>, <to>) = 0;
-
- // virtual void onComponentReleased(<id>) = 0;
-
-protected:
- virtual ~C2ComponentListener() = default;
-};
-
struct C2FieldSupportedValuesQuery {
enum Type : uint32_t {
POSSIBLE, ///< query all possible values regardless of other settings
@@ -63,7 +44,7 @@
const C2ParamField field;
const Type type;
- C2Status status;
+ c2_status_t status;
C2FieldSupportedValues values;
C2FieldSupportedValuesQuery(const C2ParamField &field_, Type type_)
@@ -118,7 +99,7 @@
*
* \return a unique node ID for this component or component interface instance.
*/
- virtual node_id getId() const = 0;
+ virtual c2_node_id_t getId() const = 0;
/**
* Queries a set of parameters from the component or interface object.
@@ -154,7 +135,7 @@
* \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
* (unexpected)
*/
- virtual C2Status query_nb(
+ virtual c2_status_t query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -191,7 +172,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual C2Status config_nb(
+ virtual c2_status_t config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
@@ -230,7 +211,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual C2Status commit_sm(
+ virtual c2_status_t commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
@@ -256,7 +237,7 @@
* \retval C2_TIMED_OUT could not create the tunnel within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented the creation of the tunnel (unexpected)
*/
- virtual C2Status createTunnel_sm(node_id targetComponent) = 0;
+ virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) = 0;
/**
* Releases a tunnel from this component to the target component.
@@ -277,38 +258,41 @@
* \retval C2_TIMED_OUT could not mark the tunnel for release within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented the release of the tunnel (unexpected)
*/
- virtual C2Status releaseTunnel_sm(node_id targetComponent) = 0;
-
+ virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) = 0;
// REFLECTION MECHANISM (USED FOR EXTENSION)
// =============================================================================================
/**
- * Returns the parameter reflector.
- *
- * This is used to describe parameter fields.
- *
- * \return a shared parameter reflector object.
- */
- virtual std::shared_ptr<C2ParamReflector> getParamReflector() const = 0;
-
- /**
* Returns the set of supported parameters.
*
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
* \param[out] params a vector of supported parameters will be appended to this vector.
*
* \retval C2_OK the operation completed successfully.
* \retval C2_NO_MEMORY not enough memory to complete this method.
*/
- virtual C2Status getSupportedParams(
+ virtual c2_status_t querySupportedParams_nb(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
/**
+ * Retrieves the supported values for the queried fields.
*
- * \todo should this take a list considering that setting some fields may further limit other
- * fields in the same list?
+ * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
+ * currently supported values, or potential supported values) in fields.
+ * Upon return the component SHALL fill in the supported values for the fields listed as well
+ * as a status for each field. Component shall process all fields queried even if some queries
+ * fail.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \param[in out] fields a vector of fields descriptor structures.
+ *
+ * \retval C2_OK the operation completed successfully.
+ * \retval C2_BAD_INDEX at least one field was not recognized as a component field
*/
- virtual C2Status getSupportedValues(
+ virtual c2_status_t querySupportedValues_nb(
std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
virtual ~C2ComponentInterface() = default;
@@ -316,6 +300,75 @@
class C2Component {
public:
+ class Listener {
+ public:
+ virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
+ std::vector<std::unique_ptr<C2Work>> workItems) = 0;
+
+ virtual void onTripped_nb(std::weak_ptr<C2Component> component,
+ std::vector<std::shared_ptr<C2SettingResult>> settingResult) = 0;
+
+ virtual void onError_nb(std::weak_ptr<C2Component> component,
+ uint32_t errorCode) = 0;
+
+ // virtual void onTunnelReleased(<from>, <to>) = 0;
+
+ // virtual void onComponentReleased(<id>) = 0;
+
+ protected:
+ virtual ~Listener() = default;
+ };
+
+ /**
+ * Sets the listener for this component
+ *
+ * This method MUST be supported in all states. The listener can only be set to non-null value
+ * in non-running state (that does not include tripped or error). It can be set to nullptr in
+ * any state. Components only use the listener in running state.
+ *
+ * If listener is nullptr, the component SHALL guarantee that no more listener callbacks are
+ * done to the original listener once this method returns. (Any pending listener callbacks will
+ * need to be completed during this call - hence this call may be temporarily blocking.)
+ *
+ * This method may be momentarily blocking, but must return within 5ms.
+ *
+ * Component SHALL handle listener notifications from the same thread (the thread used is
+ * at the component's discretion.)
+ *
+ * \note This could also be accomplished by passing a weak_ptr to a component-specific listener
+ * here and requiring the client to always promote the weak_ptr before any callback. This would
+ * put the burden on the client to clear the listener - wait for its deletion - at which point
+ * it is guaranteed that no more listener callbacks will occur.
+ *
+ * \todo TBD is this needed? or move it to createComponent()
+ *
+ * \param listener the component listener object
+ *
+ * \retval C2_BAD_STATE attempting to change the listener in the running state (user error)
+ * \retval C2_OK listener was updated successfully.
+ */
+ virtual c2_status_t setListener_sm(const std::shared_ptr<Listener> &listener) = 0;
+
+ /**
+ * Information about a component.
+ */
+ struct Traits {
+ // public:
+ // TBD
+ #if 0
+ C2String name; ///< name of the component
+ C2DomainKind domain; ///< component domain (e.g. audio or video)
+ C2ComponentKind type; ///< component type (e.g. encoder, decoder or filter)
+ C2StringLiteral mediaType; ///< media type supported by the component
+
+ /**
+ * name alias(es) for backward compatibility.
+ * \note Multiple components can have the same alias as long as their media-type differs.
+ */
+ std::vector<C2StringLiteral> aliases; ///< name aliases for backward compatibility
+ #endif
+ };
+
// METHODS AVAILABLE WHEN RUNNING
// =============================================================================================
@@ -336,7 +389,7 @@
* \retval C2_NO_MEMORY not enough memory to queue the work
* \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
*/
- virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
+ virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
/**
* Announces a work to be queued later for the component. This reserves a slot for the queue
@@ -354,8 +407,17 @@
* \retval C2_CORRUPTED some unknown error prevented recording the announcement (unexpected)
*
* \todo Can this be rolled into queue_nb?
+ * \todo Expose next work item for each component to detect stalls
*/
- virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+ virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+
+ enum flush_mode_t : uint32_t {
+ /// flush work from this component only
+ FLUSH_COMPONENT,
+ /// flush work from this component and all components connected downstream from it via
+ /// tunneling
+ FLUSH_CHAIN,
+ };
/**
* Discards and abandons any pending work for the component, and optionally any component
@@ -379,22 +441,33 @@
*
* Work that could not be abandoned or discarded immediately SHALL be marked to be
* discarded at the earliest opportunity, and SHALL be returned via the onWorkDone() callback.
+ * This shall be completed within 500ms.
*
- * \param flushThrough flush work from this component and all components connected downstream
- * from it via tunneling.
+ * \param mode flush mode
*
- * \retval C2_OK the work announcement has been successfully recorded
+ * \retval C2_OK the component has been successfully flushed
* \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
*/
- virtual C2Status flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+ virtual c2_status_t flush_sm(flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+
+ enum drain_mode_t : uint32_t {
+ /// drain component only
+ DRAIN_COMPONENT,
+ /// marks the last work item with a persistent "end-of-stream" marker that will drain
+ /// downstream components
+ /// \todo this may confuse work-ordering downstream
+ DRAIN_CHAIN,
+ /**
+ * \todo define this; we could place EOS to all upstream components, just this component, or
+ * all upstream and downstream component.
+ * \todo should EOS carry over to downstream components?
+ */
+ };
/**
- * Drains the component, and optionally downstream components
- *
- * \todo define this; we could place EOS to all upstream components, just this component, or
- * all upstream and downstream component.
- * \todo should EOS carry over to downstream components?
+ * Drains the component, and optionally downstream components. This is a signalling method;
+ * as such it does not wait for any work completion.
*
* Marks last work item as "end-of-stream", so component is notified not to wait for further
* work before it processes work already queued. This method is called to set the end-of-stream
@@ -407,16 +480,13 @@
*
* Work that is completed SHALL be returned via the onWorkDone() callback.
*
- * \param drainThrough marks the last work item with a persistent "end-of-stream" marker that
- * will drain downstream components.
+ * \param mode drain mode
*
- * \todo this may confuse work-ordering downstream; could be an mode enum
- *
- * \retval C2_OK the work announcement has been successfully recorded
+ * \retval C2_OK the drain request has been successfully recorded
* \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
*/
- virtual C2Status drain_nb(bool drainThrough) = 0;
+ virtual c2_status_t drain_nb(drain_mode_t mode) = 0;
// STATE CHANGE METHODS
// =============================================================================================
@@ -430,14 +500,12 @@
* there are no immediate guarantees. Though there are guarantees for responsiveness immediately
* after start returns.
*
- * \todo Could we just start a ComponentInterface to get a Component?
- *
- * \retval C2_OK the work announcement has been successfully recorded
+ * \retval C2_OK the component has started successfully
* \retval C2_NO_MEMORY not enough memory to start the component
* \retval C2_TIMED_OUT the component could not be started within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented starting the component (unexpected)
*/
- virtual C2Status start() = 0;
+ virtual c2_status_t start() = 0;
/**
* Stops the component.
@@ -454,14 +522,14 @@
* This does not alter any settings and tunings that may have resulted in a tripped state.
* (Is this material given the definition? Perhaps in case we want to start again.)
*/
- virtual C2Status stop() = 0;
+ virtual c2_status_t stop() = 0;
/**
* Resets the component.
*
- * This method MUST be supported in running (including tripped) state.
+ * This method MUST be supported in all (including tripped) state.
*
- * This method MUST be supported during any other call (\todo or just blocking ones?)
+ * This method MUST be supported during any other blocking call.
*
* This method MUST return withing 500ms.
*
@@ -473,22 +541,24 @@
* This brings settings back to their default - "guaranteeing" no tripped space.
*
* \todo reclaim support - it seems that since ownership is passed, this will allow reclaiming stuff.
+ *
+ * \retval C2_OK the component has been reset
+ * \retval C2_TIMED_OUT the component could not be reset within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented resetting the component (unexpected)
*/
virtual void reset() = 0;
/**
* Releases the component.
*
- * This method MUST be supported in any state. (\todo Or shall we force reset() first to bring
- * to a known state?)
+ * This method MUST be supported in stopped state.
*
- * This method MUST return withing 500ms.
+ * This method MUST return withing 500ms. Upon return all references shall be abandoned.
*
- * \todo should this return completed work, since client will just free it? Also, if it unblocks
- * a stop, where should completed work be returned?
- *
- * TODO: does it matter if this call has a short time limit? Yes, as upon return all references
- * shall be abandoned.
+ * \retval C2_OK the component has been released
+ * \retval C2_BAD_STATE the component is running
+ * \retval C2_TIMED_OUT the component could not be released within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented releasing the component (unexpected)
*/
virtual void release() = 0;
@@ -515,6 +585,8 @@
/**
* \return a vector of supported parameter indices parsed by this info parser.
*
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
* \todo sticky vs. non-sticky params? this may be communicated by param-reflector.
*/
virtual const std::vector<C2Param::Index> getParsedParams() const = 0;
@@ -528,18 +600,13 @@
* \retval C2_TIMED_OUT could not reset the parser within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented the resetting of the parser (unexpected)
*/
- virtual C2Status reset() { return C2_OK; }
+ virtual c2_status_t reset() { return C2_OK; }
- virtual C2Status parseFrame(C2BufferPack &frame);
+ virtual c2_status_t parseFrame(C2BufferPack &frame);
virtual ~C2FrameInfoParser() = default;
};
-struct C2ComponentInfo {
- // TBD
-
-};
-
class C2AllocatorStore {
public:
typedef C2Allocator::id_t id_t;
@@ -564,16 +631,18 @@
/**
* Returns the set of allocators supported by this allocator store.
*
- * This method SHALL return within 1ms.
+ * This method MUST be "non-blocking" and return within 1ms.
*
* \retval vector of allocator information (as shared pointers)
* \retval an empty vector if there was not enough memory to allocate the whole vector.
*/
- virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const = 0;
+ virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb() const = 0;
/**
* Retrieves/creates a shared allocator object.
*
+ * This method MUST be return within 5ms.
+ *
* The allocator is created on first use, and the same allocator is returned on subsequent
* concurrent uses in the same process. The allocator is freed when it is no longer referenced.
*
@@ -589,7 +658,7 @@
* \retval C2_NOT_FOUND no such allocator
* \retval C2_NO_MEMORY not enough memory to create the allocator
*/
- virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+ virtual c2_status_t fetchAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
virtual ~C2AllocatorStore() = default;
};
@@ -597,6 +666,21 @@
class C2ComponentStore {
public:
/**
+ * Returns the name of this component or component interface object.
+ * This is a unique name for this component or component interface 'class'; however, multiple
+ * instances of this component SHALL have the same name.
+ *
+ * This method MUST be supported in any state. This call does not change the state nor the
+ * internal states of the component.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this component or component interface object.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
* Creates a component.
*
* This method SHALL return within 100ms.
@@ -612,7 +696,8 @@
* \retval C2_NOT_FOUND no such component
* \retval C2_NO_MEMORY not enough memory to create the component
*/
- virtual C2Status createComponent(C2String name, std::shared_ptr<C2Component>* const component);
+ virtual c2_status_t createComponent(
+ C2String name, std::shared_ptr<C2Component>* const component) = 0;
/**
* Creates a component interface.
@@ -633,26 +718,27 @@
*
* \todo Do we need an interface, or could this just be a component that is never started?
*/
- virtual C2Status createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
+ virtual c2_status_t createInterface(
+ C2String name, std::shared_ptr<C2ComponentInterface>* const interface) = 0;
/**
* Returns the list of components supported by this component store.
*
- * This method SHALL return within 1ms.
+ * This method may be momentarily blocking, but MUST return within 5ms.
*
* \retval vector of component information.
*/
- virtual std::vector<std::unique_ptr<const C2ComponentInfo>> getComponents();
+ virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents_sm() const = 0;
// -------------------------------------- UTILITY METHODS --------------------------------------
// on-demand buffer layout conversion (swizzling)
- virtual C2Status copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
+ //
+ virtual c2_status_t copyBuffer(
+ std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) = 0;
- // C2Status selectPreferredColor(formats<A>, formats<B>);
-
- // GLOBAL SETTINGS
- // system-wide stride & slice-height (???)
+ // -------------------------------------- CONFIGURATION API -----------------------------------
+ // e.g. for global settings (system-wide stride, etc.)
/**
* Queries a set of system-wide parameters.
@@ -683,7 +769,7 @@
* \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
* (unexpected)
*/
- virtual C2Status query_sm(
+ virtual c2_status_t query_sm(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -701,15 +787,15 @@
* \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
* update may allow some subsequent parameter update.
*
- * This method MUST be "non-blocking" and return within 1ms.
+ * This method may be momentarily blocking, but MUST return within 5ms.
*
- * \param params a list of parameter updates. These will be updated to the actual
+ * \param params a list of parameter updates. These will be updated to the actual
* parameter values after the updates (this is because tuning is performed
* at best effort).
* \todo params that could not be updated are not marked here, so are
* confusing - are they "existing" values or intended to be configured
* values?
- * \param failures a list of parameter failures
+ * \param failures a list of parameter failures
*
* \retval C2_OK all parameters could be updated successfully
* \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
@@ -722,9 +808,95 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual C2Status config_nb(
+ virtual c2_status_t config_sm(
const std::vector<C2Param* const> ¶ms,
- std::list<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+
+ /**
+ * Atomically sets a set of system-wide parameters.
+ *
+ * \note There are no settable system-wide parameters defined thus far, but may be added in the
+ * future.
+ *
+ * The component store SHALL update all supported configuration at best effort(TBD)
+ * (unless configured otherwise) and skip unsupported ones. If any errors are encountered
+ * (other than unsupported parameters), the configuration SHALL be aborted as if it did not
+ * happen.
+ *
+ * \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
+ * update may allow some subsequent parameter update.
+ *
+ * This method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \param params[in,out] a list of parameter updates. These will be updated to the actual
+ * parameter values after the updates (this is because tuning is performed
+ * at best effort).
+ * \todo params that could not be updated are not marked here, so are
+ * confusing - are they "existing" values or intended to be configured
+ * values?
+ * \param failures[out] a list of parameter failures
+ *
+ * \retval C2_OK all parameters could be updated successfully
+ * \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
+ * parameters were not supported
+ * \retval C2_BAD_VALUE some supported parameters could not be updated successfully because
+ * they contained unsupported values. These are returned in |failures|.
+ * \retval C2_NO_MEMORY some supported parameters could not be updated successfully because
+ * they contained unsupported values, but could not allocate a failure
+ * object for them.
+ * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
+ * (unexpected)
+ */
+ virtual c2_status_t commit_sm(
+ const std::vector<C2Param* const> ¶ms,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+
+ // REFLECTION MECHANISM (USED FOR EXTENSION)
+ // =============================================================================================
+
+ /**
+ * Returns the parameter reflector.
+ *
+ * This is used to describe parameter fields. This is shared for all components created by
+ * this component store.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a shared parameter reflector object.
+ */
+ virtual std::shared_ptr<C2ParamReflector> getParamReflector() const = 0;
+
+ /**
+ * Returns the set of supported parameters.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \param[out] params a vector of supported parameters will be appended to this vector.
+ *
+ * \retval C2_OK the operation completed successfully.
+ * \retval C2_NO_MEMORY not enough memory to complete this method.
+ */
+ virtual c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
+
+ /**
+ * Retrieves the supported values for the queried fields.
+ *
+ * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
+ * currently supported values, or potential supported values) in fields.
+ * Upon return the store SHALL fill in the supported values for the fields listed as well
+ * as a status for each field. Store shall process all fields queried even if some queries
+ * fail.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \param[in out] fields a vector of fields descriptor structures.
+ *
+ * \retval C2_OK the operation completed successfully.
+ * \retval C2_BAD_INDEX at least one field was not recognized as a component store field
+ */
+ virtual c2_status_t querySupportedValues_nb(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
virtual ~C2ComponentStore() = default;
};
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index 52c00d5..105cf81 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -75,14 +75,9 @@
// WORK
// ================================================================================================
-// node_id-s
-typedef uint32_t node_id;
-
-enum flags_t : uint32_t {
- BUFFERFLAG_CODEC_CONFIG = (1 << 0),
- BUFFERFLAG_DROP_FRAME = (1 << 1),
- BUFFERFLAG_END_OF_STREAM = (1 << 2),
-};
+// c2_node_id_t-s
+typedef uint32_t c2_node_id_t;
+typedef c2_node_id_t c2_node_id_t;
enum {
kParamIndexWorkOrdinal,
@@ -101,6 +96,12 @@
struct C2BufferPack {
//public:
+ enum flags_t : uint32_t {
+ FLAG_CODEC_CONFIG = (1 << 0),
+ FLAG_DROP_FRAME = (1 << 1),
+ FLAG_END_OF_STREAM = (1 << 2),
+ };
+
flags_t flags;
C2WorkOrdinalStruct ordinal;
std::vector<std::shared_ptr<C2Buffer>> buffers;
@@ -113,7 +114,7 @@
struct C2Worklet {
//public:
// IN
- node_id component;
+ c2_node_id_t component;
std::list<std::unique_ptr<C2Param>> tunings; //< tunings to be applied before processing this
// worklet
@@ -165,13 +166,13 @@
std::list<std::unique_ptr<C2Worklet>> worklets;
uint32_t worklets_processed;
- C2Status result;
+ c2_status_t result;
};
struct C2WorkOutline {
//public:
C2WorkOrdinalStruct ordinal;
- std::list<node_id> chain;
+ std::list<c2_node_id_t> chain;
};
/// @}
diff --git a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
index b725d76..0613b5a 100644
--- a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
+++ b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
@@ -72,7 +72,7 @@
// If a parameter is writable this is called.
// Test one filed |writableField| for given writable parameter |param|.
- // |validValues| contains all values obtained from getSupportedValues() for |writableField|.
+ // |validValues| contains all values obtained from querySupportedValues() for |writableField|.
// The test checks validity for config() with each value, and make sure values are config-ed
// by query() them out. |invalidValues| contains some values which are not in |validValues|.
// The test expects C2_BAD_VALUE while config() with these values,
@@ -112,11 +112,11 @@
// check if a component has a parameter whose type is |T|.
// If a component has, the value should be copied into an argument, that is
// |p| in queryOnStack() and |heapParams| in queryOnHeap().
- // The return value is C2Status (e.g. C2_OK).
- template <typename T> C2Status queryOnStack(T *const p);
+ // The return value is c2_status_t (e.g. C2_OK).
+ template <typename T> c2_status_t queryOnStack(T *const p);
template <typename T>
- C2Status queryOnHeap(const T &p,
+ c2_status_t queryOnHeap(const T &p,
std::vector<std::unique_ptr<C2Param>> *const heapParams);
// Get a value whose type is |T| in a component. The value is copied to |param|.
@@ -139,7 +139,7 @@
// Execute an interface's config_nb(). |T| is a single parameter type, not std::vector.
// config() creates std::vector<C2Param *const> {p} and passes it to config_nb().
template <typename T>
- C2Status
+ c2_status_t
config(T *const p,
std::vector<std::unique_ptr<C2SettingResult>> *const failures);
@@ -150,7 +150,7 @@
// Test if config works correctly for writable parameters.
// This changes the parameter's value to |newParam|.
// |stConfig| is a return value of config().
- template <typename T> void configWritableParamValidValue(const T &newParam, C2Status *stConfig);
+ template <typename T> void configWritableParamValidValue(const T &newParam, c2_status_t *stConfig);
// Test if config works correctly in the case an invalid value |newParam| is tried to write
// to an writable parameter.
@@ -194,13 +194,13 @@
} \
} while (false)
-template <typename T> C2Status C2CompIntfTest::queryOnStack(T *const p) {
+template <typename T> c2_status_t C2CompIntfTest::queryOnStack(T *const p) {
std::vector<C2Param *const> stackParams{p};
return mIntf->query_nb(stackParams, {}, nullptr);
}
template <typename T>
-C2Status C2CompIntfTest::queryOnHeap(
+c2_status_t C2CompIntfTest::queryOnHeap(
const T &p, std::vector<std::unique_ptr<C2Param>> *const heapParams) {
uint32_t index = p.type();
if (p.forStream()) {
@@ -258,7 +258,7 @@
}
template <typename T>
-C2Status C2CompIntfTest::config(
+c2_status_t C2CompIntfTest::config(
T *const p, std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
std::vector<C2Param *const> params{p};
return mIntf->config_nb(params, failures);
@@ -286,7 +286,7 @@
}
template <typename T>
-void C2CompIntfTest::configWritableParamValidValue(const T &newParam, C2Status *configResult) {
+void C2CompIntfTest::configWritableParamValidValue(const T &newParam, c2_status_t *configResult) {
std::unique_ptr<T> p = makeParamFrom(newParam);
std::vector<C2Param *const> params{p.get()};
@@ -297,7 +297,7 @@
// because there may be dependent limitations between fields or between parameters.
// TODO(hiroh): I have to fill the return value. Comments in C2Component.h doesn't mention
// about the return value when conflict happens. I set C2_BAD_VALUE to it temporarily now.
- C2Status stConfig = mIntf->config_nb(params, &failures);
+ c2_status_t stConfig = mIntf->config_nb(params, &failures);
if (stConfig == C2_OK) {
EXPECT_EQ(0u, failures.size());
} else {
@@ -481,7 +481,7 @@
TParam *const param, TRealField *const writableField,
const std::vector<TField> &validValues,
const std::vector<TField> &invalidValues) {
- C2Status stConfig;
+ c2_status_t stConfig;
// Get the parameter's value in the beginning in order to reset the value at the end.
TRACED_FAILURE(getValue(param));
@@ -555,7 +555,7 @@
std::vector<std::unique_ptr<C2SettingResult>> failures;
// Config does not change the parameter, because param is the present param.
// This config is executed to find out if a parameter is read-only or writable.
- C2Status stStack = config(param.get(), &failures);
+ c2_status_t stStack = config(param.get(), &failures);
if (stStack == C2_BAD_VALUE) {
// Read-only
std::unique_ptr<T> newParam = makeParam<T>();
@@ -594,7 +594,7 @@
C2ParamField(param.get(), &field_type_name_::field_name_)) \
}; \
ASSERT_EQ(C2_OK, \
- mIntf->getSupportedValues(validValueInfos)); \
+ mIntf->querySupportedValues_nb(validValueInfos)); \
ASSERT_EQ(1u, validValueInfos.size()); \
std::vector<decltype(param->field_name_)> validValues; \
std::vector<decltype(param->field_name_)> invalidValues; \
@@ -640,7 +640,7 @@
setComponent(intf);
std::vector<std::shared_ptr<C2ParamDescriptor>> supportedParams;
- ASSERT_EQ(C2_OK, mIntf->getSupportedParams(&supportedParams));
+ ASSERT_EQ(C2_OK, mIntf->querySupportedParams_nb(&supportedParams));
EACH_TEST_SELF(C2ComponentLatencyInfo, TEST_U32_WRITABLE_FIELD);
EACH_TEST_SELF(C2ComponentTemporalInfo, TEST_U32_WRITABLE_FIELD);
diff --git a/media/libstagefright/codec2/tests/C2Param_test.cpp b/media/libstagefright/codec2/tests/C2Param_test.cpp
index 97c5f91..a688d2c 100644
--- a/media/libstagefright/codec2/tests/C2Param_test.cpp
+++ b/media/libstagefright/codec2/tests/C2Param_test.cpp
@@ -2393,41 +2393,41 @@
class MyComponentInstance : public C2ComponentInterface {
public:
- virtual C2String getName() const {
+ virtual C2String getName() const override {
/// \todo this seems too specific
return "sample.interface";
};
- virtual node_id getId() const {
+ virtual c2_node_id_t getId() const override {
/// \todo how are these shared?
return 0;
}
- virtual C2Status commit_sm(
+ virtual c2_status_t commit_sm(
const std::vector<C2Param* const> ¶ms,
- std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
(void)params;
(void)failures;
return C2_OMITTED;
}
- virtual C2Status config_nb(
+ virtual c2_status_t config_nb(
const std::vector<C2Param* const> ¶ms,
- std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
(void)params;
(void)failures;
return C2_OMITTED;
}
- virtual C2Status createTunnel_sm(node_id targetComponent) {
+ virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) override {
(void)targetComponent;
return C2_OMITTED;
}
- virtual C2Status query_nb(
+ virtual c2_status_t query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
- std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
+ std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
for (C2Param* const param : stackParams) {
if (!*param) { // param is already invalid - remember it
continue;
@@ -2466,7 +2466,7 @@
mMyParams.insert({mDomainInfo.type(), mDomainInfo});
}
- virtual C2Status releaseTunnel_sm(node_id targetComponent) {
+ virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) override {
(void)targetComponent;
return C2_OMITTED;
}
@@ -2477,7 +2477,7 @@
public:
MyParamReflector(const MyComponentInstance *i) : instance(i) { }
- virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) {
+ virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) override {
switch (paramIndex.coreIndex()) {
case decltype(instance->mDomainInfo)::coreIndex:
default:
@@ -2490,8 +2490,8 @@
}
};
- virtual C2Status getSupportedValues(
- std::vector<C2FieldSupportedValuesQuery> &fields) const {
+ virtual c2_status_t querySupportedValues_nb(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const override {
for (C2FieldSupportedValuesQuery &query : fields) {
if (query.field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
query.values = C2FieldSupportedValues(
@@ -2508,22 +2508,20 @@
return C2_OK;
}
- virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
+ std::shared_ptr<C2ParamReflector> getParamReflector() const {
return std::shared_ptr<C2ParamReflector>(new MyParamReflector(this));
}
- virtual C2Status getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
+ virtual c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override {
params->push_back(std::make_shared<C2ParamDescriptor>(
true /* required */, "_domain", &mDomainInfo));
- return C2_OK;
- }
-
- C2Status getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
params->push_back(std::shared_ptr<C2ParamDescriptor>(
new C2ParamDescriptor(true /* required */, "_domain", &mDomainInfo)));
return C2_OK;
}
+ virtual ~MyComponentInstance() override = default;
};
template<typename E, bool S=std::is_enum<E>::value>
@@ -2700,10 +2698,11 @@
TEST_F(C2ParamTest, ReflectorTest) {
C2ComponentDomainInfo domainInfo;
- std::shared_ptr<C2ComponentInterface> comp(new MyComponentInstance);
+ std::shared_ptr<MyComponentInstance> myComp(new MyComponentInstance);
+ std::shared_ptr<C2ComponentInterface> comp = myComp;
std::unique_ptr<C2StructDescriptor> desc{
- comp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
+ myComp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
dumpStruct(*desc);
std::vector<C2FieldSupportedValuesQuery> query = {
@@ -2714,7 +2713,7 @@
C2FieldSupportedValuesQuery::Current(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue)),
};
- EXPECT_EQ(C2_OK, comp->getSupportedValues(query));
+ EXPECT_EQ(C2_OK, comp->querySupportedValues_nb(query));
for (const C2FieldSupportedValuesQuery &q : query) {
dumpFSV(q.values, &domainInfo.mValue);
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index 3d23c23..1bcf070 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -38,7 +38,7 @@
~C2BufferTest() = default;
void allocateLinear(size_t capacity) {
- C2Status err = mLinearAllocator->newLinearAllocation(
+ c2_status_t err = mLinearAllocator->newLinearAllocation(
capacity,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&mLinearAllocation);
@@ -50,7 +50,7 @@
void mapLinear(size_t offset, size_t size, uint8_t **addr) {
ASSERT_TRUE(mLinearAllocation);
- C2Status err = mLinearAllocation->map(
+ c2_status_t err = mLinearAllocation->map(
offset,
size,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
@@ -82,7 +82,7 @@
}
void allocateGraphic(uint32_t width, uint32_t height) {
- C2Status err = mGraphicAllocator->newGraphicAllocation(
+ c2_status_t err = mGraphicAllocator->newGraphicAllocation(
width,
height,
HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -96,7 +96,7 @@
void mapGraphic(C2Rect rect, C2PlaneLayout *layout, uint8_t **addr) {
ASSERT_TRUE(mGraphicAllocation);
- C2Status err = mGraphicAllocation->map(
+ c2_status_t err = mGraphicAllocation->map(
rect,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
// TODO: fence
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
index 3e2242b..da8372c 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -38,7 +38,7 @@
using ::android::hardware::hidl_vec;
/* ===================================== GRALLOC ALLOCATION ==================================== */
-static C2Status maperr2error(Error maperr) {
+static c2_status_t maperr2error(Error maperr) {
switch (maperr) {
case Error::NONE: return C2_OK;
case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
@@ -52,12 +52,12 @@
class C2AllocationGralloc : public C2GraphicAllocation {
public:
- virtual ~C2AllocationGralloc();
+ virtual ~C2AllocationGralloc() override;
- virtual C2Status map(
+ virtual c2_status_t map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
- virtual C2Status unmap(C2Fence *fenceFd /* nullable */) override;
+ virtual c2_status_t unmap(C2Fence *fenceFd /* nullable */) override;
virtual bool isValid() const override { return true; }
virtual const C2Handle *handle() const override { return mHandle; }
virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
@@ -69,7 +69,7 @@
const sp<IMapper> &mapper,
hidl_handle &handle);
int dup() const;
- C2Status status() const;
+ c2_status_t status() const;
private:
const IMapper::BufferDescriptorInfo mInfo;
@@ -100,7 +100,7 @@
mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
}
-C2Status C2AllocationGralloc::map(
+c2_status_t C2AllocationGralloc::map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
// TODO
@@ -114,7 +114,7 @@
return C2_BAD_VALUE;
}
- C2Status err = C2_OK;
+ c2_status_t err = C2_OK;
if (!mBuffer) {
mMapper->importBuffer(
mHandle, [&err, this](const auto &maperr, const auto &buffer) {
@@ -202,9 +202,9 @@
return C2_OK;
}
-C2Status C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
+c2_status_t C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
// TODO: fence
- C2Status err = C2_OK;
+ c2_status_t err = C2_OK;
mMapper->unlock(
const_cast<native_handle_t *>(mBuffer),
[&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
@@ -235,18 +235,18 @@
C2String getName() const;
- C2Status newGraphicAllocation(
+ c2_status_t newGraphicAllocation(
uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
std::shared_ptr<C2GraphicAllocation> *allocation);
- C2Status priorGraphicAllocation(
+ c2_status_t priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation);
- C2Status status() const { return mInit; }
+ c2_status_t status() const { return mInit; }
private:
- C2Status mInit;
+ c2_status_t mInit;
sp<IAllocator> mAllocator;
sp<IMapper> mMapper;
};
@@ -268,7 +268,7 @@
return "android.allocator.gralloc";
}
-C2Status C2AllocatorGralloc::Impl::newGraphicAllocation(
+c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
std::shared_ptr<C2GraphicAllocation> *allocation) {
// TODO: buffer usage should be determined according to |usage|
@@ -281,7 +281,7 @@
(PixelFormat)format,
BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
};
- C2Status err = C2_OK;
+ c2_status_t err = C2_OK;
BufferDescriptor desc;
mMapper->createDescriptor(
info, [&err, &desc](const auto &maperr, const auto &descriptor) {
@@ -319,7 +319,7 @@
return C2_OK;
}
-C2Status C2AllocatorGralloc::Impl::priorGraphicAllocation(
+c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
(void) handle;
@@ -341,19 +341,19 @@
return mImpl->getName();
}
-C2Status C2AllocatorGralloc::newGraphicAllocation(
+c2_status_t C2AllocatorGralloc::newGraphicAllocation(
uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
std::shared_ptr<C2GraphicAllocation> *allocation) {
return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
}
-C2Status C2AllocatorGralloc::priorGraphicAllocation(
+c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
return mImpl->priorGraphicAllocation(handle, allocation);
}
-C2Status C2AllocatorGralloc::status() const {
+c2_status_t C2AllocatorGralloc::status() const {
return mImpl->status();
}
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 09df502..acd69af 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -82,20 +82,20 @@
/* ======================================= ION ALLOCATION ====================================== */
class C2AllocationIon : public C2LinearAllocation {
public:
- virtual C2Status map(
+ virtual c2_status_t map(
size_t offset, size_t size, C2MemoryUsage usage, int *fence,
- void **addr /* nonnull */);
- virtual C2Status unmap(void *addr, size_t size, int *fenceFd);
- virtual bool isValid() const;
- virtual ~C2AllocationIon();
- virtual const C2Handle *handle() const;
- virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const;
+ void **addr /* nonnull */) override;
+ virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd) override;
+ virtual bool isValid() const override;
+ virtual ~C2AllocationIon() override;
+ virtual const C2Handle *handle() const override;
+ virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const override;
// internal methods
C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
C2AllocationIon(int ionFd, size_t size, int shareFd);
int dup() const;
- C2Status status() const;
+ c2_status_t status() const;
protected:
class Impl;
@@ -142,7 +142,7 @@
(void)mCapacity; // TODO
}
- C2Status map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+ c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
(void)fenceFd; // TODO: wait for fence
*addr = nullptr;
int prot = PROT_NONE;
@@ -159,7 +159,7 @@
size_t mapOffset = offset - alignmentBytes;
size_t mapSize = size + alignmentBytes;
- C2Status err = C2_OK;
+ c2_status_t err = C2_OK;
if (mMapFd == -1) {
int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
@@ -186,7 +186,7 @@
return err;
}
- C2Status unmap(void *addr, size_t size, int *fenceFd) {
+ c2_status_t unmap(void *addr, size_t size, int *fenceFd) {
if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
size + mMapAlignmentBytes != mMapSize) {
return C2_BAD_VALUE;
@@ -210,7 +210,7 @@
(void)ion_free(mHandle.ionFd(), mHandle.buffer());
}
- C2Status status() const {
+ c2_status_t status() const {
return mInit;
}
@@ -227,7 +227,7 @@
}
private:
- C2Status mInit;
+ c2_status_t mInit;
C2HandleIon mHandle;
int mMapFd; // only one for now
void *mMapAddr;
@@ -236,12 +236,12 @@
size_t mCapacity;
};
-C2Status C2AllocationIon::map(
+c2_status_t C2AllocationIon::map(
size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
return mImpl->map(offset, size, usage, fenceFd, addr);
}
-C2Status C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+c2_status_t C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
return mImpl->unmap(addr, size, fenceFd);
}
@@ -249,7 +249,7 @@
return mImpl->status() == C2_OK;
}
-C2Status C2AllocationIon::status() const {
+c2_status_t C2AllocationIon::status() const {
return mImpl->status();
}
@@ -302,7 +302,7 @@
return "android.allocator.ion";
}
-C2Status C2AllocatorIon::newLinearAllocation(
+c2_status_t C2AllocatorIon::newLinearAllocation(
uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
if (allocation == nullptr) {
return C2_BAD_VALUE;
@@ -329,14 +329,14 @@
std::shared_ptr<C2AllocationIon> alloc
= std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
- C2Status ret = alloc->status();
+ c2_status_t ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
}
return ret;
}
-C2Status C2AllocatorIon::priorLinearAllocation(
+c2_status_t C2AllocatorIon::priorLinearAllocation(
const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
*allocation = nullptr;
if (mInit != C2_OK) {
@@ -351,7 +351,7 @@
const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
std::shared_ptr<C2AllocationIon> alloc
= std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
- C2Status ret = alloc->status();
+ c2_status_t ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
}
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index 02e2dd9..d9bde7a 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -129,26 +129,26 @@
explicit Impl(const uint8_t *data)
: mData(data), mError(C2_OK) {}
- explicit Impl(C2Status error)
+ explicit Impl(c2_status_t error)
: mData(nullptr), mError(error) {}
const uint8_t *data() const {
return mData;
}
- C2Status error() const {
+ c2_status_t error() const {
return mError;
}
private:
const uint8_t *mData;
- C2Status mError;
+ c2_status_t mError;
};
C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
: _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
-C2ReadView::C2ReadView(C2Status error)
+C2ReadView::C2ReadView(c2_status_t error)
: _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
const uint8_t *C2ReadView::data() const {
@@ -167,7 +167,7 @@
return C2ReadView(&newCapacity, data() + offset);
}
-C2Status C2ReadView::error() const {
+c2_status_t C2ReadView::error() const {
return mImpl->error();
}
@@ -176,33 +176,33 @@
explicit Impl(uint8_t *base)
: mBase(base), mError(C2_OK) {}
- explicit Impl(C2Status error)
+ explicit Impl(c2_status_t error)
: mBase(nullptr), mError(error) {}
uint8_t *base() const {
return mBase;
}
- C2Status error() const {
+ c2_status_t error() const {
return mError;
}
private:
uint8_t *mBase;
- C2Status mError;
+ c2_status_t mError;
};
C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
: _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
-C2WriteView::C2WriteView(C2Status error)
+C2WriteView::C2WriteView(c2_status_t error)
: _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
uint8_t *C2WriteView::base() { return mImpl->base(); }
uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
-C2Status C2WriteView::error() const { return mImpl->error(); }
+c2_status_t C2WriteView::error() const { return mImpl->error(); }
class C2ConstLinearBlock::Impl {
public:
@@ -212,7 +212,7 @@
~Impl() {
if (mBase != nullptr) {
// TODO: fence
- C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
+ c2_status_t err = mAllocation->unmap(mBase, mSize, nullptr);
if (err != C2_OK) {
// TODO: Log?
}
@@ -238,13 +238,13 @@
const uint8_t *base() const { return mBase; }
- C2Status error() const { return mError; }
+ c2_status_t error() const { return mError; }
private:
std::shared_ptr<C2LinearAllocation> mAllocation;
uint8_t *mBase;
size_t mSize;
- C2Status mError;
+ c2_status_t mError;
};
C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
@@ -277,7 +277,7 @@
~Impl() {
if (mBase != nullptr) {
// TODO: fence
- C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
+ c2_status_t err = mAllocation->unmap(mBase, mSize, nullptr);
if (err != C2_OK) {
// TODO: Log?
}
@@ -309,7 +309,7 @@
uint8_t *base() const { return mBase; }
- C2Status error() const { return mError; }
+ c2_status_t error() const { return mError; }
C2Fence fence() const { return mFence; }
@@ -317,7 +317,7 @@
std::shared_ptr<C2LinearAllocation> mAllocation;
uint8_t *mBase;
size_t mSize;
- C2Status mError;
+ c2_status_t mError;
C2Fence mFence;
};
@@ -349,14 +349,14 @@
const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
-C2Status C2BasicLinearBlockPool::fetchLinearBlock(
+c2_status_t C2BasicLinearBlockPool::fetchLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
block->reset();
std::shared_ptr<C2LinearAllocation> alloc;
- C2Status err = mAllocator->newLinearAllocation(capacity, usage, &alloc);
+ c2_status_t err = mAllocator->newLinearAllocation(capacity, usage, &alloc);
if (err != C2_OK) {
return err;
}
@@ -392,16 +392,16 @@
public:
Impl(uint8_t *const *data, const C2PlaneLayout &layout)
: mData(data), mLayout(layout), mError(C2_OK) {}
- explicit Impl(C2Status error) : mData(nullptr), mError(error) {}
+ explicit Impl(c2_status_t error) : mData(nullptr), mError(error) {}
uint8_t *const *data() const { return mData; }
const C2PlaneLayout &layout() const { return mLayout; }
- C2Status error() const { return mError; }
+ c2_status_t error() const { return mError; }
private:
uint8_t *const *mData;
C2PlaneLayout mLayout;
- C2Status mError;
+ c2_status_t mError;
};
C2GraphicView::C2GraphicView(
@@ -410,7 +410,7 @@
const C2PlaneLayout& layout)
: _C2PlanarSection(parent), mImpl(new Impl(data, layout)) {}
-C2GraphicView::C2GraphicView(C2Status error)
+C2GraphicView::C2GraphicView(c2_status_t error)
: _C2PlanarSection(nullptr), mImpl(new Impl(error)) {}
const uint8_t *const *C2GraphicView::data() const {
@@ -437,7 +437,7 @@
return view;
}
-C2Status C2GraphicView::error() const {
+c2_status_t C2GraphicView::error() const {
return mImpl->error();
}
@@ -453,12 +453,12 @@
}
}
- C2Status map(C2Rect rect) {
+ c2_status_t map(C2Rect rect) {
if (mData[0] != nullptr) {
// Already mapped.
return C2_OK;
}
- C2Status err = mAllocation->map(
+ c2_status_t err = mAllocation->map(
rect,
{ C2MemoryUsage::kSoftwareRead, 0 },
nullptr,
@@ -493,7 +493,7 @@
: C2Block2D(alloc), mImpl(new Impl(alloc)), mFence(fence) {}
C2Acquirable<const C2GraphicView> C2ConstGraphicBlock::map() const {
- C2Status err = mImpl->map(crop());
+ c2_status_t err = mImpl->map(crop());
if (err != C2_OK) {
C2DefaultGraphicView view(err);
return C2AcquirableConstGraphicView(err, mFence, view);
@@ -518,13 +518,13 @@
}
}
- C2Status map(C2Rect rect) {
+ c2_status_t map(C2Rect rect) {
if (mData[0] != nullptr) {
// Already mapped.
return C2_OK;
}
uint8_t *data[C2PlaneLayout::MAX_NUM_PLANES];
- C2Status err = mAllocation->map(
+ c2_status_t err = mAllocation->map(
rect,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
nullptr,
@@ -560,7 +560,7 @@
: C2Block2D(alloc), mImpl(new Impl(alloc)) {}
C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
- C2Status err = mImpl->map(crop());
+ c2_status_t err = mImpl->map(crop());
if (err != C2_OK) {
C2DefaultGraphicView view(err);
// TODO: fence
@@ -579,7 +579,7 @@
const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
-C2Status C2BasicGraphicBlockPool::fetchGraphicBlock(
+c2_status_t C2BasicGraphicBlockPool::fetchGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
@@ -588,7 +588,7 @@
block->reset();
std::shared_ptr<C2GraphicAllocation> alloc;
- C2Status err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
+ c2_status_t err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
if (err != C2_OK) {
return err;
}
@@ -650,7 +650,7 @@
const C2BufferData &data() const { return mData; }
- C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+ c2_status_t registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
auto it = std::find_if(
mNotify.begin(), mNotify.end(),
[onDestroyNotify, arg] (const auto &pair) {
@@ -663,7 +663,7 @@
return C2_OK;
}
- C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+ c2_status_t unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
auto it = std::find_if(
mNotify.begin(), mNotify.end(),
[onDestroyNotify, arg] (const auto &pair) {
@@ -684,7 +684,7 @@
return result;
}
- C2Status setInfo(const std::shared_ptr<C2Info> &info) {
+ c2_status_t setInfo(const std::shared_ptr<C2Info> &info) {
// To "update" you need to erase the existing one if any, and then insert.
(void) mInfos.erase(info->type());
(void) mInfos.insert({ info->type(), info });
@@ -720,11 +720,11 @@
const C2BufferData C2Buffer::data() const { return mImpl->data(); }
-C2Status C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+c2_status_t C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
}
-C2Status C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+c2_status_t C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
}
@@ -732,7 +732,7 @@
return mImpl->infos();
}
-C2Status C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
+c2_status_t C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
return mImpl->setInfo(info);
}
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index f8ddfef..73ffaea 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -37,40 +37,40 @@
/* ionmapper */
);
- virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator> *const allocator);
+ virtual c2_status_t fetchAllocator(id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
- virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const {
- return std::vector<std::shared_ptr<const C2Allocator::Info>>(); /// \todo
+ virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb() const override {
+ return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo
}
- virtual C2String getName() const {
+ virtual C2String getName() const override {
return "android.allocator-store";
}
private:
// returns a shared-singleton ion allocator
- std::shared_ptr<C2Allocator> getIonAllocator();
+ std::shared_ptr<C2Allocator> fetchIonAllocator();
// returns a shared-singleton gralloc allocator
- std::shared_ptr<C2Allocator> getGrallocAllocator();
+ std::shared_ptr<C2Allocator> fetchGrallocAllocator();
};
C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
}
-C2Status C2PlatformAllocatorStore::getAllocator(
+c2_status_t C2PlatformAllocatorStore::fetchAllocator(
id_t id, std::shared_ptr<C2Allocator> *const allocator) {
allocator->reset();
switch (id) {
// TODO: should we implement a generic registry for all, and use that?
case C2PlatformAllocatorStore::ION:
case C2AllocatorStore::DEFAULT_LINEAR:
- *allocator = getIonAllocator();
+ *allocator = fetchIonAllocator();
break;
case C2PlatformAllocatorStore::GRALLOC:
case C2AllocatorStore::DEFAULT_GRAPHIC:
- *allocator = getGrallocAllocator();
+ *allocator = fetchGrallocAllocator();
break;
default:
@@ -82,7 +82,7 @@
return C2_OK;
}
-std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::getIonAllocator() {
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::fetchIonAllocator() {
static std::mutex mutex;
static std::weak_ptr<C2Allocator> ionAllocator;
std::lock_guard<std::mutex> lock(mutex);
@@ -94,7 +94,7 @@
return allocator;
}
-std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::getGrallocAllocator() {
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::fetchGrallocAllocator() {
static std::mutex mutex;
static std::weak_ptr<C2Allocator> grallocAllocator;
std::lock_guard<std::mutex> lock(mutex);
@@ -110,7 +110,7 @@
return std::make_shared<C2PlatformAllocatorStore>();
}
-C2Status GetCodec2BlockPool(
+c2_status_t GetCodec2BlockPool(
C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
std::shared_ptr<C2BlockPool> *pool) {
pool->reset();
@@ -120,17 +120,17 @@
// TODO support pre-registered block pools
std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
std::shared_ptr<C2Allocator> allocator;
- C2Status res = C2_NOT_FOUND;
+ c2_status_t res = C2_NOT_FOUND;
switch (id) {
case C2BlockPool::BASIC_LINEAR:
- res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+ res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
if (res == OK) {
*pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
}
break;
case C2BlockPool::BASIC_GRAPHIC:
- res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
+ res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
if (res == OK) {
*pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
}
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 78d41c4..374b0ed 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -34,23 +34,23 @@
virtual C2String getName() const override;
- virtual std::shared_ptr<const Info> getInfo() const override {
+ virtual std::shared_ptr<const Traits> getTraits() const override {
return nullptr; // \todo
}
- virtual C2Status newGraphicAllocation(
+ virtual c2_status_t newGraphicAllocation(
uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
- virtual C2Status priorGraphicAllocation(
+ virtual c2_status_t priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
C2AllocatorGralloc();
- C2Status status() const;
+ c2_status_t status() const;
- virtual ~C2AllocatorGralloc();
+ virtual ~C2AllocatorGralloc() override;
private:
class Impl;
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index 2fff91f..bb815f9 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -33,26 +33,26 @@
virtual C2String getName() const override;
- virtual std::shared_ptr<const Info> getInfo() const override {
+ virtual std::shared_ptr<const Traits> getTraits() const override {
return nullptr; // \todo
}
- virtual C2Status newLinearAllocation(
+ virtual c2_status_t newLinearAllocation(
uint32_t capacity, C2MemoryUsage usage,
std::shared_ptr<C2LinearAllocation> *allocation) override;
- virtual C2Status priorLinearAllocation(
+ virtual c2_status_t priorLinearAllocation(
const C2Handle *handle,
std::shared_ptr<C2LinearAllocation> *allocation) override;
C2AllocatorIon();
- C2Status status() const { return mInit; }
+ virtual c2_status_t status() const { return mInit; }
- virtual ~C2AllocatorIon();
+ virtual ~C2AllocatorIon() override;
private:
- C2Status mInit;
+ c2_status_t mInit;
int mIonFd;
usage_mapper_fn mUsageMapper;
};
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index 56b0123..875a8c2 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -27,7 +27,7 @@
public:
explicit C2BasicLinearBlockPool(const std::shared_ptr<C2Allocator> &allocator);
- virtual ~C2BasicLinearBlockPool() = default;
+ virtual ~C2BasicLinearBlockPool() override = default;
virtual C2Allocator::id_t getAllocatorId() const override {
return mAllocator->getId();
@@ -37,7 +37,7 @@
return BASIC_LINEAR;
}
- virtual C2Status fetchLinearBlock(
+ virtual c2_status_t fetchLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
@@ -52,7 +52,7 @@
public:
explicit C2BasicGraphicBlockPool(const std::shared_ptr<C2Allocator> &allocator);
- virtual ~C2BasicGraphicBlockPool() = default;
+ virtual ~C2BasicGraphicBlockPool() override = default;
virtual C2Allocator::id_t getAllocatorId() const override {
return mAllocator->getId();
@@ -62,7 +62,7 @@
return BASIC_GRAPHIC;
}
- virtual C2Status fetchGraphicBlock(
+ virtual c2_status_t fetchGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
diff --git a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
index aea3a6f..41132b9 100644
--- a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
+++ b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
@@ -23,17 +23,17 @@
namespace android {
// standard ERRNO mappings
-template<int N> constexpr C2Status _c2_errno2status_impl();
-template<> constexpr C2Status _c2_errno2status_impl<0>() { return C2_OK; }
-template<> constexpr C2Status _c2_errno2status_impl<EINVAL>() { return C2_BAD_VALUE; }
-template<> constexpr C2Status _c2_errno2status_impl<EACCES>() { return C2_REFUSED; }
-template<> constexpr C2Status _c2_errno2status_impl<EPERM>() { return C2_REFUSED; }
-template<> constexpr C2Status _c2_errno2status_impl<ENOMEM>() { return C2_NO_MEMORY; }
+template<int N> constexpr c2_status_t _c2_errno2status_impl();
+template<> constexpr c2_status_t _c2_errno2status_impl<0>() { return C2_OK; }
+template<> constexpr c2_status_t _c2_errno2status_impl<EINVAL>() { return C2_BAD_VALUE; }
+template<> constexpr c2_status_t _c2_errno2status_impl<EACCES>() { return C2_REFUSED; }
+template<> constexpr c2_status_t _c2_errno2status_impl<EPERM>() { return C2_REFUSED; }
+template<> constexpr c2_status_t _c2_errno2status_impl<ENOMEM>() { return C2_NO_MEMORY; }
-// map standard errno-s to the equivalent C2Status
+// map standard errno-s to the equivalent c2_status_t
template<int... N> struct _c2_map_errno_impl;
template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
- static C2Status map(int result) {
+ static c2_status_t map(int result) {
if (result == E) {
return _c2_errno2status_impl <E>();
} else {
@@ -42,13 +42,13 @@
}
};
template<> struct _c2_map_errno_impl<> {
- static C2Status map(int result) {
+ static c2_status_t map(int result) {
return result == 0 ? C2_OK : C2_CORRUPTED;
}
};
template<int... N>
-C2Status c2_map_errno(int result) {
+c2_status_t c2_map_errno(int result) {
return _c2_map_errno_impl<N...>::map(result);
}
diff --git a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
index 40bb548..8e45705 100644
--- a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
@@ -48,10 +48,63 @@
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected,
* this return value is only possible for basic pools)
*/
-C2Status GetCodec2BlockPool(
+c2_status_t GetCodec2BlockPool(
C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
std::shared_ptr<C2BlockPool> *pool);
+/**
+ * Component factory object that enables to create a component and/or interface from a dynamically
+ * linked library. This is needed because the component/interfaces are managed objects, but we
+ * cannot safely create a managed object and pass it in C.
+ *
+ * Components/interfaces typically inherit from std::enable_shared_from_this, but C requires
+ * passing simple pointer, and shared_ptr constructor needs to know the class to be constructed
+ * derives from enable_shared_from_this.
+ *
+ */
+class C2ComponentFactory {
+public:
+ /**
+ * Creates a component.
+ *
+ * This method SHALL return within 100ms.
+ *
+ * \param component shared pointer where the created component is stored. Cleared on
+ * failure and updated on success.
+ * \param id component ID for the created component
+ *
+ * \retval C2_OK the component was created successfully
+ * \retval C2_TIMED_OUT could not create the component within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the component (unexpected)
+ *
+ * \retval C2_NO_MEMORY not enough memory to create the component
+ */
+ virtual c2_status_t createComponent(
+ std::shared_ptr<C2Component>* const component, c2_node_id_t id) = 0;
+
+ /**
+ * Creates a component interface.
+ *
+ * This method SHALL return within 100ms.
+ *
+ * \param interface shared pointer where the created interface is stored. Cleared on
+ * failure and updated on success.
+ * \param id component interface ID for the created interface
+ *
+ * \retval C2_OK the component interface was created successfully
+ * \retval C2_TIMED_OUT could not create the component interface within the time limit
+ * (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the component interface
+ * (unexpected)
+ *
+ * \retval C2_NO_MEMORY not enough memory to create the component interface
+ */
+ virtual c2_status_t createInterface(
+ std::shared_ptr<C2ComponentInterface>* const interface, c2_node_id_t id) = 0;
+
+ virtual ~C2ComponentFactory() = default;
+};
+
} // namespace android
#endif // STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
diff --git a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
index 5f09889..5ce6071 100644
--- a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
+++ b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
@@ -222,7 +222,7 @@
friend class C2ParamTest_ParamUtilsTest_Test;
public:
- static std::vector<C2String> getEnumValuesFromString(C2StringLiteral value) {
+ static std::vector<C2String> parseEnumValuesFromString(C2StringLiteral value) {
std::vector<C2String> foundNames;
size_t pos = 0, len = strlen(value);
do {
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 12eaff5..c74ca6d 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -246,7 +246,7 @@
// { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel52 },
// { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel52 },
// };
-C2SoftAvcDecIntf::C2SoftAvcDecIntf(const char *name, node_id id)
+C2SoftAvcDecIntf::C2SoftAvcDecIntf(const char *name, c2_node_id_t id)
: mName(name),
mId(id),
mDomainInfo(C2DomainVideo),
@@ -434,11 +434,11 @@
return mName;
}
-node_id C2SoftAvcDecIntf::getId() const {
+c2_node_id_t C2SoftAvcDecIntf::getId() const {
return mId;
}
-C2Status C2SoftAvcDecIntf::query_nb(
+c2_status_t C2SoftAvcDecIntf::query_nb(
const std::vector<C2Param* const> & stackParams,
const std::vector<C2Param::Index> & heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -473,10 +473,10 @@
return C2_OK;
}
-C2Status C2SoftAvcDecIntf::config_nb(
+c2_status_t C2SoftAvcDecIntf::config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
- C2Status err = C2_OK;
+ c2_status_t err = C2_OK;
for (C2Param *param : params) {
uint32_t index = restoreIndex(param);
if (param->index() == mOutputBlockPools.get()->index()) {
@@ -504,20 +504,20 @@
return err;
}
-C2Status C2SoftAvcDecIntf::commit_sm(
+c2_status_t C2SoftAvcDecIntf::commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
// TODO
return config_nb(params, failures);
}
-C2Status C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
+c2_status_t C2SoftAvcDecIntf::createTunnel_sm(c2_node_id_t targetComponent) {
// Tunneling is not supported
(void) targetComponent;
return C2_OMITTED;
}
-C2Status C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
+c2_status_t C2SoftAvcDecIntf::releaseTunnel_sm(c2_node_id_t targetComponent) {
// Tunneling is not supported
(void) targetComponent;
return C2_OMITTED;
@@ -527,15 +527,15 @@
return mParamReflector;
}
-C2Status C2SoftAvcDecIntf::getSupportedParams(
+c2_status_t C2SoftAvcDecIntf::querySupportedParams_nb(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
params->insert(params->begin(), mParamDescs.begin(), mParamDescs.end());
return C2_OK;
}
-C2Status C2SoftAvcDecIntf::getSupportedValues(
+c2_status_t C2SoftAvcDecIntf::querySupportedValues_nb(
std::vector<C2FieldSupportedValuesQuery> &fields) const {
- C2Status res = C2_OK;
+ c2_status_t res = C2_OK;
for (C2FieldSupportedValuesQuery &query : fields) {
if (mSupportedValues.count(query.field) == 0) {
query.status = C2_BAD_INDEX;
@@ -642,10 +642,8 @@
C2SoftAvcDec::C2SoftAvcDec(
const char *name,
- node_id id,
- const std::shared_ptr<C2ComponentListener> &listener)
+ c2_node_id_t id)
: mIntf(std::make_shared<C2SoftAvcDecIntf>(name, id)),
- mListener(listener),
mThread(new QueueProcessThread),
mCodecCtx(NULL),
mFlushOutBuffer(NULL),
@@ -666,7 +664,22 @@
CHECK_EQ(deInitDecoder(), (status_t)OK);
}
-C2Status C2SoftAvcDec::queue_nb(
+c2_status_t C2SoftAvcDec::setListener_sm(
+ const std::shared_ptr<C2Component::Listener> &listener) {
+ std::unique_lock<std::mutex> lock(mListenerLock);
+ // TODO: we really need to lock the running check as well
+ if (listener && mThread->isRunning()) {
+ return C2_BAD_STATE;
+ }
+ mListener = listener;
+ if (mActiveListener && !listener) {
+ // wait until no active listeners are in use
+ mActiveListenerChanged.wait(lock, [this]{ return !mActiveListener; });
+ }
+ return C2_OK;
+}
+
+c2_status_t C2SoftAvcDec::queue_nb(
std::list<std::unique_ptr<C2Work>>* const items) {
if (!mThread->isRunning()) {
return C2_CORRUPTED;
@@ -681,16 +694,16 @@
return C2_OK;
}
-C2Status C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
+c2_status_t C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
// Tunneling is not supported
(void) items;
return C2_OMITTED;
}
-C2Status C2SoftAvcDec::flush_sm(
- bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
+c2_status_t C2SoftAvcDec::flush_sm(
+ flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
// Tunneling is not supported
- (void) flushThrough;
+ (void) mode;
if (!mThread->isRunning()) {
return C2_CORRUPTED;
@@ -713,9 +726,9 @@
return C2_OK;
}
-C2Status C2SoftAvcDec::drain_nb(bool drainThrough) {
+c2_status_t C2SoftAvcDec::drain_nb(drain_mode_t mode) {
// Tunneling is not supported
- (void) drainThrough;
+ (void) mode;
if (!mThread->isRunning()) {
return C2_CORRUPTED;
@@ -723,20 +736,20 @@
std::unique_lock<std::mutex> lock(mQueueLock);
if (!mQueue.empty()) {
C2BufferPack &lastInput = mQueue.back()->input;
- lastInput.flags = (flags_t)(lastInput.flags | BUFFERFLAG_END_OF_STREAM);
+ lastInput.flags = (C2BufferPack::flags_t)(lastInput.flags | C2BufferPack::FLAG_END_OF_STREAM);
mQueueCond.notify_all();
}
return C2_OK;
}
-C2Status C2SoftAvcDec::start() {
+c2_status_t C2SoftAvcDec::start() {
if (!mThread->isRunning()) {
mThread->start(shared_from_this());
}
return C2_OK;
}
-C2Status C2SoftAvcDec::stop() {
+c2_status_t C2SoftAvcDec::stop() {
ALOGV("stop");
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::system_clock::time_point deadline = now + std::chrono::milliseconds(500);
@@ -843,7 +856,16 @@
}
if (!done.empty()) {
- mListener->onWorkDone(shared_from_this(), std::move(done));
+ std::unique_lock<std::mutex> lock(mListenerLock);
+ mActiveListener = mListener;
+
+ if (mActiveListener) {
+ lock.unlock();
+ mActiveListener->onWorkDone_nb(shared_from_this(), std::move(done));
+ lock.lock();
+ mActiveListener.reset();
+ mActiveListenerChanged.notify_all();
+ }
}
}
@@ -1206,14 +1228,14 @@
std::vector<std::unique_ptr<C2Work>> done;
done.emplace_back(std::move(work));
- mListener->onWorkDone(shared_from_this(), std::move(done));
- if (!(work->input.flags & BUFFERFLAG_END_OF_STREAM)) {
+ mListener->onWorkDone_nb(shared_from_this(), std::move(done));
+ if (!(work->input.flags & C2BufferPack::FLAG_END_OF_STREAM)) {
return;
}
mReceivedEOS = true;
// TODO: flush
- } else if (work->input.flags & BUFFERFLAG_END_OF_STREAM) {
+ } else if (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) {
mReceivedEOS = true;
}
@@ -1231,7 +1253,7 @@
mIntf->mOutputBlockPools->flexCount() ?
mIntf->mOutputBlockPools->m.mValues[0] : C2BlockPool::BASIC_GRAPHIC;
if (!mOutputBlockPool || mOutputBlockPool->getLocalId() != poolId) {
- C2Status err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
+ c2_status_t err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
if (err != C2_OK) {
// TODO: trip
}
@@ -1359,7 +1381,7 @@
done[0]->worklets.front()->output.buffers.emplace_back(
std::make_shared<GraphicBuffer>(std::move(mAllocatedBlock)));
done[0]->worklets.front()->output.ordinal = done[0]->input.ordinal;
- mListener->onWorkDone(shared_from_this(), std::move(done));
+ mListener->onWorkDone_nb(shared_from_this(), std::move(done));
} else if (mIsInFlush) {
ALOGV("flush");
/* If in flush mode and no output is returned by the codec,
@@ -1440,4 +1462,29 @@
return C2_OK;
}
+class C2SoftAvcDecFactory : public C2ComponentFactory {
+public:
+ virtual c2_status_t createComponent(
+ std::shared_ptr<C2Component>* const component, c2_node_id_t id) override {
+ *component = std::make_shared<C2SoftAvcDec>("avc", id);
+ return C2_OK;
+ }
+
+ virtual c2_status_t createInterface(
+ std::shared_ptr<C2ComponentInterface>* const interface, c2_node_id_t id) override {
+ *interface = std::make_shared<C2SoftAvcDecIntf>("avc", id);
+ return C2_OK;
+ }
+
+ virtual ~C2SoftAvcDecFactory() override = default;
+};
+
} // namespace android
+
+extern "C" ::android::C2ComponentFactory* CreateCodec2Factory() {
+ return new ::android::C2SoftAvcDecFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::android::C2ComponentFactory* factory) {
+ delete factory;
+}
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index 41ccf39..5deaf5d 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -79,35 +79,36 @@
SupportedValuesWithFields(const C2FieldSupportedValues &supported) : supported(supported) {}
};
- C2SoftAvcDecIntf(const char *name, node_id id);
+ C2SoftAvcDecIntf(const char *name, c2_node_id_t id);
virtual ~C2SoftAvcDecIntf() = default;
// From C2ComponentInterface
virtual C2String getName() const override;
- virtual node_id getId() const override;
- virtual C2Status query_nb(
+ virtual c2_node_id_t getId() const override;
+ virtual c2_status_t query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
- virtual C2Status config_nb(
+ virtual c2_status_t config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
- virtual C2Status commit_sm(
+ virtual c2_status_t commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
- virtual C2Status createTunnel_sm(node_id targetComponent) override;
- virtual C2Status releaseTunnel_sm(node_id targetComponent) override;
- virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
- virtual C2Status getSupportedParams(
+ virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) override;
+ virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) override;
+ // TODO: move this into some common store class
+ std::shared_ptr<C2ParamReflector> getParamReflector() const;
+ virtual c2_status_t querySupportedParams_nb(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override;
- virtual C2Status getSupportedValues(
+ virtual c2_status_t querySupportedValues_nb(
std::vector<C2FieldSupportedValuesQuery> &fields) const override;
private:
class ParamReflector;
const C2String mName;
- const node_id mId;
+ const c2_node_id_t mId;
C2ComponentDomainInfo mDomainInfo;
// TODO: config desc
@@ -146,18 +147,18 @@
: public C2Component,
public std::enable_shared_from_this<C2SoftAvcDec> {
public:
- C2SoftAvcDec(
- const char *name, node_id id, const std::shared_ptr<C2ComponentListener> &listener);
+ C2SoftAvcDec(const char *name, c2_node_id_t id);
virtual ~C2SoftAvcDec();
// From C2Component
- virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
- virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) override;
- virtual C2Status flush_sm(
- bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
- virtual C2Status drain_nb(bool drainThrough) override;
- virtual C2Status start() override;
- virtual C2Status stop() override;
+ virtual c2_status_t setListener_sm(const std::shared_ptr<Listener> &listener) override;
+ virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
+ virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) override;
+ virtual c2_status_t flush_sm(
+ flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
+ virtual c2_status_t drain_nb(drain_mode_t mode) override;
+ virtual c2_status_t start() override;
+ virtual c2_status_t stop() override;
virtual void reset() override;
virtual void release() override;
virtual std::shared_ptr<C2ComponentInterface> intf() override;
@@ -192,7 +193,11 @@
using IndexType = decltype(C2WorkOrdinalStruct().frame_index);
const std::shared_ptr<C2SoftAvcDecIntf> mIntf;
- const std::shared_ptr<C2ComponentListener> mListener;
+ std::shared_ptr<Listener> mListener;
+ std::shared_ptr<Listener> mActiveListener;
+ std::mutex mListenerLock;
+ std::condition_variable mActiveListenerChanged;
+
std::shared_ptr<C2BlockPool> mOutputBlockPool;
std::mutex mQueueLock;
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index c7e1c82..8e2c4b9 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -58,6 +58,9 @@
#include <C2PlatformSupport.h>
#include <C2Work.h>
+extern "C" ::android::C2ComponentFactory *CreateCodec2Factory();
+extern "C" void DestroyCodec2Factory(::android::C2ComponentFactory *);
+
#include "../avcdec/C2SoftAvcDec.h"
using namespace android;
@@ -110,22 +113,22 @@
sp<SurfaceControl> mControl;
};
-class Listener : public C2ComponentListener {
+class Listener : public C2Component::Listener {
public:
explicit Listener(SimplePlayer *thiz) : mThis(thiz) {}
virtual ~Listener() = default;
- virtual void onWorkDone(std::weak_ptr<C2Component> component,
+ virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
std::vector<std::unique_ptr<C2Work>> workItems) override {
mThis->onWorkDone(component, std::move(workItems));
}
- virtual void onTripped(std::weak_ptr<C2Component> component,
+ virtual void onTripped_nb(std::weak_ptr<C2Component> component,
std::vector<std::shared_ptr<C2SettingResult>> settingResult) override {
mThis->onTripped(component, settingResult);
}
- virtual void onError(std::weak_ptr<C2Component> component,
+ virtual void onError_nb(std::weak_ptr<C2Component> component,
uint32_t errorCode) override {
mThis->onError(component, errorCode);
}
@@ -142,7 +145,7 @@
CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
- CHECK_EQ(store->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
+ CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
mLinearPool = std::make_shared<C2BasicLinearBlockPool>(mAllocIon);
mControl = mComposerClient->createSurface(
@@ -208,7 +211,12 @@
return;
}
- std::shared_ptr<C2Component> component(std::make_shared<C2SoftAvcDec>("avc", 0, mListener));
+ std::unique_ptr<C2ComponentFactory> factory(CreateCodec2Factory());
+ std::shared_ptr<C2Component> component;
+ (void)factory->createComponent(&component, 0);
+ DestroyCodec2Factory(factory.release());
+
+ (void)component->setListener_sm(mListener);
std::unique_ptr<C2PortBlockPoolsTuning::output> pools =
C2PortBlockPoolsTuning::output::alloc_unique({ (uint64_t)C2BlockPool::BASIC_GRAPHIC });
std::vector<std::unique_ptr<C2SettingResult>> result;
@@ -322,7 +330,7 @@
mQueueCondition.wait_for(l, 100ms);
}
}
- work->input.flags = (flags_t)0;
+ work->input.flags = (C2BufferPack::flags_t)0;
work->input.ordinal.timestamp = timestamp;
work->input.ordinal.frame_index = numFrames;
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index 4984f69..9414aab 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -40,7 +40,8 @@
uint32_t channels,
uint32_t outSampleRate = 0,
uid_t uid = -1,
- pid_t pid = -1);
+ pid_t pid = -1,
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
status_t initCheck() const;
@@ -58,6 +59,11 @@
status_t dataCallback(const AudioRecord::Buffer& buffer);
virtual void signalBufferReturned(MediaBuffer *buffer);
+ status_t setInputDevice(audio_port_handle_t deviceId);
+ status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
+ status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
+ status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
+
protected:
virtual ~AudioSource();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 7e9ef26..506420c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -526,6 +526,13 @@
};
// --- PlaybackThread ---
+#ifdef FLOAT_EFFECT_CHAIN
+#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
+using effect_buffer_t = float;
+#else
+#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_16_BIT
+using effect_buffer_t = int16_t;
+#endif
#include "Threads.h"
diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h
index 845697a..bad46dc 100644
--- a/services/audioflinger/Configuration.h
+++ b/services/audioflinger/Configuration.h
@@ -41,4 +41,7 @@
// uncomment to log CPU statistics every n wall clock seconds
//#define DEBUG_CPU_USAGE 10
+// define FLOAT_EFFECT_CHAIN to request float effects (falls back to int16_t if unavailable)
+#define FLOAT_EFFECT_CHAIN
+
#endif // ANDROID_AUDIOFLINGER_CONFIGURATION_H
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index bd5f146..e0d0d7b 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -19,6 +19,8 @@
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
+#include <algorithm>
+
#include "Configuration.h"
#include <utils/Log.h>
#include <system/audio_effects/effect_aec.h>
@@ -47,8 +49,6 @@
#define ALOGVV(a...) do { } while(0)
#endif
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
namespace android {
// ----------------------------------------------------------------------------
@@ -73,6 +73,9 @@
// mDisableWaitCnt is set by process() and updateState() and not used before then
mSuspended(false),
mAudioFlinger(thread->mAudioFlinger)
+#ifdef FLOAT_EFFECT_CHAIN
+ , mSupportsFloat(false)
+#endif
{
ALOGV("Constructor %p pinned %d", this, pinned);
int lStatus;
@@ -285,31 +288,114 @@
return;
}
+ // TODO: Implement multichannel effects; here outChannelCount == FCC_2 == 2
+ const uint32_t inChannelCount =
+ audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
+ const uint32_t outChannelCount =
+ audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
+ const bool auxType =
+ (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY;
+
if (isProcessEnabled()) {
- // do 32 bit to 16 bit conversion for auxiliary effect input buffer
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- ditherAndClamp(mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.frameCount/2);
- }
int ret;
if (isProcessImplemented()) {
- // do the actual processing in the effect engine
+ if (auxType) {
+ // We overwrite the aux input buffer here and clear after processing.
+ // Note that aux input buffers are format q4_27.
+#ifdef FLOAT_EFFECT_CHAIN
+ if (mSupportsFloat) {
+ // Do in-place float conversion for auxiliary effect input buffer.
+ static_assert(sizeof(float) <= sizeof(int32_t),
+ "in-place conversion requires sizeof(float) <= sizeof(int32_t)");
+
+ const int32_t * const p32 = mConfig.inputCfg.buffer.s32;
+ float * const pFloat = mConfig.inputCfg.buffer.f32;
+ memcpy_to_float_from_q4_27(pFloat, p32, mConfig.inputCfg.buffer.frameCount);
+ } else {
+ memcpy_to_i16_from_q4_27(mConfig.inputCfg.buffer.s16,
+ mConfig.inputCfg.buffer.s32,
+ mConfig.inputCfg.buffer.frameCount);
+ }
+#else
+ memcpy_to_i16_from_q4_27(mConfig.inputCfg.buffer.s16,
+ mConfig.inputCfg.buffer.s32,
+ mConfig.inputCfg.buffer.frameCount);
+#endif
+ }
+#ifdef FLOAT_EFFECT_CHAIN
+ if (mSupportsFloat) {
+ ret = mEffectInterface->process();
+ } else {
+ { // convert input to int16_t as effect doesn't support float.
+ if (!auxType) {
+ if (mInBuffer16.get() == nullptr) {
+ ALOGW("%s: mInBuffer16 is null, bypassing", __func__);
+ goto data_bypass;
+ }
+ const float * const pIn = mInBuffer->audioBuffer()->f32;
+ int16_t * const pIn16 = mInBuffer16->audioBuffer()->s16;
+ memcpy_to_i16_from_float(
+ pIn16, pIn, inChannelCount * mConfig.inputCfg.buffer.frameCount);
+ }
+ if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ if (mOutBuffer16.get() == nullptr) {
+ ALOGW("%s: mOutBuffer16 is null, bypassing", __func__);
+ goto data_bypass;
+ }
+ int16_t * const pOut16 = mOutBuffer16->audioBuffer()->s16;
+ const float * const pOut = mOutBuffer->audioBuffer()->f32;
+ memcpy_to_i16_from_float(
+ pOut16,
+ pOut,
+ outChannelCount * mConfig.outputCfg.buffer.frameCount);
+ }
+ }
+
+ ret = mEffectInterface->process();
+
+ { // convert output back to float.
+ const int16_t * const pOut16 = mOutBuffer16->audioBuffer()->s16;
+ float * const pOut = mOutBuffer->audioBuffer()->f32;
+ memcpy_to_float_from_i16(
+ pOut, pOut16, outChannelCount * mConfig.outputCfg.buffer.frameCount);
+ }
+ }
+#else
ret = mEffectInterface->process();
+#endif
} else {
- if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
- size_t frameCnt = mConfig.inputCfg.buffer.frameCount * FCC_2; //always stereo here
- int16_t *in = mConfig.inputCfg.buffer.s16;
- int16_t *out = mConfig.outputCfg.buffer.s16;
+#ifdef FLOAT_EFFECT_CHAIN
+ data_bypass:
+#endif
+ if (!auxType /* aux effects do not require data bypass */
+ && mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw
+ && inChannelCount == outChannelCount) {
+ const size_t sampleCount = std::min(
+ mConfig.inputCfg.buffer.frameCount,
+ mConfig.outputCfg.buffer.frameCount) * outChannelCount;
+
+#ifdef FLOAT_EFFECT_CHAIN
+ const float * const in = mConfig.inputCfg.buffer.f32;
+ float * const out = mConfig.outputCfg.buffer.f32;
if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
- for (size_t i = 0; i < frameCnt; i++) {
- out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
- }
+ accumulate_float(out, in, sampleCount);
} else {
- memcpy(mConfig.outputCfg.buffer.raw, mConfig.inputCfg.buffer.raw,
- frameCnt * sizeof(int16_t));
+ memcpy(mConfig.outputCfg.buffer.f32, mConfig.inputCfg.buffer.f32,
+ sampleCount * sizeof(*mConfig.outputCfg.buffer.f32));
}
+
+#else
+ const int16_t * const in = mConfig.inputCfg.buffer.s16;
+ int16_t * const out = mConfig.outputCfg.buffer.s16;
+
+ if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ accumulate_i16(out, in, sampleCount);
+ } else {
+ memcpy(mConfig.outputCfg.buffer.s16, mConfig.inputCfg.buffer.s16,
+ sampleCount * sizeof(*mConfig.outputCfg.buffer.s16));
+ }
+#endif
}
ret = -ENODATA;
}
@@ -319,22 +405,33 @@
}
// clear auxiliary effect input buffer for next accumulation
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- memset(mConfig.inputCfg.buffer.raw, 0,
- mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
+ if (auxType) {
+ // input always q4_27 regardless of FLOAT_EFFECT_CHAIN.
+ const size_t size =
+ mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t);
+ memset(mConfig.inputCfg.buffer.raw, 0, size);
}
} else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
+ // mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw
mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
// If an insert effect is idle and input buffer is different from output buffer,
// accumulate input onto output
sp<EffectChain> chain = mChain.promote();
- if (chain != 0 && chain->activeTrackCnt() != 0) {
- size_t frameCnt = mConfig.inputCfg.buffer.frameCount * FCC_2; //always stereo here
- int16_t *in = mConfig.inputCfg.buffer.s16;
- int16_t *out = mConfig.outputCfg.buffer.s16;
- for (size_t i = 0; i < frameCnt; i++) {
- out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
- }
+ if (chain != 0
+ && chain->activeTrackCnt() != 0
+ && inChannelCount == outChannelCount) {
+ const size_t sampleCount = std::min(
+ mConfig.inputCfg.buffer.frameCount,
+ mConfig.outputCfg.buffer.frameCount) * outChannelCount;
+#ifdef FLOAT_EFFECT_CHAIN
+ const float * const in = mConfig.inputCfg.buffer.f32;
+ float * const out = mConfig.outputCfg.buffer.f32;
+ accumulate_float(out, in, sampleCount);
+#else
+ const int16_t * const in = mConfig.inputCfg.buffer.s16;
+ int16_t * const out = mConfig.outputCfg.buffer.s16;
+ accumulate_i16(out, in, sampleCount);
+#endif
}
}
}
@@ -349,6 +446,7 @@
status_t AudioFlinger::EffectModule::configure()
{
+ ALOGVV("configure() started");
status_t status;
sp<ThreadBase> thread;
uint32_t size;
@@ -384,8 +482,8 @@
}
}
- mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
- mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
+ mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
mConfig.inputCfg.samplingRate = thread->sampleRate();
mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
mConfig.inputCfg.bufferProvider.cookie = NULL;
@@ -413,12 +511,6 @@
mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
mConfig.inputCfg.buffer.frameCount = thread->frameCount();
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
- if (mInBuffer != 0) {
- mInBuffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
- }
- if (mOutBuffer != 0) {
- mOutBuffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
- }
ALOGV("configure() %p thread %p buffer %p framecount %zu",
this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
@@ -430,32 +522,60 @@
&mConfig,
&size,
&cmdStatus);
- if (status == 0) {
+ if (status == NO_ERROR) {
status = cmdStatus;
+#ifdef FLOAT_EFFECT_CHAIN
+ mSupportsFloat = true;
+#endif
}
-
- if (status == 0 &&
- (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0)) {
- uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
- effect_param_t *p = (effect_param_t *)buf32;
-
- p->psize = sizeof(uint32_t);
- p->vsize = sizeof(uint32_t);
- size = sizeof(int);
- *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
-
- uint32_t latency = 0;
- PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId);
- if (pbt != NULL) {
- latency = pbt->latency_l();
+#ifdef FLOAT_EFFECT_CHAIN
+ else {
+ ALOGV("EFFECT_CMD_SET_CONFIG failed with float format, retry with int16_t.");
+ mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t),
+ &mConfig,
+ &size,
+ &cmdStatus);
+ if (status == NO_ERROR) {
+ status = cmdStatus;
+ mSupportsFloat = false;
+ ALOGVV("config worked with 16 bit");
+ } else {
+ ALOGE("%s failed %d with int16_t (as well as float)", __func__, status);
}
+ }
+#endif
- *((int32_t *)p->data + 1)= latency;
- mEffectInterface->command(EFFECT_CMD_SET_PARAM,
- sizeof(effect_param_t) + 8,
- &buf32,
- &size,
- &cmdStatus);
+ if (status == NO_ERROR) {
+ // Establish Buffer strategy
+ setInBuffer(mInBuffer);
+ setOutBuffer(mOutBuffer);
+
+ // Update visualizer latency
+ if (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) {
+ uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+ effect_param_t *p = (effect_param_t *)buf32;
+
+ p->psize = sizeof(uint32_t);
+ p->vsize = sizeof(uint32_t);
+ size = sizeof(int);
+ *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
+
+ uint32_t latency = 0;
+ PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId);
+ if (pbt != NULL) {
+ latency = pbt->latency_l();
+ }
+
+ *((int32_t *)p->data + 1)= latency;
+ mEffectInterface->command(EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + 8,
+ &buf32,
+ &size,
+ &cmdStatus);
+ }
}
mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
@@ -463,6 +583,7 @@
exit:
mStatus = status;
+ ALOGVV("configure ended");
return status;
}
@@ -774,6 +895,7 @@
}
void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ ALOGVV("setInBuffer %p",(&buffer));
if (buffer != 0) {
mConfig.inputCfg.buffer.raw = buffer->audioBuffer()->raw;
buffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
@@ -782,9 +904,40 @@
}
mInBuffer = buffer;
mEffectInterface->setInBuffer(buffer);
+
+#ifdef FLOAT_EFFECT_CHAIN
+ // aux effects do in place conversion to float - we don't allocate mInBuffer16 for them.
+ // Theoretically insert effects can also do in-place conversions (destroying
+ // the original buffer) when the output buffer is identical to the input buffer,
+ // but we don't optimize for it here.
+ const bool auxType = (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY;
+ if (!auxType && !mSupportsFloat && mInBuffer.get() != nullptr) {
+ // we need to translate - create hidl shared buffer and intercept
+ const size_t inFrameCount = mConfig.inputCfg.buffer.frameCount;
+ const int inChannels = audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
+ const size_t size = inChannels * inFrameCount * sizeof(int16_t);
+
+ ALOGV("%s: setInBuffer updating for inChannels:%d inFrameCount:%zu total size:%zu",
+ __func__, inChannels, inFrameCount, size);
+
+ if (size > 0 && (mInBuffer16.get() == nullptr || size > mInBuffer16->getSize())) {
+ mInBuffer16.clear();
+ ALOGV("%s: allocating mInBuffer16 %zu", __func__, size);
+ (void)EffectBufferHalInterface::allocate(size, &mInBuffer16);
+ }
+ if (mInBuffer16.get() != nullptr) {
+ // FIXME: confirm buffer has enough size.
+ mInBuffer16->setFrameCount(inFrameCount);
+ mEffectInterface->setInBuffer(mInBuffer16);
+ } else if (size > 0) {
+ ALOGE("%s cannot create mInBuffer16", __func__);
+ }
+ }
+#endif
}
void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ ALOGVV("setOutBuffer %p",(&buffer));
if (buffer != 0) {
mConfig.outputCfg.buffer.raw = buffer->audioBuffer()->raw;
buffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
@@ -793,6 +946,31 @@
}
mOutBuffer = buffer;
mEffectInterface->setOutBuffer(buffer);
+
+#ifdef FLOAT_EFFECT_CHAIN
+ // Note: Any effect that does not accumulate does not need mOutBuffer16 and
+ // can do in-place conversion from int16_t to float. We don't optimize here.
+ if (!mSupportsFloat && mOutBuffer.get() != nullptr) {
+ const size_t outFrameCount = mConfig.outputCfg.buffer.frameCount;
+ const int outChannels = audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
+ const size_t size = outChannels * outFrameCount * sizeof(int16_t);
+
+ ALOGV("%s: setOutBuffer updating for outChannels:%d outFrameCount:%zu total size:%zu",
+ __func__, outChannels, outFrameCount, size);
+
+ if (size > 0 && (mOutBuffer16.get() == nullptr || size > mOutBuffer16->getSize())) {
+ mOutBuffer16.clear();
+ ALOGV("%s: allocating mOutBuffer16 %zu", __func__, size);
+ (void)EffectBufferHalInterface::allocate(size, &mOutBuffer16);
+ }
+ if (mOutBuffer16.get() != nullptr) {
+ mOutBuffer16->setFrameCount(outFrameCount);
+ mEffectInterface->setOutBuffer(mOutBuffer16);
+ } else if (size > 0) {
+ ALOGE("%s cannot create mOutBuffer16", __func__);
+ }
+ }
+#endif
}
status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
@@ -1126,6 +1304,22 @@
formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
result.append(buffer);
+#ifdef FLOAT_EFFECT_CHAIN
+ if (!mSupportsFloat) {
+ int16_t* pIn16 = mInBuffer16 != 0 ? mInBuffer16->audioBuffer()->s16 : NULL;
+ int16_t* pOut16 = mOutBuffer16 != 0 ? mOutBuffer16->audioBuffer()->s16 : NULL;
+
+ result.append("\t\t- Float and int16 buffers\n");
+ result.append("\t\t\tIn_float In_int16 Out_float Out_int16\n");
+ snprintf(buffer, SIZE,"\t\t\t%p %p %p %p\n",
+ mConfig.inputCfg.buffer.raw,
+ pIn16,
+ pOut16,
+ mConfig.outputCfg.buffer.raw);
+ result.append(buffer);
+ }
+#endif
+
snprintf(buffer, SIZE, "\t\t%zu Clients:\n", mHandles.size());
result.append(buffer);
result.append("\t\t\t Pid Priority Ctrl Locked client server\n");
@@ -1602,8 +1796,11 @@
// and sample format changes for effects.
// Currently effects processing is only available for stereo, AUDIO_FORMAT_PCM_16_BIT
// (4 bytes frame size)
+
const size_t frameSize =
- audio_bytes_per_sample(AUDIO_FORMAT_PCM_16_BIT) * min(FCC_2, thread->channelCount());
+ audio_bytes_per_sample(EFFECT_BUFFER_FORMAT)
+ * std::min((uint32_t)FCC_2, thread->channelCount());
+
memset(mInBuffer->audioBuffer()->raw, 0, thread->frameCount() * frameSize);
mInBuffer->commit();
}
@@ -1718,8 +1915,13 @@
// calling the process in effect engine
size_t numSamples = thread->frameCount();
sp<EffectBufferHalInterface> halBuffer;
+#ifdef FLOAT_EFFECT_CHAIN
+ status_t result = EffectBufferHalInterface::allocate(
+ numSamples * sizeof(float), &halBuffer);
+#else
status_t result = EffectBufferHalInterface::allocate(
numSamples * sizeof(int32_t), &halBuffer);
+#endif
if (result != OK) return result;
effect->setInBuffer(halBuffer);
// auxiliary effects output samples to chain input buffer for further processing
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index e29798b..1864e0f 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -168,6 +168,12 @@
bool mSuspended; // effect is suspended: temporarily disabled by framework
bool mOffloaded; // effect is currently offloaded to the audio DSP
wp<AudioFlinger> mAudioFlinger;
+
+#ifdef FLOAT_EFFECT_CHAIN
+ bool mSupportsFloat; // effect supports float processing
+ sp<EffectBufferHalInterface> mInBuffer16; // Buffers for interacting with HAL at 16 bits
+ sp<EffectBufferHalInterface> mOutBuffer16;
+#endif
};
// The EffectHandle class implements the IEffect interface. It provides resources
@@ -308,14 +314,14 @@
void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
mInBuffer = buffer;
}
- int16_t *inBuffer() const {
- return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
+ effect_buffer_t *inBuffer() const {
+ return mInBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mInBuffer->ptr()) : NULL;
}
void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
mOutBuffer = buffer;
}
- int16_t *outBuffer() const {
- return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
+ effect_buffer_t *outBuffer() const {
+ return mOutBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mOutBuffer->ptr()) : NULL;
}
void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 946d88f..e97bb06 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -68,8 +68,8 @@
status_t attachAuxEffect(int EffectId);
void setAuxBuffer(int EffectId, int32_t *buffer);
int32_t *auxBuffer() const { return mAuxBuffer; }
- void setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; }
- int16_t *mainBuffer() const { return mMainBuffer; }
+ void setMainBuffer(effect_buffer_t *buffer) { mMainBuffer = buffer; }
+ effect_buffer_t *mainBuffer() const { return mMainBuffer; }
int auxEffectId() const { return mAuxEffectId; }
virtual status_t getTimestamp(AudioTimestamp& timestamp);
void signal();
@@ -150,7 +150,8 @@
// allocated statically at track creation time,
// and is even allocated (though unused) for fast tracks
// FIXME don't allocate track name for fast tracks
- int16_t *mMainBuffer;
+ effect_buffer_t *mMainBuffer;
+
int32_t *mAuxBuffer;
int mAuxEffectId;
bool mHasVolumeController;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8e6c720..b2a1e18 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2537,7 +2537,7 @@
free(mEffectBuffer);
mEffectBuffer = NULL;
if (mEffectBufferEnabled) {
- mEffectBufferFormat = AUDIO_FORMAT_PCM_16_BIT; // Note: Effects support 16b only
+ mEffectBufferFormat = EFFECT_BUFFER_FORMAT;
mEffectBufferSize = mNormalFrameCount * mChannelCount
* audio_bytes_per_sample(mEffectBufferFormat);
(void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
@@ -2884,8 +2884,7 @@
&halInBuffer);
if (result != OK) return result;
halOutBuffer = halInBuffer;
- int16_t *buffer = reinterpret_cast<int16_t*>(halInBuffer->externalData());
-
+ effect_buffer_t *buffer = reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData());
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
if (session > AUDIO_SESSION_OUTPUT_MIX) {
// Only one effect chain can be present in direct output thread and it uses
@@ -2893,10 +2892,14 @@
if (mType != DIRECT) {
size_t numSamples = mNormalFrameCount * mChannelCount;
status_t result = EffectBufferHalInterface::allocate(
- numSamples * sizeof(int16_t),
+ numSamples * sizeof(effect_buffer_t),
&halInBuffer);
if (result != OK) return result;
+#ifdef FLOAT_EFFECT_CHAIN
+ buffer = halInBuffer->audioBuffer()->f32;
+#else
buffer = halInBuffer->audioBuffer()->s16;
+#endif
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
}
@@ -2971,7 +2974,7 @@
for (size_t i = 0; i < mTracks.size(); ++i) {
sp<Track> track = mTracks[i];
if (session == track->sessionId()) {
- track->setMainBuffer(reinterpret_cast<int16_t*>(mSinkBuffer));
+ track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
chain->decTrackCnt();
}
}
@@ -4554,7 +4557,7 @@
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
- AudioMixer::MIXER_FORMAT, (void *)AUDIO_FORMAT_PCM_16_BIT);
+ AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 2ca273f..c7b60d6 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -741,11 +741,10 @@
virtual String8 getParameters(const String8& keys);
virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
- // FIXME rename mixBuffer() to sinkBuffer() and remove int16_t* dependency.
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::PlaybackThread::Track::Track().
- int16_t *mixBuffer() const {
- return reinterpret_cast<int16_t *>(mSinkBuffer); };
+ effect_buffer_t *sinkBuffer() const {
+ return reinterpret_cast<effect_buffer_t *>(mSinkBuffer); };
virtual void detachAuxEffect_l(int effectId);
status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 50c0e23..1445572 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -395,7 +395,7 @@
mSharedBuffer(sharedBuffer),
mStreamType(streamType),
mName(-1), // see note below
- mMainBuffer(thread->mixBuffer()),
+ mMainBuffer(thread->sinkBuffer()),
mAuxBuffer(NULL),
mAuxEffectId(0), mHasVolumeController(false),
mPresentationCompleteFrames(0),
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 80a8dc6..62cbfc1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5595,6 +5595,11 @@
case AUDIO_FORMAT_E_AC3:
case AUDIO_FORMAT_DTS:
case AUDIO_FORMAT_DTS_HD:
+ // If ALWAYS, remove all other surround formats here since we will add them later.
+ if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
+ formats.removeAt(formatIndex);
+ formatIndex--;
+ }
supportsOtherSurround = true;
break;
case AUDIO_FORMAT_IEC61937:
@@ -5640,8 +5645,7 @@
// If ALWAYS, add support for raw surround formats if all are missing.
// This assumes that if any of these formats are reported by the HAL
// then the report is valid and should not be modified.
- if ((forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS)
- && !supportsOtherSurround) {
+ if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
formats.add(AUDIO_FORMAT_E_AC3);
formats.add(AUDIO_FORMAT_DTS);
formats.add(AUDIO_FORMAT_DTS_HD);
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index 83992aa..8444444 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -159,7 +159,8 @@
mMaxRecordAgeNs(kMaxRecordAgeNs),
mMaxRecordSets(kMaxRecordSets),
mNewSetInterval(kNewSetIntervalNs),
- mDumpProto(MediaAnalyticsItem::PROTO_V0) {
+ mDumpProto(MediaAnalyticsItem::PROTO_V1),
+ mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) {
ALOGD("MediaAnalyticsService created");
// clear our queues
@@ -381,6 +382,7 @@
String16 summaryOption("-summary");
bool summary = false;
String16 protoOption("-proto");
+ int chosenProto = mDumpProtoDefault;
String16 clearOption("-clear");
bool clear = false;
String16 sinceOption("-since");
@@ -400,7 +402,7 @@
i++;
if (i < n) {
String8 value(args[i]);
- int proto = MediaAnalyticsItem::PROTO_V0; // default to original
+ int proto = MediaAnalyticsItem::PROTO_V0;
char *endp;
const char *p = value.string();
proto = strtol(p, &endp, 10);
@@ -410,8 +412,12 @@
} else if (proto > MediaAnalyticsItem::PROTO_LAST) {
proto = MediaAnalyticsItem::PROTO_LAST;
}
- mDumpProto = proto;
+ chosenProto = proto;
+ } else {
+ result.append("unable to parse value for -proto\n\n");
}
+ } else {
+ result.append("missing value for -proto\n\n");
}
} else if (args[i] == sinceOption) {
i++;
@@ -437,7 +443,7 @@
} else if (args[i] == helpOption) {
result.append("Recognized parameters:\n");
result.append("-help this help message\n");
- result.append("-proto X dump using protocol X (defaults to 1)");
+ result.append("-proto # dump using protocol #");
result.append("-summary show summary info\n");
result.append("-clear clears out saved records\n");
result.append("-only X process records for component X\n");
@@ -450,6 +456,8 @@
Mutex::Autolock _l(mLock);
+ mDumpProto = chosenProto;
+
// we ALWAYS dump this piece
snprintf(buffer, SIZE, "Dump of the %s process:\n", kServiceName);
result.append(buffer);
diff --git a/services/mediaanalytics/MediaAnalyticsService.h b/services/mediaanalytics/MediaAnalyticsService.h
index 52e4631..3b34f44 100644
--- a/services/mediaanalytics/MediaAnalyticsService.h
+++ b/services/mediaanalytics/MediaAnalyticsService.h
@@ -125,6 +125,7 @@
// support for generating output
int mDumpProto;
+ int mDumpProtoDefault;
String8 dumpQueue(List<MediaAnalyticsItem*> *);
String8 dumpQueue(List<MediaAnalyticsItem*> *, nsecs_t, const char *only);