Merge "Revert "Revert "Revert "Remove unused modules made for non-Treble OMX""""
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 0771fc8..07d4e7e 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -140,5 +140,7 @@
void prepare2(int maxCount, int streamId);
+ void updateOutputConfiguration(int streamId, in OutputConfiguration outputConfiguration);
+
void finalizeOutputConfigurations(int streamId, in OutputConfiguration outputConfiguration);
}
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 468a1eb..813d6c9 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -160,12 +160,12 @@
}
OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
- int surfaceSetID) {
+ int surfaceSetID, bool isShared) {
mGbps.push_back(gbp);
mRotation = rotation;
mSurfaceSetID = surfaceSetID;
mIsDeferred = false;
- mIsShared = false;
+ mIsShared = isShared;
}
status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 8e641c7..3599604 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -64,7 +64,7 @@
OutputConfiguration(const android::Parcel& parcel);
OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
- int surfaceSetID = INVALID_SET_ID);
+ int surfaceSetID = INVALID_SET_ID, bool isShared = false);
bool operator == (const OutputConfiguration& other) const {
return ( mRotation == other.mRotation &&
@@ -110,6 +110,7 @@
bool gbpsEqual(const OutputConfiguration& other) const;
bool gbpsLessThan(const OutputConfiguration& other) const;
+ void addGraphicProducer(sp<IGraphicBufferProducer> gbp) {mGbps.push_back(gbp);}
private:
std::vector<sp<IGraphicBufferProducer>> mGbps;
int mRotation;
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 2a6b182..fd95296 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -135,3 +135,19 @@
}
return session->abortCaptures();
}
+
+EXPORT
+camera_status_t ACameraCaptureSession_updateSharedOutput(ACameraCaptureSession* session,
+ ACaptureSessionOutput* output) {
+ ATRACE_CALL();
+ if (session == nullptr) {
+ ALOGE("%s: Error: session is null", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+ return session->updateOutputConfiguration(output);
+}
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index 9f6d1f7..ac4beea 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -103,11 +103,74 @@
__FUNCTION__, window, out);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- *out = new ACaptureSessionOutput(window);
+ *out = new ACaptureSessionOutput(window, false);
return ACAMERA_OK;
}
EXPORT
+camera_status_t ACaptureSessionSharedOutput_create(
+ ANativeWindow* window, /*out*/ACaptureSessionOutput** out) {
+ ATRACE_CALL();
+ if (window == nullptr || out == nullptr) {
+ ALOGE("%s: Error: bad argument. window %p, out %p",
+ __FUNCTION__, window, out);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = new ACaptureSessionOutput(window, true);
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out,
+ ANativeWindow* window) {
+ ATRACE_CALL();
+ if ((window == nullptr) || (out == nullptr)) {
+ ALOGE("%s: Error: bad argument. window %p, out %p",
+ __FUNCTION__, window, out);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if (!out->mIsShared) {
+ ALOGE("%s: Error trying to insert a new window in non-shared output configuration",
+ __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+ if (out->mWindow == window) {
+ ALOGE("%s: Error trying to add the same window associated with the output configuration",
+ __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ auto insert = out->mSharedWindows.insert(window);
+ camera_status_t ret = (insert.second) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
+ return ret;
+}
+
+EXPORT
+camera_status_t ACaptureSessionSharedOutput_remove(ACaptureSessionOutput *out,
+ ANativeWindow* window) {
+ ATRACE_CALL();
+ if ((window == nullptr) || (out == nullptr)) {
+ ALOGE("%s: Error: bad argument. window %p, out %p",
+ __FUNCTION__, window, out);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if (!out->mIsShared) {
+ ALOGE("%s: Error trying to remove a window in non-shared output configuration",
+ __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+ if (out->mWindow == window) {
+ ALOGE("%s: Error trying to remove the same window associated with the output configuration",
+ __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ auto remove = out->mSharedWindows.erase(window);
+ camera_status_t ret = (remove) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
+ return ret;
+}
+
+EXPORT
void ACaptureSessionOutput_free(ACaptureSessionOutput* output) {
ATRACE_CALL();
if (output != nullptr) {
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index b9c159d..6d1d5ce 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -148,6 +148,23 @@
return ret;
}
+camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->updateOutputConfiguration(output);
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
ACameraDevice*
ACameraCaptureSession::getDevice() {
Mutex::Autolock _l(mSessionLock);
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 339c665..a2068e7 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -24,7 +24,8 @@
using namespace android;
struct ACaptureSessionOutput {
- explicit ACaptureSessionOutput(ANativeWindow* window) : mWindow(window) {};
+ explicit ACaptureSessionOutput(ANativeWindow* window, bool isShared = false) :
+ mWindow(window), mIsShared(isShared) {};
bool operator == (const ACaptureSessionOutput& other) const {
return mWindow == other.mWindow;
@@ -40,6 +41,8 @@
}
ANativeWindow* mWindow;
+ std::set<ANativeWindow *> mSharedWindows;
+ bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
};
@@ -89,6 +92,8 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ camera_status_t updateOutputConfiguration(ACaptureSessionOutput *output);
+
ACameraDevice* getDevice();
private:
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 907802c..9ce0ac8 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -289,6 +289,82 @@
return ACAMERA_OK;
}
+camera_status_t CameraDevice::updateOutputConfiguration(ACaptureSessionOutput *output) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ if (output == nullptr) {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!output->mIsShared) {
+ ALOGE("Error output configuration is not shared");
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+
+ int32_t streamId = -1;
+ for (auto& kvPair : mConfiguredOutputs) {
+ if (kvPair.second.first == output->mWindow) {
+ streamId = kvPair.first;
+ break;
+ }
+ }
+ if (streamId < 0) {
+ ALOGE("Error: Invalid output configuration");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ sp<IGraphicBufferProducer> iGBP(nullptr);
+ ret = getIGBPfromAnw(output->mWindow, iGBP);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
+ return ret;
+ }
+
+ OutputConfiguration outConfig(iGBP, output->mRotation, OutputConfiguration::INVALID_SET_ID,
+ true);
+
+ for (auto& anw : output->mSharedWindows) {
+ ret = getIGBPfromAnw(anw, iGBP);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
+ return ret;
+ }
+ outConfig.addGraphicProducer(iGBP);
+ }
+
+ auto remoteRet = mRemote->updateOutputConfiguration(streamId, outConfig);
+ if (!remoteRet.isOk()) {
+ switch (remoteRet.serviceSpecificErrorCode()) {
+ case hardware::ICameraService::ERROR_INVALID_OPERATION:
+ ALOGE("Camera device %s invalid operation: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ break;
+ case hardware::ICameraService::ERROR_ALREADY_EXISTS:
+ ALOGE("Camera device %s output surface already exists: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ break;
+ case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
+ ALOGE("Camera device %s invalid input argument: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ break;
+ default:
+ ALOGE("Camera device %s failed to add shared output: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ }
+
+ return ACAMERA_OK;
+}
+
camera_status_t
CameraDevice::allocateCaptureRequest(
const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
@@ -540,7 +616,8 @@
return ret;
}
outputSet.insert(std::make_pair(
- anw, OutputConfiguration(iGBP, outConfig.mRotation)));
+ anw, OutputConfiguration(iGBP, outConfig.mRotation,
+ OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
}
auto addSet = outputSet;
std::vector<int> deleteList;
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 6ed3881..23cc1a1 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -36,7 +36,8 @@
#include <camera/camera2/OutputConfiguration.h>
#include <camera/camera2/CaptureRequest.h>
-#include <camera/NdkCameraDevice.h>
+#include <camera/NdkCameraManager.h>
+#include <camera/NdkCameraCaptureSession.h>
#include "ACameraMetadata.h"
namespace android {
@@ -122,6 +123,8 @@
/*out*/int* captureSequenceId,
bool isRepeating);
+ camera_status_t updateOutputConfiguration(ACaptureSessionOutput *output);
+
static camera_status_t allocateCaptureRequest(
const ACaptureRequest* request, sp<CaptureRequest>& outReq);
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index d96f538..67003c1 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -591,6 +591,54 @@
#endif /* __ANDROID_API__ >= 24 */
+#if __ANDROID_API__ >= 28
+
+typedef struct ACaptureSessionOutput ACaptureSessionOutput;
+
+/**
+ * Update shared ACaptureSessionOutput.
+ *
+ * <p>A shared ACaptureSessionOutput (see {@link ACaptureSessionSharedOutput_create}) that
+ * was modified via calls to {@link ACaptureSessionSharedOutput_add} or
+ * {@link ACaptureSessionSharedOutput_remove} must be updated by calling this method before its
+ * changes take effect. After the update call returns with {@link ACAMERA_OK}, any newly added
+ * native windows can be used as a target in subsequent capture requests.</p>
+ *
+ * <p>Native windows that get removed must not be part of any active repeating or single/burst
+ * request or have any pending results. Consider updating repeating requests via
+ * {@link ACaptureSessionOutput_setRepeatingRequest} and then wait for the last frame number
+ * when the sequence completes
+ * {@link ACameraCaptureSession_captureCallback#onCaptureSequenceCompleted}.</p>
+ *
+ * <p>Native windows that get added must not be part of any other registered ACaptureSessionOutput
+ * and must be compatible. Compatible windows must have matching format, rotation and
+ * consumer usage.</p>
+ *
+ * <p>A shared ACameraCaptureSession can support up to 4 additional native windows.</p>
+ *
+ * @param session the capture session of interest
+ * @param output the modified output configuration
+ *
+ * @return <ul><li>
+ * {@link ACAMERA_OK} if the method succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session or output is NULL; or output
+ * contains invalid native windows; or if an attempt was made to add
+ * a native window to a different output configuration; or new native window is not
+ * compatible; or any removed native window still has pending requests;</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_OPERATION} if output configuration is not shared (see
+ * {@link ACaptureSessionSharedOutput_create}; or the number of additional
+ * native windows goes beyond the supported limit.</li>
+ * <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal
+ * error</li>
+ * <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li></ul>
+ */
+camera_status_t ACameraCaptureSession_updateSharedOutput(ACameraCaptureSession* session,
+ ACaptureSessionOutput* output);
+#endif /* __ANDROID_API__ >= 28 */
+
__END_DECLS
#endif /* _NDK_CAMERA_CAPTURE_SESSION_H */
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 6c9e85a..3a6f3ef 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -661,6 +661,67 @@
#endif /* __ANDROID_API__ >= 24 */
+#if __ANDROID_API__ >= 28
+
+/**
+ * Create a shared ACaptureSessionOutput object.
+ *
+ * <p>The ACaptureSessionOutput is used in {@link ACaptureSessionOutputContainer_add} method to add
+ * an output {@link ANativeWindow} to ACaptureSessionOutputContainer. Use
+ * {@link ACaptureSessionOutput_free} to free the object and its memory after application no longer
+ * needs the {@link ACaptureSessionOutput}. A shared ACaptureSessionOutput can be further modified
+ * via {@link ACaptureSessionSharedOutput_add} or {@link ACaptureSessionSharedOutput_remove} and
+ * must be updated via {@link ACameraCaptureSession_updateSharedOutput}.</p>
+ *
+ * @param anw the {@link ANativeWindow} to be associated with the {@link ACaptureSessionOutput}
+ * @param output the output {@link ACaptureSessionOutput} will be stored here if the
+ * method call succeeds.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds. The created container will be
+ * filled in the output argument.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if anw or output is NULL.</li></ul>
+ *
+ * @see ACaptureSessionOutputContainer_add
+ */
+camera_status_t ACaptureSessionSharedOutput_create(
+ ANativeWindow* anw, /*out*/ACaptureSessionOutput** output);
+
+/**
+ * Add a native window to shared ACaptureSessionOutput.
+ *
+ * The ACaptureSessionOutput must be created via {@link ACaptureSessionSharedOutput_create}.
+ *
+ * @param output the shared ACaptureSessionOutput to be extended.
+ * @param anw The new native window.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if anw or output is NULL; or output is not
+ * shared see {@link ACaptureSessionSharedOutput_create}; or anw matches with the native
+ * window associated with ACaptureSessionOutput; or anw is already present inside
+ * ACaptureSessionOutput.</li></ul>
+ */
+camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *output, ANativeWindow *anw);
+
+/**
+ * Remove a native window from shared ACaptureSessionOutput.
+ *
+ * @param output the {@link ACaptureSessionOutput} to be modified.
+ * @param anw The native window to be removed.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if anw or output is NULL; or output is not
+ * shared see {@link ACaptureSessionSharedOutput_create}; or anw matches with the native
+ * window associated with ACaptureSessionOutput; or anw is not present inside
+ * ACaptureSessionOutput.</li></ul>
+ */
+camera_status_t ACaptureSessionSharedOutput_remove(ACaptureSessionOutput *output,
+ ANativeWindow* anw);
+
+#endif /* __ANDROID_API__ >= 28 */
+
__END_DECLS
#endif /* _NDK_CAMERA_DEVICE_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 629d75a..1793877 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -471,10 +471,6 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of android.control.maxRegionsAe.</p>
- * <p>The data representation is int[5 * area_count].
- * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
- * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
- * ymax.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -495,6 +491,10 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
+ * <p>The data representation is <code>int[5 * area_count]</code>.
+ * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+ * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+ * ymax.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -633,10 +633,6 @@
* Otherwise will always be present.</p>
* <p>The maximum number of focus areas supported by the device is determined by the value
* of android.control.maxRegionsAf.</p>
- * <p>The data representation is int[5 * area_count].
- * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
- * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
- * ymax.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -657,6 +653,10 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
+ * <p>The data representation is <code>int[5 * area_count]</code>.
+ * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+ * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+ * ymax.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -791,10 +791,6 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of android.control.maxRegionsAwb.</p>
- * <p>The data representation is int[5 * area_count].
- * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
- * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
- * ymax.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -815,6 +811,10 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
+ * <p>The data representation is <code>int[5 * area_count]</code>.
+ * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+ * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+ * ymax.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -885,11 +885,10 @@
* <p>When set to AUTO, the individual algorithm controls in
* ACAMERA_CONTROL_* are in effect, such as ACAMERA_CONTROL_AF_MODE.</p>
* <p>When set to USE_SCENE_MODE, the individual controls in
- * ACAMERA_CONTROL_* are mostly disabled, and the camera device implements
- * one of the scene mode settings (such as ACTION, SUNSET, or PARTY)
- * as it wishes. The camera device scene mode 3A settings are provided by
- * capture results {@link ACameraMetadata} from
- * {@link ACameraCaptureSession_captureCallback_result}.</p>
+ * ACAMERA_CONTROL_* are mostly disabled, and the camera device
+ * implements one of the scene mode settings (such as ACTION,
+ * SUNSET, or PARTY) as it wishes. The camera device scene mode
+ * 3A settings are provided by {@link ACameraCaptureSession_captureCallback_result capture results}.</p>
* <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
* is that this frame will not be used by camera device background 3A statistics
* update, as if this frame is never captured. This mode can be used in the scenario
@@ -1043,20 +1042,18 @@
* <p>For constant-framerate recording, for each normal
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>, that is, a
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a>
- * in the range [
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_LOW</a>,
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_2160P</a>],
- * if the profile is supported by the device and has
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a>
- * <code>x</code>, this list will always include (<code>x</code>,<code>x</code>).</p>
+ * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a> in
+ * the range [<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_LOW</a>,
+ * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_2160P</a>], if the profile is
+ * supported by the device and has
+ * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code>, this list will
+ * always include (<code>x</code>,<code>x</code>).</p>
* </li>
* <li>
* <p>Also, a camera device must either not support any
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,
* or support at least one
- * normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>
- * that has
+ * normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code> >= 24.</p>
* </li>
* </ul>
@@ -1619,13 +1616,13 @@
* compared to previous regular requests. enableZsl does not affect requests with other
* capture intents.</p>
* <p>For example, when requests are submitted in the following order:
- * Request A: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is PREVIEW
- * Request B: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is STILL_CAPTURE</p>
+ * Request A: enableZsl is ON, ACAMERA_CONTROL_CAPTURE_INTENT is PREVIEW
+ * Request B: enableZsl is ON, ACAMERA_CONTROL_CAPTURE_INTENT is STILL_CAPTURE</p>
* <p>The output images for request B may have contents captured before the output images for
* request A, and the result metadata for request B may be older than the result metadata for
* request A.</p>
- * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the
- * past for requests with STILL_CAPTURE capture intent.</p>
+ * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in
+ * the past for requests with STILL_CAPTURE capture intent.</p>
* <p>For applications targeting SDK versions O and newer, the value of enableZsl in
* TEMPLATE_STILL_CAPTURE template may be <code>true</code>. The value in other templates is always
* <code>false</code> if present.</p>
@@ -1959,14 +1956,14 @@
* <p>When an ACAMERA_JPEG_ORIENTATION of non-zero degree is requested,
* the camera device will handle thumbnail rotation in one of the following ways:</p>
* <ul>
- * <li>Set the
- * <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
+ * <li>Set the <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
* and keep jpeg and thumbnail image data unrotated.</li>
* <li>Rotate the jpeg and thumbnail image data and not set
- * <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>.
- * In this case, LIMITED or FULL hardware level devices will report rotated thumnail size
- * in capture result, so the width and height will be interchanged if 90 or 270 degree
- * orientation is requested. LEGACY device will always report unrotated thumbnail size.</li>
+ * <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>. In this
+ * case, LIMITED or FULL hardware level devices will report rotated thumnail size in
+ * capture result, so the width and height will be interchanged if 90 or 270 degree
+ * orientation is requested. LEGACY device will always report unrotated thumbnail
+ * size.</li>
* </ul>
*
* @see ACAMERA_JPEG_ORIENTATION
@@ -2218,9 +2215,8 @@
* <p>The position of the camera device's lens optical center,
* as a three-dimensional vector <code>(x,y,z)</code>, relative to the
* optical center of the largest camera device facing in the
- * same direction as this camera, in the
- * <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate axes</a>.
- * Note that only the axis definitions are shared with
+ * same direction as this camera, in the <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate
+ * axes</a>. Note that only the axis definitions are shared with
* the sensor coordinate system, but not the origin.</p>
* <p>If this device is the largest or only camera device with a
* given facing, then this position will be <code>(0, 0, 0)</code>; a
@@ -2662,11 +2658,12 @@
* into the 3 stream types as below:</p>
* <ul>
* <li>Processed (but stalling): any non-RAW format with a stallDurations > 0.
- * Typically {@link AIMAGE_FORMAT_JPEG} format.</li>
- * <li>Raw formats: {@link AIMAGE_FORMAT_RAW16}, {@link AIMAGE_FORMAT_RAW10}, or
- * {@link AIMAGE_FORMAT_RAW12}.</li>
- * <li>Processed (but not-stalling): any non-RAW format without a stall duration.
- * Typically {@link AIMAGE_FORMAT_YUV_420_888}.</li>
+ * Typically {@link AIMAGE_FORMAT_JPEG JPEG format}.</li>
+ * <li>Raw formats: {@link AIMAGE_FORMAT_RAW16 RAW_SENSOR}, {@link AIMAGE_FORMAT_RAW10 RAW10}, or
+ * {@link AIMAGE_FORMAT_RAW12 RAW12}.</li>
+ * <li>Processed (but not-stalling): any non-RAW format without a stall duration. Typically
+ * {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888},
+ * <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#NV21">NV21</a>, or <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12">YV12</a>.</li>
* </ul>
*
* @see ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
@@ -2787,7 +2784,7 @@
ACAMERA_REQUEST_START + 12,
/**
* <p>A list of all keys that the camera device has available
- * to use with {@link ACaptureRequest}.</p>
+ * to use with {@link ACaptureRequest }.</p>
*
* <p>Type: int32[n]</p>
*
@@ -2809,9 +2806,7 @@
ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS = // int32[n]
ACAMERA_REQUEST_START + 13,
/**
- * <p>A list of all keys that the camera device has available
- * to query with {@link ACameraMetadata} from
- * {@link ACameraCaptureSession_captureCallback_result}.</p>
+ * <p>A list of all keys that the camera device has available to use with {@link ACameraCaptureSession_captureCallback_result }.</p>
*
* <p>Type: int32[n]</p>
*
@@ -2842,9 +2837,7 @@
ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS = // int32[n]
ACAMERA_REQUEST_START + 14,
/**
- * <p>A list of all keys that the camera device has available
- * to query with {@link ACameraMetadata} from
- * {@link ACameraManager_getCameraCharacteristics}.</p>
+ * <p>A list of all keys that the camera device has available to use with {@link ACameraManager_getCameraCharacteristics }.</p>
*
* <p>Type: int32[n]</p>
*
@@ -2876,7 +2869,6 @@
* </ul></p>
*
* <p>This control can be used to implement digital zoom.</p>
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>The crop region coordinate system is based off
* ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with <code>(0, 0)</code> being the
* top-left corner of the sensor active array.</p>
@@ -2906,6 +2898,7 @@
* for rounding and other hardware requirements; the final
* crop region used will be included in the output capture
* result.</p>
+ * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
*
* @see ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -3061,13 +3054,14 @@
* ignored).</p>
* <p>The following formats may always have a stall duration:</p>
* <ul>
- * <li>{@link AIMAGE_FORMAT_JPEG}</li>
- * <li>{@link AIMAGE_FORMAT_RAW16}</li>
+ * <li>{@link AIMAGE_FORMAT_JPEG }</li>
+ * <li>{@link AIMAGE_FORMAT_RAW16 }</li>
* </ul>
* <p>The following formats will never have a stall duration:</p>
* <ul>
- * <li>{@link AIMAGE_FORMAT_YUV_420_888}</li>
- * <li>{@link AIMAGE_FORMAT_RAW10}</li>
+ * <li>{@link AIMAGE_FORMAT_YUV_420_888 }</li>
+ * <li>{@link AIMAGE_FORMAT_RAW10 }</li>
+ * <li>{@link AIMAGE_FORMAT_RAW12 }</li>
* </ul>
* <p>All other formats may or may not have an allowed stall duration on
* a per-capability basis; refer to ACAMERA_REQUEST_AVAILABLE_CAPABILITIES
@@ -3177,39 +3171,29 @@
* can run concurrently to the rest of the camera pipeline, but
* cannot process more than 1 capture at a time.</li>
* </ul>
- * <p>The necessary information for the application, given the model above,
- * is provided via
- * {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}.
- * These are used to determine the maximum frame rate / minimum frame
- * duration that is possible for a given stream configuration.</p>
+ * <p>The necessary information for the application, given the model above, is provided via
+ * {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }.
+ * These are used to determine the maximum frame rate / minimum frame duration that is
+ * possible for a given stream configuration.</p>
* <p>Specifically, the application can use the following rules to
* determine the minimum frame duration it can request from the camera
* device:</p>
* <ol>
- * <li>Let the set of currently configured input/output streams
- * be called <code>S</code>.</li>
- * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking
- * it up in {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}
- * (with its respective size/format). Let this set of frame durations be
- * called <code>F</code>.</li>
- * <li>For any given request <code>R</code>, the minimum frame duration allowed
- * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams
- * used in <code>R</code> be called <code>S_r</code>.</li>
+ * <li>Let the set of currently configured input/output streams be called <code>S</code>.</li>
+ * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking it up in {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }
+ * (with its respective size/format). Let this set of frame durations be called <code>F</code>.</li>
+ * <li>For any given request <code>R</code>, the minimum frame duration allowed for <code>R</code> is the maximum
+ * out of all values in <code>F</code>. Let the streams used in <code>R</code> be called <code>S_r</code>.</li>
* </ol>
- * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link
- * ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS}
- * using its respective size/format), then the frame duration in <code>F</code>
- * determines the steady state frame rate that the application will get
- * if it uses <code>R</code> as a repeating request. Let this special kind of
- * request be called <code>Rsimple</code>.</p>
- * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
- * by a single capture of a new request <code>Rstall</code> (which has at least
- * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
- * same minimum frame duration this will not cause a frame rate loss
- * if all buffers from the previous <code>Rstall</code> have already been
- * delivered.</p>
- * <p>For more details about stalling, see
- * {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS}.</p>
+ * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS }
+ * using its respective size/format), then the frame duration in <code>F</code> determines the steady
+ * state frame rate that the application will get if it uses <code>R</code> as a repeating request. Let
+ * this special kind of request be called <code>Rsimple</code>.</p>
+ * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved by a single capture of a
+ * new request <code>Rstall</code> (which has at least one in-use stream with a non-0 stall time) and if
+ * <code>Rstall</code> has the same minimum frame duration this will not cause a frame rate loss if all
+ * buffers from the previous <code>Rstall</code> have already been delivered.</p>
+ * <p>For more details about stalling, see {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS }.</p>
* <p>This control is only effective if ACAMERA_CONTROL_AE_MODE or ACAMERA_CONTROL_MODE is set to
* OFF; otherwise the auto-exposure algorithm will override this value.</p>
*
@@ -3567,14 +3551,12 @@
* timestamps for other captures from the same camera device, but are
* not guaranteed to be comparable to any other time source.</p>
* <p>When ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE <code>==</code> REALTIME, the
- * timestamps measure time in the same timebase as
- * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">elapsedRealtimeNanos</a>
- * (or CLOCK_BOOTTIME), and they can
+ * timestamps measure time in the same timebase as <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>, and they can
* be compared to other timestamps from other subsystems that
* are using that base.</p>
* <p>For reprocessing, the timestamp will match the start of exposure of
- * the input image, i.e. {@link CaptureResult#SENSOR_TIMESTAMP the
- * timestamp} in the TotalCaptureResult that was used to create the
+ * the input image, i.e. <a href="https://developer.android.com/reference/CaptureResult.html#SENSOR_TIMESTAMP">the
+ * timestamp</a> in the TotalCaptureResult that was used to create the
* reprocess capture request.</p>
*
* @see ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE
@@ -3775,7 +3757,6 @@
* optically shielded pixel areas. By blocking light, these pixels
* provides a reliable black reference for black level compensation
* in active array region.</p>
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>This key provides a list of disjoint rectangles specifying the
* regions of optically shielded (with metal shield) black pixel
* regions if the camera device is capable of reading out these black
@@ -3785,6 +3766,7 @@
* black level of each captured raw images.</p>
* <p>When this key is reported, the ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL and
* ACAMERA_SENSOR_DYNAMIC_WHITE_LEVEL will also be reported.</p>
+ * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
* @see ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL
@@ -3825,9 +3807,8 @@
* layout key (see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT), i.e. the
* nth value given corresponds to the black level offset for the nth
* color channel listed in the CFA.</p>
- * <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is
- * available or the camera device advertises this key via
- * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS}.</p>
+ * <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is available or the
+ * camera device advertises this key via {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.</p>
*
* @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
* @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
@@ -3853,7 +3834,7 @@
* estimated white level for each frame.</p>
* <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is
* available or the camera device advertises this key via
- * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS}.</p>
+ * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.</p>
*
* @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
* @see ACAMERA_SENSOR_INFO_WHITE_LEVEL
@@ -3882,13 +3863,13 @@
* <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of
* the full pixel array, and the size of the full pixel array is given by
* ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE.</p>
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>The coordinate system for most other keys that list pixel coordinates, including
* ACAMERA_SCALER_CROP_REGION, is defined relative to the active array rectangle given in
* this field, with <code>(0, 0)</code> being the top-left of this rectangle.</p>
* <p>The active array may be smaller than the full pixel array, since the full array may
* include black calibration pixels or other inactive regions, and geometric correction
* resulting in scaling or cropping may have been applied.</p>
+ * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE
@@ -3960,8 +3941,7 @@
* <p>Attempting to use frame durations beyond the maximum will result in the frame
* duration being clipped to the maximum. See that control for a full definition of frame
* durations.</p>
- * <p>Refer to {@link
- * ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}
+ * <p>Refer to {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }
* for the minimum frame duration values.</p>
*/
ACAMERA_SENSOR_INFO_MAX_FRAME_DURATION = // int64
@@ -4000,9 +3980,9 @@
* the raw buffers produced by this sensor.</p>
* <p>If a camera device supports raw sensor formats, either this or
* ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE is the maximum dimensions for the raw
- * output formats listed in ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS (this depends on
- * whether or not the image sensor returns buffers containing pixels that are not
- * part of the active array region for blacklevel calibration or other purposes).</p>
+ * output formats listed in {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS }
+ * (this depends on whether or not the image sensor returns buffers containing pixels that
+ * are not part of the active array region for blacklevel calibration or other purposes).</p>
* <p>Some parts of the full pixel array may not receive light from the scene,
* or be otherwise inactive. The ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE key
* defines the rectangle of active pixels that will be included in processed image
@@ -4092,7 +4072,6 @@
* <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
* </ul></p>
*
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>This is the rectangle representing the size of the active region of the sensor (i.e.
* the region that actually receives light from the scene) before any geometric correction
* has been applied, and should be treated as the active region rectangle for any of the
@@ -4143,6 +4122,7 @@
* ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE.</p>
* <p>The pre-correction active array may be smaller than the full pixel array, since the
* full array may include black calibration pixels or other inactive regions.</p>
+ * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_LENS_RADIAL_DISTORTION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -4302,10 +4282,10 @@
* <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
* </ul></p>
*
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>The coordinate system is that of ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with
* <code>(0, 0)</code> being the top-left pixel of the active array.</p>
- * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF</p>
+ * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF
+ * The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see ACAMERA_STATISTICS_FACE_DETECT_MODE
@@ -4832,7 +4812,7 @@
* <p>See the individual level enums for full descriptions of the supported capabilities. The
* ACAMERA_REQUEST_AVAILABLE_CAPABILITIES entry describes the device's capabilities at a
* finer-grain level, if needed. In addition, many controls have their available settings or
- * ranges defined in individual metadata tag entries in this document.</p>
+ * ranges defined in individual entries from {@link ACameraManager_getCameraCharacteristics }.</p>
* <p>Some features are not part of any particular hardware level or capability and must be
* queried separately. These include:</p>
* <ul>
@@ -6157,13 +6137,13 @@
ACAMERA_EDGE_MODE_HIGH_QUALITY = 2,
/**
- * <p>Edge enhancement is applied at different levels for different output streams,
- * based on resolution. Streams at maximum recording resolution (see {@link
- * ACameraDevice_createCaptureSession}) or below have
- * edge enhancement applied, while higher-resolution streams have no edge enhancement
- * applied. The level of edge enhancement for low-resolution streams is tuned so that
- * frame rate is not impacted, and the quality is equal to or better than FAST (since it
- * is only applied to lower-resolution outputs, quality may improve from FAST).</p>
+ * <p>Edge enhancement is applied at different
+ * levels for different output streams, based on resolution. Streams at maximum recording
+ * resolution (see {@link ACameraDevice_createCaptureSession })
+ * or below have edge enhancement applied, while higher-resolution streams have no edge
+ * enhancement applied. The level of edge enhancement for low-resolution streams is tuned
+ * so that frame rate is not impacted, and the quality is equal to or better than FAST
+ * (since it is only applied to lower-resolution outputs, quality may improve from FAST).</p>
* <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
* with YUV or PRIVATE reprocessing, where the application continuously captures
* high-resolution intermediate buffers into a circular buffer, from which a final image is
@@ -6412,13 +6392,12 @@
/**
* <p>Noise reduction is applied at different levels for different output streams,
- * based on resolution. Streams at maximum recording resolution (see {@link
- * ACameraDevice_createCaptureSession}) or below have noise
- * reduction applied, while higher-resolution streams have MINIMAL (if supported) or no
- * noise reduction applied (if MINIMAL is not supported.) The degree of noise reduction
- * for low-resolution streams is tuned so that frame rate is not impacted, and the quality
- * is equal to or better than FAST (since it is only applied to lower-resolution outputs,
- * quality may improve from FAST).</p>
+ * based on resolution. Streams at maximum recording resolution (see {@link ACameraDevice_createCaptureSession })
+ * or below have noise reduction applied, while higher-resolution streams have MINIMAL (if
+ * supported) or no noise reduction applied (if MINIMAL is not supported.) The degree of
+ * noise reduction for low-resolution streams is tuned so that frame rate is not impacted,
+ * and the quality is equal to or better than FAST (since it is only applied to
+ * lower-resolution outputs, quality may improve from FAST).</p>
* <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
* with YUV or PRIVATE reprocessing, where the application continuously captures
* high-resolution intermediate buffers into a circular buffer, from which a final image is
@@ -6635,18 +6614,16 @@
* to FAST. Additionally, maximum-resolution images can be captured at >= 10 frames
* per second. Here, 'high resolution' means at least 8 megapixels, or the maximum
* resolution of the device, whichever is smaller.</p>
- * <p>More specifically, this means that at least one output {@link
- * AIMAGE_FORMAT_YUV_420_888} size listed in
- * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS} is larger or equal to the
- * 'high resolution' defined above, and can be captured at at least 20 fps.
- * For the largest {@link AIMAGE_FORMAT_YUV_420_888} size listed in
- * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}, camera device can capture this
- * size for at least 10 frames per second.
- * Also the ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry lists at least one FPS range
- * where the minimum FPS is >= 1 / minimumFrameDuration for the largest YUV_420_888 size.</p>
- * <p>If the device supports the {@link AIMAGE_FORMAT_RAW10}, {@link
- * AIMAGE_FORMAT_RAW12}, then those can also be captured at the same rate
- * as the maximum-size YUV_420_888 resolution is.</p>
+ * <p>More specifically, this means that at least one output {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
+ * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS }
+ * is larger or equal to the 'high resolution' defined above, and can be captured at at
+ * least 20 fps. For the largest {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
+ * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS },
+ * camera device can capture this size for at least 10 frames per second. Also the
+ * ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry lists at least one FPS range where
+ * the minimum FPS is >= 1 / minimumFrameDuration for the largest YUV_420_888 size.</p>
+ * <p>If the device supports the {@link AIMAGE_FORMAT_RAW10 }, {@link AIMAGE_FORMAT_RAW12 }, then those can also be
+ * captured at the same rate as the maximum-size YUV_420_888 resolution is.</p>
* <p>In addition, the ACAMERA_SYNC_MAX_LATENCY field is guaranted to have a value between 0
* and 4, inclusive. ACAMERA_CONTROL_AE_LOCK_AVAILABLE and ACAMERA_CONTROL_AWB_LOCK_AVAILABLE
* are also guaranteed to be <code>true</code> so burst capture with these two locks ON yields
@@ -6663,13 +6640,13 @@
* <p>The camera device can produce depth measurements from its field of view.</p>
* <p>This capability requires the camera device to support the following:</p>
* <ul>
- * <li>{@link AIMAGE_FORMAT_DEPTH16} is supported as an output format.</li>
- * <li>{@link AIMAGE_FORMAT_DEPTH_POINT_CLOUD} is optionally supported as an
- * output format.</li>
- * <li>This camera device, and all camera devices with the same ACAMERA_LENS_FACING,
- * will list the following calibration entries in {@link ACameraMetadata} from both
- * {@link ACameraManager_getCameraCharacteristics} and
- * {@link ACameraCaptureSession_captureCallback_result}:<ul>
+ * <li>{@link AIMAGE_FORMAT_DEPTH16 } is supported as
+ * an output format.</li>
+ * <li>{@link AIMAGE_FORMAT_DEPTH_POINT_CLOUD } is
+ * optionally supported as an output format.</li>
+ * <li>This camera device, and all camera devices with the same ACAMERA_LENS_FACING, will
+ * list the following calibration metadata entries in both {@link ACameraManager_getCameraCharacteristics }
+ * and {@link ACameraCaptureSession_captureCallback_result }:<ul>
* <li>ACAMERA_LENS_POSE_TRANSLATION</li>
* <li>ACAMERA_LENS_POSE_ROTATION</li>
* <li>ACAMERA_LENS_INTRINSIC_CALIBRATION</li>
@@ -6683,8 +6660,7 @@
* </ul>
* <p>Generally, depth output operates at a slower frame rate than standard color capture,
* so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
- * should be accounted for (see
- * {@link ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS}).
+ * should be accounted for (see {@link ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS }).
* On a device that supports both depth and color-based output, to enable smooth preview,
* using a repeating burst is recommended, where a depth-output target is only included
* once every N frames, where N is the ratio between preview output rate and depth output
@@ -6918,8 +6894,8 @@
/**
* <p>Timestamps from ACAMERA_SENSOR_TIMESTAMP are in the same timebase as
- * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">elapsedRealtimeNanos</a>
- * (or CLOCK_BOOTTIME), and they can be compared to other timestamps using that base.</p>
+ * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>,
+ * and they can be compared to other timestamps using that base.</p>
*
* @see ACAMERA_SENSOR_TIMESTAMP
*/
@@ -7104,7 +7080,7 @@
* <p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
* better.</p>
* <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
- * {@link ACameraDevice_createCaptureSession} documentation are guaranteed to be supported.</p>
+ * {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
* <p>All <code>LIMITED</code> devices support the <code>BACKWARDS_COMPATIBLE</code> capability, indicating basic
* support for color image capture. The only exception is that the device may
* alternatively support only the <code>DEPTH_OUTPUT</code> capability, if it can only output depth
@@ -7130,7 +7106,7 @@
/**
* <p>This camera device is capable of supporting advanced imaging applications.</p>
* <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code> tables in the
- * {@link ACameraDevice_createCaptureSession} documentation are guaranteed to be supported.</p>
+ * {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
* <p>A <code>FULL</code> device will support below capabilities:</p>
* <ul>
* <li><code>BURST_CAPTURE</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
@@ -7157,8 +7133,7 @@
/**
* <p>This camera device is running in backward compatibility mode.</p>
- * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link
- * ACameraDevice_createCaptureSession} documentation are supported.</p>
+ * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are supported.</p>
* <p>A <code>LEGACY</code> device does not support per-frame control, manual sensor control, manual
* post-processing, arbitrary cropping regions, and has relaxed performance constraints.
* No additional capabilities beyond <code>BACKWARD_COMPATIBLE</code> will ever be listed by a
@@ -7179,9 +7154,7 @@
* <p>This camera device is capable of YUV reprocessing and RAW data capture, in addition to
* FULL-level capabilities.</p>
* <p>The stream configurations listed in the <code>LEVEL_3</code>, <code>RAW</code>, <code>FULL</code>, <code>LEGACY</code> and
- * <code>LIMITED</code> tables in the {@link
- * ACameraDevice_createCaptureSession}
- * documentation are guaranteed to be supported.</p>
+ * <code>LIMITED</code> tables in the {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
* <p>The following additional capabilities are guaranteed to be supported:</p>
* <ul>
* <li><code>YUV_REPROCESSING</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 41bb22b..0a8a6e9 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -6,6 +6,7 @@
ACameraCaptureSession_getDevice;
ACameraCaptureSession_setRepeatingRequest;
ACameraCaptureSession_stopRepeating;
+ ACameraCaptureSession_updateSharedOutput;
ACameraDevice_close;
ACameraDevice_createCaptureRequest;
ACameraDevice_createCaptureSession;
@@ -40,6 +41,9 @@
ACaptureSessionOutputContainer_free;
ACaptureSessionOutputContainer_remove;
ACaptureSessionOutput_create;
+ ACaptureSessionSharedOutput_create;
+ ACaptureSessionSharedOutput_add;
+ ACaptureSessionSharedOutput_remove;
ACaptureSessionOutput_free;
local:
*;
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 0777890..ee87751 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -13,11 +13,12 @@
libbinder \
libcutils \
liblog \
+ libhidltransport \
+ libhwbinder \
libmedialogservice \
libnbaio \
libsoundtriggerservice \
- libutils \
- libhwbinder
+ libutils
# TODO oboeservice is the old folder name for aaudioservice. It will be changed.
LOCAL_C_INCLUDES := \
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 474ef97..5a9d1bb 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -25,12 +25,9 @@
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
#include <utils/Log.h>
-// FIXME: remove when BUG 31748996 is fixed
-#include <hwbinder/IPCThreadState.h>
-#include <hwbinder/ProcessState.h>
-
// from LOCAL_C_INCLUDES
#include "aaudio/AAudioTesting.h"
#include "AudioFlinger.h"
@@ -128,6 +125,7 @@
prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me also
setpgid(0, 0); // but if I die first, don't kill my parent
}
+ android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
@@ -145,10 +143,6 @@
SoundTriggerHwService::instantiate();
ProcessState::self()->startThreadPool();
-
-// FIXME: remove when BUG 31748996 is fixed
- android::hardware::ProcessState::self()->startThreadPool();
-
IPCThreadState::self()->joinThreadPool();
}
}
diff --git a/media/libaaudio/examples/utils/AAudioExampleUtils.h b/media/libaaudio/examples/utils/AAudioExampleUtils.h
index 2671c3a..46b8895 100644
--- a/media/libaaudio/examples/utils/AAudioExampleUtils.h
+++ b/media/libaaudio/examples/utils/AAudioExampleUtils.h
@@ -32,6 +32,7 @@
#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000)
+template <class T = aaudio_sharing_mode_t>
const char *getSharingModeText(aaudio_sharing_mode_t mode) {
const char *text = "unknown";
switch (mode) {
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index fa1d253..cfb5be6 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -811,6 +811,20 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_HK_RINGTONE
+ { .segments = { { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0},
+ { .duration = 0, .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_IE_RINGTONE
+ { .segments = { { .duration = 180, .waveFreq = { 425, 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 425, 0 }, 0, 0 },
+ { .duration = 4500, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_IE_CALL_WAITING
};
// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -875,6 +889,16 @@
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
TONE_HK_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // IRELAND
+ TONE_SUP_DIAL, // TONE_SUP_DIAL
+ TONE_SUP_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_IE_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_IE_RINGTONE // TONE_SUP_RINGTONE
}
};
@@ -944,6 +968,8 @@
mRegion = SINGAPORE;
} else if (strstr(value, "hk") != NULL) {
mRegion = HONGKONG;
+ } else if (strstr(value, "ie") != NULL) {
+ mRegion = IRELAND;
} else {
mRegion = CEPT;
}
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 97bc825..247703f 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -209,6 +209,9 @@
// HONG KONG Supervisory tones
TONE_HK_BUSY, // Busy tone: 480 Hz + 620 Hz, 500ms ON, 500ms OFF...
TONE_HK_RINGTONE, // Ring Tone: 440 Hz + 480 Hz repeated with pattern 0,4s on, 0,2s off, 0,4s on and 3s off.
+ // IRELAND Supervisory tones
+ TONE_IE_RINGTONE, // Ring Tone: A 400Hz + 450Hz tone repeated in a 0.4s on, 0.2s off, 0.4s on, 2.0s off pattern.
+ TONE_IE_CALL_WAITING, // Call waiting tone: 425Hz tone repeated in a 0.18s on, 0.2s off, 0.2s on, 4.5s off pattern.
NUM_ALTERNATE_TONES
};
@@ -219,6 +222,7 @@
AUSTRALIA,
SINGAPORE,
HONGKONG,
+ IRELAND,
CEPT,
NUM_REGIONS
};
diff --git a/media/libaudiohal/HalDeathHandlerHidl.cpp b/media/libaudiohal/HalDeathHandlerHidl.cpp
index a742671..1e3ab58 100644
--- a/media/libaudiohal/HalDeathHandlerHidl.cpp
+++ b/media/libaudiohal/HalDeathHandlerHidl.cpp
@@ -48,12 +48,13 @@
void HalDeathHandler::serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) {
// No matter which of the service objects has died,
- // we need to run all the registered handlers and crash our process.
+ // we need to run all the registered handlers and exit.
std::lock_guard<std::mutex> guard(mHandlersLock);
for (const auto& handler : mHandlers) {
handler.second();
}
- LOG_ALWAYS_FATAL("HAL server crashed, need to restart");
+ ALOGE("HAL server crashed, audio server is restarting");
+ exit(1);
}
} // namespace android
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 238925d..3e72c89 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -813,7 +813,7 @@
mMixerInFormat, sampleRate, playbackRate);
reconfigureBufferProviders();
} else {
- reinterpret_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
+ static_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
->setPlaybackRate(playbackRate);
}
return true;
diff --git a/media/libmedia/BufferingSettings.cpp b/media/libmedia/BufferingSettings.cpp
index a69497e..271a238 100644
--- a/media/libmedia/BufferingSettings.cpp
+++ b/media/libmedia/BufferingSettings.cpp
@@ -23,43 +23,16 @@
namespace android {
-// static
-bool BufferingSettings::IsValidBufferingMode(int mode) {
- return (mode >= BUFFERING_MODE_NONE && mode < BUFFERING_MODE_COUNT);
-}
-
-// static
-bool BufferingSettings::IsTimeBasedBufferingMode(int mode) {
- return (mode == BUFFERING_MODE_TIME_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE);
-}
-
-// static
-bool BufferingSettings::IsSizeBasedBufferingMode(int mode) {
- return (mode == BUFFERING_MODE_SIZE_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE);
-}
-
BufferingSettings::BufferingSettings()
- : mInitialBufferingMode(BUFFERING_MODE_NONE),
- mRebufferingMode(BUFFERING_MODE_NONE),
- mInitialWatermarkMs(kNoWatermark),
- mInitialWatermarkKB(kNoWatermark),
- mRebufferingWatermarkLowMs(kNoWatermark),
- mRebufferingWatermarkHighMs(kNoWatermark),
- mRebufferingWatermarkLowKB(kNoWatermark),
- mRebufferingWatermarkHighKB(kNoWatermark) { }
+ : mInitialMarkMs(kNoMark),
+ mResumePlaybackMarkMs(kNoMark) { }
status_t BufferingSettings::readFromParcel(const Parcel* parcel) {
if (parcel == nullptr) {
return BAD_VALUE;
}
- mInitialBufferingMode = (BufferingMode)parcel->readInt32();
- mRebufferingMode = (BufferingMode)parcel->readInt32();
- mInitialWatermarkMs = parcel->readInt32();
- mInitialWatermarkKB = parcel->readInt32();
- mRebufferingWatermarkLowMs = parcel->readInt32();
- mRebufferingWatermarkHighMs = parcel->readInt32();
- mRebufferingWatermarkLowKB = parcel->readInt32();
- mRebufferingWatermarkHighKB = parcel->readInt32();
+ mInitialMarkMs = parcel->readInt32();
+ mResumePlaybackMarkMs = parcel->readInt32();
return OK;
}
@@ -68,26 +41,17 @@
if (parcel == nullptr) {
return BAD_VALUE;
}
- parcel->writeInt32(mInitialBufferingMode);
- parcel->writeInt32(mRebufferingMode);
- parcel->writeInt32(mInitialWatermarkMs);
- parcel->writeInt32(mInitialWatermarkKB);
- parcel->writeInt32(mRebufferingWatermarkLowMs);
- parcel->writeInt32(mRebufferingWatermarkHighMs);
- parcel->writeInt32(mRebufferingWatermarkLowKB);
- parcel->writeInt32(mRebufferingWatermarkHighKB);
+ parcel->writeInt32(mInitialMarkMs);
+ parcel->writeInt32(mResumePlaybackMarkMs);
return OK;
}
String8 BufferingSettings::toString() const {
String8 s;
- s.appendFormat("initialMode(%d), rebufferingMode(%d), "
- "initialMarks(%d ms, %d KB), rebufferingMarks(%d, %d)ms, (%d, %d)KB",
- mInitialBufferingMode, mRebufferingMode,
- mInitialWatermarkMs, mInitialWatermarkKB,
- mRebufferingWatermarkLowMs, mRebufferingWatermarkHighMs,
- mRebufferingWatermarkLowKB, mRebufferingWatermarkHighKB);
+ s.appendFormat(
+ "initialMarks(%d ms), resumePlaybackMarks(%d ms)",
+ mInitialMarkMs, mResumePlaybackMarkMs);
return s;
}
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 3fb1d7a..e2eccdd 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -44,7 +44,7 @@
SET_DATA_SOURCE_STREAM,
SET_DATA_SOURCE_CALLBACK,
SET_BUFFERING_SETTINGS,
- GET_DEFAULT_BUFFERING_SETTINGS,
+ GET_BUFFERING_SETTINGS,
PREPARE_ASYNC,
START,
STOP,
@@ -184,14 +184,14 @@
return reply.readInt32();
}
- status_t getDefaultBufferingSettings(BufferingSettings* buffering /* nonnull */)
+ status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */)
{
if (buffering == nullptr) {
return BAD_VALUE;
}
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
- remote()->transact(GET_DEFAULT_BUFFERING_SETTINGS, data, &reply);
+ remote()->transact(GET_BUFFERING_SETTINGS, data, &reply);
status_t err = reply.readInt32();
if (err == OK) {
err = buffering->readFromParcel(&reply);
@@ -700,10 +700,10 @@
reply->writeInt32(setBufferingSettings(buffering));
return NO_ERROR;
} break;
- case GET_DEFAULT_BUFFERING_SETTINGS: {
+ case GET_BUFFERING_SETTINGS: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
BufferingSettings buffering;
- status_t err = getDefaultBufferingSettings(&buffering);
+ status_t err = getBufferingSettings(&buffering);
reply->writeInt32(err);
if (err == OK) {
buffering.writeToParcel(reply);
diff --git a/media/libmedia/include/media/BufferingSettings.h b/media/libmedia/include/media/BufferingSettings.h
index e812d2a..d2a3e40 100644
--- a/media/libmedia/include/media/BufferingSettings.h
+++ b/media/libmedia/include/media/BufferingSettings.h
@@ -21,45 +21,14 @@
namespace android {
-enum BufferingMode : int {
- // Do not support buffering.
- BUFFERING_MODE_NONE = 0,
- // Support only time based buffering.
- BUFFERING_MODE_TIME_ONLY = 1,
- // Support only size based buffering.
- BUFFERING_MODE_SIZE_ONLY = 2,
- // Support both time and size based buffering, time based calculation precedes size based.
- // Size based calculation will be used only when time information is not available for
- // the stream.
- BUFFERING_MODE_TIME_THEN_SIZE = 3,
- // Number of modes.
- BUFFERING_MODE_COUNT = 4,
-};
-
struct BufferingSettings : public Parcelable {
- static const int kNoWatermark = -1;
+ static const int kNoMark = -1;
- static bool IsValidBufferingMode(int mode);
- static bool IsTimeBasedBufferingMode(int mode);
- static bool IsSizeBasedBufferingMode(int mode);
+ int mInitialMarkMs;
- BufferingMode mInitialBufferingMode; // for prepare
- BufferingMode mRebufferingMode; // for playback
-
- int mInitialWatermarkMs; // time based
- int mInitialWatermarkKB; // size based
-
- // When cached data is below this mark, playback will be paused for buffering
- // till data reach |mRebufferingWatermarkHighMs| or end of stream.
- int mRebufferingWatermarkLowMs;
- // When cached data is above this mark, buffering will be paused.
- int mRebufferingWatermarkHighMs;
-
- // When cached data is below this mark, playback will be paused for buffering
- // till data reach |mRebufferingWatermarkHighKB| or end of stream.
- int mRebufferingWatermarkLowKB;
- // When cached data is above this mark, buffering will be paused.
- int mRebufferingWatermarkHighKB;
+ // When cached data is above this mark, playback will be resumed if it has been paused
+ // due to low cached data.
+ int mResumePlaybackMarkMs;
BufferingSettings();
diff --git a/media/libmedia/include/media/IMediaPlayer.h b/media/libmedia/include/media/IMediaPlayer.h
index 2129222..97a998e 100644
--- a/media/libmedia/include/media/IMediaPlayer.h
+++ b/media/libmedia/include/media/IMediaPlayer.h
@@ -61,7 +61,7 @@
virtual status_t setDataSource(const sp<IDataSource>& source) = 0;
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) = 0;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) = 0;
virtual status_t prepareAsync() = 0;
diff --git a/media/libmedia/include/media/mediaplayer.h b/media/libmedia/include/media/mediaplayer.h
index 6d39ded..dc3b3aa 100644
--- a/media/libmedia/include/media/mediaplayer.h
+++ b/media/libmedia/include/media/mediaplayer.h
@@ -227,7 +227,6 @@
status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer);
status_t setListener(const sp<MediaPlayerListener>& listener);
- status_t getDefaultBufferingSettings(BufferingSettings* buffering /* nonnull */);
status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */);
status_t setBufferingSettings(const BufferingSettings& buffering);
status_t prepare();
@@ -316,7 +315,6 @@
float mSendLevel;
struct sockaddr_in mRetransmitEndpoint;
bool mRetransmitEndpointValid;
- BufferingSettings mCurrentBufferingSettings;
};
}; // namespace android
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index a6cdb13..26908e5 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -139,10 +139,8 @@
mPlayer = player;
if (player != 0) {
mCurrentState = MEDIA_PLAYER_INITIALIZED;
- player->getDefaultBufferingSettings(&mCurrentBufferingSettings);
err = NO_ERROR;
} else {
- mCurrentBufferingSettings = BufferingSettings();
ALOGE("Unable to create media player");
}
}
@@ -249,17 +247,6 @@
return mPlayer->setVideoSurfaceTexture(bufferProducer);
}
-status_t MediaPlayer::getDefaultBufferingSettings(BufferingSettings* buffering /* nonnull */)
-{
- ALOGV("getDefaultBufferingSettings");
-
- Mutex::Autolock _l(mLock);
- if (mPlayer == 0) {
- return NO_INIT;
- }
- return mPlayer->getDefaultBufferingSettings(buffering);
-}
-
status_t MediaPlayer::getBufferingSettings(BufferingSettings* buffering /* nonnull */)
{
ALOGV("getBufferingSettings");
@@ -268,8 +255,7 @@
if (mPlayer == 0) {
return NO_INIT;
}
- *buffering = mCurrentBufferingSettings;
- return NO_ERROR;
+ return mPlayer->getBufferingSettings(buffering);
}
status_t MediaPlayer::setBufferingSettings(const BufferingSettings& buffering)
@@ -280,11 +266,7 @@
if (mPlayer == 0) {
return NO_INIT;
}
- status_t err = mPlayer->setBufferingSettings(buffering);
- if (err == NO_ERROR) {
- mCurrentBufferingSettings = buffering;
- }
- return err;
+ return mPlayer->setBufferingSettings(buffering);
}
// must call with lock held
@@ -636,7 +618,6 @@
// setDataSource has to be called again to create a
// new mediaplayer.
mPlayer = 0;
- mCurrentBufferingSettings = BufferingSettings();
return ret;
}
clear_l();
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 84abfee..6b2c81d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1058,18 +1058,18 @@
return p->setBufferingSettings(buffering);
}
-status_t MediaPlayerService::Client::getDefaultBufferingSettings(
+status_t MediaPlayerService::Client::getBufferingSettings(
BufferingSettings* buffering /* nonnull */)
{
sp<MediaPlayerBase> p = getPlayer();
// TODO: create mPlayer on demand.
if (p == 0) return UNKNOWN_ERROR;
- status_t ret = p->getDefaultBufferingSettings(buffering);
+ status_t ret = p->getBufferingSettings(buffering);
if (ret == NO_ERROR) {
- ALOGV("[%d] getDefaultBufferingSettings{%s}",
+ ALOGV("[%d] getBufferingSettings{%s}",
mConnId, buffering->toString().string());
} else {
- ALOGV("[%d] getDefaultBufferingSettings returned %d", mConnId, ret);
+ ALOGE("[%d] getBufferingSettings returned %d", mConnId, ret);
}
return ret;
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 7f8ec85..71e87a0 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -319,7 +319,7 @@
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer);
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) override;
virtual status_t prepareAsync();
virtual status_t start();
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index 1bd9a88..a03884f 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -185,7 +185,7 @@
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) {
*buffering = BufferingSettings();
return OK;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 94e3395..a3f4efb 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -45,9 +45,10 @@
namespace android {
-static const int kLowWaterMarkMs = 2000; // 2secs
-static const int kHighWaterMarkMs = 5000; // 5secs
-static const int kHighWaterMarkRebufferMs = 15000; // 15secs
+static const int kInitialMarkMs = 5000; // 5secs
+
+//static const int kPausePlaybackMarkMs = 2000; // 2secs
+static const int kResumePlaybackMarkMs = 15000; // 15secs
NuPlayer::GenericSource::GenericSource(
const sp<AMessage> ¬ify,
@@ -79,7 +80,8 @@
ALOGV("GenericSource");
CHECK(mediaClock != NULL);
- getDefaultBufferingSettings(&mBufferingSettings);
+ mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
+ mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs;
resetDataSource();
}
@@ -88,6 +90,7 @@
mHTTPService.clear();
mHttpSource.clear();
+ mDisconnected = false;
mUri.clear();
mUriHeaders.clear();
if (mFd >= 0) {
@@ -159,15 +162,27 @@
status_t NuPlayer::GenericSource::initFromDataSource() {
sp<IMediaExtractor> extractor;
CHECK(mDataSource != NULL);
+ sp<DataSource> dataSource = mDataSource;
- extractor = MediaExtractorFactory::Create(mDataSource, NULL);
+ mLock.unlock();
+ // This might take long time if data source is not reliable.
+ extractor = MediaExtractorFactory::Create(dataSource, NULL);
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
return UNKNOWN_ERROR;
}
- mFileMeta = extractor->getMetaData();
+ sp<MetaData> fileMeta = extractor->getMetaData();
+
+ size_t numtracks = extractor->countTracks();
+ if (numtracks == 0) {
+ ALOGE("initFromDataSource, source has no track!");
+ return UNKNOWN_ERROR;
+ }
+
+ mLock.lock();
+ mFileMeta = fileMeta;
if (mFileMeta != NULL) {
int64_t duration;
if (mFileMeta->findInt64(kKeyDuration, &duration)) {
@@ -177,12 +192,6 @@
int32_t totalBitrate = 0;
- size_t numtracks = extractor->countTracks();
- if (numtracks == 0) {
- ALOGE("initFromDataSource, source has no track!");
- return UNKNOWN_ERROR;
- }
-
mMimes.clear();
for (size_t i = 0; i < numtracks; ++i) {
@@ -265,37 +274,22 @@
return OK;
}
-status_t NuPlayer::GenericSource::getDefaultBufferingSettings(
+status_t NuPlayer::GenericSource::getBufferingSettings(
BufferingSettings* buffering /* nonnull */) {
- buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
- buffering->mRebufferingMode = BUFFERING_MODE_TIME_ONLY;
- buffering->mInitialWatermarkMs = kHighWaterMarkMs;
- buffering->mRebufferingWatermarkLowMs = kLowWaterMarkMs;
- buffering->mRebufferingWatermarkHighMs = kHighWaterMarkRebufferMs;
+ {
+ Mutex::Autolock _l(mLock);
+ *buffering = mBufferingSettings;
+ }
- ALOGV("getDefaultBufferingSettings{%s}", buffering->toString().string());
+ ALOGV("getBufferingSettings{%s}", buffering->toString().string());
return OK;
}
status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
ALOGV("setBufferingSettings{%s}", buffering.toString().string());
- if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
- || buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
- || (buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode)
- && buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs)) {
- return BAD_VALUE;
- }
-
Mutex::Autolock _l(mLock);
mBufferingSettings = buffering;
- if (mBufferingSettings.mInitialBufferingMode == BUFFERING_MODE_NONE) {
- mBufferingSettings.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
- }
- if (mBufferingSettings.mRebufferingMode == BUFFERING_MODE_NONE) {
- mBufferingSettings.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
- mBufferingSettings.mRebufferingWatermarkHighMs = INT32_MAX;
- }
return OK;
}
@@ -391,9 +385,15 @@
}
}
- mDataSource = DataSourceFactory::CreateFromURI(
+ mLock.unlock();
+ // This might take long time if connection has some issue.
+ sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
mHTTPService, uri, &mUriHeaders, &contentType,
static_cast<HTTPBase *>(mHttpSource.get()));
+ mLock.lock();
+ if (!mDisconnected) {
+ mDataSource = dataSource;
+ }
} else {
if (property_get_bool("media.stagefright.extractremote", true) &&
!FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
@@ -555,6 +555,7 @@
Mutex::Autolock _l(mLock);
dataSource = mDataSource;
httpSource = mHttpSource;
+ mDisconnected = true;
}
if (dataSource != NULL) {
@@ -676,6 +677,12 @@
break;
}
+ case kWhatSeek:
+ {
+ onSeek(msg);
+ break;
+ }
+
case kWhatReadBuffer:
{
onReadBuffer(msg);
@@ -853,8 +860,10 @@
}
} else {
int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
+ // TODO: maxRebufferingMarkMs could be larger than
+ // mBufferingSettings.mResumePlaybackMarkMs
int64_t restartBufferingMarkUs =
- mBufferingSettings.mRebufferingWatermarkHighMs * 1000ll / 2;
+ mBufferingSettings.mResumePlaybackMarkMs * 1000ll / 2;
if (finalResult == OK) {
if (durationUs < restartBufferingMarkUs) {
postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
@@ -1094,8 +1103,39 @@
}
status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
- Mutex::Autolock _l(mLock);
ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
+ sp<AMessage> msg = new AMessage(kWhatSeek, this);
+ msg->setInt64("seekTimeUs", seekTimeUs);
+ msg->setInt32("mode", mode);
+
+ // Need to call readBuffer on |mLooper| to ensure the calls to
+ // IMediaSource::read* are serialized. Note that IMediaSource::read*
+ // is called without |mLock| acquired and MediaSource is not thread safe.
+ sp<AMessage> response;
+ status_t err = msg->postAndAwaitResponse(&response);
+ if (err == OK && response != NULL) {
+ CHECK(response->findInt32("err", &err));
+ }
+
+ return err;
+}
+
+void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
+ int64_t seekTimeUs;
+ int32_t mode;
+ CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
+ CHECK(msg->findInt32("mode", &mode));
+
+ sp<AMessage> response = new AMessage;
+ status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
+ response->setInt32("err", err);
+
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+ response->postReply(replyID);
+}
+
+status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
if (mVideoTrack.mSource != NULL) {
++mVideoDataGeneration;
@@ -1318,13 +1358,14 @@
Vector<MediaBuffer *> mediaBuffers;
status_t err = NO_ERROR;
+ sp<IMediaSource> source = track->mSource;
mLock.unlock();
if (couldReadMultiple) {
- err = track->mSource->readMultiple(
+ err = source->readMultiple(
&mediaBuffers, maxBuffers - numBuffers, &options);
} else {
MediaBuffer *mbuf = NULL;
- err = track->mSource->read(&mbuf, &options);
+ err = source->read(&mbuf, &options);
if (err == OK && mbuf != NULL) {
mediaBuffers.push_back(mbuf);
}
@@ -1408,8 +1449,10 @@
status_t finalResult;
int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
- int64_t markUs = (mPreparing ? mBufferingSettings.mInitialWatermarkMs
- : mBufferingSettings.mRebufferingWatermarkHighMs) * 1000ll;
+ // TODO: maxRebufferingMarkMs could be larger than
+ // mBufferingSettings.mResumePlaybackMarkMs
+ int64_t markUs = (mPreparing ? mBufferingSettings.mInitialMarkMs
+ : mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
if (mPreparing || mSentPauseOnBuffering) {
Track *counterTrack =
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index f4debc1..cb9c27f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -54,7 +54,7 @@
status_t setDataSource(const sp<DataSource>& dataSource);
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
@@ -112,6 +112,7 @@
kWhatSendTimedTextData,
kWhatChangeAVSource,
kWhatPollBuffering,
+ kWhatSeek,
kWhatReadBuffer,
kWhatStart,
kWhatResume,
@@ -158,6 +159,7 @@
int64_t mOffset;
int64_t mLength;
+ bool mDisconnected;
sp<DataSource> mDataSource;
sp<NuCachedSource2> mCachedSource;
sp<DataSource> mHttpSource;
@@ -182,6 +184,9 @@
void finishPrepareAsync();
status_t startSources();
+ void onSeek(const sp<AMessage>& msg);
+ status_t doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode);
+
void onPrepareAsync();
void fetchTextData(
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index ad4c223..11f1bfd 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -35,7 +35,6 @@
// default buffer prepare/ready/underflow marks
static const int kReadyMarkMs = 5000; // 5 seconds
static const int kPrepareMarkMs = 1500; // 1.5 seconds
-static const int kUnderflowMarkMs = 1000; // 1 second
namespace android {
@@ -54,7 +53,8 @@
mFetchMetaDataGeneration(0),
mHasMetadata(false),
mMetadataSelected(false) {
- getDefaultBufferingSettings(&mBufferingSettings);
+ mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
+ mBufferingSettings.mResumePlaybackMarkMs = kReadyMarkMs;
if (headers) {
mExtraHeaders = *headers;
@@ -82,35 +82,16 @@
}
}
-status_t NuPlayer::HTTPLiveSource::getDefaultBufferingSettings(
+status_t NuPlayer::HTTPLiveSource::getBufferingSettings(
BufferingSettings* buffering /* nonnull */) {
- buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
- buffering->mRebufferingMode = BUFFERING_MODE_TIME_ONLY;
- buffering->mInitialWatermarkMs = kPrepareMarkMs;
- buffering->mRebufferingWatermarkLowMs = kUnderflowMarkMs;
- buffering->mRebufferingWatermarkHighMs = kReadyMarkMs;
+ *buffering = mBufferingSettings;
return OK;
}
status_t NuPlayer::HTTPLiveSource::setBufferingSettings(const BufferingSettings& buffering) {
- if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
- || buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
- || (buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode)
- && buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs)) {
- return BAD_VALUE;
- }
-
mBufferingSettings = buffering;
- if (mBufferingSettings.mInitialBufferingMode == BUFFERING_MODE_NONE) {
- mBufferingSettings.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
- }
- if (mBufferingSettings.mRebufferingMode == BUFFERING_MODE_NONE) {
- mBufferingSettings.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
- mBufferingSettings.mRebufferingWatermarkHighMs = INT32_MAX;
- }
-
if (mLiveSession != NULL) {
mLiveSession->setBufferingSettings(mBufferingSettings);
}
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 2866a6a..2d6c604 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -34,7 +34,7 @@
const char *url,
const KeyedVector<String8, String8> *headers);
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 2aa5c40..6c4b823 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -182,6 +182,7 @@
mAudioDecoderGeneration(0),
mVideoDecoderGeneration(0),
mRendererGeneration(0),
+ mLastStartedPlayingTimeNs(0),
mPreviousSeekTimeUs(0),
mAudioEOS(false),
mVideoEOS(false),
@@ -338,9 +339,9 @@
mDataSourceType = DATA_SOURCE_TYPE_MEDIA;
}
-status_t NuPlayer::getDefaultBufferingSettings(
+status_t NuPlayer::getBufferingSettings(
BufferingSettings *buffering /* nonnull */) {
- sp<AMessage> msg = new AMessage(kWhatGetDefaultBufferingSettings, this);
+ sp<AMessage> msg = new AMessage(kWhatGetBufferingSettings, this);
sp<AMessage> response;
status_t err = msg->postAndAwaitResponse(&response);
if (err == OK && response != NULL) {
@@ -566,16 +567,16 @@
break;
}
- case kWhatGetDefaultBufferingSettings:
+ case kWhatGetBufferingSettings:
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- ALOGV("kWhatGetDefaultBufferingSettings");
+ ALOGV("kWhatGetBufferingSettings");
BufferingSettings buffering;
status_t err = OK;
if (mSource != NULL) {
- err = mSource->getDefaultBufferingSettings(&buffering);
+ err = mSource->getBufferingSettings(&buffering);
} else {
err = INVALID_OPERATION;
}
@@ -1309,6 +1310,7 @@
ALOGV("kWhatReset");
mResetting = true;
+ stopPlaybackTimer("kWhatReset");
mDeferredActions.push_back(
new FlushDecoderAction(
@@ -1449,7 +1451,7 @@
ALOGW("resume called when renderer is gone or not set");
}
- mLastStartedPlayingTimeNs = systemTime();
+ startPlaybackTimer("onresume");
}
status_t NuPlayer::onInstantiateSecureDecoders() {
@@ -1569,12 +1571,43 @@
mAudioDecoder->setRenderer(mRenderer);
}
- mLastStartedPlayingTimeNs = systemTime();
+ startPlaybackTimer("onstart");
postScanSources();
}
+void NuPlayer::startPlaybackTimer(const char *where) {
+ Mutex::Autolock autoLock(mPlayingTimeLock);
+ if (mLastStartedPlayingTimeNs == 0) {
+ mLastStartedPlayingTimeNs = systemTime();
+ ALOGV("startPlaybackTimer() time %20" PRId64 " (%s)", mLastStartedPlayingTimeNs, where);
+ }
+}
+
+void NuPlayer::stopPlaybackTimer(const char *where) {
+ Mutex::Autolock autoLock(mPlayingTimeLock);
+
+ ALOGV("stopPlaybackTimer() time %20" PRId64 " (%s)", mLastStartedPlayingTimeNs, where);
+
+ if (mLastStartedPlayingTimeNs != 0) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ int64_t now = systemTime();
+ int64_t played = now - mLastStartedPlayingTimeNs;
+ ALOGV("stopPlaybackTimer() log %20" PRId64 "", played);
+
+ if (played > 0) {
+ driver->notifyMorePlayingTimeUs((played+500)/1000);
+ }
+ }
+ mLastStartedPlayingTimeNs = 0;
+ }
+}
+
void NuPlayer::onPause() {
+
+ stopPlaybackTimer("onPause");
+
if (mPaused) {
return;
}
@@ -1590,13 +1623,6 @@
ALOGW("pause called when renderer is gone or not set");
}
- sp<NuPlayerDriver> driver = mDriver.promote();
- if (driver != NULL) {
- int64_t now = systemTime();
- int64_t played = now - mLastStartedPlayingTimeNs;
-
- driver->notifyMorePlayingTimeUs((played+500)/1000);
- }
}
bool NuPlayer::audioDecoderStillNeeded() {
@@ -2223,6 +2249,8 @@
CHECK(mAudioDecoder == NULL);
CHECK(mVideoDecoder == NULL);
+ stopPlaybackTimer("performReset");
+
cancelPollDuration();
++mScanSourcesGeneration;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index eefc2a6..492b8d4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -52,7 +52,7 @@
void setDataSourceAsync(const sp<DataSource> &source);
- status_t getDefaultBufferingSettings(BufferingSettings* buffering /* nonnull */);
+ status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */);
status_t setBufferingSettings(const BufferingSettings& buffering);
void prepareAsync();
@@ -152,7 +152,7 @@
kWhatGetTrackInfo = 'gTrI',
kWhatGetSelectedTrack = 'gSel',
kWhatSelectTrack = 'selT',
- kWhatGetDefaultBufferingSettings = 'gDBS',
+ kWhatGetBufferingSettings = 'gBus',
kWhatSetBufferingSettings = 'sBuS',
kWhatPrepareDrm = 'pDrm',
kWhatReleaseDrm = 'rDrm',
@@ -178,7 +178,10 @@
int32_t mVideoDecoderGeneration;
int32_t mRendererGeneration;
+ Mutex mPlayingTimeLock;
int64_t mLastStartedPlayingTimeNs;
+ void stopPlaybackTimer(const char *where);
+ void startPlaybackTimer(const char *where);
int64_t mPreviousSeekTimeUs;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 6d51905..bd54df0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -231,8 +231,8 @@
return OK;
}
-status_t NuPlayerDriver::getDefaultBufferingSettings(BufferingSettings* buffering) {
- ALOGV("getDefaultBufferingSettings(%p)", this);
+status_t NuPlayerDriver::getBufferingSettings(BufferingSettings* buffering) {
+ ALOGV("getBufferingSettings(%p)", this);
{
Mutex::Autolock autoLock(mLock);
if (mState == STATE_IDLE) {
@@ -240,7 +240,7 @@
}
}
- return mPlayer->getDefaultBufferingSettings(buffering);
+ return mPlayer->getBufferingSettings(buffering);
}
status_t NuPlayerDriver::setBufferingSettings(const BufferingSettings& buffering) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 666359a..6ca6344 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -46,7 +46,7 @@
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer> &bufferProducer);
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 8ba9c0d..2df5e88 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -66,7 +66,7 @@
: mNotify(notify) {
}
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) = 0;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) = 0;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 8b3d0dc..851217b 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -62,7 +62,8 @@
mSeekGeneration(0),
mEOSTimeoutAudio(0),
mEOSTimeoutVideo(0) {
- getDefaultBufferingSettings(&mBufferingSettings);
+ mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
+ mBufferingSettings.mResumePlaybackMarkMs = kOverflowMarkMs;
if (headers) {
mExtraHeaders = *headers;
@@ -84,32 +85,17 @@
}
}
-status_t NuPlayer::RTSPSource::getDefaultBufferingSettings(
+status_t NuPlayer::RTSPSource::getBufferingSettings(
BufferingSettings* buffering /* nonnull */) {
- buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
- buffering->mRebufferingMode = BUFFERING_MODE_TIME_ONLY;
- buffering->mInitialWatermarkMs = kPrepareMarkMs;
- buffering->mRebufferingWatermarkLowMs = kUnderflowMarkMs;
- buffering->mRebufferingWatermarkHighMs = kOverflowMarkMs;
-
+ Mutex::Autolock _l(mBufferingSettingsLock);
+ *buffering = mBufferingSettings;
return OK;
}
status_t NuPlayer::RTSPSource::setBufferingSettings(const BufferingSettings& buffering) {
- if (mLooper == NULL) {
- mBufferingSettings = buffering;
- return OK;
- }
-
- sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this);
- writeToAMessage(msg, buffering);
- sp<AMessage> response;
- status_t err = msg->postAndAwaitResponse(&response);
- if (err == OK && response != NULL) {
- CHECK(response->findInt32("err", &err));
- }
-
- return err;
+ Mutex::Autolock _l(mBufferingSettingsLock);
+ mBufferingSettings = buffering;
+ return OK;
}
void NuPlayer::RTSPSource::prepareAsync() {
@@ -356,8 +342,17 @@
}
int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
+ int64_t initialMarkUs;
+ int64_t maxRebufferingMarkUs;
+ {
+ Mutex::Autolock _l(mBufferingSettingsLock);
+ initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000ll;
+ // TODO: maxRebufferingMarkUs could be larger than
+ // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
+ maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000ll;
+ }
// isFinished when duration is 0 checks for EOS result only
- if (bufferedDurationUs > mBufferingSettings.mInitialWatermarkMs * 1000
+ if (bufferedDurationUs > initialMarkUs
|| src->isFinished(/* duration */ 0)) {
++preparedCount;
}
@@ -366,15 +361,15 @@
++overflowCount;
++finishedCount;
} else {
- if (bufferedDurationUs < mBufferingSettings.mRebufferingWatermarkLowMs * 1000) {
+ // TODO: redefine kUnderflowMarkMs to a fair value,
+ if (bufferedDurationUs < kUnderflowMarkMs * 1000) {
++underflowCount;
}
- if (bufferedDurationUs > mBufferingSettings.mRebufferingWatermarkHighMs * 1000) {
+ if (bufferedDurationUs > maxRebufferingMarkUs) {
++overflowCount;
}
int64_t startServerMarkUs =
- (mBufferingSettings.mRebufferingWatermarkLowMs
- + mBufferingSettings.mRebufferingWatermarkHighMs) / 2 * 1000ll;
+ (kUnderflowMarkMs * 1000ll + maxRebufferingMarkUs) / 2;
if (bufferedDurationUs < startServerMarkUs) {
++startCount;
}
@@ -512,36 +507,6 @@
} else if (msg->what() == kWhatSignalEOS) {
onSignalEOS(msg);
return;
- } else if (msg->what() == kWhatSetBufferingSettings) {
- sp<AReplyToken> replyID;
- CHECK(msg->senderAwaitsResponse(&replyID));
-
- BufferingSettings buffering;
- readFromAMessage(msg, &buffering);
-
- status_t err = OK;
- if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
- || buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
- || (buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs
- && buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode))) {
- err = BAD_VALUE;
- } else {
- if (buffering.mInitialBufferingMode == BUFFERING_MODE_NONE) {
- buffering.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
- }
- if (buffering.mRebufferingMode == BUFFERING_MODE_NONE) {
- buffering.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
- buffering.mRebufferingWatermarkHighMs = INT32_MAX;
- }
-
- mBufferingSettings = buffering;
- }
-
- sp<AMessage> response = new AMessage;
- response->setInt32("err", err);
- response->postReply(replyID);
-
- return;
}
CHECK_EQ(msg->what(), kWhatNotify);
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 0812991..03fce08 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -40,7 +40,7 @@
uid_t uid = 0,
bool isSDP = false);
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
@@ -71,7 +71,6 @@
kWhatPerformSeek = 'seek',
kWhatPollBuffering = 'poll',
kWhatSignalEOS = 'eos ',
- kWhatSetBufferingSettings = 'sBuS',
};
enum State {
@@ -109,6 +108,8 @@
bool mBuffering;
bool mInPreparationPhase;
bool mEOSPending;
+
+ Mutex mBufferingSettingsLock;
BufferingSettings mBufferingSettings;
sp<ALooper> mLooper;
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 36abcdd..388ca20 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -51,19 +51,14 @@
}
}
-status_t NuPlayer::StreamingSource::getDefaultBufferingSettings(
+status_t NuPlayer::StreamingSource::getBufferingSettings(
BufferingSettings *buffering /* nonnull */) {
*buffering = BufferingSettings();
return OK;
}
status_t NuPlayer::StreamingSource::setBufferingSettings(
- const BufferingSettings &buffering) {
- if (buffering.mInitialBufferingMode != BUFFERING_MODE_NONE
- || buffering.mRebufferingMode != BUFFERING_MODE_NONE) {
- return BAD_VALUE;
- }
-
+ const BufferingSettings & /* buffering */) {
return OK;
}
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
index 2e1d2b3..76d1d0b 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.h
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h
@@ -32,7 +32,7 @@
const sp<AMessage> ¬ify,
const sp<IStreamSource> &source);
- virtual status_t getDefaultBufferingSettings(
+ virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 6e77f15..68bbd18 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1790,41 +1790,17 @@
}
void writeToAMessage(const sp<AMessage> &msg, const BufferingSettings &buffering) {
- msg->setInt32("init-mode", buffering.mInitialBufferingMode);
- msg->setInt32("rebuffer-mode", buffering.mRebufferingMode);
- msg->setInt32("init-ms", buffering.mInitialWatermarkMs);
- msg->setInt32("init-kb", buffering.mInitialWatermarkKB);
- msg->setInt32("rebuffer-low-ms", buffering.mRebufferingWatermarkLowMs);
- msg->setInt32("rebuffer-high-ms", buffering.mRebufferingWatermarkHighMs);
- msg->setInt32("rebuffer-low-kb", buffering.mRebufferingWatermarkLowKB);
- msg->setInt32("rebuffer-high-kb", buffering.mRebufferingWatermarkHighKB);
+ msg->setInt32("init-ms", buffering.mInitialMarkMs);
+ msg->setInt32("resume-playback-ms", buffering.mResumePlaybackMarkMs);
}
void readFromAMessage(const sp<AMessage> &msg, BufferingSettings *buffering /* nonnull */) {
int32_t value;
- if (msg->findInt32("init-mode", &value)) {
- buffering->mInitialBufferingMode = (BufferingMode)value;
- }
- if (msg->findInt32("rebuffer-mode", &value)) {
- buffering->mRebufferingMode = (BufferingMode)value;
- }
if (msg->findInt32("init-ms", &value)) {
- buffering->mInitialWatermarkMs = value;
+ buffering->mInitialMarkMs = value;
}
- if (msg->findInt32("init-kb", &value)) {
- buffering->mInitialWatermarkKB = value;
- }
- if (msg->findInt32("rebuffer-low-ms", &value)) {
- buffering->mRebufferingWatermarkLowMs = value;
- }
- if (msg->findInt32("rebuffer-high-ms", &value)) {
- buffering->mRebufferingWatermarkHighMs = value;
- }
- if (msg->findInt32("rebuffer-low-kb", &value)) {
- buffering->mRebufferingWatermarkLowKB = value;
- }
- if (msg->findInt32("rebuffer-high-kb", &value)) {
- buffering->mRebufferingWatermarkHighKB = value;
+ if (msg->findInt32("resume-playback-ms", &value)) {
+ buffering->mResumePlaybackMarkMs = value;
}
}
diff --git a/media/libstagefright/codec2/include/C2.h b/media/libstagefright/codec2/include/C2.h
index 7d00a03..bd563ff 100644
--- a/media/libstagefright/codec2/include/C2.h
+++ b/media/libstagefright/codec2/include/C2.h
@@ -66,8 +66,8 @@
* mitigate binary breaks by adhering to the following conventions:
*
* - at most one vtable with placeholder virtual methods
- * - all optional/placeholder virtual methods returning a status_t, with C2_NOT_IMPLEMENTED not
- * requiring any update to input/output arguments.
+ * - all optional/placeholder virtual methods returning a C2Status, with C2_OMITTED not requiring
+ * any update to input/output arguments.
* - limiting symbol export of inline methods
* - use of pimpl (or shared-pimpl)
*
@@ -98,49 +98,62 @@
* C2String: basic string implementation
*/
typedef std::string C2String;
+
+/**
+ * C2StringLiteral: basic string literal implementation.
+ * \note these are never owned by any object, and can only refer to C string literals.
+ */
typedef const char *C2StringLiteral;
/**
- * C2Error: status codes used.
+ * C2Status: status codes used.
*/
-typedef int32_t C2Error;
-enum {
+enum C2Status : int32_t {
+
+/*
+ * Use android status constants if available. Otherwise, define the android status constants as
+ * additional enum values using POSIX errno constants.
+ */
#ifndef __ANDROID__
- OK = 0,
+ ALREADY_EXISTS = -EEXIST,
BAD_VALUE = -EINVAL,
BAD_INDEX = -EOVERFLOW,
- UNKNOWN_TRANSACTION = -EBADMSG,
- ALREADY_EXISTS = -EEXIST,
- NAME_NOT_FOUND = -ENOENT,
+ FAILED_TRANSACTION = -ENOTSUP,
INVALID_OPERATION = -ENOSYS,
+ NAME_NOT_FOUND = -ENOENT,
NO_MEMORY = -ENOMEM,
+ NO_INIT = -ENODEV,
+ OK = 0,
PERMISSION_DENIED = -EPERM,
TIMED_OUT = -ETIMEDOUT,
- UNKNOWN_ERROR = -EINVAL,
+ UNKNOWN_ERROR = -EFAULT,
+ UNKNOWN_TRANSACTION = -EBADMSG,
#endif
- C2_OK = OK, ///< operation completed successfully
+ C2_OK = OK, ///< operation completed successfully
// bad input
- C2_BAD_VALUE = BAD_VALUE, ///< argument has invalid value (user error)
- C2_BAD_INDEX = BAD_INDEX, ///< argument uses invalid index (user error)
- C2_UNSUPPORTED = UNKNOWN_TRANSACTION, ///< argument/index is value but not supported \todo is this really BAD_INDEX/VALUE?
+ C2_BAD_VALUE = BAD_VALUE, ///< argument has invalid value (user error)
+ C2_BAD_INDEX = BAD_INDEX, ///< argument uses invalid index (user error)
+ C2_CANNOT_DO = FAILED_TRANSACTION, ///< argument/index is valid but not possible
// bad sequencing of events
- C2_DUPLICATE = ALREADY_EXISTS, ///< object already exists
- C2_NOT_FOUND = NAME_NOT_FOUND, ///< object not found
- C2_BAD_STATE = INVALID_OPERATION, ///< operation is not permitted in the current state
+ C2_DUPLICATE = ALREADY_EXISTS, ///< object already exists
+ C2_NOT_FOUND = NAME_NOT_FOUND, ///< object not found
+ C2_BAD_STATE = INVALID_OPERATION, ///< operation is not permitted in the current state
// bad environment
- C2_NO_MEMORY = NO_MEMORY, ///< not enough memory to complete operation
- C2_NO_PERMISSION = PERMISSION_DENIED, ///< missing permission to complete operation
- C2_TIMED_OUT = TIMED_OUT, ///< operation did not complete within timeout
+ C2_NO_MEMORY = NO_MEMORY, ///< not enough memory to complete operation
+ C2_REFUSED = PERMISSION_DENIED, ///< missing permission to complete operation
+
+ C2_TIMED_OUT = TIMED_OUT, ///< operation did not complete within timeout
// bad versioning
- C2_NOT_IMPLEMENTED = UNKNOWN_TRANSACTION, ///< operation is not implemented (optional only) \todo for now reuse error code
+ C2_OMITTED = UNKNOWN_TRANSACTION, ///< operation is not implemented/supported (optional only)
// unknown fatal
- C2_CORRUPTED = UNKNOWN_ERROR, ///< some unexpected error prevented the operation
+ C2_CORRUPTED = UNKNOWN_ERROR, ///< some unexpected error prevented the operation
+ C2_NO_INIT = NO_INIT, ///< status has not been initialized
};
/// @}
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 9580449..cb8c2d2 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -88,10 +88,10 @@
* \retval C2_TIMED_OUT the fence has not been signaled within the timeout
* \retval C2_BAD_STATE the fence has been abandoned without being signaled (it will never
* be signaled)
- * \retval C2_NO_PERMISSION no permission to wait for the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to wait for the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented waiting for the fence (unexpected)
*/
- C2Error wait(nsecs_t timeoutNs);
+ C2Status wait(nsecs_t timeoutNs);
/**
* Used to check if this fence is valid (if there is a chance for it to be signaled.)
@@ -155,10 +155,10 @@
* \retval C2_OK the fence(s) were successfully signaled
* \retval C2_BAD_STATE the fence(s) have already been abandoned or merged (caller error)
* \retval C2_DUPLICATE the fence(s) have already been signaled (caller error)
- * \retval C2_NO_PERMISSION no permission to signal the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to signal the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
*/
- C2Error fire();
+ C2Status fire();
/**
* Trigger this event from the merging of the supplied fences. This means that it will be
@@ -169,10 +169,10 @@
* \retval C2_NO_MEMORY not enough memory to perform the merging
* \retval C2_DUPLICATE the fence have already been merged (caller error)
* \retval C2_BAD_STATE the fence have already been signaled or abandoned (caller error)
- * \retval C2_NO_PERMISSION no permission to merge the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to merge the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented merging the fence(s) (unexpected)
*/
- C2Error merge(std::vector<C2Fence> fences);
+ C2Status merge(std::vector<C2Fence> fences);
/**
* Abandons the event and any associated fence(s).
@@ -183,10 +183,10 @@
* \retval C2_OK the fence(s) were successfully signaled
* \retval C2_BAD_STATE the fence(s) have already been signaled or merged (caller error)
* \retval C2_DUPLICATE the fence(s) have already been abandoned (caller error)
- * \retval C2_NO_PERMISSION no permission to abandon the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to abandon the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
*/
- C2Error abandon();
+ C2Status abandon();
private:
class Impl;
@@ -197,15 +197,15 @@
/// @{
/**
- * Interface for objects that encapsulate an updatable error value.
+ * Interface for objects that encapsulate an updatable status value.
*/
-struct _C2InnateError {
- inline C2Error error() const { return mError; }
+struct _C2InnateStatus {
+ inline C2Status status() const { return mStatus; }
protected:
- _C2InnateError(C2Error error) : mError(error) { }
+ _C2InnateStatus(C2Status status) : mStatus(status) { }
- C2Error mError; // this error is updatable by the object
+ C2Status mStatus; // this status is updatable by the object
};
/// @}
@@ -230,10 +230,10 @@
}
protected:
- C2Acquirable(C2Error error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
+ C2Acquirable(C2Status error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
private:
- C2Error mInitialError;
+ C2Status mInitialError;
T mT; // TODO: move instead of copy
};
@@ -449,11 +449,11 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Error error();
+ C2Status error() const;
protected:
C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
- explicit C2ReadView(C2Error error);
+ explicit C2ReadView(C2Status error);
private:
class Impl;
@@ -482,11 +482,11 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Error error();
+ C2Status error() const;
protected:
C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
- explicit C2WriteView(C2Error error);
+ explicit C2WriteView(C2Status 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)
*/
- C2Error reserve(size_t size, C2Fence *fence /* nullable */);
+ C2Status 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)
*/
- C2Error abandon(size_t size);
+ C2Status 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)
*/
- C2Error share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
+ C2Status 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.
*/
- C2Error error();
+ C2Status 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)
*/
- C2Error commit(size_t size, C2Fence fence);
+ C2Status 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.
*/
- C2Error error() const;
+ C2Status error() const;
protected:
C2GraphicView(
const _C2PlanarCapacityAspect *parent,
uint8_t *const *data,
const C2PlaneLayout& layout);
- explicit C2GraphicView(C2Error error);
+ explicit C2GraphicView(C2Status 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)
*/
- C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+ C2Status 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)
*/
- C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+ C2Status 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).
*/
- C2Error setInfo(const std::shared_ptr<C2Info> &info);
+ C2Status setInfo(const std::shared_ptr<C2Info> &info);
/**
* Checks if there is a certain type of metadata attached to this buffer.
@@ -1377,7 +1377,7 @@
* \todo Do we need to support sync operation as we could just wait for the fence?
*
* \retval C2_OK the operation was successful
- * \retval C2_NO_PERMISSION no permission to map the portion
+ * \retval C2_REFUSED no permission to map the portion
* \retval C2_TIMED_OUT the operation timed out
* \retval C2_DUPLICATE if the allocation is already mapped.
* \retval C2_NO_MEMORY not enough memory to complete the operation
@@ -1385,7 +1385,7 @@
* the usage flags are invalid (caller error)
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
*/
- virtual C2Error map(
+ virtual C2Status map(
size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
void **addr /* nonnull */) = 0;
@@ -1407,9 +1407,9 @@
* \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped
* regions (caller error)
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
- * \retval C2_NO_PERMISSION no permission to unmap the portion (unexpected - system)
+ * \retval C2_REFUSED no permission to unmap the portion (unexpected - system)
*/
- virtual C2Error unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
+ virtual C2Status unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
/**
* Returns true if this is a valid allocation.
@@ -1463,7 +1463,7 @@
* \todo Do we need to support sync operation as we could just wait for the fence?
*
* \retval C2_OK the operation was successful
- * \retval C2_NO_PERMISSION no permission to map the section
+ * \retval C2_REFUSED no permission to map the section
* \retval C2_DUPLICATE there is already a mapped region (caller error)
* \retval C2_TIMED_OUT the operation timed out
* \retval C2_NO_MEMORY not enough memory to complete the operation
@@ -1472,7 +1472,7 @@
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
*/
- virtual C2Error map(
+ virtual C2Status map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
// TODO: return <addr, size> buffers with plane sizes
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
@@ -1490,9 +1490,9 @@
* \retval C2_TIMED_OUT the operation timed out
* \retval C2_NOT_FOUND there is no mapped region (caller error)
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
- * \retval C2_NO_PERMISSION no permission to unmap the section (unexpected - system)
+ * \retval C2_REFUSED no permission to unmap the section (unexpected - system)
*/
- virtual C2Error unmap(C2Fence *fenceFd /* nullable */) = 0;
+ virtual C2Status unmap(C2Fence *fenceFd /* nullable */) = 0;
/**
* Returns true if this is a valid allocation.
@@ -1545,16 +1545,16 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
+ * \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateLinearBuffer(
+ virtual C2Status allocateLinearBuffer(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1568,16 +1568,16 @@
* \retval C2_OK the allocation was recreated successfully
* \retval C2_NO_MEMORY not enough memory to recreate the allocation
* \retval C2_TIMED_OUT the recreation timed out (unexpected)
- * \retval C2_NO_PERMISSION no permission to recreate the allocation
+ * \retval C2_REFUSED no permission to recreate the allocation
* \retval C2_BAD_VALUE invalid handle (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
+ * \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error recreateLinearBuffer(
+ virtual C2Status recreateLinearBuffer(
const C2Handle *handle __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1601,17 +1601,17 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 2D allocations
+ * \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateGraphicBuffer(
+ virtual C2Status allocateGraphicBuffer(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1625,16 +1625,16 @@
* \retval C2_OK the allocation was recreated successfully
* \retval C2_NO_MEMORY not enough memory to recreate the allocation
* \retval C2_TIMED_OUT the recreation timed out (unexpected)
- * \retval C2_NO_PERMISSION no permission to recreate the allocation
+ * \retval C2_REFUSED no permission to recreate the allocation
* \retval C2_BAD_VALUE invalid handle (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 2D allocations
+ * \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
*/
- virtual C2Error recreateGraphicBuffer(
+ virtual C2Status recreateGraphicBuffer(
const C2Handle *handle __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
protected:
@@ -1669,16 +1669,16 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support linear allocations
+ * \retval C2_OMITTED this allocator does not support linear allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateLinearBlock(
+ virtual C2Status allocateLinearBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
*block = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1698,16 +1698,16 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support circular allocations
+ * \retval C2_OMITTED this allocator does not support circular allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateCircularBlock(
+ virtual C2Status allocateCircularBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
*block = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1731,17 +1731,17 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 2D allocations
+ * \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateGraphicBlock(
+ virtual C2Status allocateGraphicBlock(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
*block = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
protected:
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index a9b1702..2ac9c72 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -55,6 +55,31 @@
virtual ~C2ComponentListener() = default;
};
+struct C2FieldSupportedValuesQuery {
+ enum Type : uint32_t {
+ POSSIBLE, ///< query all possible values regardless of other settings
+ CURRENT, ///< query currently possible values given dependent settings
+ };
+
+ const C2ParamField field;
+ const Type type;
+ C2Status status;
+ C2FieldSupportedValues values;
+
+ C2FieldSupportedValuesQuery(const C2ParamField &field_, Type type_)
+ : field(field_), type(type_), status(C2_NO_INIT) { }
+
+ static C2FieldSupportedValuesQuery&&
+ Current(const C2ParamField &field_) {
+ return std::move(C2FieldSupportedValuesQuery(field_, CURRENT));
+ }
+
+ static C2FieldSupportedValuesQuery&&
+ Possible(const C2ParamField &field_) {
+ return std::move(C2FieldSupportedValuesQuery(field_, POSSIBLE));
+ }
+};
+
/**
* Component interface object. This object contains all of the configuration of a potential or
* actual component. It can be created and used independently of an actual C2Component instance to
@@ -129,7 +154,7 @@
* \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
* (unexpected)
*/
- virtual status_t query_nb(
+ virtual C2Status query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -166,7 +191,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
@@ -205,7 +230,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual status_t commit_sm(
+ virtual C2Status commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
@@ -225,12 +250,13 @@
* \retval C2_OK the tunnel was successfully created
* \retval C2_BAD_INDEX the target component does not exist
* \retval C2_DUPLICATE the tunnel already exists
- * \retval C2_UNSUPPORTED the tunnel is not supported
+ * \retval C2_OMITTED tunneling is not supported by this component
+ * \retval C2_CANNOT_DO the specific tunnel is not supported
*
* \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 status_t createTunnel_sm(node_id targetComponent) = 0;
+ virtual C2Status createTunnel_sm(node_id targetComponent) = 0;
/**
* Releases a tunnel from this component to the target component.
@@ -246,11 +272,12 @@
* \retval C2_OK the tunnel was marked for release successfully
* \retval C2_BAD_INDEX the target component does not exist
* \retval C2_NOT_FOUND the tunnel does not exist
+ * \retval C2_OMITTED tunneling is not supported by this component
*
* \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 status_t releaseTunnel_sm(node_id targetComponent) = 0;
+ virtual C2Status releaseTunnel_sm(node_id targetComponent) = 0;
// REFLECTION MECHANISM (USED FOR EXTENSION)
@@ -273,7 +300,7 @@
* \retval C2_OK the operation completed successfully.
* \retval C2_NO_MEMORY not enough memory to complete this method.
*/
- virtual status_t getSupportedParams(
+ virtual C2Status getSupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
/**
@@ -281,9 +308,8 @@
* \todo should this take a list considering that setting some fields may further limit other
* fields in the same list?
*/
- virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const = 0;
+ virtual C2Status getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
virtual ~C2ComponentInterface() = default;
};
@@ -305,12 +331,12 @@
*
* \retval C2_OK the work was successfully queued
* \retval C2_BAD_INDEX some component(s) in the work do(es) not exist
- * \retval C2_UNSUPPORTED the components are not tunneled
+ * \retval C2_CANNOT_DO the components are not tunneled
*
* \retval C2_NO_MEMORY not enough memory to queue the work
* \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
*/
- virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
+ virtual C2Status 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
@@ -322,14 +348,14 @@
*
* \retval C2_OK the work announcement has been successfully recorded
* \retval C2_BAD_INDEX some component(s) in the work outline do(es) not exist
- * \retval C2_UNSUPPORTED the componentes are not tunneled
+ * \retval C2_CANNOT_DO the componentes are not tunneled
*
* \retval C2_NO_MEMORY not enough memory to record the work announcement
* \retval C2_CORRUPTED some unknown error prevented recording the announcement (unexpected)
*
* \todo Can this be rolled into queue_nb?
*/
- virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+ virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) = 0;
/**
* Discards and abandons any pending work for the component, and optionally any component
@@ -361,7 +387,7 @@
* \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 status_t flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+ virtual C2Status flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
/**
* Drains the component, and optionally downstream components
@@ -390,7 +416,7 @@
* \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 status_t drain_nb(bool drainThrough) = 0;
+ virtual C2Status drain_nb(bool drainThrough) = 0;
// STATE CHANGE METHODS
// =============================================================================================
@@ -411,7 +437,7 @@
* \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 status_t start() = 0;
+ virtual C2Status start() = 0;
/**
* Stops the component.
@@ -428,7 +454,7 @@
* 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 status_t stop() = 0;
+ virtual C2Status stop() = 0;
/**
* Resets the component.
@@ -502,9 +528,9 @@
* \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 status_t reset() { return C2_OK; }
+ virtual C2Status reset() { return C2_OK; }
- virtual status_t parseFrame(C2BufferPack &frame);
+ virtual C2Status parseFrame(C2BufferPack &frame);
virtual ~C2FrameInfoParser() = default;
};
@@ -542,7 +568,7 @@
* \retval C2_NOT_FOUND no such allocator
* \retval C2_NO_MEMORY not enough memory to create the allocator
*/
- virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+ virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
virtual ~C2AllocatorStore() = default;
};
@@ -565,7 +591,7 @@
* \retval C2_NOT_FOUND no such component
* \retval C2_NO_MEMORY not enough memory to create the component
*/
- virtual status_t createComponent(C2String name, std::shared_ptr<C2Component>* const component);
+ virtual C2Status createComponent(C2String name, std::shared_ptr<C2Component>* const component);
/**
* Creates a component interface.
@@ -586,7 +612,7 @@
*
* \todo Do we need an interface, or could this just be a component that is never started?
*/
- virtual status_t createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
+ virtual C2Status createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
/**
* Returns the list of components supported by this component store.
@@ -600,9 +626,9 @@
// -------------------------------------- UTILITY METHODS --------------------------------------
// on-demand buffer layout conversion (swizzling)
- virtual status_t copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
+ virtual C2Status copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
- // status_t selectPreferredColor(formats<A>, formats<B>);
+ // C2Status selectPreferredColor(formats<A>, formats<B>);
// GLOBAL SETTINGS
// system-wide stride & slice-height (???)
@@ -636,7 +662,7 @@
* \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
* (unexpected)
*/
- virtual status_t query_sm(
+ virtual C2Status query_sm(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -675,7 +701,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::list<std::unique_ptr<C2SettingResult>>* const failures) = 0;
diff --git a/media/libstagefright/codec2/include/C2Config.h b/media/libstagefright/codec2/include/C2Config.h
index b1ac8bc..d4294c4 100644
--- a/media/libstagefright/codec2/include/C2Config.h
+++ b/media/libstagefright/codec2/include/C2Config.h
@@ -41,7 +41,7 @@
enum name : type { __VA_ARGS__ }; \
DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, type, names, __VA_ARGS__)
-enum C2ParamIndexKind : uint32_t {
+enum C2ParamIndexKind : C2Param::ParamIndex {
/// domain
kParamIndexDomain,
@@ -231,13 +231,10 @@
int32_t mWidth; ///< video width
int32_t mHeight; ///< video height
- DEFINE_C2STRUCT_NO_BASE(VideoSize)
-} C2_PACK;
-
-DESCRIBE_C2STRUCT(VideoSize, {
+ DEFINE_AND_DESCRIBE_BASE_C2STRUCT(VideoSize)
C2FIELD(mWidth, "width")
C2FIELD(mHeight, "height")
-})
+};
// video size for video decoder [OUT]
typedef C2StreamParam<C2Info, C2VideoSizeStruct, kParamIndexVideoSize> C2VideoSizeStreamInfo;
diff --git a/media/libstagefright/codec2/include/C2Param.h b/media/libstagefright/codec2/include/C2Param.h
index 0fb9881a..f0b92a3 100644
--- a/media/libstagefright/codec2/include/C2Param.h
+++ b/media/libstagefright/codec2/include/C2Param.h
@@ -71,7 +71,7 @@
* an error for the specific setting, but should continue to apply other settings.
* TODO: this currently may result in unintended results.
*
- * **NOTE:** unlike OMX, params are not versioned. Instead, a new struct with new base index
+ * **NOTE:** unlike OMX, params are not versioned. Instead, a new struct with new param index
* SHALL be added as new versions are required.
*
* The proper subtype (Setting, Info or Param) is incorporated into the class type. Define structs
@@ -104,7 +104,7 @@
// layout:
//
// +------+-----+---+------+--------+----|------+--------------+
- // | kind | dir | - |stream|streamID|flex|vendor| base index |
+ // | kind | dir | - |stream|streamID|flex|vendor| core index |
// +------+-----+---+------+--------+----+------+--------------+
// bit: 31..30 29.28 25 24 .. 17 16 15 14 .. 0
//
@@ -121,6 +121,19 @@
};
/**
+ * Parameter index is associated with each parameter. It is used to identify and distinguish
+ * global parameters, and also parameters on a given port or stream. They must be unique for the
+ * set of global parameters, as well as for the set of parameters on each port or each stream,
+ * but the same parameter index can be used for parameters on different streams or ports, as
+ * well as for global parameters and port/stream parameters.
+ *
+ * Parameter index is also used to describe the layout of the parameter structures. Multiple
+ * parameter types can share the same layout, but the layout for all parameters with the same
+ * parameter index across all components must be identical.
+ */
+ typedef uint32_t ParamIndex;
+
+ /**
* base index (including the vendor extension bit) is a global index for
* C2 parameter structs. (e.g. the same indices cannot be reused for different
* structs for different components).
@@ -149,7 +162,7 @@
kFlexibleFlag = 0x00010000,
kVendorFlag = 0x00008000,
kParamMask = 0x0000FFFF,
- kBaseMask = kParamMask | kFlexibleFlag,
+ kCoreMask = kParamMask | kFlexibleFlag,
};
public:
@@ -170,11 +183,12 @@
/// returns true iff this is a flexible parameter (with variable size)
inline bool isFlexible() const { return mIndex & kFlexibleFlag; }
- /// returns the base type: the index for the underlying struct
- inline unsigned int baseIndex() const { return mIndex & kBaseMask; }
+ /// returns the core parameter type (index) for the underlying struct.
+ /// This is the combination of the parameter index and the flexible flag.
+ inline unsigned int coreIndex() const { return mIndex & kCoreMask; }
- /// returns the param index for the underlying struct
- inline unsigned int paramIndex() const { return mIndex & kParamMask; }
+ /// returns the parameter index for the underlying struct
+ inline ParamIndex paramIndex() const { return mIndex & kParamMask; }
DEFINE_FIELD_BASED_COMPARISON_OPERATORS(BaseIndex, mIndex)
@@ -330,6 +344,10 @@
/// returns the parameter type: the parameter index without the stream ID
inline uint32_t type() const { return _mIndex.type(); }
+ /// returns the index of this parameter
+ /// \todo: should we restrict this to C2ParamField?
+ inline uint32_t index() const { return (uint32_t)_mIndex; }
+
/// returns the kind of this parameter
inline Kind kind() const { return _mIndex.kind(); }
@@ -450,8 +468,8 @@
friend struct _C2ParamInspector; // for testing
/// returns the base type: the index for the underlying struct (for testing
- /// as this can be gotten by the baseIndex enum)
- inline uint32_t _baseIndex() const { return _mIndex.baseIndex(); }
+ /// as this can be gotten by the coreIndex enum)
+ inline uint32_t _coreIndex() const { return _mIndex.coreIndex(); }
/// returns true iff |o| has the same size and index as this. This performs the
/// basic check for equality.
@@ -548,7 +566,6 @@
/**
* Constructor used to identify a field in an object.
*
- * \param U[type] pointer to the object that contains this field
* \param pm[im] member pointer to the field
*/
template<typename R, typename T, typename B=typename std::remove_extent<R>::type>
@@ -583,23 +600,93 @@
};
/**
- * Structure uniquely specifying a field in a configuration
+ * Structure uniquely specifying a 'field' in a configuration. The field
+ * can be a field of a configuration, a subfield of a field of a configuration,
+ * and even the whole configuration. Moreover, if the field can point to an
+ * element in a array field, or to the entire array field.
+ *
+ * This structure is used for querying supported values for a field, as well
+ * as communicating configuration failures and conflicts when trying to change
+ * a configuration for a component/interface or a store.
*/
struct C2ParamField {
//public:
- // TODO: fix what this is for T[] (for now size becomes T[1])
+ /**
+ * Create a field identifier using a configuration parameter (variable),
+ * and a pointer to member.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * struct C2SomeParam {
+ * uint32_t mField;
+ * uint32_t mArray[2];
+ * C2OtherStruct mStruct;
+ * uint32_t mFlexArray[];
+ * } *mParam;
+ *
+ * C2ParamField(mParam, &mParam->mField);
+ * C2ParamField(mParam, &mParam->mArray);
+ * C2ParamField(mParam, &mParam->mArray[0]);
+ * C2ParamField(mParam, &mParam->mStruct.mSubField);
+ * C2ParamField(mParam, &mParam->mFlexArray);
+ * C2ParamField(mParam, &mParam->mFlexArray[2]);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \todo fix what this is for T[] (for now size becomes T[1])
+ *
+ * \param param pointer to parameter
+ * \param offset member pointer
+ */
template<typename S, typename T>
inline C2ParamField(S* param, T* offset)
: _mIndex(param->index()),
_mFieldId(offset) {}
+ /**
+ * Create a field identifier using a configuration parameter (variable),
+ * and a member pointer. This method cannot be used to refer to an
+ * array element or a subfield.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * C2SomeParam mParam;
+ * C2ParamField(&mParam, &C2SomeParam::mMemberField);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \param p pointer to parameter
+ * \param T member pointer to the field member
+ */
template<typename R, typename T, typename U>
- inline C2ParamField(U *p, R T::* pm) : _mIndex(p->type()), _mFieldId(p, pm) { }
+ inline C2ParamField(U *p, R T::* pm) : _mIndex(p->index()), _mFieldId(p, pm) { }
+ /**
+ * Create a field identifier to a configuration parameter (variable).
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * C2SomeParam mParam;
+ * C2ParamField(&mParam);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \param param pointer to parameter
+ */
+ template<typename S>
+ inline C2ParamField(S* param)
+ : _mIndex(param->index()), _mFieldId(0u, param->size()) {}
+
+ /**
+ * Equality operator.
+ */
inline bool operator==(const C2ParamField &other) const {
return _mIndex == other._mIndex && _mFieldId == other._mFieldId;
}
+ /**
+ * Ordering operator.
+ */
inline bool operator<(const C2ParamField &other) const {
return _mIndex < other._mIndex ||
(_mIndex == other._mIndex && _mFieldId < other._mFieldId);
@@ -608,8 +695,8 @@
DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
private:
- C2Param::Index _mIndex;
- _C2FieldId _mFieldId;
+ C2Param::Index _mIndex; ///< parameter index
+ _C2FieldId _mFieldId; ///< field identifier
};
/**
@@ -711,7 +798,7 @@
///< however, bytes cannot be individually addressed by clients.
// complex types
- STRUCT_FLAG = 0x10000, ///< structs. Marked with this flag in addition to their baseIndex.
+ STRUCT_FLAG = 0x10000, ///< structs. Marked with this flag in addition to their coreIndex.
};
typedef std::pair<C2String, C2Value::Primitive> named_value_type;
@@ -802,12 +889,12 @@
return getType(&underlying);
}
- // verify C2Struct by having a fieldList and a baseIndex.
+ // verify C2Struct by having a fieldList and a coreIndex.
template<typename T,
- class=decltype(T::baseIndex + 1), class=decltype(T::fieldList)>
+ class=decltype(T::coreIndex + 1), class=decltype(T::fieldList)>
inline static Type getType(T*) {
static_assert(!std::is_base_of<C2Param, T>::value, "cannot use C2Params as fields");
- return (Type)(T::baseIndex | STRUCT_FLAG);
+ return (Type)(T::coreIndex | STRUCT_FLAG);
}
};
@@ -832,7 +919,7 @@
struct C2StructDescriptor {
public:
/// Returns the parameter type
- inline C2Param::BaseIndex baseIndex() const { return _mType.baseIndex(); }
+ inline C2Param::BaseIndex coreIndex() const { return _mType.coreIndex(); }
// Returns the number of fields in this param (not counting any recursive fields).
// Must be at least 1 for valid params.
@@ -849,7 +936,7 @@
template<typename T>
inline C2StructDescriptor(T*)
- : C2StructDescriptor(T::baseIndex, T::fieldList) { }
+ : C2StructDescriptor(T::coreIndex, T::fieldList) { }
inline C2StructDescriptor(
C2Param::BaseIndex type,
@@ -914,24 +1001,30 @@
};
/// \ingroup internal
-/// Define a structure without baseIndex.
-#define DEFINE_C2STRUCT_NO_BASE(name) \
+/// Define a structure without coreIndex.
+#define DEFINE_BASE_C2STRUCT(name) \
public: \
typedef C2##name##Struct _type; /**< type name shorthand */ \
const static std::initializer_list<const C2FieldDescriptor> fieldList; /**< structure fields */
-/// Define a structure with matching baseIndex.
+/// Define a structure with matching coreIndex.
#define DEFINE_C2STRUCT(name) \
public: \
- enum : uint32_t { baseIndex = kParamIndex##name }; \
- DEFINE_C2STRUCT_NO_BASE(name)
+ enum : uint32_t { coreIndex = kParamIndex##name }; \
+ DEFINE_BASE_C2STRUCT(name)
-/// Define a flexible structure with matching baseIndex.
+/// Define a flexible structure without coreIndex.
+#define DEFINE_BASE_FLEX_C2STRUCT(name, flexMember) \
+public: \
+ FLEX(C2##name##Struct, flexMember) \
+ DEFINE_BASE_C2STRUCT(name)
+
+/// Define a flexible structure with matching coreIndex.
#define DEFINE_FLEX_C2STRUCT(name, flexMember) \
public: \
FLEX(C2##name##Struct, flexMember) \
- enum : uint32_t { baseIndex = kParamIndex##name | C2Param::BaseIndex::_kFlexibleFlag }; \
- DEFINE_C2STRUCT_NO_BASE(name)
+ enum : uint32_t { coreIndex = kParamIndex##name | C2Param::BaseIndex::_kFlexibleFlag }; \
+ DEFINE_BASE_C2STRUCT(name)
#ifdef __C2_GENERATE_GLOBAL_VARS__
/// \ingroup internal
@@ -1037,17 +1130,30 @@
#define C2SOLE_FIELD(member, name) \
C2FieldDescriptor(&_type::member, name, 0)
-/// Define a structure with matching baseIndex and start describing its fields.
+/// Define a structure with matching coreIndex and start describing its fields.
/// This must be at the end of the structure definition.
#define DEFINE_AND_DESCRIBE_C2STRUCT(name) \
DEFINE_C2STRUCT(name) } C2_PACK; \
const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
-/// Define a flexible structure with matching baseIndex and start describing its fields.
+/// Define a flexible structure with matching coreIndex and start describing its fields.
/// This must be at the end of the structure definition.
#define DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember) \
DEFINE_FLEX_C2STRUCT(name, flexMember) } C2_PACK; \
const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
+
+/// Define a base structure (with no coreIndex) and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_BASE_C2STRUCT(name) \
+ DEFINE_BASE_C2STRUCT(name) } C2_PACK; \
+ const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
+
+/// Define a flexible base structure (with no coreIndex) and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_BASE_FLEX_C2STRUCT(name, flexMember) \
+ DEFINE_BASE_FLEX_C2STRUCT(name, flexMember) } C2_PACK; \
+ const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
+
#else
/// \if 0
/* Alternate declaration of field definitions in case no field list is to be generated.
@@ -1056,14 +1162,22 @@
#define C2FIELD(member, name)
/// \deprecated
#define C2SOLE_FIELD(member, name)
-/// Define a structure with matching baseIndex and start describing its fields.
+/// Define a structure with matching coreIndex and start describing its fields.
/// This must be at the end of the structure definition.
#define DEFINE_AND_DESCRIBE_C2STRUCT(name) \
DEFINE_C2STRUCT(name) } C2_PACK; namespace ignored {
-/// Define a flexible structure with matching baseIndex and start describing its fields.
+/// Define a flexible structure with matching coreIndex and start describing its fields.
/// This must be at the end of the structure definition.
#define DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember) \
DEFINE_FLEX_C2STRUCT(name, flexMember) } C2_PACK; namespace ignored {
+/// Define a base structure (with no coreIndex) and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_BASE_C2STRUCT(name) \
+ DEFINE_BASE_C2STRUCT(name) } C2_PACK; namespace ignored {
+/// Define a flexible base structure (with no coreIndex) and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_BASE_FLEX_C2STRUCT(name, flexMember) \
+ DEFINE_BASE_FLEX_C2STRUCT(name, flexMember) } C2_PACK; namespace ignored {
/// \endif
#endif
@@ -1080,7 +1194,8 @@
/**
* Describes a parameter structure.
*
- * \param[in] paramIndex the base index of the parameter structure
+ * \param[in] coreIndex the base index of the parameter structure containing at least the
+ * core index
*
* \return the description of the parameter structure
* \retval nullptr if the parameter is not supported by this reflector
@@ -1093,55 +1208,13 @@
* descriptions, but we want to conserve memory if client only wants the description
* of a few indices.
*/
- virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) = 0;
+ virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex coreIndex) = 0;
protected:
virtual ~C2ParamReflector() = default;
};
/**
- * A useable supported values for a field.
- *
- * This can be either a range or a set of values. The range can be linear or geometric with a
- * clear minimum and maximum value, and can have an optional step size or geometric ratio. Values
- * can optionally represent flags.
- *
- * \note Do not use flags to represent bitfields. Use individual values or separate fields instead.
- */
-template<typename T>
-struct C2TypedFieldSupportedValues {
-//public:
- enum Type {
- RANGE, ///< a numeric range that can be continuous or discrete
- VALUES, ///< a list of values
- FLAGS ///< a list of flags that can be OR-ed
- };
-
- Type type;
-
- struct {
- T min;
- T max;
- T step;
- T nom;
- T denom;
- } range;
- std::vector<T> values;
-
- C2TypedFieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
- : type(RANGE),
- range{min, max, step, (T)1, (T)1} { }
-
- C2TypedFieldSupportedValues(T min, T max, T nom, T den) :
- type(RANGE),
- range{min, max, (T)0, nom, den} { }
-
- C2TypedFieldSupportedValues(bool flags, std::initializer_list<T> list) :
- type(flags ? FLAGS : VALUES),
- values(list) {}
-};
-
-/**
* Generic supported values for a field.
*
* This can be either a range or a set of values. The range can be linear or geometric with a
@@ -1153,6 +1226,7 @@
struct C2FieldSupportedValues {
//public:
enum Type {
+ EMPTY, ///< no supported values
RANGE, ///< a numeric range that can be continuous or discrete
VALUES, ///< a list of values
FLAGS ///< a list of flags that can be OR-ed
@@ -1171,6 +1245,10 @@
} range;
std::vector<Primitive> values;
+ C2FieldSupportedValues()
+ : type(EMPTY) {
+ }
+
template<typename T>
C2FieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
: type(RANGE),
@@ -1199,6 +1277,9 @@
}
}
+ /// \internal
+ /// \todo: create separate values vs. flags initializer as for flags we want
+ /// to list both allowed and disallowed flags
template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
C2FieldSupportedValues(bool flags, const T*)
: type(flags ? FLAGS : VALUES),
@@ -1210,6 +1291,21 @@
}
};
+/**
+ * Spported values for a specific field.
+ *
+ * This is a pair of the field specifier together with an optional supported values object.
+ * This structure is used when reporting parameter configuration failures and conflicts.
+ */
+struct C2ParamFieldValues {
+ C2ParamField paramOrField; ///< the field or parameter
+ /// optional supported values for the field if paramOrField specifies an actual field that is
+ /// numeric (non struct, blob or string). Supported values for arrays (including string and
+ /// blobs) describe the supported values for each element (character for string, and bytes for
+ /// blobs). It is optional for read-only strings and blobs.
+ std::unique_ptr<C2FieldSupportedValues> values;
+};
+
/// @}
} // namespace android
diff --git a/media/libstagefright/codec2/include/C2ParamDef.h b/media/libstagefright/codec2/include/C2ParamDef.h
index f369617..8656629 100644
--- a/media/libstagefright/codec2/include/C2ParamDef.h
+++ b/media/libstagefright/codec2/include/C2ParamDef.h
@@ -59,35 +59,35 @@
|| decltype(_C2Comparable_impl::__testNE<S>(0))::value> {
};
-/// Helper class that checks if a type has a baseIndex constant.
-struct C2_HIDE _C2BaseIndexHelper_impl
+/// Helper class that checks if a type has a coreIndex constant.
+struct C2_HIDE _C2CoreIndexHelper_impl
{
- template<typename S, int=S::baseIndex>
- static std::true_type __testBaseIndex(int);
+ template<typename S, int=S::coreIndex>
+ static std::true_type __testCoreIndex(int);
template<typename>
- static std::false_type __testBaseIndex(...);
+ static std::false_type __testCoreIndex(...);
};
-/// Helper template that verifies a type's baseIndex and creates it if the type does not have one.
-template<typename S, int BaseIndex,
- bool HasBase=decltype(_C2BaseIndexHelper_impl::__testBaseIndex<S>(0))::value>
-struct C2_HIDE C2BaseIndexOverride {
- // TODO: what if we allow structs without baseIndex?
- static_assert(BaseIndex == S::baseIndex, "baseIndex differs from structure");
+/// Helper template that verifies a type's coreIndex and creates it if the type does not have one.
+template<typename S, int CoreIndex,
+ bool HasBase=decltype(_C2CoreIndexHelper_impl::__testCoreIndex<S>(0))::value>
+struct C2_HIDE C2CoreIndexOverride {
+ // TODO: what if we allow structs without coreIndex?
+ static_assert(CoreIndex == S::coreIndex, "coreIndex differs from structure");
};
-/// Specialization for types without a baseIndex.
-template<typename S, int BaseIndex>
-struct C2_HIDE C2BaseIndexOverride<S, BaseIndex, false> {
+/// Specialization for types without a coreIndex.
+template<typename S, int CoreIndex>
+struct C2_HIDE C2CoreIndexOverride<S, CoreIndex, false> {
public:
enum : uint32_t {
- baseIndex = BaseIndex, ///< baseIndex override.
+ coreIndex = CoreIndex, ///< coreIndex override.
};
};
-/// Helper template that adds a baseIndex to a type if it does not have one.
-template<typename S, int BaseIndex>
-struct C2_HIDE C2AddBaseIndex : public S, public C2BaseIndexOverride<S, BaseIndex> {};
+/// Helper template that adds a coreIndex to a type if it does not have one.
+template<typename S, int CoreIndex>
+struct C2_HIDE C2AddCoreIndex : public S, public C2CoreIndexOverride<S, CoreIndex> {};
/**
* \brief Helper class to check struct requirements for parameters.
@@ -96,7 +96,7 @@
* - verify default constructor, no virtual methods, and no equality operators.
* - expose typeIndex, and non-flex flexSize.
*/
-template<typename S, int BaseIndex, unsigned TypeIndex>
+template<typename S, int CoreIndex, unsigned TypeIndex>
struct C2_HIDE C2StructCheck {
static_assert(
std::is_default_constructible<S>::value, "C2 structure must have default constructor");
@@ -105,7 +105,7 @@
public:
enum : uint32_t {
- typeIndex = BaseIndex | TypeIndex
+ typeIndex = CoreIndex | TypeIndex
};
protected:
@@ -161,17 +161,19 @@
* \brief Helper class to check flexible struct requirements and add common operations.
*
* Features:
- * - expose baseIndex and fieldList (this is normally inherited from the struct, but flexible
+ * - expose coreIndex and fieldList (this is normally inherited from the struct, but flexible
* structs cannot be base classes and thus inherited from)
* - disable copy assignment and construction (TODO: this is already done in the FLEX macro for the
* flexible struct, so may not be needed here)
*/
-template<typename S, int BaseIndex, unsigned TypeIndex>
-struct C2_HIDE C2FlexStructCheck : public C2StructCheck<S, BaseIndex, TypeIndex> {
+template<typename S, int ParamIndex, unsigned TypeIndex>
+struct C2_HIDE C2FlexStructCheck :
+// add flexible flag as C2StructCheck defines typeIndex
+ public C2StructCheck<S, ParamIndex | C2Param::BaseIndex::_kFlexibleFlag, TypeIndex> {
public:
enum : uint32_t {
/// \hideinitializer
- baseIndex = BaseIndex | C2Param::BaseIndex::_kFlexibleFlag, ///< flexible struct base-index
+ coreIndex = ParamIndex | C2Param::BaseIndex::_kFlexibleFlag, ///< flexible struct core-index
};
const static std::initializer_list<const C2FieldDescriptor> fieldList; // TODO assign here
@@ -181,8 +183,8 @@
protected:
// cannot copy flexible params
- C2FlexStructCheck(const C2FlexStructCheck<S, BaseIndex, TypeIndex> &) = delete;
- C2FlexStructCheck& operator= (const C2FlexStructCheck<S, BaseIndex, TypeIndex> &) = delete;
+ C2FlexStructCheck(const C2FlexStructCheck<S, ParamIndex, TypeIndex> &) = delete;
+ C2FlexStructCheck& operator= (const C2FlexStructCheck<S, ParamIndex, TypeIndex> &) = delete;
// constants used for helper methods
enum : uint32_t {
@@ -215,8 +217,9 @@
// TODO: this probably does not work.
/// Expose fieldList from subClass;
-template<typename S, int BaseIndex, unsigned TypeIndex>
-const std::initializer_list<const C2FieldDescriptor> C2FlexStructCheck<S, BaseIndex, TypeIndex>::fieldList = S::fieldList;
+template<typename S, int ParamIndex, unsigned TypeIndex>
+const std::initializer_list<const C2FieldDescriptor>
+C2FlexStructCheck<S, ParamIndex, TypeIndex>::fieldList = S::fieldList;
/// Define From() cast operators for params.
#define DEFINE_CAST_OPERATORS(_type) \
@@ -299,7 +302,7 @@
* Global-parameter template.
*
* Base template to define a global setting/tuning or info based on a structure and
- * an optional BaseIndex. Global parameters are not tied to a port (input or output).
+ * an optional ParamIndex. Global parameters are not tied to a port (input or output).
*
* Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
* structure can be accessed directly, and constructors and potential public methods are also
@@ -307,13 +310,14 @@
*
* \tparam T param type C2Setting, C2Tuning or C2Info
* \tparam S wrapped structure
- * \tparam BaseIndex optional base-index override. Must be specified for common/reused structures.
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
*/
-template<typename T, typename S, int BaseIndex=S::baseIndex, class Flex=void>
-struct C2_HIDE C2GlobalParam : public T, public S, public C2BaseIndexOverride<S, BaseIndex>,
- public C2StructCheck<S, BaseIndex, T::indexFlags | T::Type::kDirGlobal> {
+template<typename T, typename S, int ParamIndex=S::coreIndex, class Flex=void>
+struct C2_HIDE C2GlobalParam : public T, public S, public C2CoreIndexOverride<S, ParamIndex>,
+ public C2StructCheck<S, ParamIndex, T::indexFlags | T::Type::kDirGlobal> {
private:
- typedef C2GlobalParam<T, S, BaseIndex> _type;
+ typedef C2GlobalParam<T, S, ParamIndex> _type;
public:
/// Wrapper around base structure's constructor.
@@ -327,21 +331,22 @@
* Global-parameter template for flexible structures.
*
* Base template to define a global setting/tuning or info based on a flexible structure and
- * an optional BaseIndex. Global parameters are not tied to a port (input or output).
+ * an optional ParamIndex. Global parameters are not tied to a port (input or output).
*
* \tparam T param type C2Setting, C2Tuning or C2Info
* \tparam S wrapped flexible structure
- * \tparam BaseIndex optional base-index override. Must be specified for common/reused structures.
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
*
* Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
* structures can be accessed via the m member variable; however, the constructors of the structure
* are wrapped directly. (This is because flexible types cannot be subclassed.)
*/
-template<typename T, typename S, int BaseIndex>
-struct C2_HIDE C2GlobalParam<T, S, BaseIndex, IF_FLEXIBLE(S)>
- : public T, public C2FlexStructCheck<S, BaseIndex, T::indexFlags | T::Type::kDirGlobal> {
+template<typename T, typename S, int ParamIndex>
+struct C2_HIDE C2GlobalParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
+ : public T, public C2FlexStructCheck<S, ParamIndex, T::indexFlags | T::Type::kDirGlobal> {
private:
- typedef C2GlobalParam<T, S, BaseIndex> _type;
+ typedef C2GlobalParam<T, S, ParamIndex> _type;
/// Wrapper around base structure's constructor.
template<typename ...Args>
@@ -359,12 +364,13 @@
* Port-parameter template.
*
* Base template to define a port setting/tuning or info based on a structure and
- * an optional BaseIndex. Port parameters are tied to a port (input or output), but not to a
+ * an optional ParamIndex. Port parameters are tied to a port (input or output), but not to a
* specific stream.
*
* \tparam T param type C2Setting, C2Tuning or C2Info
* \tparam S wrapped structure
- * \tparam BaseIndex optional base-index override. Must be specified for common/reused structures.
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
*
* Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
* structure can be accessed directly, and constructors and potential public methods are also
@@ -373,11 +379,11 @@
* There are 3 flavors of port parameters: unspecified, input and output. Parameters with
* unspecified port expose a setPort method, and add an initial port parameter to the constructor.
*/
-template<typename T, typename S, int BaseIndex=S::baseIndex, class Flex=void>
-struct C2_HIDE C2PortParam : public T, public S, public C2BaseIndexOverride<S, BaseIndex>,
- private C2StructCheck<S, BaseIndex, T::indexFlags | T::Index::kDirUndefined> {
+template<typename T, typename S, int ParamIndex=S::coreIndex, class Flex=void>
+struct C2_HIDE C2PortParam : public T, public S, public C2CoreIndexOverride<S, ParamIndex>,
+ private C2StructCheck<S, ParamIndex, T::indexFlags | T::Index::kDirUndefined> {
private:
- typedef C2PortParam<T, S, BaseIndex> _type;
+ typedef C2PortParam<T, S, ParamIndex> _type;
public:
/// Default constructor.
@@ -392,8 +398,8 @@
DEFINE_CAST_OPERATORS(_type)
/// Specialization for an input port parameter.
- struct input : public T, public S, public C2BaseIndexOverride<S, BaseIndex>,
- public C2StructCheck<S, BaseIndex, T::indexFlags | T::Index::kDirInput> {
+ struct input : public T, public S, public C2CoreIndexOverride<S, ParamIndex>,
+ public C2StructCheck<S, ParamIndex, T::indexFlags | T::Index::kDirInput> {
/// Wrapper around base structure's constructor.
template<typename ...Args>
inline input(const Args(&... args)) : T(sizeof(_type), input::typeIndex), S(args...) { }
@@ -403,8 +409,8 @@
};
/// Specialization for an output port parameter.
- struct output : public T, public S, public C2BaseIndexOverride<S, BaseIndex>,
- public C2StructCheck<S, BaseIndex, T::indexFlags | T::Index::kDirOutput> {
+ struct output : public T, public S, public C2CoreIndexOverride<S, ParamIndex>,
+ public C2StructCheck<S, ParamIndex, T::indexFlags | T::Index::kDirOutput> {
/// Wrapper around base structure's constructor.
template<typename ...Args>
inline output(const Args(&... args)) : T(sizeof(_type), output::typeIndex), S(args...) { }
@@ -417,12 +423,13 @@
* Port-parameter template for flexible structures.
*
* Base template to define a port setting/tuning or info based on a flexible structure and
- * an optional BaseIndex. Port parameters are tied to a port (input or output), but not to a
+ * an optional ParamIndex. Port parameters are tied to a port (input or output), but not to a
* specific stream.
*
* \tparam T param type C2Setting, C2Tuning or C2Info
* \tparam S wrapped flexible structure
- * \tparam BaseIndex optional base-index override. Must be specified for common/reused structures.
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
*
* Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
* structures can be accessed via the m member variable; however, the constructors of the structure
@@ -431,11 +438,11 @@
* There are 3 flavors of port parameters: unspecified, input and output. Parameters with
* unspecified port expose a setPort method, and add an initial port parameter to the constructor.
*/
-template<typename T, typename S, int BaseIndex>
-struct C2_HIDE C2PortParam<T, S, BaseIndex, IF_FLEXIBLE(S)>
- : public T, public C2FlexStructCheck<S, BaseIndex, T::indexFlags | T::Type::kDirUndefined> {
+template<typename T, typename S, int ParamIndex>
+struct C2_HIDE C2PortParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
+ : public T, public C2FlexStructCheck<S, ParamIndex, T::indexFlags | T::Type::kDirUndefined> {
private:
- typedef C2PortParam<T, S, BaseIndex> _type;
+ typedef C2PortParam<T, S, ParamIndex> _type;
/// Default constructor for basic allocation: new(flexCount) P.
inline C2PortParam(size_t flexCount) : T(_type::calcSize(flexCount), _type::typeIndex) { }
@@ -455,8 +462,8 @@
DEFINE_CAST_OPERATORS(_type)
/// Specialization for an input port parameter.
- struct input : public T, public C2BaseIndexOverride<S, BaseIndex>,
- public C2FlexStructCheck<S, BaseIndex, T::indexFlags | T::Index::kDirInput> {
+ struct input : public T,
+ public C2FlexStructCheck<S, ParamIndex, T::indexFlags | T::Index::kDirInput> {
private:
/// Wrapper around base structure's constructor while also specifying port/direction.
template<typename ...Args>
@@ -471,8 +478,8 @@
};
/// Specialization for an output port parameter.
- struct output : public T, public C2BaseIndexOverride<S, BaseIndex>,
- public C2FlexStructCheck<S, BaseIndex, T::indexFlags | T::Index::kDirOutput> {
+ struct output : public T,
+ public C2FlexStructCheck<S, ParamIndex, T::indexFlags | T::Index::kDirOutput> {
private:
/// Wrapper around base structure's constructor while also specifying port/direction.
template<typename ...Args>
@@ -491,12 +498,13 @@
* Stream-parameter template.
*
* Base template to define a stream setting/tuning or info based on a structure and
- * an optional BaseIndex. Stream parameters are tied to a specific stream on a port (input or
+ * an optional ParamIndex. Stream parameters are tied to a specific stream on a port (input or
* output).
*
* \tparam T param type C2Setting, C2Tuning or C2Info
* \tparam S wrapped structure
- * \tparam BaseIndex optional base-index override. Must be specified for common/reused structures.
+ * \tparam ParamIndex optional paramter index override. Must be specified for base/reused
+ * structures.
*
* Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
* structure can be accessed directly, and constructors and potential public methods are also
@@ -507,12 +515,12 @@
* parameters with unspecified port expose a setPort method, and add an additional initial port
* parameter to the constructor.
*/
-template<typename T, typename S, int BaseIndex=S::baseIndex, class Flex=void>
-struct C2_HIDE C2StreamParam : public T, public S, public C2BaseIndexOverride<S, BaseIndex>,
- private C2StructCheck<S, BaseIndex,
+template<typename T, typename S, int ParamIndex=S::coreIndex, class Flex=void>
+struct C2_HIDE C2StreamParam : public T, public S, public C2CoreIndexOverride<S, ParamIndex>,
+ private C2StructCheck<S, ParamIndex,
T::indexFlags | T::Index::kStreamFlag | T::Index::kDirUndefined> {
private:
- typedef C2StreamParam<T, S, BaseIndex> _type;
+ typedef C2StreamParam<T, S, ParamIndex> _type;
public:
/// Default constructor. Port/direction and stream-ID is undefined.
@@ -531,8 +539,8 @@
DEFINE_CAST_OPERATORS(_type)
/// Specialization for an input stream parameter.
- struct input : public T, public S, public C2BaseIndexOverride<S, BaseIndex>,
- public C2StructCheck<S, BaseIndex,
+ struct input : public T, public S, public C2CoreIndexOverride<S, ParamIndex>,
+ public C2StructCheck<S, ParamIndex,
T::indexFlags | T::Index::kStreamFlag | T::Type::kDirInput> {
/// Default constructor. Stream-ID is undefined.
inline input() : T(sizeof(_type), input::typeIndex) { }
@@ -547,8 +555,8 @@
};
/// Specialization for an output stream parameter.
- struct output : public T, public S, public C2BaseIndexOverride<S, BaseIndex>,
- public C2StructCheck<S, BaseIndex,
+ struct output : public T, public S, public C2CoreIndexOverride<S, ParamIndex>,
+ public C2StructCheck<S, ParamIndex,
T::indexFlags | T::Index::kStreamFlag | T::Type::kDirOutput> {
/// Default constructor. Stream-ID is undefined.
inline output() : T(sizeof(_type), output::typeIndex) { }
@@ -567,12 +575,13 @@
* Stream-parameter template for flexible structures.
*
* Base template to define a stream setting/tuning or info based on a flexible structure and
- * an optional BaseIndex. Stream parameters are tied to a specific stream on a port (input or
+ * an optional ParamIndex. Stream parameters are tied to a specific stream on a port (input or
* output).
*
* \tparam T param type C2Setting, C2Tuning or C2Info
* \tparam S wrapped flexible structure
- * \tparam BaseIndex optional base-index override. Must be specified for common/reused structures.
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
*
* Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
* structures can be accessed via the m member variable; however, the constructors of the structure
@@ -583,13 +592,13 @@
* parameters with unspecified port expose a setPort method, and add an additional initial port
* parameter to the constructor.
*/
-template<typename T, typename S, int BaseIndex>
-struct C2_HIDE C2StreamParam<T, S, BaseIndex, IF_FLEXIBLE(S)>
- : public T, public C2BaseIndexOverride<S, BaseIndex>,
- private C2FlexStructCheck<S, BaseIndex,
+template<typename T, typename S, int ParamIndex>
+struct C2_HIDE C2StreamParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
+ : public T,
+ public C2FlexStructCheck<S, ParamIndex,
T::indexFlags | T::Index::kStreamFlag | T::Index::kDirUndefined> {
private:
- typedef C2StreamParam<T, S> _type;
+ typedef C2StreamParam<T, S, ParamIndex> _type;
/// Default constructor. Port/direction and stream-ID is undefined.
inline C2StreamParam(size_t flexCount) : T(_type::calcSize(flexCount), _type::typeIndex, 0u) { }
/// Wrapper around base structure's constructor while also specifying port/direction and
@@ -611,8 +620,8 @@
DEFINE_CAST_OPERATORS(_type)
/// Specialization for an input stream parameter.
- struct input : public T, public C2BaseIndexOverride<S, BaseIndex>,
- public C2FlexStructCheck<S, BaseIndex,
+ struct input : public T,
+ public C2FlexStructCheck<S, ParamIndex,
T::indexFlags | T::Index::kStreamFlag | T::Type::kDirInput> {
private:
/// Default constructor. Stream-ID is undefined.
@@ -633,8 +642,8 @@
};
/// Specialization for an output stream parameter.
- struct output : public T, public C2BaseIndexOverride<S, BaseIndex>,
- public C2FlexStructCheck<S, BaseIndex,
+ struct output : public T,
+ public C2FlexStructCheck<S, ParamIndex,
T::indexFlags | T::Index::kStreamFlag | T::Type::kDirOutput> {
private:
/// Default constructor. Stream-ID is undefined.
@@ -659,7 +668,7 @@
/**
* \ingroup internal
- * A structure template encapsulating a single element with default constructors and no base-index.
+ * A structure template encapsulating a single element with default constructors and no core-index.
*/
template<typename T>
struct C2SimpleValueStruct {
@@ -668,7 +677,7 @@
inline C2SimpleValueStruct() = default;
// Constructor with an initial value.
inline C2SimpleValueStruct(T value) : mValue(value) {}
- DEFINE_C2STRUCT_NO_BASE(SimpleValue)
+ DEFINE_BASE_C2STRUCT(SimpleValue)
};
// TODO: move this and next to some generic place
@@ -757,7 +766,7 @@
/**
* Specialization for a flexible blob and string arrays. A structure template encapsulating a single
- * flexible array member with default flexible constructors and no base-index. This type cannot be
+ * flexible array member with default flexible constructors and no core-index. This type cannot be
* constructed on its own as it's size is 0.
*
* \internal This is different from C2SimpleArrayStruct<T[]> simply because its member has the name
@@ -770,7 +779,7 @@
T mValue[];
inline C2SimpleValueStruct() = default;
- DEFINE_C2STRUCT_NO_BASE(SimpleValue)
+ DEFINE_BASE_C2STRUCT(SimpleValue)
FLEX(C2SimpleValueStruct, mValue)
private:
@@ -792,7 +801,7 @@
/**
* A structure template encapsulating a single flexible array element of a specific type (T) with
- * default constructors and no base-index. This type cannot be constructed on its own as it's size
+ * default constructors and no core-index. This type cannot be constructed on its own as it's size
* is 0. Instead, it is meant to be used as a parameter, e.g.
*
* typedef C2StreamParam<C2Info, C2SimpleArrayStruct<C2MyFancyStruct>,
@@ -806,8 +815,8 @@
T mValues[]; ///< array member
/// Default constructor
inline C2SimpleArrayStruct() = default;
- DEFINE_C2STRUCT_NO_BASE(SimpleArray)
- FLEX(C2SimpleArrayStruct, mValues)
+ DEFINE_BASE_FLEX_C2STRUCT(SimpleArray, mValues)
+ //FLEX(C2SimpleArrayStruct, mValues)
private:
/// Construct from a C2MemoryBlock.
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index a378623..69c16ab 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -28,28 +28,47 @@
#include <list>
#include <vector>
-typedef int status_t;
-
namespace android {
/// \defgroup work Work and data processing
/// @{
+/**
+ * Information describing the reason a parameter settings may fail, or
+ * may be overriden.
+ */
struct C2SettingResult {
- enum Failure {
+ enum Failure : uint32_t {
READ_ONLY, ///< parameter is read-only and cannot be set
MISMATCH, ///< parameter mismatches input data
BAD_VALUE, ///< parameter does not accept value
BAD_TYPE, ///< parameter is not supported
BAD_PORT, ///< parameter is not supported on the specific port
BAD_INDEX, ///< parameter is not supported on the specific stream
- CONFLICT, ///< parameter is in conflict with another setting
+ CONFLICT, ///< parameter is in conflict with an/other setting(s)
+ /// parameter is out of range due to other settings (this failure mode
+ /// can only be used for strict parameters)
+ UNSUPPORTED,
+
+
+ /// requested parameter value is in conflict with an/other setting(s)
+ /// and has been corrected to the closest supported value. This failure
+ /// mode is given to provide suggestion to the client as to how to
+ /// enable the requested parameter value.
+ INFO_CONFLICT,
};
- C2ParamField field;
- Failure failure;
- std::unique_ptr<C2FieldSupportedValues> supportedValues; //< if different from normal (e.g. in conflict w/another param or input data)
- std::list<C2ParamField> conflictingFields;
+ Failure failure; ///< failure code
+
+ /// Failing (or corrected) field. Currently supported values for the field. This is set if
+ /// different from the globally supported values (e.g. due to restrictions by another param or
+ /// input data)
+ /// \todo need to define suggestions for masks to be set and unset.
+ C2ParamFieldValues field;
+
+ /// Conflicting parameters or fields with optional suggestions with (optional) suggested values
+ /// for any conflicting fields to avoid the conflict.
+ std::list<C2ParamFieldValues> conflicts;
};
// ================================================================================================
@@ -146,7 +165,7 @@
std::list<std::unique_ptr<C2Worklet>> worklets;
uint32_t worklets_processed;
- status_t result;
+ C2Status result;
};
struct C2WorkOutline {
diff --git a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
index 0c8ca3e..b725d76 100644
--- a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
+++ b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
@@ -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 status_t (e.g. C2_OK).
- template <typename T> status_t queryOnStack(T *const p);
+ // The return value is C2Status (e.g. C2_OK).
+ template <typename T> C2Status queryOnStack(T *const p);
template <typename T>
- status_t queryOnHeap(const T &p,
+ C2Status 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>
- status_t
+ C2Status
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, status_t *stConfig);
+ template <typename T> void configWritableParamValidValue(const T &newParam, C2Status *stConfig);
// Test if config works correctly in the case an invalid value |newParam| is tried to write
// to an writable parameter.
@@ -162,7 +162,7 @@
// config() should be failed if these values are used as new values.
// This function should be called only for writable and supported parameters.
template <typename TField>
- void getTestValues(const std::vector<C2FieldSupportedValues> &validValueInfos,
+ void getTestValues(const C2FieldSupportedValues &validValueInfos,
std::vector<TField> *const validValues,
std::vector<TField> *const invalidValues);
@@ -194,13 +194,13 @@
} \
} while (false)
-template <typename T> status_t C2CompIntfTest::queryOnStack(T *const p) {
+template <typename T> C2Status C2CompIntfTest::queryOnStack(T *const p) {
std::vector<C2Param *const> stackParams{p};
return mIntf->query_nb(stackParams, {}, nullptr);
}
template <typename T>
-status_t C2CompIntfTest::queryOnHeap(
+C2Status 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>
-status_t C2CompIntfTest::config(
+C2Status 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, status_t *configResult) {
+void C2CompIntfTest::configWritableParamValidValue(const T &newParam, C2Status *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.
- status_t stConfig = mIntf->config_nb(params, &failures);
+ C2Status stConfig = mIntf->config_nb(params, &failures);
if (stConfig == C2_OK) {
EXPECT_EQ(0u, failures.size());
} else {
@@ -325,7 +325,7 @@
// If another field type is added, it is necessary to add function for that.
template <>
void C2CompIntfTest::getTestValues(
- const std::vector<C2FieldSupportedValues> &validValueInfos,
+ const C2FieldSupportedValues &validValueInfos,
std::vector<C2DomainKind> *const validValues,
std::vector<C2DomainKind> *const invalidValues) {
UNUSED(validValueInfos);
@@ -339,7 +339,7 @@
template <typename TField>
void C2CompIntfTest::getTestValues(
- const std::vector<C2FieldSupportedValues> &validValueInfos,
+ const C2FieldSupportedValues &validValueInfos,
std::vector<TField> *const validValues,
std::vector<TField> *const invalidValues) {
@@ -366,9 +366,14 @@
};
// The size of validValueInfos is one.
- const auto &c2FSV = validValueInfos[0];
+ const auto &c2FSV = validValueInfos;
switch (c2FSV.type) {
+ case C2FieldSupportedValues::Type::EMPTY: {
+ invalidValues->emplace_back(TField(0));
+ // TODO(hiroh) : Should other invalid values be tested?
+ break;
+ }
case C2FieldSupportedValues::Type::RANGE: {
const auto &range = c2FSV.range;
auto rmin = prim2Value(range.min);
@@ -476,7 +481,7 @@
TParam *const param, TRealField *const writableField,
const std::vector<TField> &validValues,
const std::vector<TField> &invalidValues) {
- status_t stConfig;
+ C2Status stConfig;
// Get the parameter's value in the beginning in order to reset the value at the end.
TRACED_FAILURE(getValue(param));
@@ -550,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.
- status_t stStack = config(param.get(), &failures);
+ C2Status stStack = config(param.get(), &failures);
if (stStack == C2_BAD_VALUE) {
// Read-only
std::unique_ptr<T> newParam = makeParam<T>();
@@ -584,15 +589,16 @@
#define TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, field_name_) \
do { \
std::unique_ptr<TParam_> param = makeParam<TParam_>(); \
- std::vector<C2FieldSupportedValues> validValueInfos; \
+ std::vector<C2FieldSupportedValuesQuery> validValueInfos = { \
+ C2FieldSupportedValuesQuery::Current( \
+ C2ParamField(param.get(), &field_type_name_::field_name_)) \
+ }; \
ASSERT_EQ(C2_OK, \
- mIntf->getSupportedValues( \
- {C2ParamField(param.get(), &field_type_name_::field_name_)}, \
- &validValueInfos)); \
+ mIntf->getSupportedValues(validValueInfos)); \
ASSERT_EQ(1u, validValueInfos.size()); \
std::vector<decltype(param->field_name_)> validValues; \
std::vector<decltype(param->field_name_)> invalidValues; \
- getTestValues(validValueInfos, &validValues, &invalidValues); \
+ getTestValues(validValueInfos[0].values, &validValues, &invalidValues); \
testWritableParam(param.get(), ¶m->field_name_, validValues,\
invalidValues); \
} while (0)
diff --git a/media/libstagefright/codec2/tests/C2Param_test.cpp b/media/libstagefright/codec2/tests/C2Param_test.cpp
index 9a2ead6..97c5f91 100644
--- a/media/libstagefright/codec2/tests/C2Param_test.cpp
+++ b/media/libstagefright/codec2/tests/C2Param_test.cpp
@@ -93,9 +93,9 @@
struct C2SizeStruct {
int32_t mNumber;
int32_t mHeight;
- enum : uint32_t { baseIndex = kParamIndexSize }; // <= needed for C2FieldDescriptor
+ enum : uint32_t { coreIndex = kParamIndexSize }; // <= needed for C2FieldDescriptor
const static std::initializer_list<const C2FieldDescriptor> fieldList; // <= needed for C2FieldDescriptor
- const static FD::Type TYPE = (FD::Type)(baseIndex | FD::STRUCT_FLAG);
+ const static FD::Type TYPE = (FD::Type)(coreIndex | FD::STRUCT_FLAG);
};
DEFINE_NO_NAMED_VALUES_FOR(C2SizeStruct)
@@ -121,7 +121,7 @@
bool mYesNo[100];
const static std::initializer_list<const C2FieldDescriptor> fieldList;
- // enum : uint32_t { baseIndex = kParamIndexTest };
+ // enum : uint32_t { coreIndex = kParamIndexTest };
// typedef C2TestStruct_A _type;
} __attribute__((packed));
@@ -296,7 +296,7 @@
int32_t mFlex[];
const static std::initializer_list<const C2FieldDescriptor> fieldList;
- // enum : uint32_t { baseIndex = kParamIndexTestFlex, flexSize = 4 };
+ // enum : uint32_t { coreIndex = kParamIndexTestFlex, flexSize = 4 };
// typedef C2TestStruct_FlexS32 _type;
// typedef int32_t flexType;
};
@@ -310,7 +310,7 @@
int32_t mFlex[];
const static std::initializer_list<const C2FieldDescriptor> fieldList;
- // enum : uint32_t { baseIndex = kParamIndexTestFlexEnd, flexSize = 4 };
+ // enum : uint32_t { coreIndex = kParamIndexTestFlexEnd, flexSize = 4 };
// typedef C2TestStruct_FlexEnd _type;
// typedef int32_t flexType;
};
@@ -365,7 +365,7 @@
int64_t mFlexSigned64[];
const static std::initializer_list<const C2FieldDescriptor> fieldList;
- // enum : uint32_t { baseIndex = kParamIndexTestFlexS64, flexSize = 8 };
+ // enum : uint32_t { coreIndex = kParamIndexTestFlexS64, flexSize = 8 };
// typedef C2TestStruct_FlexS64 _type;
// typedef int64_t flexType;
};
@@ -379,7 +379,7 @@
int64_t mSigned64Flex[];
const static std::initializer_list<const C2FieldDescriptor> fieldList;
- // enum : uint32_t { baseIndex = C2TestStruct_FlexEndS64, flexSize = 8 };
+ // enum : uint32_t { coreIndex = C2TestStruct_FlexEndS64, flexSize = 8 };
// typedef C2TestStruct_FlexEndS64 _type;
// typedef int64_t flexType;
};
@@ -426,7 +426,7 @@
C2SizeStruct mFlexSize[];
const static std::initializer_list<const C2FieldDescriptor> fieldList;
- // enum : uint32_t { baseIndex = kParamIndexTestFlexSize, flexSize = 8 };
+ // enum : uint32_t { coreIndex = kParamIndexTestFlexSize, flexSize = 8 };
// typedef C2TestStruct_FlexSize _type;
// typedef C2SizeStruct flexType;
};
@@ -440,7 +440,7 @@
C2SizeStruct mSizeFlex[];
const static std::initializer_list<const C2FieldDescriptor> fieldList;
- // enum : uint32_t { baseIndex = C2TestStruct_FlexEndSize, flexSize = 8 };
+ // enum : uint32_t { coreIndex = C2TestStruct_FlexEndSize, flexSize = 8 };
// typedef C2TestStruct_FlexEndSize _type;
// typedef C2SizeStruct flexType;
};
@@ -471,6 +471,29 @@
C2FIELD(mFlexSize, "flex")
}) // ; optional
+struct C2TestBaseFlexEndSizeStruct {
+ int32_t mSigned32;
+ C2SizeStruct mFlexSize[];
+ C2TestBaseFlexEndSizeStruct() {}
+
+ DEFINE_BASE_FLEX_C2STRUCT(TestBaseFlexEndSize, mFlexSize)
+} C2_PACK;
+
+DESCRIBE_C2STRUCT(TestBaseFlexEndSize, {
+ C2FIELD(mSigned32, "s32")
+ C2FIELD(mFlexSize, "flex")
+}) // ; optional
+
+struct C2TestBaseFlexEndSize2Struct {
+ int32_t mSigned32;
+ C2SizeStruct mFlexSize[];
+ C2TestBaseFlexEndSize2Struct() {}
+
+ DEFINE_AND_DESCRIBE_BASE_FLEX_C2STRUCT(TestBaseFlexEndSize2, mFlexSize)
+ C2FIELD(mSigned32, "s32")
+ C2FIELD(mFlexSize, "flex")
+};
+
template<>
std::vector<std::vector<const C2FieldDescriptor>>
//std::initializer_list<std::initializer_list<const C2FieldDescriptor>>
@@ -480,6 +503,8 @@
C2TestStruct_FlexEndSize::fieldList,
C2TestFlexSizeStruct::fieldList,
C2TestFlexEndSizeStruct::fieldList,
+ C2TestBaseFlexEndSizeStruct::fieldList,
+ C2TestBaseFlexEndSize2Struct::fieldList,
};
}
@@ -498,6 +523,9 @@
EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&((C2TestFlexEndSizeStruct*)0)->mSigned32));
EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&((C2TestFlexEndSizeStruct*)0)->mFlexSize));
+ EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&((C2TestBaseFlexEndSizeStruct*)0)->mSigned32));
+ EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&((C2TestBaseFlexEndSizeStruct*)0)->mFlexSize));
+
// member pointer constructor
EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::mSigned32));
EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::mSigned64));
@@ -512,6 +540,9 @@
EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId((C2TestFlexEndSizeStruct*)0, &C2TestFlexEndSizeStruct::mSigned32));
EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId((C2TestFlexEndSizeStruct*)0, &C2TestFlexEndSizeStruct::mFlexSize));
+ EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId((C2TestBaseFlexEndSizeStruct*)0, &C2TestBaseFlexEndSizeStruct::mSigned32));
+ EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId((C2TestBaseFlexEndSizeStruct*)0, &C2TestBaseFlexEndSizeStruct::mFlexSize));
+
// member pointer sans type pointer
EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&C2TestStruct_A::mSigned32));
EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&C2TestStruct_A::mSigned64));
@@ -526,8 +557,12 @@
EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&C2TestFlexEndSizeStruct::mSigned32));
EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&C2TestFlexEndSizeStruct::mFlexSize));
+ EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&C2TestBaseFlexEndSizeStruct::mSigned32));
+ EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&C2TestBaseFlexEndSizeStruct::mFlexSize));
+
typedef C2GlobalParam<C2Info, C2TestAStruct> C2TestAInfo;
typedef C2GlobalParam<C2Info, C2TestFlexEndSizeStruct> C2TestFlexEndSizeInfo;
+ typedef C2GlobalParam<C2Info, C2TestBaseFlexEndSizeStruct, kParamIndexTestFlexEndSize> C2TestFlexEndSizeInfoFromBase;
// pointer constructor in C2Param
EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&((C2TestAInfo*)0)->mSigned32));
@@ -543,6 +578,9 @@
EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&((C2TestFlexEndSizeInfo*)0)->m.mSigned32));
EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId(&((C2TestFlexEndSizeInfo*)0)->m.mFlexSize));
+ EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&((C2TestFlexEndSizeInfoFromBase*)0)->m.mSigned32));
+ EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId(&((C2TestFlexEndSizeInfoFromBase*)0)->m.mFlexSize));
+
// member pointer in C2Param
EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::mSigned32));
EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::mSigned64));
@@ -558,6 +596,8 @@
// EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&C2TestFlexEndSizeInfo::m.mSigned32));
// EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId(&C2TestFlexEndSizeInfo::m.mFlexSize));
+ // EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&C2TestFlexEndSizeInfoFromBase::m.mSigned32));
+ // EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId(&C2TestFlexEndSizeInfoFromBase::m.mFlexSize));
}
@@ -636,6 +676,10 @@
typedef C2GlobalParam<C2Info, C2TestFlexEndSizeStruct> C2TestFlexEndSizeInfo;
static_assert(offsetof(C2TestFlexEndSizeInfo, m.mSigned32) == 8, "offset should be 8");
static_assert(offsetof(C2TestFlexEndSizeInfo, m.mFlexSize) == 12, "offset should be 12");
+
+ typedef C2GlobalParam<C2Info, C2TestBaseFlexEndSizeStruct, kParamIndexTestFlexEndSize> C2TestFlexEndSizeInfoFromBase;
+ static_assert(offsetof(C2TestFlexEndSizeInfoFromBase, m.mSigned32) == 8, "offset should be 8");
+ static_assert(offsetof(C2TestFlexEndSizeInfoFromBase, m.mFlexSize) == 12, "offset should be 12");
}
/* ===================================== PARAM USAGE TESTS ===================================== */
@@ -649,6 +693,15 @@
C2FIELD(mNumber, "number")
};
+struct C2NumberBaseStruct {
+ int32_t mNumber;
+ C2NumberBaseStruct() {}
+ C2NumberBaseStruct(int32_t _number) : mNumber(_number) {}
+
+ DEFINE_AND_DESCRIBE_BASE_C2STRUCT(NumberBase)
+ C2FIELD(mNumber, "number")
+};
+
struct C2NumbersStruct {
int32_t mNumbers[];
C2NumbersStruct() {}
@@ -691,7 +744,7 @@
struct C2NumbersStruct {
int32_t mNumbers[];
- enum { baseIndex = kParamIndexNumber };
+ enum { coreIndex = kParamIndexNumber };
const static std::initializer_list<const C2FieldDescriptor> fieldList;
C2NumbersStruct() {}
@@ -725,7 +778,7 @@
C2Param::Index index(paramType);
switch (paramType) {
- case C2NumberConfig::baseIndex:
+ case C2NumberConfig::coreIndex:
return std::unique_ptr<C2ParamDescriptor>(new C2ParamDescriptor{
true /* isRequired */,
"number",
@@ -774,19 +827,21 @@
struct _C2ParamInspector {
static void StaticTest();
+ static void StaticFromBaseTest();
static void StaticFlexTest();
+ static void StaticFlexFromBaseTest();
};
// TEST_F(_C2ParamInspector, StaticTest) {
void _C2ParamInspector::StaticTest() {
typedef C2Param::Index I;
- // C2NumberStruct: baseIndex = kIndex (args)
- static_assert(C2NumberStruct::baseIndex == kParamIndexNumber, "bad index");
+ // C2NumberStruct: coreIndex = kIndex (args)
+ static_assert(C2NumberStruct::coreIndex == kParamIndexNumber, "bad index");
static_assert(sizeof(C2NumberStruct) == 4, "bad size");
// C2NumberTuning: kIndex | tun | global (args)
- static_assert(C2NumberTuning::baseIndex == kParamIndexNumber, "bad index");
+ static_assert(C2NumberTuning::coreIndex == kParamIndexNumber, "bad index");
static_assert(C2NumberTuning::typeIndex == (kParamIndexNumber | I::kTypeTuning | I::kDirGlobal), "bad index");
static_assert(sizeof(C2NumberTuning) == 12, "bad size");
@@ -798,11 +853,11 @@
static_assert(sizeof(C2NumberPortTuning) == 12, "bad size");
// C2NumberPortTuning::input: kIndex | tun | port | input (args)
// C2NumberPortTuning::output: kIndex | tun | port | output (args)
- static_assert(C2NumberPortTuning::input::baseIndex ==
+ static_assert(C2NumberPortTuning::input::coreIndex ==
kParamIndexNumber, "bad index");
static_assert(C2NumberPortTuning::input::typeIndex ==
(kParamIndexNumber | I::kTypeTuning | I::kDirInput), "bad index");
- static_assert(C2NumberPortTuning::output::baseIndex ==
+ static_assert(C2NumberPortTuning::output::coreIndex ==
kParamIndexNumber, "bad index");
static_assert(C2NumberPortTuning::output::typeIndex ==
(kParamIndexNumber | I::kTypeTuning | I::kDirOutput), "bad index");
@@ -819,11 +874,11 @@
static_assert(sizeof(C2NumberStreamTuning) == 12u, "bad size");
// C2NumberStreamTuning::input kIndex | tun | str | input (int, args)
// C2NumberStreamTuning::output kIx | tun | str | output (int, args)
- static_assert(C2NumberStreamTuning::input::baseIndex ==
+ static_assert(C2NumberStreamTuning::input::coreIndex ==
kParamIndexNumber, "bad index");
static_assert(C2NumberStreamTuning::input::typeIndex ==
(kParamIndexNumber | I::kTypeTuning | I::kDirInput | I::kStreamFlag), "bad index");
- static_assert(C2NumberStreamTuning::output::baseIndex ==
+ static_assert(C2NumberStreamTuning::output::coreIndex ==
kParamIndexNumber, "bad index");
static_assert(C2NumberStreamTuning::output::typeIndex ==
(kParamIndexNumber | I::kTypeTuning | I::kDirOutput | I::kStreamFlag), "bad index");
@@ -837,15 +892,80 @@
static_assert(offsetof(C2NumberStreamTuning::output, mNumber) == 8, "bad offset");
}
+void _C2ParamInspector::StaticFromBaseTest() {
+ enum { kParamIndexMy = 3102 };
+ typedef C2NumberBaseStruct C2MyStruct;
+ typedef C2GlobalParam<C2Setting, C2MyStruct, kParamIndexMy> C2MySetting;
+ typedef C2PortParam<C2Setting, C2MyStruct, kParamIndexMy> C2MyPortSetting;
+ typedef C2StreamParam<C2Setting, C2MyStruct, kParamIndexMy> C2MyStreamSetting;
+
+ typedef C2Param::Index I;
+
+ // C2MyStruct has no coreIndex
+ //static_assert(C2MyStruct::coreIndex == kParamIndexMy, "bad index");
+ static_assert(sizeof(C2MyStruct) == 4, "bad size");
+
+ // C2MySetting: kIndex | tun | global (args)
+ static_assert(C2MySetting::coreIndex == kParamIndexMy, "bad index");
+ static_assert(C2MySetting::typeIndex == (kParamIndexMy | I::kTypeSetting | I::kDirGlobal), "bad index");
+ static_assert(sizeof(C2MySetting) == 12, "bad size");
+
+ static_assert(offsetof(C2MySetting, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MySetting, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MySetting, mNumber) == 8, "bad offset");
+
+ // C2MyPortSetting: kIndex | tun | port (bool, args)
+ static_assert(sizeof(C2MyPortSetting) == 12, "bad size");
+ // C2MyPortSetting::input: kIndex | tun | port | input (args)
+ // C2MyPortSetting::output: kIndex | tun | port | output (args)
+ static_assert(C2MyPortSetting::input::coreIndex ==
+ kParamIndexMy, "bad index");
+ static_assert(C2MyPortSetting::input::typeIndex ==
+ (kParamIndexMy | I::kTypeSetting | I::kDirInput), "bad index");
+ static_assert(C2MyPortSetting::output::coreIndex ==
+ kParamIndexMy, "bad index");
+ static_assert(C2MyPortSetting::output::typeIndex ==
+ (kParamIndexMy | I::kTypeSetting | I::kDirOutput), "bad index");
+ static_assert(sizeof(C2MyPortSetting::input) == 12, "bad size");
+ static_assert(sizeof(C2MyPortSetting::output) == 12, "bad size");
+ static_assert(offsetof(C2MyPortSetting::input, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyPortSetting::input, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyPortSetting::input, mNumber) == 8, "bad offset");
+ static_assert(offsetof(C2MyPortSetting::output, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyPortSetting::output, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyPortSetting::output, mNumber) == 8, "bad offset");
+
+ // C2MyStreamSetting: kIndex | tun | str (bool, uint, args)
+ static_assert(sizeof(C2MyStreamSetting) == 12u, "bad size");
+ // C2MyStreamSetting::input kIndex | tun | str | input (int, args)
+ // C2MyStreamSetting::output kIx | tun | str | output (int, args)
+ static_assert(C2MyStreamSetting::input::coreIndex ==
+ kParamIndexMy, "bad index");
+ static_assert(C2MyStreamSetting::input::typeIndex ==
+ (kParamIndexMy | I::kTypeSetting | I::kDirInput | I::kStreamFlag), "bad index");
+ static_assert(C2MyStreamSetting::output::coreIndex ==
+ kParamIndexMy, "bad index");
+ static_assert(C2MyStreamSetting::output::typeIndex ==
+ (kParamIndexMy | I::kTypeSetting | I::kDirOutput | I::kStreamFlag), "bad index");
+ static_assert(sizeof(C2MyStreamSetting::input) == 12u, "bad size");
+ static_assert(sizeof(C2MyStreamSetting::output) == 12u, "bad size");
+ static_assert(offsetof(C2MyStreamSetting::input, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyStreamSetting::input, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyStreamSetting::input, mNumber) == 8, "bad offset");
+ static_assert(offsetof(C2MyStreamSetting::output, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyStreamSetting::output, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyStreamSetting::output, mNumber) == 8, "bad offset");
+}
+
void _C2ParamInspector::StaticFlexTest() {
typedef C2Param::Index I;
- // C2NumbersStruct: baseIndex = kIndex (args)
- static_assert(C2NumbersStruct::baseIndex == (I::kFlexibleFlag | kParamIndexNumbers), "bad index");
+ // C2NumbersStruct: coreIndex = kIndex (args)
+ static_assert(C2NumbersStruct::coreIndex == (I::kFlexibleFlag | kParamIndexNumbers), "bad index");
static_assert(sizeof(C2NumbersStruct) == 0, "bad size");
// C2NumbersTuning: kIndex | tun | global (args)
- static_assert(C2NumbersTuning::baseIndex == (I::kFlexibleFlag | kParamIndexNumbers), "bad index");
+ static_assert(C2NumbersTuning::coreIndex == (I::kFlexibleFlag | kParamIndexNumbers), "bad index");
static_assert(C2NumbersTuning::typeIndex == (I::kFlexibleFlag | kParamIndexNumbers | I::kTypeTuning | I::kDirGlobal), "bad index");
static_assert(sizeof(C2NumbersTuning) == 8, "bad size");
@@ -857,11 +977,11 @@
static_assert(sizeof(C2NumbersPortTuning) == 8, "bad size");
// C2NumbersPortTuning::input: kIndex | tun | port | input (args)
// C2NumbersPortTuning::output: kIndex | tun | port | output (args)
- static_assert(C2NumbersPortTuning::input::baseIndex ==
+ static_assert(C2NumbersPortTuning::input::coreIndex ==
(I::kFlexibleFlag | kParamIndexNumbers), "bad index");
static_assert(C2NumbersPortTuning::input::typeIndex ==
(I::kFlexibleFlag | kParamIndexNumbers | I::kTypeTuning | I::kDirInput), "bad index");
- static_assert(C2NumbersPortTuning::output::baseIndex ==
+ static_assert(C2NumbersPortTuning::output::coreIndex ==
(I::kFlexibleFlag | kParamIndexNumbers), "bad index");
static_assert(C2NumbersPortTuning::output::typeIndex ==
(I::kFlexibleFlag | kParamIndexNumbers | I::kTypeTuning | I::kDirOutput), "bad index");
@@ -878,11 +998,11 @@
static_assert(sizeof(C2NumbersStreamTuning) == 8, "bad size");
// C2NumbersStreamTuning::input kIndex | tun | str | input (int, args)
// C2NumbersStreamTuning::output kIx | tun | str | output (int, args)
- static_assert(C2NumbersStreamTuning::input::baseIndex ==
+ static_assert(C2NumbersStreamTuning::input::coreIndex ==
(I::kFlexibleFlag | kParamIndexNumbers), "bad index");
static_assert(C2NumbersStreamTuning::input::typeIndex ==
(I::kFlexibleFlag | kParamIndexNumbers | I::kTypeTuning | I::kDirInput | I::kStreamFlag), "bad index");
- static_assert(C2NumbersStreamTuning::output::baseIndex ==
+ static_assert(C2NumbersStreamTuning::output::coreIndex ==
(I::kFlexibleFlag | kParamIndexNumbers), "bad index");
static_assert(C2NumbersStreamTuning::output::typeIndex ==
(I::kFlexibleFlag | kParamIndexNumbers | I::kTypeTuning | I::kDirOutput | I::kStreamFlag), "bad index");
@@ -896,6 +1016,80 @@
static_assert(offsetof(C2NumbersStreamTuning::output, m.mNumbers) == 8, "bad offset");
}
+template<bool, unsigned ...N>
+struct _print_as_warning { };
+
+template<unsigned ...N>
+struct _print_as_warning<true, N...> : std::true_type { };
+
+#define static_assert_equals(a, b, msg) \
+static_assert(_print_as_warning<(a) == (b), a, b>::value, msg)
+
+void _C2ParamInspector::StaticFlexFromBaseTest() {
+ enum { kParamIndexMy = 1203 };
+ typedef C2TestBaseFlexEndSizeStruct C2MyStruct;
+ typedef C2GlobalParam<C2Info, C2MyStruct, kParamIndexMy> C2MyInfo;
+ typedef C2PortParam<C2Info, C2MyStruct, kParamIndexMy> C2MyPortInfo;
+ typedef C2StreamParam<C2Info, C2MyStruct, kParamIndexMy> C2MyStreamInfo;
+
+ typedef C2Param::Index I;
+
+ // C2MyStruct has no coreIndex
+ //static_assert(C2MyStruct::coreIndex == (I::kFlexibleFlag | kParamIndexMy), "bad index");
+ static_assert(sizeof(C2MyStruct) == 4, "bad size");
+
+ // C2MyInfo: kIndex | tun | global (args)
+ static_assert_equals(C2MyInfo::coreIndex, (I::kFlexibleFlag | kParamIndexMy), "bad index");
+ static_assert_equals(C2MyInfo::typeIndex, (I::kFlexibleFlag | kParamIndexMy | I::kTypeInfo | I::kDirGlobal), "bad index");
+ static_assert(sizeof(C2MyInfo) == 12, "bad size");
+
+ static_assert(offsetof(C2MyInfo, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyInfo, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyInfo, m.mSigned32) == 8, "bad offset");
+
+ // C2MyPortInfo: kIndex | tun | port (bool, args)
+ static_assert(sizeof(C2MyPortInfo) == 12, "bad size");
+ // C2MyPortInfo::input: kIndex | tun | port | input (args)
+ // C2MyPortInfo::output: kIndex | tun | port | output (args)
+ static_assert(C2MyPortInfo::input::coreIndex ==
+ (I::kFlexibleFlag | kParamIndexMy), "bad index");
+ static_assert(C2MyPortInfo::input::typeIndex ==
+ (I::kFlexibleFlag | kParamIndexMy | I::kTypeInfo | I::kDirInput), "bad index");
+ static_assert(C2MyPortInfo::output::coreIndex ==
+ (I::kFlexibleFlag | kParamIndexMy), "bad index");
+ static_assert(C2MyPortInfo::output::typeIndex ==
+ (I::kFlexibleFlag | kParamIndexMy | I::kTypeInfo | I::kDirOutput), "bad index");
+ static_assert(sizeof(C2MyPortInfo::input) == 12, "bad size");
+ static_assert(sizeof(C2MyPortInfo::output) == 12, "bad size");
+ static_assert(offsetof(C2MyPortInfo::input, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyPortInfo::input, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyPortInfo::input, m.mSigned32) == 8, "bad offset");
+ static_assert(offsetof(C2MyPortInfo::output, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyPortInfo::output, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyPortInfo::output, m.mSigned32) == 8, "bad offset");
+
+ // C2MyStreamInfo: kIndex | tun | str (bool, uint, args)
+ static_assert(sizeof(C2MyStreamInfo) == 12, "bad size");
+ // C2MyStreamInfo::input kIndex | tun | str | input (int, args)
+ // C2MyStreamInfo::output kIx | tun | str | output (int, args)
+ static_assert(C2MyStreamInfo::input::coreIndex ==
+ (I::kFlexibleFlag | kParamIndexMy), "bad index");
+ static_assert(C2MyStreamInfo::input::typeIndex ==
+ (I::kFlexibleFlag | kParamIndexMy | I::kTypeInfo | I::kDirInput | I::kStreamFlag), "bad index");
+ static_assert(C2MyStreamInfo::output::coreIndex ==
+ (I::kFlexibleFlag | kParamIndexMy), "bad index");
+ static_assert(C2MyStreamInfo::output::typeIndex ==
+ (I::kFlexibleFlag | kParamIndexMy | I::kTypeInfo | I::kDirOutput | I::kStreamFlag), "bad index");
+ static_assert(sizeof(C2MyStreamInfo::input) == 12, "bad size");
+ static_assert(sizeof(C2MyStreamInfo::output) == 12, "bad size");
+ static_assert(offsetof(C2MyStreamInfo::input, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyStreamInfo::input, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyStreamInfo::input, m.mSigned32) == 8, "bad offset");
+ static_assert(offsetof(C2MyStreamInfo::output, _mSize) == 0, "bad size");
+ static_assert(offsetof(C2MyStreamInfo::output, _mIndex) == 4, "bad offset");
+ static_assert(offsetof(C2MyStreamInfo::output, m.mSigned32) == 8, "bad offset");
+}
+
TEST_F(C2ParamTest, ParamOpsTest) {
const C2NumberStruct str(100);
C2NumberStruct bstr;
@@ -904,10 +1098,10 @@
EXPECT_EQ(100, str.mNumber);
bstr.mNumber = 100;
- C2Param::BaseIndex index = C2NumberStruct::baseIndex;
+ C2Param::BaseIndex index = C2NumberStruct::coreIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_FALSE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumber);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumber);
EXPECT_EQ(index.paramIndex(), kParamIndexNumber);
}
@@ -941,15 +1135,15 @@
EXPECT_EQ(tun, btun);
// index
- EXPECT_EQ(C2Param::Type(tun.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(tun.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(tun.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(tun.type(), C2NumberTuning::typeIndex);
EXPECT_EQ(tun.stream(), ~0u);
- C2Param::BaseIndex index = C2NumberTuning::baseIndex;
+ C2Param::BaseIndex index = C2NumberTuning::coreIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_FALSE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumber);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumber);
EXPECT_EQ(index.paramIndex(), kParamIndexNumber);
C2Param::Type type = C2NumberTuning::typeIndex;
@@ -1095,22 +1289,22 @@
EXPECT_TRUE(inp1 == boutp1);
// index
- EXPECT_EQ(C2Param::Type(inp1.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(inp1.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(inp1.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(inp1.type(), C2NumberPortTuning::input::typeIndex);
EXPECT_EQ(inp1.stream(), ~0u);
- EXPECT_EQ(C2Param::Type(inp2.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(inp2.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(inp2.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(inp2.type(), C2NumberPortTuning::input::typeIndex);
EXPECT_EQ(inp2.stream(), ~0u);
- EXPECT_EQ(C2Param::Type(outp1.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outp1.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outp1.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(outp1.type(), C2NumberPortTuning::output::typeIndex);
EXPECT_EQ(outp1.stream(), ~0u);
- EXPECT_EQ(C2Param::Type(outp2.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outp2.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outp2.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(outp2.type(), C2NumberPortTuning::output::typeIndex);
EXPECT_EQ(outp2.stream(), ~0u);
@@ -1118,13 +1312,13 @@
C2Param::BaseIndex index = C2NumberPortTuning::input::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_FALSE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumber);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumber);
EXPECT_EQ(index.paramIndex(), kParamIndexNumber);
index = C2NumberPortTuning::output::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_FALSE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumber);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumber);
EXPECT_EQ(index.paramIndex(), kParamIndexNumber);
C2Param::Type type = C2NumberPortTuning::input::typeIndex;
@@ -1315,32 +1509,32 @@
EXPECT_TRUE(ins1 == bouts1);
// index
- EXPECT_EQ(C2Param::Type(ins1.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(ins1.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(ins1.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(ins1.type(), C2NumberStreamTuning::input::typeIndex);
- EXPECT_EQ(C2Param::Type(ins2.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(ins2.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(ins2.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(ins2.type(), C2NumberStreamTuning::input::typeIndex);
- EXPECT_EQ(C2Param::Type(outs1.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outs1.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outs1.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(outs1.type(), C2NumberStreamTuning::output::typeIndex);
- EXPECT_EQ(C2Param::Type(outs2.type()).baseIndex(), C2NumberStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outs2.type()).coreIndex(), C2NumberStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outs2.type()).paramIndex(), kParamIndexNumber);
EXPECT_EQ(outs2.type(), C2NumberStreamTuning::output::typeIndex);
C2Param::BaseIndex index = C2NumberStreamTuning::input::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_FALSE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumber);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumber);
EXPECT_EQ(index.paramIndex(), kParamIndexNumber);
index = C2NumberStreamTuning::output::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_FALSE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumber);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumber);
EXPECT_EQ(index.paramIndex(), kParamIndexNumber);
C2Param::Type type = C2NumberStreamTuning::input::typeIndex;
@@ -1420,11 +1614,11 @@
}
}
-void StaticTestAddBaseIndex() {
+void StaticTestAddCoreIndex() {
struct nobase {};
- struct base { enum : uint32_t { baseIndex = 1 }; };
- static_assert(C2AddBaseIndex<nobase, 2>::baseIndex == 2, "should be 2");
- static_assert(C2AddBaseIndex<base, 1>::baseIndex == 1, "should be 1");
+ struct base { enum : uint32_t { coreIndex = 1 }; };
+ static_assert(C2AddCoreIndex<nobase, 2>::coreIndex == 2, "should be 2");
+ static_assert(C2AddCoreIndex<base, 1>::coreIndex == 1, "should be 1");
}
class TestFlexHelper {
@@ -1464,10 +1658,10 @@
// EXPECT_EQ(100, str->m.mNumbers[0]);
(void)&bstr.mNumbers[0];
- C2Param::BaseIndex index = C2NumbersStruct::baseIndex;
+ C2Param::BaseIndex index = C2NumbersStruct::coreIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_TRUE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
EXPECT_EQ(index.paramIndex(), kParamIndexNumbers);
}
@@ -1504,15 +1698,15 @@
EXPECT_EQ(*tun, *btun);
// index
- EXPECT_EQ(C2Param::Type(tun->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(tun->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(tun->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(tun->type(), C2NumbersTuning::typeIndex);
EXPECT_EQ(tun->stream(), ~0u);
- C2Param::BaseIndex index = C2NumbersTuning::baseIndex;
+ C2Param::BaseIndex index = C2NumbersTuning::coreIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_TRUE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
EXPECT_EQ(index.paramIndex(), kParamIndexNumbers);
C2Param::Type type = C2NumbersTuning::typeIndex;
@@ -1673,22 +1867,22 @@
EXPECT_TRUE(*inp1 == *boutp1);
// index
- EXPECT_EQ(C2Param::Type(inp1->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(inp1->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(inp1->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(inp1->type(), C2NumbersPortTuning::input::typeIndex);
EXPECT_EQ(inp1->stream(), ~0u);
- EXPECT_EQ(C2Param::Type(inp2->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(inp2->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(inp2->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(inp2->type(), C2NumbersPortTuning::input::typeIndex);
EXPECT_EQ(inp2->stream(), ~0u);
- EXPECT_EQ(C2Param::Type(outp1->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outp1->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outp1->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(outp1->type(), C2NumbersPortTuning::output::typeIndex);
EXPECT_EQ(outp1->stream(), ~0u);
- EXPECT_EQ(C2Param::Type(outp2->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outp2->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outp2->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(outp2->type(), C2NumbersPortTuning::output::typeIndex);
EXPECT_EQ(outp2->stream(), ~0u);
@@ -1696,13 +1890,13 @@
C2Param::BaseIndex index = C2NumbersPortTuning::input::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_TRUE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
EXPECT_EQ(index.paramIndex(), kParamIndexNumbers);
index = C2NumbersPortTuning::output::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_TRUE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
EXPECT_EQ(index.paramIndex(), kParamIndexNumbers);
C2Param::Type type = C2NumbersPortTuning::input::typeIndex;
@@ -1910,32 +2104,32 @@
EXPECT_TRUE(*ins1 == *bouts1);
// index
- EXPECT_EQ(C2Param::Type(ins1->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(ins1->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(ins1->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(ins1->type(), C2NumbersStreamTuning::input::typeIndex);
- EXPECT_EQ(C2Param::Type(ins2->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(ins2->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(ins2->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(ins2->type(), C2NumbersStreamTuning::input::typeIndex);
- EXPECT_EQ(C2Param::Type(outs1->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outs1->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outs1->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(outs1->type(), C2NumbersStreamTuning::output::typeIndex);
- EXPECT_EQ(C2Param::Type(outs2->type()).baseIndex(), C2NumbersStruct::baseIndex);
+ EXPECT_EQ(C2Param::Type(outs2->type()).coreIndex(), C2NumbersStruct::coreIndex);
EXPECT_EQ(C2Param::Type(outs2->type()).paramIndex(), kParamIndexNumbers);
EXPECT_EQ(outs2->type(), C2NumbersStreamTuning::output::typeIndex);
C2Param::BaseIndex index = C2NumbersStreamTuning::input::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_TRUE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
EXPECT_EQ(index.paramIndex(), kParamIndexNumbers);
index = C2NumbersStreamTuning::output::typeIndex;
EXPECT_FALSE(index.isVendor());
EXPECT_TRUE(index.isFlexible());
- EXPECT_EQ(index.baseIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
+ EXPECT_EQ(index.coreIndex(), kParamIndexNumbers | C2Param::BaseIndex::_kFlexibleFlag);
EXPECT_EQ(index.paramIndex(), kParamIndexNumbers);
C2Param::Type type = C2NumbersStreamTuning::input::typeIndex;
@@ -2197,36 +2391,6 @@
typedef C2PortParam<C2Tuning, C2VideoConfigStruct> C2VideoConfigPortTuning;
-class MyReflector : public C2ParamReflector {
-private:
- std::unique_ptr<C2VideoConfigPortTuning::input> inputVideoConfigTuning;
- std::unique_ptr<C2VideoConfigPortTuning::output> outputVideoConfigTuning;
-
-public:
- void describeSupportedValues() {
- C2TypedFieldSupportedValues<int32_t> supportedWidths(16, 1920, 8);
- C2FieldSupportedValues supportedWidths2(16, 1920, 8);
-
-
- std::list<C2FieldSupportedValues> supported;
- //supported.emplace_push(inputVideoConfigTuning->mNumber, range(16, 1920, 8));
- //supported.emplace_push(inputVideoConfigTuning->mHeight, range(16, 1088, 8));
- //supported.emplace_push(inputVideoConfigTuning->mMetadataType, all_enums);
- //supported.emplace_push(inputVideoConfigTuning->mSupportedFormats, { 0, 1, 5, 7 });
- }
-
- virtual std::unique_ptr<android::C2StructDescriptor> describe(C2Param::BaseIndex paramType) {
- switch (paramType.baseIndex()) {
- case C2VideoConfigPortTuning::baseIndex:
- return std::unique_ptr<C2StructDescriptor>(new C2StructDescriptor{
- paramType.baseIndex(),
- C2VideoConfigPortTuning::fieldList,
- });
- }
- return nullptr;
- }
-};
-
class MyComponentInstance : public C2ComponentInterface {
public:
virtual C2String getName() const {
@@ -2239,28 +2403,28 @@
return 0;
}
- virtual status_t commit_sm(
+ virtual C2Status commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
(void)params;
(void)failures;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
- virtual status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
(void)params;
(void)failures;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
- virtual status_t createTunnel_sm(node_id targetComponent) {
+ virtual C2Status createTunnel_sm(node_id targetComponent) {
(void)targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
- virtual status_t query_nb(
+ virtual C2Status query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -2302,9 +2466,9 @@
mMyParams.insert({mDomainInfo.type(), mDomainInfo});
}
- virtual status_t releaseTunnel_sm(node_id targetComponent) {
+ virtual C2Status releaseTunnel_sm(node_id targetComponent) {
(void)targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
class MyParamReflector : public C2ParamReflector {
@@ -2314,8 +2478,8 @@
MyParamReflector(const MyComponentInstance *i) : instance(i) { }
virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) {
- switch (paramIndex.baseIndex()) {
- case decltype(instance->mDomainInfo)::baseIndex:
+ switch (paramIndex.coreIndex()) {
+ case decltype(instance->mDomainInfo)::coreIndex:
default:
return std::unique_ptr<C2StructDescriptor>(new C2StructDescriptor{
instance->mDomainInfo.type(),
@@ -2326,17 +2490,19 @@
}
};
- virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const {
- for (const C2ParamField &field : fields) {
- if (field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
- values->push_back(C2FieldSupportedValues(
+ virtual C2Status getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const {
+ for (C2FieldSupportedValuesQuery &query : fields) {
+ if (query.field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
+ query.values = C2FieldSupportedValues(
false /* flag */,
&mDomainInfo.mValue
//,
//{(int32_t)C2DomainVideo}
- ));
+ );
+ query.status = C2_OK;
+ } else {
+ query.status = C2_BAD_INDEX;
}
}
return C2_OK;
@@ -2346,13 +2512,13 @@
return std::shared_ptr<C2ParamReflector>(new MyParamReflector(this));
}
- virtual status_t getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
+ virtual C2Status getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
params->push_back(std::make_shared<C2ParamDescriptor>(
true /* required */, "_domain", &mDomainInfo));
return C2_OK;
}
- status_t getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
+ 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;
@@ -2490,7 +2656,7 @@
void dumpStruct(const C2StructDescriptor &sd) {
using namespace std;
cout << "struct ";
- dumpType(sd.baseIndex());
+ dumpType(sd.coreIndex());
cout << " {" << endl;
//C2FieldDescriptor &f;
for (const C2FieldDescriptor &f : sd) {
@@ -2535,21 +2701,23 @@
TEST_F(C2ParamTest, ReflectorTest) {
C2ComponentDomainInfo domainInfo;
std::shared_ptr<C2ComponentInterface> comp(new MyComponentInstance);
- std::vector<C2FieldSupportedValues> values;
std::unique_ptr<C2StructDescriptor> desc{
comp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
dumpStruct(*desc);
- EXPECT_EQ(
- C2_OK,
- comp->getSupportedValues(
- { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue) },
- &values)
- );
+ std::vector<C2FieldSupportedValuesQuery> query = {
+ { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+ C2FieldSupportedValuesQuery::CURRENT },
+ C2FieldSupportedValuesQuery(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+ C2FieldSupportedValuesQuery::CURRENT),
+ C2FieldSupportedValuesQuery::Current(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue)),
+ };
- for (const C2FieldSupportedValues &sv : values) {
- dumpFSV(sv, &domainInfo.mValue);
+ EXPECT_EQ(C2_OK, comp->getSupportedValues(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 a185880..8c78334 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) {
- C2Error err = mLinearAllocator->allocateLinearBuffer(
+ C2Status err = mLinearAllocator->allocateLinearBuffer(
capacity,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&mLinearAllocation);
@@ -50,7 +50,7 @@
void mapLinear(size_t offset, size_t size, uint8_t **addr) {
ASSERT_TRUE(mLinearAllocation);
- C2Error err = mLinearAllocation->map(
+ C2Status err = mLinearAllocation->map(
offset,
size,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
@@ -82,7 +82,7 @@
}
void allocateGraphic(uint32_t width, uint32_t height) {
- C2Error err = mGraphicAllocator->allocateGraphicBuffer(
+ C2Status err = mGraphicAllocator->allocateGraphicBuffer(
width,
height,
HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -96,7 +96,7 @@
void mapGraphic(C2Rect rect, C2PlaneLayout *layout, uint8_t **addr) {
ASSERT_TRUE(mGraphicAllocation);
- C2Error err = mGraphicAllocation->map(
+ C2Status 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 baa6637..6530cc1 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -38,14 +38,14 @@
using ::android::hardware::hidl_vec;
/* ===================================== GRALLOC ALLOCATION ==================================== */
-static C2Error maperr2error(Error maperr) {
+static C2Status maperr2error(Error maperr) {
switch (maperr) {
case Error::NONE: return C2_OK;
case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
case Error::BAD_BUFFER: return C2_BAD_VALUE;
case Error::BAD_VALUE: return C2_BAD_VALUE;
case Error::NO_RESOURCES: return C2_NO_MEMORY;
- case Error::UNSUPPORTED: return C2_UNSUPPORTED;
+ case Error::UNSUPPORTED: return C2_CANNOT_DO;
}
return C2_CORRUPTED;
}
@@ -54,10 +54,10 @@
public:
virtual ~C2AllocationGralloc();
- virtual C2Error map(
+ virtual C2Status map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
- virtual C2Error unmap(C2Fence *fenceFd /* nullable */) override;
+ virtual C2Status 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;
- C2Error status() const;
+ C2Status status() const;
private:
const IMapper::BufferDescriptorInfo mInfo;
@@ -100,7 +100,7 @@
mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
}
-C2Error C2AllocationGralloc::map(
+C2Status C2AllocationGralloc::map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
// TODO
@@ -114,7 +114,7 @@
return C2_BAD_VALUE;
}
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
if (!mBuffer) {
mMapper->importBuffer(
mHandle, [&err, this](const auto &maperr, const auto &buffer) {
@@ -195,16 +195,16 @@
return err;
}
// TODO
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
mLocked = true;
return C2_OK;
}
-C2Error C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
+C2Status C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
// TODO: fence
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
mMapper->unlock(
const_cast<native_handle_t *>(mBuffer),
[&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
@@ -231,18 +231,18 @@
public:
Impl();
- C2Error allocateGraphicBuffer(
+ C2Status allocateGraphicBuffer(
uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
std::shared_ptr<C2GraphicAllocation> *allocation);
- C2Error recreateGraphicBuffer(
+ C2Status recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation);
- C2Error status() const { return mInit; }
+ C2Status status() const { return mInit; }
private:
- C2Error mInit;
+ C2Status mInit;
sp<IAllocator> mAllocator;
sp<IMapper> mMapper;
};
@@ -256,7 +256,7 @@
}
}
-C2Error C2AllocatorGralloc::Impl::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::allocateGraphicBuffer(
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|
@@ -269,7 +269,7 @@
(PixelFormat)format,
BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
};
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
BufferDescriptor desc;
mMapper->createDescriptor(
info, [&err, &desc](const auto &maperr, const auto &descriptor) {
@@ -307,33 +307,33 @@
return C2_OK;
}
-C2Error C2AllocatorGralloc::Impl::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
(void) handle;
// TODO: need to figure out BufferDescriptorInfo from the handle.
allocation->reset();
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
C2AllocatorGralloc::C2AllocatorGralloc() : mImpl(new Impl) {}
C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
-C2Error C2AllocatorGralloc::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::allocateGraphicBuffer(
uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
std::shared_ptr<C2GraphicAllocation> *allocation) {
return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
}
-C2Error C2AllocatorGralloc::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
return mImpl->recreateGraphicBuffer(handle, allocation);
}
-C2Error C2AllocatorGralloc::status() const {
+C2Status C2AllocatorGralloc::status() const {
return mImpl->status();
}
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 7aa7769..06b4874 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -82,10 +82,10 @@
/* ======================================= ION ALLOCATION ====================================== */
class C2AllocationIon : public C2LinearAllocation {
public:
- virtual C2Error map(
+ virtual C2Status map(
size_t offset, size_t size, C2MemoryUsage usage, int *fence,
void **addr /* nonnull */);
- virtual C2Error unmap(void *addr, size_t size, int *fenceFd);
+ virtual C2Status unmap(void *addr, size_t size, int *fenceFd);
virtual bool isValid() const;
virtual ~C2AllocationIon();
virtual const C2Handle *handle() const;
@@ -95,7 +95,7 @@
C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
C2AllocationIon(int ionFd, size_t size, int shareFd);
int dup() const;
- C2Error status() const;
+ C2Status status() const;
protected:
class Impl;
@@ -121,18 +121,28 @@
}
Impl(int ionFd, size_t capacity, int shareFd)
- : mHandle(ionFd, -1),
+ : mInit(C2_OK),
+ mHandle(ionFd, -1),
mMapFd(-1),
mCapacity(capacity) {
ion_user_handle_t buffer;
- mInit = ion_import(mHandle.ionFd(), shareFd, &buffer);
- if (mInit == 0) {
+ int ret = ion_import(mHandle.ionFd(), shareFd, &buffer);
+ switch (-ret) {
+ case 0:
mHandle.setBuffer(buffer);
+ break;
+ case EBADF: // bad ion handle - should not happen
+ case ENOTTY: // bad ion driver
+ mInit = C2_CORRUPTED;
+ break;
+ default:
+ mInit = c2_map_errno<ENOMEM, EACCES, EINVAL>(-ret);
+ break;
}
(void)mCapacity; // TODO
}
- C2Error map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+ C2Status 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;
@@ -149,7 +159,7 @@
size_t mapOffset = offset - alignmentBytes;
size_t mapSize = size + alignmentBytes;
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
if (mMapFd == -1) {
int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
@@ -176,7 +186,7 @@
return err;
}
- C2Error unmap(void *addr, size_t size, int *fenceFd) {
+ C2Status unmap(void *addr, size_t size, int *fenceFd) {
if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
size + mMapAlignmentBytes != mMapSize) {
return C2_BAD_VALUE;
@@ -200,7 +210,7 @@
(void)ion_free(mHandle.ionFd(), mHandle.buffer());
}
- C2Error status() const {
+ C2Status status() const {
return mInit;
}
@@ -217,7 +227,7 @@
}
private:
- C2Error mInit;
+ C2Status mInit;
C2HandleIon mHandle;
int mMapFd; // only one for now
void *mMapAddr;
@@ -226,12 +236,12 @@
size_t mCapacity;
};
-C2Error C2AllocationIon::map(
+C2Status C2AllocationIon::map(
size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
return mImpl->map(offset, size, usage, fenceFd, addr);
}
-C2Error C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+C2Status C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
return mImpl->unmap(addr, size, fenceFd);
}
@@ -239,7 +249,7 @@
return mImpl->status() == C2_OK;
}
-C2Error C2AllocationIon::status() const {
+C2Status C2AllocationIon::status() const {
return mImpl->status();
}
@@ -272,7 +282,7 @@
C2AllocatorIon::C2AllocatorIon() : mInit(C2_OK), mIonFd(ion_open()) {
if (mIonFd < 0) {
switch (errno) {
- case ENOENT: mInit = C2_UNSUPPORTED; break;
+ case ENOENT: mInit = C2_OMITTED; break;
default: mInit = c2_map_errno<EACCES>(errno); break;
}
}
@@ -284,7 +294,7 @@
}
}
-C2Error C2AllocatorIon::allocateLinearBuffer(
+C2Status C2AllocatorIon::allocateLinearBuffer(
uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
if (allocation == nullptr) {
return C2_BAD_VALUE;
@@ -292,7 +302,7 @@
allocation->reset();
if (mInit != C2_OK) {
- return C2_UNSUPPORTED;
+ return mInit;
}
// get align, heapMask and flags
@@ -311,18 +321,18 @@
std::shared_ptr<C2AllocationIon> alloc
= std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
- C2Error ret = alloc->status();
+ C2Status ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
}
return ret;
}
-C2Error C2AllocatorIon::recreateLinearBuffer(
+C2Status C2AllocatorIon::recreateLinearBuffer(
const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
*allocation = nullptr;
if (mInit != C2_OK) {
- return C2_UNSUPPORTED;
+ return mInit;
}
if (!C2HandleIon::isValid(handle)) {
@@ -333,7 +343,7 @@
const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
std::shared_ptr<C2AllocationIon> alloc
= std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
- C2Error ret = alloc->status();
+ C2Status 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 1ffbf49..d3f0d70 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(C2Error error)
+ explicit Impl(C2Status error)
: mData(nullptr), mError(error) {}
const uint8_t *data() const {
return mData;
}
- C2Error error() const {
+ C2Status error() const {
return mError;
}
private:
const uint8_t *mData;
- C2Error mError;
+ C2Status mError;
};
C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
: _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
-C2ReadView::C2ReadView(C2Error error)
+C2ReadView::C2ReadView(C2Status error)
: _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
const uint8_t *C2ReadView::data() const {
@@ -167,7 +167,7 @@
return C2ReadView(&newCapacity, data() + offset);
}
-C2Error C2ReadView::error() {
+C2Status C2ReadView::error() const {
return mImpl->error();
}
@@ -176,33 +176,33 @@
explicit Impl(uint8_t *base)
: mBase(base), mError(C2_OK) {}
- explicit Impl(C2Error error)
+ explicit Impl(C2Status error)
: mBase(nullptr), mError(error) {}
uint8_t *base() const {
return mBase;
}
- C2Error error() const {
+ C2Status error() const {
return mError;
}
private:
uint8_t *mBase;
- C2Error mError;
+ C2Status mError;
};
C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
: _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
-C2WriteView::C2WriteView(C2Error error)
+C2WriteView::C2WriteView(C2Status error)
: _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
uint8_t *C2WriteView::base() { return mImpl->base(); }
uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
-C2Error C2WriteView::error() { return mImpl->error(); }
+C2Status C2WriteView::error() const { return mImpl->error(); }
class C2ConstLinearBlock::Impl {
public:
@@ -212,7 +212,7 @@
~Impl() {
if (mBase != nullptr) {
// TODO: fence
- C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+ C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
if (err != C2_OK) {
// TODO: Log?
}
@@ -238,13 +238,13 @@
const uint8_t *base() const { return mBase; }
- C2Error error() const { return mError; }
+ C2Status error() const { return mError; }
private:
std::shared_ptr<C2LinearAllocation> mAllocation;
uint8_t *mBase;
size_t mSize;
- C2Error mError;
+ C2Status mError;
};
C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
@@ -277,7 +277,7 @@
~Impl() {
if (mBase != nullptr) {
// TODO: fence
- C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+ C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
if (err != C2_OK) {
// TODO: Log?
}
@@ -309,7 +309,7 @@
uint8_t *base() const { return mBase; }
- C2Error error() const { return mError; }
+ C2Status error() const { return mError; }
C2Fence fence() const { return mFence; }
@@ -317,7 +317,7 @@
std::shared_ptr<C2LinearAllocation> mAllocation;
uint8_t *mBase;
size_t mSize;
- C2Error mError;
+ C2Status mError;
C2Fence mFence;
};
@@ -349,14 +349,14 @@
const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
-C2Error C2DefaultBlockAllocator::allocateLinearBlock(
+C2Status C2DefaultBlockAllocator::allocateLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
block->reset();
std::shared_ptr<C2LinearAllocation> alloc;
- C2Error err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
+ C2Status err = mAllocator->allocateLinearBuffer(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(C2Error error) : mData(nullptr), mError(error) {}
+ explicit Impl(C2Status error) : mData(nullptr), mError(error) {}
uint8_t *const *data() const { return mData; }
const C2PlaneLayout &layout() const { return mLayout; }
- C2Error error() const { return mError; }
+ C2Status error() const { return mError; }
private:
uint8_t *const *mData;
C2PlaneLayout mLayout;
- C2Error mError;
+ C2Status mError;
};
C2GraphicView::C2GraphicView(
@@ -410,7 +410,7 @@
const C2PlaneLayout& layout)
: _C2PlanarSection(parent), mImpl(new Impl(data, layout)) {}
-C2GraphicView::C2GraphicView(C2Error error)
+C2GraphicView::C2GraphicView(C2Status error)
: _C2PlanarSection(nullptr), mImpl(new Impl(error)) {}
const uint8_t *const *C2GraphicView::data() const {
@@ -437,7 +437,7 @@
return view;
}
-C2Error C2GraphicView::error() const {
+C2Status C2GraphicView::error() const {
return mImpl->error();
}
@@ -453,12 +453,12 @@
}
}
- C2Error map(C2Rect rect) {
+ C2Status map(C2Rect rect) {
if (mData[0] != nullptr) {
// Already mapped.
return C2_OK;
}
- C2Error err = mAllocation->map(
+ C2Status 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 {
- C2Error err = mImpl->map(crop());
+ C2Status err = mImpl->map(crop());
if (err != C2_OK) {
C2DefaultGraphicView view(err);
return C2AcquirableConstGraphicView(err, mFence, view);
@@ -518,13 +518,13 @@
}
}
- C2Error map(C2Rect rect) {
+ C2Status map(C2Rect rect) {
if (mData[0] != nullptr) {
// Already mapped.
return C2_OK;
}
uint8_t *data[C2PlaneLayout::MAX_NUM_PLANES];
- C2Error err = mAllocation->map(
+ C2Status err = mAllocation->map(
rect,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
nullptr,
@@ -560,7 +560,7 @@
: C2Block2D(alloc), mImpl(new Impl(alloc)) {}
C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
- C2Error err = mImpl->map(crop());
+ C2Status 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) {}
-C2Error C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
+C2Status C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
@@ -588,7 +588,7 @@
block->reset();
std::shared_ptr<C2GraphicAllocation> alloc;
- C2Error err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
+ C2Status err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
if (err != C2_OK) {
return err;
}
@@ -650,7 +650,7 @@
const C2BufferData &data() const { return mData; }
- C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+ C2Status 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;
}
- C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+ C2Status 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;
}
- C2Error setInfo(const std::shared_ptr<C2Info> &info) {
+ C2Status 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(); }
-C2Error C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
}
-C2Error C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
}
@@ -732,7 +732,7 @@
return mImpl->infos();
}
-C2Error C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
+C2Status 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 f21a3f0..42bdf0e 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -35,7 +35,7 @@
C2PlatformAllocatorStore(
/* ionmapper */
);
- virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
+ virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
private:
// returns a shared-singleton ion allocator
@@ -48,7 +48,7 @@
C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
}
-status_t C2PlatformAllocatorStore::createAllocator(
+C2Status C2PlatformAllocatorStore::createAllocator(
ID id, std::shared_ptr<C2Allocator> *const allocator) {
allocator->reset();
switch (id) {
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 94f74c8..9bfd987 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -30,17 +30,17 @@
typedef std::function<int (C2MemoryUsage, size_t,
/* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
- virtual C2Error allocateGraphicBuffer(
+ virtual C2Status allocateGraphicBuffer(
uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
- virtual C2Error recreateGraphicBuffer(
+ virtual C2Status recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
C2AllocatorGralloc();
- C2Error status() const;
+ C2Status status() const;
virtual ~C2AllocatorGralloc();
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index a453a7d..00c33fe 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -29,22 +29,22 @@
typedef std::function<int (C2MemoryUsage, size_t,
/* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
- virtual C2Error allocateLinearBuffer(
+ virtual C2Status allocateLinearBuffer(
uint32_t capacity, C2MemoryUsage usage,
std::shared_ptr<C2LinearAllocation> *allocation) override;
- virtual C2Error recreateLinearBuffer(
+ virtual C2Status recreateLinearBuffer(
const C2Handle *handle,
std::shared_ptr<C2LinearAllocation> *allocation) override;
C2AllocatorIon();
- C2Error status() const { return mInit; }
+ C2Status status() const { return mInit; }
virtual ~C2AllocatorIon();
private:
- C2Error mInit;
+ C2Status 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 6a8f94e..f1e8acb 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -29,7 +29,7 @@
virtual ~C2DefaultBlockAllocator() = default;
- virtual C2Error allocateLinearBlock(
+ virtual C2Status allocateLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
@@ -45,7 +45,7 @@
virtual ~C2DefaultGraphicBlockAllocator() = default;
- virtual C2Error allocateGraphicBlock(
+ virtual C2Status allocateGraphicBlock(
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 f834cdb..aea3a6f 100644
--- a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
+++ b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
@@ -23,32 +23,32 @@
namespace android {
// standard ERRNO mappings
-template<int N> constexpr C2Error _c2_errno2error_impl();
-template<> constexpr C2Error _c2_errno2error_impl<0>() { return C2_OK; }
-template<> constexpr C2Error _c2_errno2error_impl<EINVAL>() { return C2_BAD_VALUE; }
-template<> constexpr C2Error _c2_errno2error_impl<EACCES>() { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<EPERM>() { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<ENOMEM>() { return C2_NO_MEMORY; }
+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; }
-// map standard errno-s to the equivalent C2Error
+// map standard errno-s to the equivalent C2Status
template<int... N> struct _c2_map_errno_impl;
template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
- static C2Error map(int result) {
+ static C2Status map(int result) {
if (result == E) {
- return _c2_errno2error_impl<E>();
+ return _c2_errno2status_impl <E>();
} else {
return _c2_map_errno_impl<N...>::map(result);
}
}
};
template<> struct _c2_map_errno_impl<> {
- static C2Error map(int result) {
+ static C2Status map(int result) {
return result == 0 ? C2_OK : C2_CORRUPTED;
}
};
template<int... N>
-C2Error c2_map_errno(int result) {
+C2Status c2_map_errno(int result) {
return _c2_map_errno_impl<N...>::map(result);
}
diff --git a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
index edae303..5f09889 100644
--- a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
+++ b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
@@ -278,7 +278,7 @@
C2_HIDE
void addC2Params(std::list<const C2FieldDescriptor> &fields, _C2Tuple<T, Params...> *)
{
- //C2Param::index_t index = T::baseIndex;
+ //C2Param::index_t index = T::coreIndex;
//(void)index;
fields.insert(fields.end(), T::fieldList);
addC2Params(fields, (_C2Tuple<Params...> *)nullptr);
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 3aa8c38..77db255 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -94,11 +94,15 @@
bool validateField(
const C2FieldSupportedValues &supportedValues, const T &value) {
switch (supportedValues.type) {
+ case C2FieldSupportedValues::EMPTY:
+ {
+ return false;
+ }
case C2FieldSupportedValues::RANGE:
{
// TODO: handle step, nom, denom
- return Getter<T>::get(supportedValues.range.min) < value
- && value < Getter<T>::get(supportedValues.range.max);
+ return Getter<T>::get(supportedValues.range.min) <= value
+ && value <= Getter<T>::get(supportedValues.range.max);
}
case C2FieldSupportedValues::VALUES:
{
@@ -153,7 +157,7 @@
const C2FieldSupportedValues &supportedValues = mSupportedValues.at(field).supported;
if (!validateField(supportedValues, param->mValue)) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
}
return nullptr;
}
@@ -171,13 +175,13 @@
const C2FieldSupportedValues &supportedWidth = mSupportedValues.at(field).supported;
if (!validateField(supportedWidth, param->mWidth)) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
}
field = C2ParamField(param, &T::mHeight);
const C2FieldSupportedValues &supportedHeight = mSupportedValues.at(field).supported;
if (!validateField(supportedHeight, param->mHeight)) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
}
return nullptr;
}
@@ -191,7 +195,7 @@
T* param = (T*)c2param;
if (strncmp(param->m.mValue, mExpected, param->flexCount()) != 0) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {C2ParamField(param, &T::m), C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {C2ParamField(param, &T::m), nullptr}, {}});
}
return nullptr;
}
@@ -209,15 +213,15 @@
} // namespace
#define CASE(member) \
- case decltype(component->member)::baseIndex: \
+ case decltype(component->member)::coreIndex: \
return std::unique_ptr<C2StructDescriptor>(new C2StructDescriptor( \
static_cast<decltype(component->member) *>(nullptr)))
class C2SoftAvcDecIntf::ParamReflector : public C2ParamReflector {
public:
- virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) override {
+ virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex coreIndex) override {
constexpr C2SoftAvcDecIntf *component = nullptr;
- switch (paramIndex.baseIndex()) {
+ switch (coreIndex.coreIndex()) {
CASE(mDomainInfo);
CASE(mInputStreamCount);
CASE(mInputStreamFormat);
@@ -226,7 +230,7 @@
CASE(mMaxVideoSizeHint);
// port mime configs are stored as unique_ptr.
- case C2PortMimeConfig::baseIndex:
+ case C2PortMimeConfig::coreIndex:
return std::unique_ptr<C2StructDescriptor>(new C2StructDescriptor(
static_cast<C2PortMimeConfig *>(nullptr)));
}
@@ -428,7 +432,7 @@
return mId;
}
-status_t C2SoftAvcDecIntf::query_nb(
+C2Status C2SoftAvcDecIntf::query_nb(
const std::vector<C2Param* const> & stackParams,
const std::vector<C2Param::Index> & heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -461,10 +465,10 @@
return C2_OK;
}
-status_t C2SoftAvcDecIntf::config_nb(
+C2Status C2SoftAvcDecIntf::config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
- status_t err = C2_OK;
+ C2Status err = C2_OK;
for (C2Param *param : params) {
uint32_t index = restoreIndex(param);
if (mParams.count(index) == 0) {
@@ -485,45 +489,48 @@
return err;
}
-status_t C2SoftAvcDecIntf::commit_sm(
+C2Status C2SoftAvcDecIntf::commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
// TODO
return config_nb(params, failures);
}
-status_t C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
// Tunneling is not supported
(void) targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
-status_t C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
// Tunneling is not supported
(void) targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
std::shared_ptr<C2ParamReflector> C2SoftAvcDecIntf::getParamReflector() const {
return mParamReflector;
}
-status_t C2SoftAvcDecIntf::getSupportedParams(
+C2Status C2SoftAvcDecIntf::getSupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
params->insert(params->begin(), mParamDescs.begin(), mParamDescs.end());
return C2_OK;
}
-status_t C2SoftAvcDecIntf::getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const {
- for (const auto &field : fields) {
- if (mSupportedValues.count(field) == 0) {
- return BAD_VALUE;
+C2Status C2SoftAvcDecIntf::getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const {
+ C2Status res = C2_OK;
+ for (C2FieldSupportedValuesQuery &query : fields) {
+ if (mSupportedValues.count(query.field) == 0) {
+ query.status = C2_BAD_INDEX;
+ res = C2_BAD_INDEX;
+ } else {
+ query.status = C2_OK;
+ query.values = mSupportedValues.at(query.field).supported;
}
- values->push_back(mSupportedValues.at(field).supported);
}
- return C2_OK;
+ return res;
}
void C2SoftAvcDecIntf::updateSupportedValues() {
@@ -644,7 +651,7 @@
CHECK_EQ(deInitDecoder(), (status_t)OK);
}
-status_t C2SoftAvcDec::queue_nb(
+C2Status C2SoftAvcDec::queue_nb(
std::list<std::unique_ptr<C2Work>>* const items) {
if (!mThread->isRunning()) {
return C2_CORRUPTED;
@@ -659,13 +666,13 @@
return C2_OK;
}
-status_t C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
+C2Status C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
// Tunneling is not supported
(void) items;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
-status_t C2SoftAvcDec::flush_sm(
+C2Status C2SoftAvcDec::flush_sm(
bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
// Tunneling is not supported
(void) flushThrough;
@@ -691,7 +698,7 @@
return C2_OK;
}
-status_t C2SoftAvcDec::drain_nb(bool drainThrough) {
+C2Status C2SoftAvcDec::drain_nb(bool drainThrough) {
// Tunneling is not supported
(void) drainThrough;
@@ -707,14 +714,14 @@
return C2_OK;
}
-status_t C2SoftAvcDec::start() {
+C2Status C2SoftAvcDec::start() {
if (!mThread->isRunning()) {
mThread->start(shared_from_this());
}
return C2_OK;
}
-status_t C2SoftAvcDec::stop() {
+C2Status 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);
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index 6a83d1d..cc33083 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -85,24 +85,23 @@
// From C2ComponentInterface
virtual C2String getName() const override;
virtual node_id getId() const override;
- virtual status_t query_nb(
+ virtual C2Status 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 status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
- virtual status_t commit_sm(
+ virtual C2Status commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
- virtual status_t createTunnel_sm(node_id targetComponent) override;
- virtual status_t releaseTunnel_sm(node_id targetComponent) 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 status_t getSupportedParams(
+ virtual C2Status getSupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override;
- virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const override;
+ virtual C2Status getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const override;
private:
class ParamReflector;
@@ -150,13 +149,13 @@
virtual ~C2SoftAvcDec();
// From C2Component
- virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
- virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) override;
- virtual status_t flush_sm(
+ 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 status_t drain_nb(bool drainThrough) override;
- virtual status_t start() override;
- virtual status_t stop() override;
+ virtual C2Status drain_nb(bool drainThrough) override;
+ virtual C2Status start() override;
+ virtual C2Status stop() override;
virtual void reset() override;
virtual void release() override;
virtual std::shared_ptr<C2ComponentInterface> intf() override;
@@ -228,9 +227,9 @@
bool mChangingResolution;
bool mFlushNeeded;
bool mSignalledError;
- int32_t mWidth;
- int32_t mHeight;
- int32_t mStride;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mStride;
size_t mInputOffset;
void processQueue();
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 143fd59..4c2e0d4 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -49,6 +49,10 @@
const int64_t LiveSession::kUpSwitchMarginUs = 5000000ll;
const int64_t LiveSession::kResumeThresholdUs = 100000ll;
+//TODO: redefine this mark to a fair value
+// default buffer underflow mark
+static const int kUnderflowMarkMs = 1000; // 1 second
+
struct LiveSession::BandwidthEstimator : public RefBase {
BandwidthEstimator();
@@ -840,7 +844,7 @@
// (If we don't have that cushion we'd rather cancel and try again.)
int64_t delayUs =
switchUp ?
- (mBufferingSettings.mRebufferingWatermarkLowMs * 1000ll + 1000000ll)
+ (kUnderflowMarkMs * 1000ll + 1000000ll)
: 0;
bool needResumeUntil = false;
sp<AMessage> stopParams = msg;
@@ -2202,14 +2206,14 @@
++activeCount;
int64_t readyMarkUs =
(mInPreparationPhase ?
- mBufferingSettings.mInitialWatermarkMs :
- mBufferingSettings.mRebufferingWatermarkHighMs) * 1000ll;
+ mBufferingSettings.mInitialMarkMs :
+ mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
if (bufferedDurationUs > readyMarkUs
|| mPacketSources[i]->isFinished(0)) {
++readyCount;
}
if (!mPacketSources[i]->isFinished(0)) {
- if (bufferedDurationUs < mBufferingSettings.mRebufferingWatermarkLowMs * 1000ll) {
+ if (bufferedDurationUs < kUnderflowMarkMs * 1000ll) {
++underflowCount;
}
if (bufferedDurationUs > mUpSwitchMark) {
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index cb9827f..217e0c9 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -311,7 +311,7 @@
int MtpFfsHandle::configure(bool usePtp) {
// Wait till previous server invocation has closed
- if (!mLock.try_lock_for(std::chrono::milliseconds(1000))) {
+ if (!mLock.try_lock_for(std::chrono::milliseconds(300))) {
LOG(ERROR) << "MtpServer was unable to get configure lock";
return -1;
}
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 7b3e96e..6080868 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -134,12 +134,11 @@
sHandle = new MtpDevHandle();
}
}
- if (sHandle->configure(usePtp)) {
- ALOGE("Failed to configure Mtp driver!");
- return -1;
- }
+
+ int ret = sHandle->configure(usePtp);
+ if (ret) ALOGE("Failed to configure MTP driver!");
android::base::SetProperty("sys.usb.ffs.mtp.ready", "1");
- return 0;
+ return ret;
}
void MtpServer::addStorage(MtpStorage* storage) {
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index c4ff537..20b1667 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -37,8 +37,8 @@
mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
}
-// Can only be called by free() with mLock hold
AImage::~AImage() {
+ Mutex::Autolock _l(mLock);
if (!mIsClosed) {
LOG_ALWAYS_FATAL(
"Error: AImage %p is deleted before returning buffer to AImageReader!", this);
@@ -78,7 +78,6 @@
ALOGE("Cannot free AImage before close!");
return;
}
- Mutex::Autolock _l(mLock);
delete this;
}
diff --git a/media/ndk/OWNERS b/media/ndk/OWNERS
index 43e4bb3..11e8340 100644
--- a/media/ndk/OWNERS
+++ b/media/ndk/OWNERS
@@ -1 +1,5 @@
marcone@google.com
+# For AImage/AImageReader
+etalvala@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 31f0550..9bd68e1 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -35,7 +35,8 @@
* A device mask for all audio input devices that are considered "virtual" when evaluating
* active inputs in getActiveInputs()
*/
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|\
+ AUDIO_DEVICE_IN_BUS|AUDIO_DEVICE_IN_FM_TUNER)
/**
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 9c24641..80a8dc6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -755,6 +755,13 @@
{
routing_strategy strategy = getStrategy(stream);
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
+
+ // Note that related method getOutputForAttr() uses getOutputForDevice() not selectOutput().
+ // We use selectOutput() here since we don't have the desired AudioTrack sample rate,
+ // format, flags, etc. This may result in some discrepancy for functions that utilize
+ // getOutput() solely on audio_stream_type such as AudioSystem::getOutputFrameCount()
+ // and AudioSystem::getOutputSamplingRate().
+
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID);
@@ -1102,8 +1109,9 @@
int commonFlags = popcount(outputDesc->mProfile->getFlags() & flags);
if (commonFlags >= maxCommonFlags) {
if (commonFlags == maxCommonFlags) {
- if (AudioPort::isBetterFormatMatch(
- outputDesc->mFormat, bestFormatForFlags, format)) {
+ if (format != AUDIO_FORMAT_INVALID
+ && AudioPort::isBetterFormatMatch(
+ outputDesc->mFormat, bestFormatForFlags, format)) {
outputForFlags = outputs[i];
bestFormatForFlags = outputDesc->mFormat;
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index f985382..a376ab4 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -530,10 +530,11 @@
}
int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
+ std::vector<int> surfaceIds;
err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
streamInfo.height, streamInfo.format, streamInfo.dataSpace,
static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
- &streamId, outputConfiguration.getSurfaceSetID(), isShared);
+ &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared);
if (err != OK) {
res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -545,7 +546,8 @@
for (auto& binder : binders) {
ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d",
__FUNCTION__, binder.get(), streamId, i);
- mStreamMap.add(binder, StreamSurfaceId(streamId, i++));
+ mStreamMap.add(binder, StreamSurfaceId(streamId, surfaceIds[i]));
+ i++;
}
mStreamInfoMap[streamId] = streamInfo;
@@ -592,10 +594,12 @@
}
int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
std::vector<sp<Surface>> noSurface;
+ std::vector<int> surfaceIds;
err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
height, format, dataSpace,
static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
- &streamId, outputConfiguration.getSurfaceSetID(), isShared, consumerUsage);
+ &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared,
+ consumerUsage);
if (err != OK) {
res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -721,6 +725,130 @@
return res;
}
+binder::Status CameraDeviceClient::updateOutputConfiguration(int streamId,
+ const hardware::camera2::params::OutputConfiguration &outputConfiguration) {
+ ATRACE_CALL();
+
+ binder::Status res;
+ if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+
+ if (!mDevice.get()) {
+ return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+ }
+
+ const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
+ outputConfiguration.getGraphicBufferProducers();
+ auto producerCount = bufferProducers.size();
+ if (producerCount == 0) {
+ ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "bufferProducers must not be empty");
+ }
+
+ // The first output is the one associated with the output configuration.
+ // It should always be present, valid and the corresponding stream id should match.
+ sp<IBinder> binder = IInterface::asBinder(bufferProducers[0]);
+ ssize_t index = mStreamMap.indexOfKey(binder);
+ if (index == NAME_NOT_FOUND) {
+ ALOGE("%s: Outputconfiguration is invalid", __FUNCTION__);
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "OutputConfiguration is invalid");
+ }
+ if (mStreamMap.valueFor(binder).streamId() != streamId) {
+ ALOGE("%s: Stream Id: %d provided doesn't match the id: %d in the stream map",
+ __FUNCTION__, streamId, mStreamMap.valueFor(binder).streamId());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Stream id is invalid");
+ }
+
+ std::vector<size_t> removedSurfaceIds;
+ std::vector<sp<IBinder>> removedOutputs;
+ std::vector<sp<Surface>> newOutputs;
+ std::vector<OutputStreamInfo> streamInfos;
+ KeyedVector<sp<IBinder>, sp<IGraphicBufferProducer>> newOutputsMap;
+ for (auto &it : bufferProducers) {
+ newOutputsMap.add(IInterface::asBinder(it), it);
+ }
+
+ for (size_t i = 0; i < mStreamMap.size(); i++) {
+ ssize_t idx = newOutputsMap.indexOfKey(mStreamMap.keyAt(i));
+ if (idx == NAME_NOT_FOUND) {
+ if (mStreamMap[i].streamId() == streamId) {
+ removedSurfaceIds.push_back(mStreamMap[i].surfaceId());
+ removedOutputs.push_back(mStreamMap.keyAt(i));
+ }
+ } else {
+ if (mStreamMap[i].streamId() != streamId) {
+ ALOGE("%s: Output surface already part of a different stream", __FUNCTION__);
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Target Surface is invalid");
+ }
+ newOutputsMap.removeItemsAt(idx);
+ }
+ }
+
+ for (size_t i = 0; i < newOutputsMap.size(); i++) {
+ OutputStreamInfo outInfo;
+ sp<Surface> surface;
+ res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
+ newOutputsMap.valueAt(i));
+ if (!res.isOk())
+ return res;
+
+ // Stream sharing is only supported for IMPLEMENTATION_DEFINED
+ // formats.
+ if (outInfo.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ String8 msg = String8::format("Camera %s: Stream sharing is only supported for "
+ "IMPLEMENTATION_DEFINED format", mCameraIdStr.string());
+ ALOGW("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+ streamInfos.push_back(outInfo);
+ newOutputs.push_back(surface);
+ }
+
+ //Trivial case no changes required
+ if (removedSurfaceIds.empty() && newOutputs.empty()) {
+ return binder::Status::ok();
+ }
+
+ KeyedVector<sp<Surface>, size_t> outputMap;
+ auto ret = mDevice->updateStream(streamId, newOutputs, streamInfos, removedSurfaceIds,
+ &outputMap);
+ if (ret != OK) {
+ switch (ret) {
+ case NAME_NOT_FOUND:
+ case BAD_VALUE:
+ case -EBUSY:
+ res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Camera %s: Error updating stream: %s (%d)",
+ mCameraIdStr.string(), strerror(ret), ret);
+ break;
+ default:
+ res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
+ "Camera %s: Error updating stream: %s (%d)",
+ mCameraIdStr.string(), strerror(ret), ret);
+ break;
+ }
+ } else {
+ for (const auto &it : removedOutputs) {
+ mStreamMap.removeItem(it);
+ }
+
+ for (size_t i = 0; i < outputMap.size(); i++) {
+ mStreamMap.add(IInterface::asBinder(outputMap.keyAt(i)->getIGraphicBufferProducer()),
+ StreamSurfaceId(streamId, outputMap.valueAt(i)));
+ }
+
+ ALOGV("%s: Camera %s: Successful stream ID %d update",
+ __FUNCTION__, mCameraIdStr.string(), streamId);
+ }
+
+ return res;
+}
+
bool CameraDeviceClient::isPublicFormat(int32_t format)
{
switch(format) {
@@ -1242,15 +1370,12 @@
}
std::vector<sp<Surface>> consumerSurfaces;
- std::vector<size_t> consumerSurfaceIds;
- size_t surfaceId = 0;
for (auto& bufferProducer : bufferProducers) {
// Don't create multiple streams for the same target surface
ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
if (index != NAME_NOT_FOUND) {
ALOGV("Camera %s: Surface already has a stream created "
" for it (ID %zd)", mCameraIdStr.string(), index);
- surfaceId++;
continue;
}
@@ -1262,8 +1387,6 @@
return res;
consumerSurfaces.push_back(surface);
- consumerSurfaceIds.push_back(surfaceId);
- surfaceId++;
}
// Gracefully handle case where finalizeOutputConfigurations is called
@@ -1275,12 +1398,13 @@
// Finish the deferred stream configuration with the surface.
status_t err;
- err = mDevice->setConsumerSurfaces(streamId, consumerSurfaces);
+ std::vector<int> consumerSurfaceIds;
+ err = mDevice->setConsumerSurfaces(streamId, consumerSurfaces, &consumerSurfaceIds);
if (err == OK) {
for (size_t i = 0; i < consumerSurfaces.size(); i++) {
sp<IBinder> binder = IInterface::asBinder(
consumerSurfaces[i]->getIGraphicBufferProducer());
- ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %zu", __FUNCTION__,
+ ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d", __FUNCTION__,
binder.get(), streamId, consumerSurfaceIds[i]);
mStreamMap.add(binder, StreamSurfaceId(streamId, consumerSurfaceIds[i]));
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 50661cb..e1a11db 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -26,6 +26,8 @@
#include "common/FrameProcessorBase.h"
#include "common/Camera2ClientBase.h"
+using android::camera3::OutputStreamInfo;
+
namespace android {
struct CameraDeviceClientBase :
@@ -131,6 +133,10 @@
// Prepare stream by preallocating up to maxCount of its buffers
virtual binder::Status prepare2(int32_t maxCount, int32_t streamId) override;
+ // Update an output configuration
+ virtual binder::Status updateOutputConfiguration(int streamId,
+ const hardware::camera2::params::OutputConfiguration &outputConfiguration) override;
+
// Finalize the output configurations with surfaces not added before.
virtual binder::Status finalizeOutputConfigurations(int32_t streamId,
const hardware::camera2::params::OutputConfiguration &outputConfiguration) override;
@@ -206,24 +212,6 @@
}; // class StreamSurfaceId
- // OutputStreamInfo describes the property of a camera stream.
- class OutputStreamInfo {
- public:
- int width;
- int height;
- int format;
- android_dataspace dataSpace;
- uint64_t consumerUsage;
- bool finalized = false;
- OutputStreamInfo() :
- width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
- consumerUsage(0) {}
- OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
- uint64_t _consumerUsage) :
- width(_width), height(_height), format(_format),
- dataSpace(_dataSpace), consumerUsage(_consumerUsage) {}
- };
-
private:
/** ICameraDeviceUser interface-related private members */
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 51ef160..4ce82dc 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -156,13 +156,14 @@
result = " Device dump:\n";
write(fd, result.string(), result.size());
- if (!mDevice.get()) {
+ sp<CameraDeviceBase> device = mDevice;
+ if (!device.get()) {
result = " *** Device is detached\n";
write(fd, result.string(), result.size());
return NO_ERROR;
}
- status_t res = mDevice->dump(fd, args);
+ status_t res = device->dump(fd, args);
if (res != OK) {
result = String8::format(" Error dumping device: %s (%d)",
strerror(-res), res);
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 3919bfa..68384b0 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -23,6 +23,7 @@
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
#include <utils/Timers.h>
#include <utils/List.h>
@@ -118,6 +119,7 @@
virtual status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) = 0;
@@ -131,6 +133,7 @@
virtual status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) = 0;
@@ -347,8 +350,15 @@
* Set the deferred consumer surface and finish the rest of the stream configuration.
*/
virtual status_t setConsumerSurfaces(int streamId,
- const std::vector<sp<Surface>>& consumers) = 0;
+ const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds /*out*/) = 0;
+ /**
+ * Update a given stream.
+ */
+ virtual status_t updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
+ const std::vector<android::camera3::OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds,
+ KeyedVector<sp<Surface>, size_t> *outputMap/*out*/) = 0;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index ced1d3a..e0a2dd4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1222,7 +1222,7 @@
status_t Camera3Device::createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
- int streamSetId, bool isShared, uint64_t consumerUsage) {
+ std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -1234,14 +1234,15 @@
consumers.push_back(consumer);
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
- format, dataSpace, rotation, id, streamSetId, isShared, consumerUsage);
+ format, dataSpace, rotation, id, surfaceIds, streamSetId, isShared, consumerUsage);
}
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
- int streamSetId, bool isShared, uint64_t consumerUsage) {
+ std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
+
Mutex::Autolock il(mInterfaceLock);
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Mutex::Autolock l(mLock);
@@ -1330,6 +1331,19 @@
width, height, format, dataSpace, rotation,
mTimestampOffset, streamSetId);
}
+
+ size_t consumerCount = consumers.size();
+ for (size_t i = 0; i < consumerCount; i++) {
+ int id = newStream->getSurfaceId(consumers[i]);
+ if (id < 0) {
+ SET_ERR_L("Invalid surface id");
+ return BAD_VALUE;
+ }
+ if (surfaceIds != nullptr) {
+ surfaceIds->push_back(id);
+ }
+ }
+
newStream->setStatusTracker(mStatusTracker);
newStream->setBufferManager(mBufferManager);
@@ -1936,10 +1950,15 @@
}
status_t Camera3Device::setConsumerSurfaces(int streamId,
- const std::vector<sp<Surface>>& consumers) {
+ const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
ATRACE_CALL();
ALOGV("%s: Camera %s: set consumer surface for stream %d",
__FUNCTION__, mId.string(), streamId);
+
+ if (surfaceIds == nullptr) {
+ return BAD_VALUE;
+ }
+
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
@@ -1960,6 +1979,15 @@
return res;
}
+ for (auto &consumer : consumers) {
+ int id = stream->getSurfaceId(consumer);
+ if (id < 0) {
+ CLOGE("Invalid surface id!");
+ return BAD_VALUE;
+ }
+ surfaceIds->push_back(id);
+ }
+
if (stream->isConsumerConfigurationDeferred()) {
if (!stream->isConfiguring()) {
CLOGE("Stream %d was already fully configured.", streamId);
@@ -1977,6 +2005,40 @@
return OK;
}
+status_t Camera3Device::updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
+ const std::vector<OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds, KeyedVector<sp<Surface>, size_t> *outputMap) {
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ ssize_t idx = mOutputStreams.indexOfKey(streamId);
+ if (idx == NAME_NOT_FOUND) {
+ CLOGE("Stream %d is unknown", streamId);
+ return idx;
+ }
+
+ for (const auto &it : removedSurfaceIds) {
+ if (mRequestThread->isOutputSurfacePending(streamId, it)) {
+ CLOGE("Shared surface still part of a pending request!");
+ return -EBUSY;
+ }
+ }
+
+ sp<Camera3OutputStreamInterface> stream = mOutputStreams[idx];
+ status_t res = stream->updateStream(newSurfaces, outputInfo, removedSurfaceIds, outputMap);
+ if (res != OK) {
+ CLOGE("Stream %d failed to update stream (error %d %s) ",
+ streamId, res, strerror(-res));
+ if (res == UNKNOWN_ERROR) {
+ SET_ERR_L("%s: Stream update failed to revert to previous output configuration!",
+ __FUNCTION__);
+ }
+ return res;
+ }
+
+ return res;
+}
+
/**
* Camera3Device private methods
*/
@@ -4342,6 +4404,46 @@
return false;
}
+bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mRequestLock);
+
+ for (const auto& nextRequest : mNextRequests) {
+ for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
+ if (s.first == streamId) {
+ const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
+ if (it != s.second.end()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ for (const auto& request : mRequestQueue) {
+ for (const auto& s : request->mOutputSurfaces) {
+ if (s.first == streamId) {
+ const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
+ if (it != s.second.end()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ for (const auto& request : mRepeatingRequests) {
+ for (const auto& s : request->mOutputSurfaces) {
+ if (s.first == streamId) {
+ const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
+ if (it != s.second.end()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
nsecs_t Camera3Device::getExpectedInFlightDuration() {
ATRACE_CALL();
Mutex::Autolock al(mInFlightLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index fbbbd08..357b893 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -44,6 +44,8 @@
#include "utils/LatencyHistogram.h"
#include <camera_metadata_hidden.h>
+using android::camera3::OutputStreamInfo;
+
/**
* Function pointer types with C calling convention to
* use for HAL callback functions.
@@ -117,11 +119,13 @@
status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) override;
@@ -176,7 +180,17 @@
* Set the deferred consumer surfaces to the output stream and finish the deferred
* consumer configuration.
*/
- status_t setConsumerSurfaces(int streamId, const std::vector<sp<Surface>>& consumers) override;
+ status_t setConsumerSurfaces(
+ int streamId, const std::vector<sp<Surface>>& consumers,
+ std::vector<int> *surfaceIds /*out*/) override;
+
+ /**
+ * Update a given stream.
+ */
+ status_t updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
+ const std::vector<OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds,
+ KeyedVector<sp<Surface>, size_t> *outputMap/*out*/);
private:
@@ -705,6 +719,12 @@
*/
bool isStreamPending(sp<camera3::Camera3StreamInterface>& stream);
+ /**
+ * Returns true if the surface is a target of any queued or repeating
+ * capture request
+ */
+ bool isOutputSurfacePending(int streamId, size_t surfaceId);
+
// dump processCaptureRequest latency
void dumpCaptureRequestLatency(int fd, const char* name) {
mRequestLatency.dump(fd, name);
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 6e2978f..4b36ea2 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -113,6 +113,15 @@
__FUNCTION__, mId);
return INVALID_OPERATION;
}
+
+status_t Camera3DummyStream::updateStream(const std::vector<sp<Surface>> &/*outputSurfaces*/,
+ const std::vector<OutputStreamInfo> &/*outputInfo*/,
+ const std::vector<size_t> &/*removedSurfaceIds*/,
+ KeyedVector<sp<Surface>, size_t> * /*outputMap*/) {
+ ALOGE("%s: this method is not supported!", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 492fb49..3212031 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -71,6 +71,19 @@
*/
virtual status_t setConsumers(const std::vector<sp<Surface>>& consumers);
+ /**
+ * Query the output surface id.
+ */
+ virtual ssize_t getSurfaceId(const sp<Surface> &/*surface*/) { return 0; }
+
+ /**
+ * Update the stream output surfaces.
+ */
+ virtual status_t updateStream(const std::vector<sp<Surface>> &outputSurfaces,
+ const std::vector<OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds,
+ KeyedVector<sp<Surface>, size_t> *outputMap/*out*/);
+
protected:
/**
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 0a02a32..329172a 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -691,6 +691,14 @@
return OK;
}
+status_t Camera3OutputStream::updateStream(const std::vector<sp<Surface>> &/*outputSurfaces*/,
+ const std::vector<OutputStreamInfo> &/*outputInfo*/,
+ const std::vector<size_t> &/*removedSurfaceIds*/,
+ KeyedVector<sp<Surface>, size_t> * /*outputMapo*/) {
+ ALOGE("%s: this method is not supported!", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
void Camera3OutputStream::BufferReleasedListener::onBufferReleased() {
sp<Camera3OutputStream> stream = mParent.promote();
if (stream == nullptr) {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 7023d5d..fbb14fe 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -172,6 +172,19 @@
*/
status_t setBufferManager(sp<Camera3BufferManager> bufferManager);
+ /**
+ * Query the ouput surface id.
+ */
+ virtual ssize_t getSurfaceId(const sp<Surface> &/*surface*/) { return 0; }
+
+ /**
+ * Update the stream output surfaces.
+ */
+ virtual status_t updateStream(const std::vector<sp<Surface>> &outputSurfaces,
+ const std::vector<OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds,
+ KeyedVector<sp<Surface>, size_t> *outputMap/*out*/);
+
protected:
Camera3OutputStream(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height, int format,
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 8107dd0..edfbab1 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA3_OUTPUT_STREAM_INTERFACE_H
#include "Camera3StreamInterface.h"
+#include <utils/KeyedVector.h>
namespace android {
@@ -59,6 +60,19 @@
*
*/
virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) = 0;
+
+ /**
+ * Query the surface id.
+ */
+ virtual ssize_t getSurfaceId(const sp<Surface> &surface) = 0;
+
+ /**
+ * Update the stream output surfaces.
+ */
+ virtual status_t updateStream(const std::vector<sp<Surface>> &outputSurfaces,
+ const std::vector<OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds,
+ KeyedVector<sp<Surface>, size_t> *outputMap/*out*/) = 0;
};
} // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index fb7472b..1c9417b 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -20,6 +20,8 @@
namespace camera3 {
+const size_t Camera3SharedOutputStream::kMaxOutputs;
+
Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
const std::vector<sp<Surface>>& surfaces,
uint32_t width, uint32_t height, int format,
@@ -28,8 +30,14 @@
nsecs_t timestampOffset, int setId) :
Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
format, dataSpace, rotation, consumerUsage,
- timestampOffset, setId),
- mSurfaces(surfaces) {
+ timestampOffset, setId) {
+ size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
+ if (surfaces.size() > consumerCount) {
+ ALOGE("%s: Trying to add more consumers than the maximum ", __func__);
+ }
+ for (size_t i = 0; i < consumerCount; i++) {
+ mSurfaces[i] = surfaces[i];
+ }
}
Camera3SharedOutputStream::~Camera3SharedOutputStream() {
@@ -44,7 +52,16 @@
uint64_t usage;
getEndpointUsage(&usage);
- res = mStreamSplitter->connect(mSurfaces, usage, camera3_stream::max_buffers, &mConsumer);
+ std::unordered_map<size_t, sp<Surface>> initialSurfaces;
+ for (size_t i = 0; i < kMaxOutputs; i++) {
+ if (mSurfaces[i] != nullptr) {
+ initialSurfaces.emplace(i, mSurfaces[i]);
+ }
+ }
+
+ android::PixelFormat format = isFormatOverridden() ? getOriginalFormat() : getFormat();
+ res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera3_stream::max_buffers,
+ getWidth(), getHeight(), format, &mConsumer);
if (res != OK) {
ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
__FUNCTION__, strerror(-res), res);
@@ -68,7 +85,11 @@
bool Camera3SharedOutputStream::isConsumerConfigurationDeferred(size_t surface_id) const {
Mutex::Autolock l(mLock);
- return (surface_id >= mSurfaces.size());
+ if (surface_id >= kMaxOutputs) {
+ return true;
+ }
+
+ return (mSurfaces[surface_id] == nullptr);
}
status_t Camera3SharedOutputStream::setConsumers(const std::vector<sp<Surface>>& surfaces) {
@@ -85,11 +106,17 @@
return INVALID_OPERATION;
}
- mSurfaces.push_back(surface);
+ ssize_t id = getNextSurfaceIdLocked();
+ if (id < 0) {
+ ALOGE("%s: No surface ids available!", __func__);
+ return NO_MEMORY;
+ }
+
+ mSurfaces[id] = surface;
// Only call addOutput if the splitter has been connected.
if (mStreamSplitter != nullptr) {
- ret = mStreamSplitter->addOutput(surface);
+ ret = mStreamSplitter->addOutput(id, surface);
if (ret != OK) {
ALOGE("%s: addOutput failed with error code %d", __FUNCTION__, ret);
return ret;
@@ -200,9 +227,9 @@
// Called before shared buffer queue is constructed.
*usage = getPresetConsumerUsage();
- for (const auto& surface : mSurfaces) {
- if (surface != nullptr) {
- res = getEndpointUsageForSurface(&u, surface);
+ for (size_t id = 0; id < kMaxOutputs; id++) {
+ if (mSurfaces[id] != nullptr) {
+ res = getEndpointUsageForSurface(&u, mSurfaces[id]);
*usage |= u;
}
}
@@ -215,6 +242,140 @@
return res;
}
+ssize_t Camera3SharedOutputStream::getNextSurfaceIdLocked() {
+ ssize_t id = -1;
+ for (size_t i = 0; i < kMaxOutputs; i++) {
+ if (mSurfaces[i] == nullptr) {
+ id = i;
+ break;
+ }
+ }
+
+ return id;
+}
+
+ssize_t Camera3SharedOutputStream::getSurfaceId(const sp<Surface> &surface) {
+ Mutex::Autolock l(mLock);
+ ssize_t id = -1;
+ for (size_t i = 0; i < kMaxOutputs; i++) {
+ if (mSurfaces[i] == surface) {
+ id = i;
+ break;
+ }
+ }
+
+ return id;
+}
+
+status_t Camera3SharedOutputStream::revertPartialUpdateLocked(
+ const KeyedVector<sp<Surface>, size_t> &removedSurfaces,
+ const KeyedVector<sp<Surface>, size_t> &attachedSurfaces) {
+ status_t ret = OK;
+
+ for (size_t i = 0; i < attachedSurfaces.size(); i++) {
+ size_t index = attachedSurfaces.valueAt(i);
+ if (mStreamSplitter != nullptr) {
+ ret = mStreamSplitter->removeOutput(index);
+ if (ret != OK) {
+ return UNKNOWN_ERROR;
+ }
+ }
+ mSurfaces[index] = nullptr;
+ }
+
+ for (size_t i = 0; i < removedSurfaces.size(); i++) {
+ size_t index = removedSurfaces.valueAt(i);
+ if (mStreamSplitter != nullptr) {
+ ret = mStreamSplitter->addOutput(index, removedSurfaces.keyAt(i));
+ if (ret != OK) {
+ return UNKNOWN_ERROR;
+ }
+ }
+ mSurfaces[index] = removedSurfaces.keyAt(i);
+ }
+
+ return ret;
+}
+
+status_t Camera3SharedOutputStream::updateStream(const std::vector<sp<Surface>> &outputSurfaces,
+ const std::vector<OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds,
+ KeyedVector<sp<Surface>, size_t> *outputMap) {
+ status_t ret = OK;
+ Mutex::Autolock l(mLock);
+
+ if ((outputMap == nullptr) || (outputInfo.size() != outputSurfaces.size()) ||
+ (outputSurfaces.size() > kMaxOutputs)) {
+ return BAD_VALUE;
+ }
+
+ uint64_t usage;
+ getEndpointUsage(&usage);
+ KeyedVector<sp<Surface>, size_t> removedSurfaces;
+ //Check whether the new surfaces are compatible.
+ for (const auto &infoIt : outputInfo) {
+ bool imgReaderUsage = (infoIt.consumerUsage & GRALLOC_USAGE_SW_READ_OFTEN) ? true : false;
+ bool sizeMismatch = ((static_cast<uint32_t>(infoIt.width) != getWidth()) ||
+ (static_cast<uint32_t> (infoIt.height) != getHeight())) ?
+ true : false;
+ if ((imgReaderUsage && sizeMismatch) ||
+ (infoIt.format != getOriginalFormat() && infoIt.format != getFormat()) ||
+ (infoIt.dataSpace != getDataSpace() &&
+ infoIt.dataSpace != getOriginalDataSpace())) {
+ ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x "
+ " don't match source stream format: 0x%x dataSpace: 0x%x", __FUNCTION__,
+ infoIt.format, infoIt.dataSpace, getFormat(), getDataSpace());
+ return BAD_VALUE;
+ }
+ }
+
+ //First remove all absent outputs
+ for (const auto &it : removedSurfaceIds) {
+ if (mStreamSplitter != nullptr) {
+ ret = mStreamSplitter->removeOutput(it);
+ if (ret != OK) {
+ ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
+ status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
+ if (res != OK) {
+ return res;
+ }
+ return ret;
+
+ }
+ }
+ mSurfaces[it] = nullptr;
+ removedSurfaces.add(mSurfaces[it], it);
+ }
+
+ //Next add the new outputs
+ for (const auto &it : outputSurfaces) {
+ ssize_t surfaceId = getNextSurfaceIdLocked();
+ if (surfaceId < 0) {
+ ALOGE("%s: No more available output slots!", __FUNCTION__);
+ status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
+ if (res != OK) {
+ return res;
+ }
+ return NO_MEMORY;
+ }
+ if (mStreamSplitter != nullptr) {
+ ret = mStreamSplitter->addOutput(surfaceId, it);
+ if (ret != OK) {
+ ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
+ status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
+ if (res != OK) {
+ return res;
+ }
+ return ret;
+ }
+ }
+ mSurfaces[surfaceId] = it;
+ outputMap->add(it, surfaceId);
+ }
+
+ return ret;
+}
+
} // namespace camera3
} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 22bb2fc..6eab8bd 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -46,9 +46,24 @@
virtual status_t setConsumers(const std::vector<sp<Surface>>& consumers);
+ virtual ssize_t getSurfaceId(const sp<Surface> &surface);
+
+ virtual status_t updateStream(const std::vector<sp<Surface>> &outputSurfaces,
+ const std::vector<OutputStreamInfo> &outputInfo,
+ const std::vector<size_t> &removedSurfaceIds,
+ KeyedVector<sp<Surface>, size_t> *outputMap/*out*/);
+
private:
- // Surfaces passed in constructor from app
- std::vector<sp<Surface> > mSurfaces;
+
+ static const size_t kMaxOutputs = 4;
+
+ // Map surfaceId -> output surfaces
+ sp<Surface> mSurfaces[kMaxOutputs];
+
+ ssize_t getNextSurfaceIdLocked();
+
+ status_t revertPartialUpdateLocked(const KeyedVector<sp<Surface>, size_t> &removedSurfaces,
+ const KeyedVector<sp<Surface>, size_t> &attachedSurfaces);
/**
* The Camera3StreamSplitter object this stream uses for stream
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index cc9bf8e..9ed7184 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -43,6 +43,24 @@
class StatusTracker;
+// OutputStreamInfo describes the property of a camera stream.
+class OutputStreamInfo {
+ public:
+ int width;
+ int height;
+ int format;
+ android_dataspace dataSpace;
+ uint64_t consumerUsage;
+ bool finalized = false;
+ OutputStreamInfo() :
+ width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
+ consumerUsage(0) {}
+ OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
+ uint64_t _consumerUsage) :
+ width(_width), height(_height), format(_format),
+ dataSpace(_dataSpace), consumerUsage(_consumerUsage) {}
+};
+
/**
* An interface for managing a single stream of input and/or output data from
* the camera device.
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index a0a50c2..49a10dc 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -38,8 +38,9 @@
namespace android {
-status_t Camera3StreamSplitter::connect(const std::vector<sp<Surface> >& surfaces,
- uint64_t consumerUsage, size_t halMaxBuffers, sp<Surface>* consumer) {
+status_t Camera3StreamSplitter::connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
+ uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
+ uint32_t height, android::PixelFormat format, sp<Surface>* consumer) {
ATRACE_CALL();
if (consumer == nullptr) {
SP_LOGE("%s: consumer pointer is NULL", __FUNCTION__);
@@ -62,12 +63,12 @@
mConsumerName = getUniqueConsumerName();
// Add output surfaces. This has to be before creating internal buffer queue
// in order to get max consumer side buffers.
- for (size_t i = 0; i < surfaces.size(); i++) {
- if (surfaces[i] == nullptr) {
+ for (auto &it : surfaces) {
+ if (it.second == nullptr) {
SP_LOGE("%s: Fatal: surface is NULL", __FUNCTION__);
return BAD_VALUE;
}
- res = addOutputLocked(surfaces[i]);
+ res = addOutputLocked(it.first, it.second);
if (res != OK) {
SP_LOGE("%s: Failed to add output surface: %s(%d)",
__FUNCTION__, strerror(-res), res);
@@ -94,8 +95,20 @@
return NO_MEMORY;
}
+ res = mProducer->setAsyncMode(true);
+ if (res != OK) {
+ SP_LOGE("%s: Failed to enable input queue async mode: %s(%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+
res = mConsumer->consumerConnect(this, /* controlledByApp */ false);
+ mWidth = width;
+ mHeight = height;
+ mFormat = format;
+ mProducerUsage = producerUsage;
+
SP_LOGV("%s: connected", __FUNCTION__);
return res;
}
@@ -117,10 +130,13 @@
mNotifiers.clear();
for (auto& output : mOutputs) {
- output->disconnect(NATIVE_WINDOW_API_CAMERA);
+ if (output.second != nullptr) {
+ output.second->disconnect(NATIVE_WINDOW_API_CAMERA);
+ }
}
mOutputs.clear();
mOutputSlots.clear();
+ mConsumerBufferCount.clear();
mConsumer->consumerDisconnect();
@@ -139,10 +155,10 @@
disconnect();
}
-status_t Camera3StreamSplitter::addOutput(const sp<Surface>& outputQueue) {
+status_t Camera3StreamSplitter::addOutput(size_t surfaceId, const sp<Surface>& outputQueue) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
- status_t res = addOutputLocked(outputQueue);
+ status_t res = addOutputLocked(surfaceId, outputQueue);
if (res != OK) {
SP_LOGE("%s: addOutputLocked failed %d", __FUNCTION__, res);
@@ -154,18 +170,30 @@
return res;
}
-status_t Camera3StreamSplitter::addOutputLocked(const sp<Surface>& outputQueue) {
+status_t Camera3StreamSplitter::addOutputLocked(size_t surfaceId, const sp<Surface>& outputQueue) {
ATRACE_CALL();
if (outputQueue == nullptr) {
SP_LOGE("addOutput: outputQueue must not be NULL");
return BAD_VALUE;
}
+ if (mOutputs[surfaceId] != nullptr) {
+ SP_LOGE("%s: surfaceId: %u already taken!", __FUNCTION__, (unsigned) surfaceId);
+ return BAD_VALUE;
+ }
+
+ status_t res = native_window_set_buffers_dimensions(outputQueue.get(),
+ mWidth, mHeight);
+ if (res != NO_ERROR) {
+ SP_LOGE("addOutput: failed to set buffer dimensions (%d)", res);
+ return res;
+ }
+
sp<IGraphicBufferProducer> gbp = outputQueue->getIGraphicBufferProducer();
// Connect to the buffer producer
sp<OutputListener> listener(new OutputListener(this, gbp));
IInterface::asBinder(gbp)->linkToDeath(listener);
- status_t res = outputQueue->connect(NATIVE_WINDOW_API_CAMERA, listener);
+ res = outputQueue->connect(NATIVE_WINDOW_API_CAMERA, listener);
if (res != NO_ERROR) {
SP_LOGE("addOutput: failed to connect (%d)", res);
return res;
@@ -208,7 +236,8 @@
}
// Add new entry into mOutputs
- mOutputs.push_back(gbp);
+ mOutputs[surfaceId] = gbp;
+ mConsumerBufferCount[surfaceId] = maxConsumerBuffers;
mNotifiers[gbp] = listener;
mOutputSlots[gbp] = std::make_unique<OutputSlots>(totalBufferCount);
@@ -216,8 +245,72 @@
return NO_ERROR;
}
+status_t Camera3StreamSplitter::removeOutput(size_t surfaceId) {
+ ATRACE_CALL();
+ Mutex::Autolock lock(mMutex);
+
+ status_t res = removeOutputLocked(surfaceId);
+ if (res != OK) {
+ SP_LOGE("%s: removeOutputLocked failed %d", __FUNCTION__, res);
+ return res;
+ }
+
+ res = mConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers+1);
+ if (res != OK) {
+ SP_LOGE("%s: setMaxAcquiredBufferCount failed %d", __FUNCTION__, res);
+ return res;
+ }
+
+ return res;
+}
+
+status_t Camera3StreamSplitter::removeOutputLocked(size_t surfaceId) {
+ if (mOutputs[surfaceId] == nullptr) {
+ SP_LOGE("%s: output surface is not present!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ sp<IGraphicBufferProducer> gbp = mOutputs[surfaceId];
+ //Search and decrement the ref. count of any buffers that are
+ //still attached to the removed surface.
+ std::vector<uint64_t> pendingBufferIds;
+ auto& outputSlots = *mOutputSlots[gbp];
+ for (const auto &it : outputSlots) {
+ if (it.get() != nullptr) {
+ pendingBufferIds.push_back(it->getId());
+ }
+ }
+ mOutputs[surfaceId] = nullptr;
+ mOutputSlots[gbp] = nullptr;
+ for (const auto &id : pendingBufferIds) {
+ decrementBufRefCountLocked(id, surfaceId);
+ }
+
+ auto res = IInterface::asBinder(gbp)->unlinkToDeath(mNotifiers[gbp]);
+ if (res != OK) {
+ SP_LOGE("%s: Failed to unlink producer death listener: %d ", __FUNCTION__, res);
+ return res;
+ }
+
+ res = gbp->disconnect(NATIVE_WINDOW_API_CAMERA);
+ if (res != OK) {
+ SP_LOGE("%s: Unable disconnect from producer interface: %d ", __FUNCTION__, res);
+ return res;
+ }
+
+ mNotifiers[gbp] = nullptr;
+ if (mConsumerBufferCount[surfaceId] < mMaxHalBuffers) {
+ mMaxConsumerBuffers -= mConsumerBufferCount[surfaceId];
+ } else {
+ SP_LOGE("%s: Cached consumer buffer count mismatch!", __FUNCTION__);
+ }
+ mConsumerBufferCount[surfaceId] = 0;
+
+ return res;
+}
+
status_t Camera3StreamSplitter::outputBufferLocked(const sp<IGraphicBufferProducer>& output,
- const BufferItem& bufferItem) {
+ const BufferItem& bufferItem, size_t surfaceId) {
ATRACE_CALL();
status_t res;
IGraphicBufferProducer::QueueBufferInput queueInput(
@@ -242,6 +335,11 @@
SP_LOGV("%s: Queuing buffer to buffer queue %p slot %d returns %d",
__FUNCTION__, output.get(), slot, res);
+ //During buffer queue 'mMutex' is not held which makes the removal of
+ //"output" possible. Check whether this is the case and return.
+ if (mOutputSlots[output] == nullptr) {
+ return res;
+ }
if (res != OK) {
if (res != NO_INIT && res != DEAD_OBJECT) {
SP_LOGE("Queuing buffer to output failed (%d)", res);
@@ -250,7 +348,7 @@
// that, increment the release count so that we still release this
// buffer eventually, and move on to the next output
onAbandonedLocked();
- decrementBufRefCountLocked(bufferItem.mGraphicBuffer->getId(), output);
+ decrementBufRefCountLocked(bufferItem.mGraphicBuffer->getId(), surfaceId);
return res;
}
@@ -258,7 +356,7 @@
// queue, no onBufferReleased is called by the buffer queue.
// Proactively trigger the callback to avoid buffer loss.
if (queueOutput.bufferReplaced) {
- onBufferReleasedByOutputLocked(output);
+ onBufferReleasedByOutputLocked(output, surfaceId);
}
return res;
@@ -271,7 +369,6 @@
status_t Camera3StreamSplitter::notifyBufferReleased(const sp<GraphicBuffer>& buffer) {
ATRACE_CALL();
- status_t res = OK;
Mutex::Autolock lock(mMutex);
@@ -279,17 +376,7 @@
std::unique_ptr<BufferTracker> tracker_ptr = std::move(mBuffers[bufferId]);
mBuffers.erase(bufferId);
- for (const auto surface : tracker_ptr->requestedSurfaces()) {
- sp<IGraphicBufferProducer>& gbp = mOutputs[surface];
- OutputSlots& outputSlots = *(mOutputSlots[gbp]);
- int slot = getSlotForOutputLocked(gbp, buffer);
- if (slot != BufferItem::INVALID_BUFFER_SLOT) {
- gbp->detachBuffer(slot);
- outputSlots[slot].clear();
- }
- }
-
- return res;
+ return OK;
}
status_t Camera3StreamSplitter::attachBufferToOutputs(ANativeWindowBuffer* anb,
@@ -307,7 +394,15 @@
for (auto& surface_id : surface_ids) {
sp<IGraphicBufferProducer>& gbp = mOutputs[surface_id];
- int slot = BufferItem::INVALID_BUFFER_SLOT;
+ if (gbp.get() == nullptr) {
+ //Output surface got likely removed by client.
+ continue;
+ }
+ int slot = getSlotForOutputLocked(gbp, gb);
+ if (slot != BufferItem::INVALID_BUFFER_SLOT) {
+ //Buffer is already attached to this output surface.
+ continue;
+ }
//Temporarly Unlock the mutex when trying to attachBuffer to the output
//queue, because attachBuffer could block in case of a slow consumer. If
//we block while holding the lock, onFrameAvailable and onBufferReleased
@@ -320,12 +415,17 @@
__FUNCTION__, gbp.get(), strerror(-res), res);
return res;
}
+ //During buffer attach 'mMutex' is not held which makes the removal of
+ //"gbp" possible. Check whether this is the case and continue.
+ if (mOutputSlots[gbp] == nullptr) {
+ continue;
+ }
auto& outputSlots = *mOutputSlots[gbp];
if (outputSlots[slot] != nullptr) {
// If the buffer is attached to a slot which already contains a buffer,
// the previous buffer will be removed from the output queue. Decrement
// the reference count accordingly.
- decrementBufRefCountLocked(outputSlots[slot]->getId(), gbp);
+ decrementBufRefCountLocked(outputSlots[slot]->getId(), surface_id);
}
SP_LOGV("%s: Attached buffer %p to slot %d on output %p.",__FUNCTION__, gb.get(),
slot, gbp.get());
@@ -349,7 +449,21 @@
mOnFrameAvailableRes.store(res);
return;
}
- if (mBuffers.find(bufferItem.mGraphicBuffer->getId()) == mBuffers.end()) {
+
+ uint64_t bufferId;
+ if (bufferItem.mGraphicBuffer != nullptr) {
+ mInputSlots[bufferItem.mSlot] = bufferItem;
+ } else if (bufferItem.mAcquireCalled) {
+ bufferItem.mGraphicBuffer = mInputSlots[bufferItem.mSlot].mGraphicBuffer;
+ mInputSlots[bufferItem.mSlot].mFrameNumber = bufferItem.mFrameNumber;
+ } else {
+ SP_LOGE("%s: Invalid input graphic buffer!", __FUNCTION__);
+ res = BAD_VALUE;
+ return;
+ }
+ bufferId = bufferItem.mGraphicBuffer->getId();
+
+ if (mBuffers.find(bufferId) == mBuffers.end()) {
SP_LOGE("%s: Acquired buffer doesn't exist in attached buffer map",
__FUNCTION__);
mOnFrameAvailableRes.store(INVALID_OPERATION);
@@ -359,24 +473,19 @@
SP_LOGV("acquired buffer %" PRId64 " from input at slot %d",
bufferItem.mGraphicBuffer->getId(), bufferItem.mSlot);
- res = mConsumer->detachBuffer(bufferItem.mSlot);
- if (res != NO_ERROR) {
- SP_LOGE("%s: detaching buffer from input failed (%d)", __FUNCTION__, res);
- mOnFrameAvailableRes.store(res);
- return;
- }
-
// Attach and queue the buffer to each of the outputs
- BufferTracker& tracker = *(mBuffers[bufferItem.mGraphicBuffer->getId()]);
+ BufferTracker& tracker = *(mBuffers[bufferId]);
SP_LOGV("%s: BufferTracker for buffer %" PRId64 ", number of requests %zu",
__FUNCTION__, bufferItem.mGraphicBuffer->getId(), tracker.requestedSurfaces().size());
for (const auto id : tracker.requestedSurfaces()) {
- LOG_ALWAYS_FATAL_IF(id >= mOutputs.size(),
- "requested surface id exceeding max registered ids");
+ if (mOutputs[id] == nullptr) {
+ //Output surface got likely removed by client.
+ continue;
+ }
- res = outputBufferLocked(mOutputs[id], bufferItem);
+ res = outputBufferLocked(mOutputs[id], bufferItem, id);
if (res != OK) {
SP_LOGE("%s: outputBufferLocked failed %d", __FUNCTION__, res);
mOnFrameAvailableRes.store(res);
@@ -389,12 +498,14 @@
mOnFrameAvailableRes.store(res);
}
-void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id,
- const sp<IGraphicBufferProducer>& from) {
+void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfaceId) {
ATRACE_CALL();
- size_t referenceCount = mBuffers[id]->decrementReferenceCountLocked();
- removeSlotForOutputLocked(from, mBuffers[id]->getBuffer());
+ if (mBuffers[id] == nullptr) {
+ return;
+ }
+
+ size_t referenceCount = mBuffers[id]->decrementReferenceCountLocked(surfaceId);
if (referenceCount > 0) {
return;
}
@@ -407,11 +518,18 @@
std::unique_ptr<BufferTracker> tracker_ptr = std::move(mBuffers[id]);
mBuffers.erase(id);
- // Attach and release the buffer back to the input
- int consumerSlot = BufferItem::INVALID_BUFFER_SLOT;
- status_t res = mConsumer->attachBuffer(&consumerSlot, tracker_ptr->getBuffer());
- if (res != NO_ERROR) {
- SP_LOGE("%s: attaching buffer to input failed (%d)", __FUNCTION__, res);
+ uint64_t bufferId = tracker_ptr->getBuffer()->getId();
+ int consumerSlot = -1;
+ uint64_t frameNumber;
+ for (const auto &it : mInputSlots) {
+ if (it.second.mGraphicBuffer->getId() == bufferId) {
+ consumerSlot = it.second.mSlot;
+ frameNumber = it.second.mFrameNumber;
+ break;
+ }
+ }
+ if (consumerSlot == -1) {
+ SP_LOGE("%s: Buffer missing inside input slots!", __FUNCTION__);
return;
}
@@ -424,8 +542,9 @@
// splitter lock.
sp<IGraphicBufferConsumer> consumer(mConsumer);
mMutex.unlock();
+ int res = NO_ERROR;
if (consumer != nullptr) {
- res = consumer->releaseBuffer(consumerSlot, /* frameNumber */ 0,
+ res = consumer->releaseBuffer(consumerSlot, frameNumber,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, tracker_ptr->getMergedFence());
} else {
SP_LOGE("%s: consumer has become null!", __FUNCTION__);
@@ -442,27 +561,61 @@
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
- onBufferReleasedByOutputLocked(from);
+ size_t surfaceId = 0;
+ bool found = false;
+ for (const auto& it : mOutputs) {
+ if (it.second == from) {
+ found = true;
+ surfaceId = it.first;
+ break;
+ }
+ }
+ if (!found) {
+ SP_LOGV("%s: output surface not registered anymore!", __FUNCTION__);
+ return;
+ }
+
+ onBufferReleasedByOutputLocked(from, surfaceId);
}
void Camera3StreamSplitter::onBufferReleasedByOutputLocked(
- const sp<IGraphicBufferProducer>& from) {
+ const sp<IGraphicBufferProducer>& from, size_t surfaceId) {
ATRACE_CALL();
sp<GraphicBuffer> buffer;
sp<Fence> fence;
- status_t res = from->detachNextBuffer(&buffer, &fence);
+ if (mOutputSlots[from] == nullptr) {
+ //Output surface got likely removed by client.
+ return;
+ }
+ auto outputSlots = *mOutputSlots[from];
+
+ int slot = BufferItem::INVALID_BUFFER_SLOT;
+ auto res = from->dequeueBuffer(&slot, &fence, mWidth, mHeight, mFormat, mProducerUsage,
+ nullptr, nullptr);
if (res == NO_INIT) {
// If we just discovered that this output has been abandoned, note that,
// but we can't do anything else, since buffer is invalid
onAbandonedLocked();
return;
- } else if (res == NO_MEMORY) {
- SP_LOGV("%s: No free buffers", __FUNCTION__);
+ } else if (res == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
+ SP_LOGE("%s: Producer needs to re-allocate buffer!", __FUNCTION__);
+ SP_LOGE("%s: This should not happen with buffer allocation disabled!", __FUNCTION__);
return;
- } else if (res != OK) {
- SP_LOGE("%s: detaching buffer from output failed (%d)", __FUNCTION__, res);
+ } else if (res == IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
+ SP_LOGE("%s: All slot->buffer mapping should be released!", __FUNCTION__);
+ SP_LOGE("%s: This should not happen with buffer allocation disabled!", __FUNCTION__);
+ return;
+ } else if (res == NO_MEMORY) {
+ SP_LOGE("%s: No free buffers", __FUNCTION__);
+ return;
+ } else if (res == WOULD_BLOCK) {
+ SP_LOGE("%s: Dequeue call will block", __FUNCTION__);
+ return;
+ } else if (res != OK || (slot == BufferItem::INVALID_BUFFER_SLOT)) {
+ SP_LOGE("%s: dequeue buffer from output failed (%d)", __FUNCTION__, res);
return;
}
+ buffer = outputSlots[slot];
BufferTracker& tracker = *(mBuffers[buffer->getId()]);
// Merge the release fence of the incoming buffer so that the fence we send
@@ -470,11 +623,11 @@
if (fence != nullptr && fence->isValid()) {
tracker.mergeFence(fence);
}
- SP_LOGV("detached buffer %" PRId64 " %p from output %p",
+ SP_LOGV("%s: dequeued buffer %" PRId64 " %p from output %p", __FUNCTION__,
buffer->getId(), buffer.get(), from.get());
// Check to see if this is the last outstanding reference to this buffer
- decrementBufRefCountLocked(buffer->getId(), from);
+ decrementBufRefCountLocked(buffer->getId(), surfaceId);
}
void Camera3StreamSplitter::onAbandonedLocked() {
@@ -501,27 +654,11 @@
}
}
- SP_LOGE("%s: Cannot find slot for gb %p on output %p", __FUNCTION__, gb.get(),
+ SP_LOGV("%s: Cannot find slot for gb %p on output %p", __FUNCTION__, gb.get(),
gbp.get());
return BufferItem::INVALID_BUFFER_SLOT;
}
-status_t Camera3StreamSplitter::removeSlotForOutputLocked(const sp<IGraphicBufferProducer>& gbp,
- const sp<GraphicBuffer>& gb) {
- auto& outputSlots = *mOutputSlots[gbp];
-
- for (size_t i = 0; i < outputSlots.size(); i++) {
- if (outputSlots[i] == gb) {
- outputSlots[i].clear();
- return NO_ERROR;
- }
- }
-
- SP_LOGE("%s: Cannot find slot for gb %p on output %p", __FUNCTION__, gb.get(),
- gbp.get());
- return BAD_VALUE;
-}
-
Camera3StreamSplitter::OutputListener::OutputListener(
wp<Camera3StreamSplitter> splitter,
wp<IGraphicBufferProducer> output)
@@ -553,7 +690,14 @@
mMergedFence = Fence::merge(String8("Camera3StreamSplitter"), mMergedFence, with);
}
-size_t Camera3StreamSplitter::BufferTracker::decrementReferenceCountLocked() {
+size_t Camera3StreamSplitter::BufferTracker::decrementReferenceCountLocked(size_t surfaceId) {
+ const auto& it = std::find(mRequestedSurfaces.begin(), mRequestedSurfaces.end(), surfaceId);
+ if (it == mRequestedSurfaces.end()) {
+ return mReferenceCount;
+ } else {
+ mRequestedSurfaces.erase(it);
+ }
+
if (mReferenceCount > 0)
--mReferenceCount;
return mReferenceCount;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 3b8839e..704f88f 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -51,22 +51,25 @@
// Connect to the stream splitter by creating buffer queue and connecting it
// with output surfaces.
- status_t connect(const std::vector<sp<Surface> >& surfaces,
- uint64_t consumerUsage, size_t halMaxBuffers,
- sp<Surface>* consumer);
+ status_t connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
+ uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
+ uint32_t height, android::PixelFormat format, sp<Surface>* consumer);
// addOutput adds an output BufferQueue to the splitter. The splitter
// connects to outputQueue as a CPU producer, and any buffers queued
- // to the input will be queued to each output. It is assumed that all of the
- // outputs are added before any buffers are queued on the input. If any
- // output is abandoned by its consumer, the splitter will abandon its input
- // queue (see onAbandoned).
+ // to the input will be queued to each output. If any output is abandoned
+ // by its consumer, the splitter will abandon its input queue (see onAbandoned).
//
// A return value other than NO_ERROR means that an error has occurred and
// outputQueue has not been added to the splitter. BAD_VALUE is returned if
// outputQueue is NULL. See IGraphicBufferProducer::connect for explanations
// of other error codes.
- status_t addOutput(const sp<Surface>& outputQueue);
+ status_t addOutput(size_t surfaceId, const sp<Surface>& outputQueue);
+
+ //removeOutput will remove a BufferQueue that was previously added to
+ //the splitter outputs. Any pending buffers in the BufferQueue will get
+ //reclaimed.
+ status_t removeOutput(size_t surfaceId);
// Notification that the graphic buffer has been released to the input
// BufferQueue. The buffer should be reused by the camera device instead of
@@ -120,7 +123,7 @@
// This is the implementation of onBufferReleasedByOutput without the mutex locked.
// It could either be called from onBufferReleasedByOutput or from
// onFrameAvailable when a buffer in the async buffer queue is overwritten.
- void onBufferReleasedByOutputLocked(const sp<IGraphicBufferProducer>& from);
+ void onBufferReleasedByOutputLocked(const sp<IGraphicBufferProducer>& from, size_t surfaceId);
// When this is called, the splitter disconnects from (i.e., abandons) its
// input queue and signals any waiting onFrameAvailable calls to wake up.
@@ -131,7 +134,7 @@
// Decrement the buffer's reference count. Once the reference count becomes
// 0, return the buffer back to the input BufferQueue.
- void decrementBufRefCountLocked(uint64_t id, const sp<IGraphicBufferProducer>& from);
+ void decrementBufRefCountLocked(uint64_t id, size_t surfaceId);
// This is a thin wrapper class that lets us determine which BufferQueue
// the IProducerListener::onBufferReleased callback is associated with. We
@@ -168,7 +171,7 @@
// Returns the new value
// Only called while mMutex is held
- size_t decrementReferenceCountLocked();
+ size_t decrementReferenceCountLocked(size_t surfaceId);
const std::vector<size_t> requestedSurfaces() const { return mRequestedSurfaces; }
@@ -191,13 +194,15 @@
// Must be accessed through RefBase
virtual ~Camera3StreamSplitter();
- status_t addOutputLocked(const sp<Surface>& outputQueue);
+ status_t addOutputLocked(size_t surfaceId, const sp<Surface>& outputQueue);
+
+ status_t removeOutputLocked(size_t surfaceId);
// Send a buffer to particular output, and increment the reference count
// of the buffer. If this output is abandoned, the buffer's reference count
// won't be incremented.
status_t outputBufferLocked(const sp<IGraphicBufferProducer>& output,
- const BufferItem& bufferItem);
+ const BufferItem& bufferItem, size_t surfaceId);
// Get unique name for the buffer queue consumer
String8 getUniqueConsumerName();
@@ -205,14 +210,14 @@
// Helper function to get the BufferQueue slot where a particular buffer is attached to.
int getSlotForOutputLocked(const sp<IGraphicBufferProducer>& gbp,
const sp<GraphicBuffer>& gb);
- // Helper function to remove the buffer from the BufferQueue slot
- status_t removeSlotForOutputLocked(const sp<IGraphicBufferProducer>& gbp,
- const sp<GraphicBuffer>& gb);
-
// Sum of max consumer buffers for all outputs
size_t mMaxConsumerBuffers = 0;
size_t mMaxHalBuffers = 0;
+ uint32_t mWidth = 0;
+ uint32_t mHeight = 0;
+ android::PixelFormat mFormat = android::PIXEL_FORMAT_NONE;
+ uint64_t mProducerUsage = 0;
static const nsecs_t kDequeueBufferTimeout = s2ns(1); // 1 sec
@@ -223,7 +228,15 @@
sp<BufferItemConsumer> mBufferItemConsumer;
sp<Surface> mSurface;
- std::vector<sp<IGraphicBufferProducer> > mOutputs;
+ //Map graphic buffer ids -> buffer items
+ std::unordered_map<uint64_t, BufferItem> mInputSlots;
+
+ //Map surface ids -> gbp outputs
+ std::unordered_map<int, sp<IGraphicBufferProducer> > mOutputs;
+
+ //Map surface ids -> consumer buffer count
+ std::unordered_map<int, size_t > mConsumerBufferCount;
+
// Map of GraphicBuffer IDs (GraphicBuffer::getId()) to buffer tracking
// objects (which are mostly for counting how many outputs have released the
// buffer, but also contain merged release fences).
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index f08be50..83992aa 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -318,6 +318,7 @@
saveItem(mFinalized, oitem, 0);
}
// new record could itself be marked finalized...
+ id = item->getSessionID();
if (finalizing) {
summarize(item);
saveItem(mFinalized, item, 0);
@@ -325,16 +326,15 @@
} else {
saveItem(mOpen, item, 1);
}
- id = item->getSessionID();
} else {
// combine the records, send it to finalized if appropriate
oitem->merge(item);
+ id = oitem->getSessionID();
if (finalizing) {
summarize(oitem);
saveItem(mFinalized, oitem, 0);
mItemsFinalized++;
}
- id = oitem->getSessionID();
// we're responsible for disposing of the dead record
delete item;
@@ -614,17 +614,28 @@
// caller should hold mLock
void MediaAnalyticsService::saveItem(List<MediaAnalyticsItem *> *l, MediaAnalyticsItem * item, int front) {
- // adding at back of queue (fifo order)
if (front) {
+ // for non-finalized stuff, since we expect to reference it again soon,
+ // make it quicker to find (nearer the front of our list)
l->push_front(item);
} else {
+ // for finalized records, which we want to dump 'in sequence order'
l->push_back(item);
}
+ // our reclaim process is for oldest-first queues
+ if (front) {
+ return;
+ }
+
+
// keep removing old records the front until we're in-bounds (count)
if (mMaxRecords > 0) {
while (l->size() > (size_t) mMaxRecords) {
MediaAnalyticsItem * oitem = *(l->begin());
+ if (oitem == item) {
+ break;
+ }
l->erase(l->begin());
delete oitem;
mItemsDiscarded++;
@@ -638,6 +649,9 @@
while (l->size() > 0) {
MediaAnalyticsItem * oitem = *(l->begin());
nsecs_t when = oitem->getTimestamp();
+ if (oitem == item) {
+ break;
+ }
// careful about timejumps too
if ((now > when) && (now-when) <= mMaxRecordAgeNs) {
// this (and the rest) are recent enough to keep
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 6d833aa..a7d6e83 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -313,7 +313,7 @@
}
-sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
+sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent(sound_trigger_service_state_t state)
{
AutoMutex lock(mMemoryDealerLock);
sp<IMemory> eventMemory;
@@ -328,34 +328,23 @@
return eventMemory;
}
-// call with mServiceLock held
-void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
+void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
Module *module)
{
- sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
+ sp<IMemory> eventMemory = prepareServiceStateEvent(state);
if (eventMemory == 0) {
return;
}
- sp<Module> strongModule;
- for (size_t i = 0; i < mModules.size(); i++) {
- if (mModules.valueAt(i).get() == module) {
- strongModule = mModules.valueAt(i);
- break;
- }
- }
- if (strongModule == 0) {
- return;
- }
sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
eventMemory);
- callbackEvent->setModule(strongModule);
+ callbackEvent->setModule(module);
sendCallbackEvent(callbackEvent);
}
-void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
- ModuleClient *moduleClient)
+void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
+ ModuleClient *moduleClient)
{
- sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
+ sp<IMemory> eventMemory = prepareServiceStateEvent(state);
if (eventMemory == 0) {
return;
}
@@ -906,7 +895,7 @@
}
exit:
- service->sendServiceStateEvent_l(state, this);
+ service->sendServiceStateEvent(state, this);
}
@@ -1051,7 +1040,7 @@
return;
}
}
- service->sendServiceStateEvent_l(state, this);
+ service->sendServiceStateEvent(state, this);
}
void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index a955f40..708fc98 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -221,10 +221,10 @@
sp<IMemory> prepareSoundModelEvent(struct sound_trigger_model_event *event);
void sendSoundModelEvent(struct sound_trigger_model_event *event, Module *module);
- sp<IMemory> prepareServiceStateEvent_l(sound_trigger_service_state_t state);
- void sendServiceStateEvent_l(sound_trigger_service_state_t state, Module *module);
- void sendServiceStateEvent_l(sound_trigger_service_state_t state,
- ModuleClient *moduleClient);
+ sp<IMemory> prepareServiceStateEvent(sound_trigger_service_state_t state);
+ void sendServiceStateEvent(sound_trigger_service_state_t state, Module *module);
+ void sendServiceStateEvent(sound_trigger_service_state_t state,
+ ModuleClient *moduleClient);
void sendCallbackEvent(const sp<CallbackEvent>& event);
void onCallbackEvent(const sp<CallbackEvent>& event);